diff options
Diffstat (limited to 'drivers/input/joydev.c')
| -rw-r--r-- | drivers/input/joydev.c | 61 | 
1 files changed, 61 insertions, 0 deletions
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index f362883c94e3..1d247bcf2ae2 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -747,6 +747,63 @@ static void joydev_cleanup(struct joydev *joydev)  		input_close_device(handle);  } +static bool joydev_dev_is_absolute_mouse(struct input_dev *dev) +{ +	DECLARE_BITMAP(jd_scratch, KEY_CNT); + +	BUILD_BUG_ON(ABS_CNT > KEY_CNT || EV_CNT > KEY_CNT); + +	/* +	 * Virtualization (VMware, etc) and remote management (HP +	 * ILO2) solutions use absolute coordinates for their virtual +	 * pointing devices so that there is one-to-one relationship +	 * between pointer position on the host screen and virtual +	 * guest screen, and so their mice use ABS_X, ABS_Y and 3 +	 * primary button events. This clashes with what joydev +	 * considers to be joysticks (a device with at minimum ABS_X +	 * axis). +	 * +	 * Here we are trying to separate absolute mice from +	 * joysticks. A device is, for joystick detection purposes, +	 * considered to be an absolute mouse if the following is +	 * true: +	 * +	 * 1) Event types are exactly EV_ABS, EV_KEY and EV_SYN. +	 * 2) Absolute events are exactly ABS_X and ABS_Y. +	 * 3) Keys are exactly BTN_LEFT, BTN_RIGHT and BTN_MIDDLE. +	 * 4) Device is not on "Amiga" bus. +	 */ + +	bitmap_zero(jd_scratch, EV_CNT); +	__set_bit(EV_ABS, jd_scratch); +	__set_bit(EV_KEY, jd_scratch); +	__set_bit(EV_SYN, jd_scratch); +	if (!bitmap_equal(jd_scratch, dev->evbit, EV_CNT)) +		return false; + +	bitmap_zero(jd_scratch, ABS_CNT); +	__set_bit(ABS_X, jd_scratch); +	__set_bit(ABS_Y, jd_scratch); +	if (!bitmap_equal(dev->absbit, jd_scratch, ABS_CNT)) +		return false; + +	bitmap_zero(jd_scratch, KEY_CNT); +	__set_bit(BTN_LEFT, jd_scratch); +	__set_bit(BTN_RIGHT, jd_scratch); +	__set_bit(BTN_MIDDLE, jd_scratch); + +	if (!bitmap_equal(dev->keybit, jd_scratch, KEY_CNT)) +		return false; + +	/* +	 * Amiga joystick (amijoy) historically uses left/middle/right +	 * button events. +	 */ +	if (dev->id.bustype == BUS_AMIGA) +		return false; + +	return true; +}  static bool joydev_match(struct input_handler *handler, struct input_dev *dev)  { @@ -758,6 +815,10 @@ static bool joydev_match(struct input_handler *handler, struct input_dev *dev)  	if (test_bit(EV_KEY, dev->evbit) && test_bit(BTN_DIGI, dev->keybit))  		return false; +	/* Avoid absolute mice */ +	if (joydev_dev_is_absolute_mouse(dev)) +		return false; +  	return true;  }  |