|
|
@@ -63,6 +63,9 @@ static void xenkbd_disconnect_backend(struct xenkbd_info *);
|
|
|
static void xenkbd_handle_motion_event(struct xenkbd_info *info,
|
|
|
struct xenkbd_motion *motion)
|
|
|
{
|
|
|
+ if (unlikely(!info->ptr))
|
|
|
+ return;
|
|
|
+
|
|
|
input_report_rel(info->ptr, REL_X, motion->rel_x);
|
|
|
input_report_rel(info->ptr, REL_Y, motion->rel_y);
|
|
|
if (motion->rel_z)
|
|
|
@@ -73,6 +76,9 @@ static void xenkbd_handle_motion_event(struct xenkbd_info *info,
|
|
|
static void xenkbd_handle_position_event(struct xenkbd_info *info,
|
|
|
struct xenkbd_position *pos)
|
|
|
{
|
|
|
+ if (unlikely(!info->ptr))
|
|
|
+ return;
|
|
|
+
|
|
|
input_report_abs(info->ptr, ABS_X, pos->abs_x);
|
|
|
input_report_abs(info->ptr, ABS_Y, pos->abs_y);
|
|
|
if (pos->rel_z)
|
|
|
@@ -97,6 +103,9 @@ static void xenkbd_handle_key_event(struct xenkbd_info *info,
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ if (unlikely(!dev))
|
|
|
+ return;
|
|
|
+
|
|
|
input_event(dev, EV_KEY, key->keycode, value);
|
|
|
input_sync(dev);
|
|
|
}
|
|
|
@@ -192,7 +201,7 @@ static int xenkbd_probe(struct xenbus_device *dev,
|
|
|
const struct xenbus_device_id *id)
|
|
|
{
|
|
|
int ret, i;
|
|
|
- unsigned int abs, touch;
|
|
|
+ bool with_mtouch, with_kbd, with_ptr;
|
|
|
struct xenkbd_info *info;
|
|
|
struct input_dev *kbd, *ptr, *mtouch;
|
|
|
|
|
|
@@ -211,93 +220,114 @@ static int xenkbd_probe(struct xenbus_device *dev,
|
|
|
if (!info->page)
|
|
|
goto error_nomem;
|
|
|
|
|
|
- /* Set input abs params to match backend screen res */
|
|
|
- abs = xenbus_read_unsigned(dev->otherend,
|
|
|
- XENKBD_FIELD_FEAT_ABS_POINTER, 0);
|
|
|
- ptr_size[KPARAM_X] = xenbus_read_unsigned(dev->otherend,
|
|
|
- XENKBD_FIELD_WIDTH,
|
|
|
- ptr_size[KPARAM_X]);
|
|
|
- ptr_size[KPARAM_Y] = xenbus_read_unsigned(dev->otherend,
|
|
|
- XENKBD_FIELD_HEIGHT,
|
|
|
- ptr_size[KPARAM_Y]);
|
|
|
- if (abs) {
|
|
|
- ret = xenbus_write(XBT_NIL, dev->nodename,
|
|
|
- XENKBD_FIELD_REQ_ABS_POINTER, "1");
|
|
|
- if (ret) {
|
|
|
- pr_warn("xenkbd: can't request abs-pointer\n");
|
|
|
- abs = 0;
|
|
|
- }
|
|
|
- }
|
|
|
+ /*
|
|
|
+ * The below are reverse logic, e.g. if the feature is set, then
|
|
|
+ * do not expose the corresponding virtual device.
|
|
|
+ */
|
|
|
+ with_kbd = !xenbus_read_unsigned(dev->otherend,
|
|
|
+ XENKBD_FIELD_FEAT_DSBL_KEYBRD, 0);
|
|
|
+
|
|
|
+ with_ptr = !xenbus_read_unsigned(dev->otherend,
|
|
|
+ XENKBD_FIELD_FEAT_DSBL_POINTER, 0);
|
|
|
|
|
|
- touch = xenbus_read_unsigned(dev->otherend,
|
|
|
- XENKBD_FIELD_FEAT_MTOUCH, 0);
|
|
|
- if (touch) {
|
|
|
+ /* Direct logic: if set, then create multi-touch device. */
|
|
|
+ with_mtouch = xenbus_read_unsigned(dev->otherend,
|
|
|
+ XENKBD_FIELD_FEAT_MTOUCH, 0);
|
|
|
+ if (with_mtouch) {
|
|
|
ret = xenbus_write(XBT_NIL, dev->nodename,
|
|
|
XENKBD_FIELD_REQ_MTOUCH, "1");
|
|
|
if (ret) {
|
|
|
pr_warn("xenkbd: can't request multi-touch");
|
|
|
- touch = 0;
|
|
|
+ with_mtouch = 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* keyboard */
|
|
|
- kbd = input_allocate_device();
|
|
|
- if (!kbd)
|
|
|
- goto error_nomem;
|
|
|
- kbd->name = "Xen Virtual Keyboard";
|
|
|
- kbd->phys = info->phys;
|
|
|
- kbd->id.bustype = BUS_PCI;
|
|
|
- kbd->id.vendor = 0x5853;
|
|
|
- kbd->id.product = 0xffff;
|
|
|
-
|
|
|
- __set_bit(EV_KEY, kbd->evbit);
|
|
|
- for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
|
|
|
- __set_bit(i, kbd->keybit);
|
|
|
- for (i = KEY_OK; i < KEY_MAX; i++)
|
|
|
- __set_bit(i, kbd->keybit);
|
|
|
-
|
|
|
- ret = input_register_device(kbd);
|
|
|
- if (ret) {
|
|
|
- input_free_device(kbd);
|
|
|
- xenbus_dev_fatal(dev, ret, "input_register_device(kbd)");
|
|
|
- goto error;
|
|
|
+ if (with_kbd) {
|
|
|
+ kbd = input_allocate_device();
|
|
|
+ if (!kbd)
|
|
|
+ goto error_nomem;
|
|
|
+ kbd->name = "Xen Virtual Keyboard";
|
|
|
+ kbd->phys = info->phys;
|
|
|
+ kbd->id.bustype = BUS_PCI;
|
|
|
+ kbd->id.vendor = 0x5853;
|
|
|
+ kbd->id.product = 0xffff;
|
|
|
+
|
|
|
+ __set_bit(EV_KEY, kbd->evbit);
|
|
|
+ for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
|
|
|
+ __set_bit(i, kbd->keybit);
|
|
|
+ for (i = KEY_OK; i < KEY_MAX; i++)
|
|
|
+ __set_bit(i, kbd->keybit);
|
|
|
+
|
|
|
+ ret = input_register_device(kbd);
|
|
|
+ if (ret) {
|
|
|
+ input_free_device(kbd);
|
|
|
+ xenbus_dev_fatal(dev, ret,
|
|
|
+ "input_register_device(kbd)");
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+ info->kbd = kbd;
|
|
|
}
|
|
|
- info->kbd = kbd;
|
|
|
|
|
|
/* pointing device */
|
|
|
- ptr = input_allocate_device();
|
|
|
- if (!ptr)
|
|
|
- goto error_nomem;
|
|
|
- ptr->name = "Xen Virtual Pointer";
|
|
|
- ptr->phys = info->phys;
|
|
|
- ptr->id.bustype = BUS_PCI;
|
|
|
- ptr->id.vendor = 0x5853;
|
|
|
- ptr->id.product = 0xfffe;
|
|
|
-
|
|
|
- if (abs) {
|
|
|
- __set_bit(EV_ABS, ptr->evbit);
|
|
|
- input_set_abs_params(ptr, ABS_X, 0, ptr_size[KPARAM_X], 0, 0);
|
|
|
- input_set_abs_params(ptr, ABS_Y, 0, ptr_size[KPARAM_Y], 0, 0);
|
|
|
- } else {
|
|
|
- input_set_capability(ptr, EV_REL, REL_X);
|
|
|
- input_set_capability(ptr, EV_REL, REL_Y);
|
|
|
- }
|
|
|
- input_set_capability(ptr, EV_REL, REL_WHEEL);
|
|
|
+ if (with_ptr) {
|
|
|
+ unsigned int abs;
|
|
|
+
|
|
|
+ /* Set input abs params to match backend screen res */
|
|
|
+ abs = xenbus_read_unsigned(dev->otherend,
|
|
|
+ XENKBD_FIELD_FEAT_ABS_POINTER, 0);
|
|
|
+ ptr_size[KPARAM_X] = xenbus_read_unsigned(dev->otherend,
|
|
|
+ XENKBD_FIELD_WIDTH,
|
|
|
+ ptr_size[KPARAM_X]);
|
|
|
+ ptr_size[KPARAM_Y] = xenbus_read_unsigned(dev->otherend,
|
|
|
+ XENKBD_FIELD_HEIGHT,
|
|
|
+ ptr_size[KPARAM_Y]);
|
|
|
+ if (abs) {
|
|
|
+ ret = xenbus_write(XBT_NIL, dev->nodename,
|
|
|
+ XENKBD_FIELD_REQ_ABS_POINTER, "1");
|
|
|
+ if (ret) {
|
|
|
+ pr_warn("xenkbd: can't request abs-pointer\n");
|
|
|
+ abs = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- __set_bit(EV_KEY, ptr->evbit);
|
|
|
- for (i = BTN_LEFT; i <= BTN_TASK; i++)
|
|
|
- __set_bit(i, ptr->keybit);
|
|
|
+ ptr = input_allocate_device();
|
|
|
+ if (!ptr)
|
|
|
+ goto error_nomem;
|
|
|
+ ptr->name = "Xen Virtual Pointer";
|
|
|
+ ptr->phys = info->phys;
|
|
|
+ ptr->id.bustype = BUS_PCI;
|
|
|
+ ptr->id.vendor = 0x5853;
|
|
|
+ ptr->id.product = 0xfffe;
|
|
|
+
|
|
|
+ if (abs) {
|
|
|
+ __set_bit(EV_ABS, ptr->evbit);
|
|
|
+ input_set_abs_params(ptr, ABS_X, 0,
|
|
|
+ ptr_size[KPARAM_X], 0, 0);
|
|
|
+ input_set_abs_params(ptr, ABS_Y, 0,
|
|
|
+ ptr_size[KPARAM_Y], 0, 0);
|
|
|
+ } else {
|
|
|
+ input_set_capability(ptr, EV_REL, REL_X);
|
|
|
+ input_set_capability(ptr, EV_REL, REL_Y);
|
|
|
+ }
|
|
|
+ input_set_capability(ptr, EV_REL, REL_WHEEL);
|
|
|
|
|
|
- ret = input_register_device(ptr);
|
|
|
- if (ret) {
|
|
|
- input_free_device(ptr);
|
|
|
- xenbus_dev_fatal(dev, ret, "input_register_device(ptr)");
|
|
|
- goto error;
|
|
|
+ __set_bit(EV_KEY, ptr->evbit);
|
|
|
+ for (i = BTN_LEFT; i <= BTN_TASK; i++)
|
|
|
+ __set_bit(i, ptr->keybit);
|
|
|
+
|
|
|
+ ret = input_register_device(ptr);
|
|
|
+ if (ret) {
|
|
|
+ input_free_device(ptr);
|
|
|
+ xenbus_dev_fatal(dev, ret,
|
|
|
+ "input_register_device(ptr)");
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+ info->ptr = ptr;
|
|
|
}
|
|
|
- info->ptr = ptr;
|
|
|
|
|
|
/* multi-touch device */
|
|
|
- if (touch) {
|
|
|
+ if (with_mtouch) {
|
|
|
int num_cont, width, height;
|
|
|
|
|
|
mtouch = input_allocate_device();
|
|
|
@@ -346,6 +376,11 @@ static int xenkbd_probe(struct xenbus_device *dev,
|
|
|
info->mtouch = mtouch;
|
|
|
}
|
|
|
|
|
|
+ if (!(with_kbd || with_ptr || with_mtouch)) {
|
|
|
+ ret = -ENXIO;
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+
|
|
|
ret = xenkbd_connect_backend(dev, info);
|
|
|
if (ret < 0)
|
|
|
goto error;
|