direct-io.hg

changeset 13822:cb50bcfcf9fa

pvfb: Split mouse and keyboard into separate devices.

This patch creates two separate input devices for keyboard and mouse
events. The reason for this is to separate them in the linux input
layer and allow them being routed different ways.

Use case: Configure the X-Server like this to get the mouse
events directly from the linux input layer, which has the major
advantage that absolute coordinates work correctly:

Section "InputDevice"
Driver "evdev"
Identifier "Mouse"
Option "Device" "/dev/input/event<nr>"
EndSection

This makes the keyboard stop working though in case mouse and
keyboard events are coming through the same input device, at least
with older Xorg (6.9) versions.

Signed-off-by: Gerd Hoffmann <kraxel@suse.de>

Assign fake pci product identifiers down from 0xffff. This may help
clarify that the devices are not actually PCI. Also it reduces
probability of accidental conflict if further real PCI assignments
occur in future (0x0002, 0x0003, ... would be obvious next identifiers
to allocate).

Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Wed Feb 07 16:12:40 2007 +0000 (2007-02-07)
parents 6e1b380947ee
children b83a81b99f20
files linux-2.6-xen-sparse/drivers/xen/fbfront/xenkbd.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/fbfront/xenkbd.c	Wed Feb 07 16:08:47 2007 +0000
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/fbfront/xenkbd.c	Wed Feb 07 16:12:40 2007 +0000
     1.3 @@ -29,10 +29,12 @@
     1.4  
     1.5  struct xenkbd_info
     1.6  {
     1.7 -	struct input_dev *dev;
     1.8 +	struct input_dev *kbd;
     1.9 +	struct input_dev *ptr;
    1.10  	struct xenkbd_page *page;
    1.11  	int irq;
    1.12  	struct xenbus_device *xbdev;
    1.13 +	char phys[32];
    1.14  };
    1.15  
    1.16  static int xenkbd_remove(struct xenbus_device *);
    1.17 @@ -56,23 +58,36 @@ static irqreturn_t input_handler(int rq,
    1.18  	rmb();			/* ensure we see ring contents up to prod */
    1.19  	for (cons = page->in_cons; cons != prod; cons++) {
    1.20  		union xenkbd_in_event *event;
    1.21 +		struct input_dev *dev;
    1.22  		event = &XENKBD_IN_RING_REF(page, cons);
    1.23  
    1.24 +		dev = info->ptr;
    1.25  		switch (event->type) {
    1.26  		case XENKBD_TYPE_MOTION:
    1.27 -			input_report_rel(info->dev, REL_X, event->motion.rel_x);
    1.28 -			input_report_rel(info->dev, REL_Y, event->motion.rel_y);
    1.29 +			input_report_rel(dev, REL_X, event->motion.rel_x);
    1.30 +			input_report_rel(dev, REL_Y, event->motion.rel_y);
    1.31  			break;
    1.32  		case XENKBD_TYPE_KEY:
    1.33 -			input_report_key(info->dev, event->key.keycode, event->key.pressed);
    1.34 +			dev = NULL;
    1.35 +			if (test_bit(event->key.keycode, info->kbd->keybit))
    1.36 +				dev = info->kbd;
    1.37 +			if (test_bit(event->key.keycode, info->ptr->keybit))
    1.38 +				dev = info->ptr;
    1.39 +			if (dev)
    1.40 +				input_report_key(dev, event->key.keycode,
    1.41 +						 event->key.pressed);
    1.42 +			else
    1.43 +				printk("xenkbd: unhandled keycode 0x%x\n",
    1.44 +				       event->key.keycode);
    1.45  			break;
    1.46  		case XENKBD_TYPE_POS:
    1.47 -			input_report_abs(info->dev, ABS_X, event->pos.abs_x);
    1.48 -			input_report_abs(info->dev, ABS_Y, event->pos.abs_y);
    1.49 +			input_report_abs(dev, ABS_X, event->pos.abs_x);
    1.50 +			input_report_abs(dev, ABS_Y, event->pos.abs_y);
    1.51  			break;
    1.52  		}
    1.53 +		if (dev)
    1.54 +			input_sync(dev);
    1.55  	}
    1.56 -	input_sync(info->dev);
    1.57  	mb();			/* ensure we got ring contents */
    1.58  	page->in_cons = cons;
    1.59  	notify_remote_via_irq(info->irq);
    1.60 @@ -85,7 +100,7 @@ int __devinit xenkbd_probe(struct xenbus
    1.61  {
    1.62  	int ret, i;
    1.63  	struct xenkbd_info *info;
    1.64 -	struct input_dev *input_dev;
    1.65 +	struct input_dev *kbd, *ptr;
    1.66  
    1.67  	info = kzalloc(sizeof(*info), GFP_KERNEL);
    1.68  	if (!info) {
    1.69 @@ -94,6 +109,7 @@ int __devinit xenkbd_probe(struct xenbus
    1.70  	}
    1.71  	dev->dev.driver_data = info;
    1.72  	info->xbdev = dev;
    1.73 +	snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename);
    1.74  
    1.75  	info->page = (void *)__get_free_page(GFP_KERNEL);
    1.76  	if (!info->page)
    1.77 @@ -101,32 +117,52 @@ int __devinit xenkbd_probe(struct xenbus
    1.78  	info->page->in_cons = info->page->in_prod = 0;
    1.79  	info->page->out_cons = info->page->out_prod = 0;
    1.80  
    1.81 -	input_dev = input_allocate_device();
    1.82 -	if (!input_dev)
    1.83 +	/* keyboard */
    1.84 +	kbd = input_allocate_device();
    1.85 +	if (!kbd)
    1.86  		goto error_nomem;
    1.87 -
    1.88 -	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
    1.89 -	input_dev->keybit[LONG(BTN_MOUSE)]
    1.90 -		= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
    1.91 -	/* TODO additional buttons */
    1.92 -	input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
    1.93 +	kbd->name = "Xen Virtual Keyboard";
    1.94 +	kbd->phys = info->phys;
    1.95 +	kbd->id.bustype = BUS_PCI;
    1.96 +	kbd->id.vendor = 0x5853;
    1.97 +	kbd->id.product = 0xffff;
    1.98 +	kbd->evbit[0] = BIT(EV_KEY);
    1.99 +	for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
   1.100 +		set_bit(i, kbd->keybit);
   1.101 +	for (i = KEY_OK; i < KEY_MAX; i++)
   1.102 +		set_bit(i, kbd->keybit);
   1.103  
   1.104 -	/* FIXME not sure this is quite right */
   1.105 -	for (i = 0; i < 256; i++)
   1.106 -		set_bit(i, input_dev->keybit);
   1.107 -
   1.108 -	input_dev->name = "Xen Virtual Keyboard/Mouse";
   1.109 -
   1.110 -	input_set_abs_params(input_dev, ABS_X, 0, XENFB_WIDTH, 0, 0);
   1.111 -	input_set_abs_params(input_dev, ABS_Y, 0, XENFB_HEIGHT, 0, 0);
   1.112 -
   1.113 -	ret = input_register_device(input_dev);
   1.114 +	ret = input_register_device(kbd);
   1.115  	if (ret) {
   1.116 -		input_free_device(input_dev);
   1.117 -		xenbus_dev_fatal(dev, ret, "input_register_device");
   1.118 +		input_free_device(kbd);
   1.119 +		xenbus_dev_fatal(dev, ret, "input_register_device(kbd)");
   1.120  		goto error;
   1.121  	}
   1.122 -	info->dev = input_dev;
   1.123 +	info->kbd = kbd;
   1.124 +
   1.125 +	/* pointing device */
   1.126 +	ptr = input_allocate_device();
   1.127 +	if (!ptr)
   1.128 +		goto error_nomem;
   1.129 +	ptr->name = "Xen Virtual Pointer";
   1.130 +	ptr->phys = info->phys;
   1.131 +	ptr->id.bustype = BUS_PCI;
   1.132 +	ptr->id.vendor = 0x5853;
   1.133 +	ptr->id.product = 0xfffe;
   1.134 +	ptr->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
   1.135 +	for (i = BTN_LEFT; i <= BTN_TASK; i++)
   1.136 +		set_bit(i, ptr->keybit);
   1.137 +	ptr->relbit[0] = BIT(REL_X) | BIT(REL_Y);
   1.138 +	input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0);
   1.139 +	input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0);
   1.140 +
   1.141 +	ret = input_register_device(ptr);
   1.142 +	if (ret) {
   1.143 +		input_free_device(ptr);
   1.144 +		xenbus_dev_fatal(dev, ret, "input_register_device(ptr)");
   1.145 +		goto error;
   1.146 +	}
   1.147 +	info->ptr = ptr;
   1.148  
   1.149  	ret = xenkbd_connect_backend(dev, info);
   1.150  	if (ret < 0)
   1.151 @@ -155,7 +191,8 @@ static int xenkbd_remove(struct xenbus_d
   1.152  	struct xenkbd_info *info = dev->dev.driver_data;
   1.153  
   1.154  	xenkbd_disconnect_backend(info);
   1.155 -	input_unregister_device(info->dev);
   1.156 +	input_unregister_device(info->kbd);
   1.157 +	input_unregister_device(info->ptr);
   1.158  	free_page((unsigned long)info->page);
   1.159  	kfree(info);
   1.160  	return 0;