--- zzzz-none-000/linux-3.10.107/drivers/input/joydev.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/input/joydev.c 2021-02-04 17:41:59.000000000 +0000 @@ -188,17 +188,6 @@ synchronize_rcu(); } -static void joydev_refresh_state(struct joydev *joydev) -{ - struct input_dev *dev = joydev->handle.dev; - int i, val; - - for (i = 0; i < joydev->nabs; i++) { - val = input_abs_get_val(dev, joydev->abspam[i]); - joydev->abs[i] = joydev_correct(val, &joydev->corr[i]); - } -} - static int joydev_open_device(struct joydev *joydev) { int retval; @@ -213,8 +202,6 @@ retval = input_open_device(&joydev->handle); if (retval) joydev->open--; - else - joydev_refresh_state(joydev); } mutex_unlock(&joydev->mutex); @@ -457,14 +444,9 @@ len = min(len, sizeof(joydev->abspam)); /* Validate the map. */ - abspam = kmalloc(len, GFP_KERNEL); - if (!abspam) - return -ENOMEM; - - if (copy_from_user(abspam, argp, len)) { - retval = -EFAULT; - goto out; - } + abspam = memdup_user(argp, len); + if (IS_ERR(abspam)) + return PTR_ERR(abspam); for (i = 0; i < joydev->nabs; i++) { if (abspam[i] > ABS_MAX) { @@ -493,14 +475,9 @@ len = min(len, sizeof(joydev->keypam)); /* Validate the map. */ - keypam = kmalloc(len, GFP_KERNEL); - if (!keypam) - return -ENOMEM; - - if (copy_from_user(keypam, argp, len)) { - retval = -EFAULT; - goto out; - } + keypam = memdup_user(argp, len); + if (IS_ERR(keypam)) + return PTR_ERR(keypam); for (i = 0; i < joydev->nkey; i++) { if (keypam[i] > KEY_MAX || keypam[i] < BTN_MISC) { @@ -760,6 +737,63 @@ 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) { @@ -771,6 +805,10 @@ 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; } @@ -811,12 +849,11 @@ joydev->handle.handler = handler; joydev->handle.private = joydev; - for (i = 0; i < ABS_CNT; i++) - if (test_bit(i, dev->absbit)) { - joydev->absmap[i] = joydev->nabs; - joydev->abspam[joydev->nabs] = i; - joydev->nabs++; - } + for_each_set_bit(i, dev->absbit, ABS_CNT) { + joydev->absmap[i] = joydev->nabs; + joydev->abspam[joydev->nabs] = i; + joydev->nabs++; + } for (i = BTN_JOYSTICK - BTN_MISC; i < KEY_MAX - BTN_MISC + 1; i++) if (test_bit(i + BTN_MISC, dev->keybit)) { @@ -836,6 +873,7 @@ j = joydev->abspam[i]; if (input_abs_get_max(dev, j) == input_abs_get_min(dev, j)) { joydev->corr[i].type = JS_CORR_NONE; + joydev->abs[i] = input_abs_get_val(dev, j); continue; } joydev->corr[i].type = JS_CORR_BROKEN; @@ -850,6 +888,10 @@ if (t) { joydev->corr[i].coef[2] = (1 << 29) / t; joydev->corr[i].coef[3] = (1 << 29) / t; + + joydev->abs[i] = + joydev_correct(input_abs_get_val(dev, j), + joydev->corr + i); } }