Loading drivers/hid/hid-wacom.c +24 −25 Original line number Diff line number Diff line Loading @@ -230,7 +230,7 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, input_report_key(input, BTN_RIGHT, 0); input_report_key(input, BTN_MIDDLE, 0); input_report_abs(input, ABS_DISTANCE, input->absmax[ABS_DISTANCE]); input_abs_get_max(input, ABS_DISTANCE)); } else { input_report_key(input, BTN_TOUCH, 0); input_report_key(input, BTN_STYLUS, 0); Loading Loading @@ -383,38 +383,37 @@ move_on: /* Basics */ input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL); input->absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE); input->relbit[0] |= BIT(REL_WHEEL); set_bit(BTN_TOOL_PEN, input->keybit); set_bit(BTN_TOUCH, input->keybit); set_bit(BTN_STYLUS, input->keybit); set_bit(BTN_STYLUS2, input->keybit); set_bit(BTN_LEFT, input->keybit); set_bit(BTN_RIGHT, input->keybit); set_bit(BTN_MIDDLE, input->keybit); __set_bit(REL_WHEEL, input->relbit); __set_bit(BTN_TOOL_PEN, input->keybit); __set_bit(BTN_TOUCH, input->keybit); __set_bit(BTN_STYLUS, input->keybit); __set_bit(BTN_STYLUS2, input->keybit); __set_bit(BTN_LEFT, input->keybit); __set_bit(BTN_RIGHT, input->keybit); __set_bit(BTN_MIDDLE, input->keybit); /* Pad */ input->evbit[0] |= BIT(EV_MSC); input->mscbit[0] |= BIT(MSC_SERIAL); set_bit(BTN_0, input->keybit); set_bit(BTN_1, input->keybit); set_bit(BTN_TOOL_FINGER, input->keybit); /* Distance, rubber and mouse */ input->absbit[0] |= BIT(ABS_DISTANCE); set_bit(BTN_TOOL_RUBBER, input->keybit); set_bit(BTN_TOOL_MOUSE, input->keybit); __set_bit(MSC_SERIAL, input->mscbit); input->absmax[ABS_PRESSURE] = 511; input->absmax[ABS_DISTANCE] = 32; __set_bit(BTN_0, input->keybit); __set_bit(BTN_1, input->keybit); __set_bit(BTN_TOOL_FINGER, input->keybit); input->absmax[ABS_X] = 16704; input->absmax[ABS_Y] = 12064; input->absfuzz[ABS_X] = 4; input->absfuzz[ABS_Y] = 4; /* Distance, rubber and mouse */ __set_bit(BTN_TOOL_RUBBER, input->keybit); __set_bit(BTN_TOOL_MOUSE, input->keybit); input_set_abs_params(input, ABS_X, 0, 16704, 4, 0); input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0); input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0); input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0); return 0; err_free: kfree(wdata); return ret; Loading drivers/input/evdev.c +73 −79 Original line number Diff line number Diff line Loading @@ -492,13 +492,15 @@ static int str_to_user(const char *str, unsigned int maxlen, void __user *p) } #define OLD_KEY_MAX 0x1ff static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user *p, int compat_mode) static int handle_eviocgbit(struct input_dev *dev, unsigned int type, unsigned int size, void __user *p, int compat_mode) { static unsigned long keymax_warn_time; unsigned long *bits; int len; switch (_IOC_NR(cmd) & EV_MAX) { switch (type) { case 0: bits = dev->evbit; len = EV_MAX; break; case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; Loading @@ -517,7 +519,7 @@ static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user * EVIOCGBIT(EV_KEY, KEY_MAX) and not realize that 'len' * should be in bytes, not in bits. */ if ((_IOC_NR(cmd) & EV_MAX) == EV_KEY && _IOC_SIZE(cmd) == OLD_KEY_MAX) { if (type == EV_KEY && size == OLD_KEY_MAX) { len = OLD_KEY_MAX; if (printk_timed_ratelimit(&keymax_warn_time, 10 * 1000)) printk(KERN_WARNING Loading @@ -528,7 +530,7 @@ static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user BITS_TO_LONGS(OLD_KEY_MAX) * sizeof(long)); } return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode); return bits_to_user(bits, len, size, p, compat_mode); } #undef OLD_KEY_MAX Loading @@ -542,8 +544,10 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, struct ff_effect effect; int __user *ip = (int __user *)p; unsigned int i, t, u, v; unsigned int size; int error; /* First we check for fixed-length commands */ switch (cmd) { case EVIOCGVERSION: Loading Loading @@ -610,87 +614,85 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, return evdev_grab(evdev, client); else return evdev_ungrab(evdev, client); } default: size = _IOC_SIZE(cmd); if (_IOC_TYPE(cmd) != 'E') return -EINVAL; /* Now check variable-length commands */ #define EVIOC_MASK_SIZE(nr) ((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) if (_IOC_DIR(cmd) == _IOC_READ) { switch (EVIOC_MASK_SIZE(cmd)) { if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0))) return handle_eviocgbit(dev, cmd, p, compat_mode); case EVIOCGKEY(0): return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd), p, compat_mode); case EVIOCGLED(0): return bits_to_user(dev->led, LED_MAX, size, p, compat_mode); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd), p, compat_mode); case EVIOCGSND(0): return bits_to_user(dev->snd, SND_MAX, size, p, compat_mode); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd), p, compat_mode); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd), p, compat_mode); case EVIOCGSW(0): return bits_to_user(dev->sw, SW_MAX, size, p, compat_mode); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) return str_to_user(dev->name, _IOC_SIZE(cmd), p); case EVIOCGNAME(0): return str_to_user(dev->name, size, p); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) return str_to_user(dev->phys, _IOC_SIZE(cmd), p); case EVIOCGPHYS(0): return str_to_user(dev->phys, size, p); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) return str_to_user(dev->uniq, _IOC_SIZE(cmd), p); case EVIOCGUNIQ(0): return str_to_user(dev->uniq, size, p); if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { t = _IOC_NR(cmd) & ABS_MAX; case EVIOC_MASK_SIZE(EVIOCSFF): if (input_ff_effect_from_user(p, size, &effect)) return -EFAULT; abs.value = dev->abs[t]; abs.minimum = dev->absmin[t]; abs.maximum = dev->absmax[t]; abs.fuzz = dev->absfuzz[t]; abs.flat = dev->absflat[t]; abs.resolution = dev->absres[t]; error = input_ff_upload(dev, &effect, file); if (copy_to_user(p, &abs, min_t(size_t, _IOC_SIZE(cmd), sizeof(struct input_absinfo)))) if (put_user(effect.id, &(((struct ff_effect __user *)p)->id))) return -EFAULT; return 0; return error; } } /* Multi-number variable-length handlers */ if (_IOC_TYPE(cmd) != 'E') return -EINVAL; if (_IOC_DIR(cmd) == _IOC_WRITE) { if (_IOC_DIR(cmd) == _IOC_READ) { if (_IOC_NR(cmd) == _IOC_NR(EVIOCSFF)) { if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0))) return handle_eviocgbit(dev, _IOC_NR(cmd) & EV_MAX, size, p, compat_mode); if (input_ff_effect_from_user(p, _IOC_SIZE(cmd), &effect)) return -EFAULT; if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { error = input_ff_upload(dev, &effect, file); t = _IOC_NR(cmd) & ABS_MAX; abs = dev->absinfo[t]; if (put_user(effect.id, &(((struct ff_effect __user *)p)->id))) if (copy_to_user(p, &abs, min_t(size_t, size, sizeof(struct input_absinfo)))) return -EFAULT; return error; return 0; } } if (_IOC_DIR(cmd) == _IOC_READ) { if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { t = _IOC_NR(cmd) & ABS_MAX; if (copy_from_user(&abs, p, min_t(size_t, _IOC_SIZE(cmd), sizeof(struct input_absinfo)))) size, sizeof(struct input_absinfo)))) return -EFAULT; if (size < sizeof(struct input_absinfo)) abs.resolution = 0; /* We can't change number of reserved MT slots */ if (t == ABS_MT_SLOT) return -EINVAL; Loading @@ -701,21 +703,13 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, * of event. */ spin_lock_irq(&dev->event_lock); dev->abs[t] = abs.value; dev->absmin[t] = abs.minimum; dev->absmax[t] = abs.maximum; dev->absfuzz[t] = abs.fuzz; dev->absflat[t] = abs.flat; dev->absres[t] = _IOC_SIZE(cmd) < sizeof(struct input_absinfo) ? 0 : abs.resolution; dev->absinfo[t] = abs; spin_unlock_irq(&dev->event_lock); return 0; } } } return -EINVAL; } Loading drivers/input/input.c +42 −4 Original line number Diff line number Diff line Loading @@ -182,7 +182,7 @@ static int input_handle_abs_event(struct input_dev *dev, is_mt_event = code >= ABS_MT_FIRST && code <= ABS_MT_LAST; if (!is_mt_event) { pold = &dev->abs[code]; pold = &dev->absinfo[code].value; } else if (dev->mt) { struct input_mt_slot *mtslot = &dev->mt[dev->slot]; pold = &mtslot->abs[code - ABS_MT_FIRST]; Loading @@ -196,7 +196,7 @@ static int input_handle_abs_event(struct input_dev *dev, if (pold) { *pval = input_defuzz_abs_event(*pval, *pold, dev->absfuzz[code]); dev->absinfo[code].fuzz); if (*pold == *pval) return INPUT_IGNORE_EVENT; Loading @@ -204,8 +204,8 @@ static int input_handle_abs_event(struct input_dev *dev, } /* Flush pending "slot" event */ if (is_mt_event && dev->slot != dev->abs[ABS_MT_SLOT]) { dev->abs[ABS_MT_SLOT] = dev->slot; if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_SLOT)) { input_abs_set_val(dev, ABS_MT_SLOT, dev->slot); input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot); } Loading Loading @@ -390,6 +390,43 @@ void input_inject_event(struct input_handle *handle, } EXPORT_SYMBOL(input_inject_event); /** * input_alloc_absinfo - allocates array of input_absinfo structs * @dev: the input device emitting absolute events * * If the absinfo struct the caller asked for is already allocated, this * functions will not do anything. */ void input_alloc_absinfo(struct input_dev *dev) { if (!dev->absinfo) dev->absinfo = kcalloc(ABS_CNT, sizeof(struct input_absinfo), GFP_KERNEL); WARN(!dev->absinfo, "%s(): kcalloc() failed?\n", __func__); } EXPORT_SYMBOL(input_alloc_absinfo); void input_set_abs_params(struct input_dev *dev, unsigned int axis, int min, int max, int fuzz, int flat) { struct input_absinfo *absinfo; input_alloc_absinfo(dev); if (!dev->absinfo) return; absinfo = &dev->absinfo[axis]; absinfo->minimum = min; absinfo->maximum = max; absinfo->fuzz = fuzz; absinfo->flat = flat; dev->absbit[BIT_WORD(axis)] |= BIT_MASK(axis); } EXPORT_SYMBOL(input_set_abs_params); /** * input_grab_device - grabs device for exclusive use * @handle: input handle that wants to own the device Loading Loading @@ -1308,6 +1345,7 @@ static void input_dev_release(struct device *device) input_ff_destroy(dev); input_mt_destroy_slots(dev); kfree(dev->absinfo); kfree(dev); module_put(THIS_MODULE); Loading drivers/input/joydev.c +16 −15 Original line number Diff line number Diff line Loading @@ -530,7 +530,7 @@ static int joydev_ioctl_common(struct joydev *joydev, { struct input_dev *dev = joydev->handle.dev; size_t len; int i, j; int i; const char *name; /* Process fixed-sized commands. */ Loading Loading @@ -565,9 +565,8 @@ static int joydev_ioctl_common(struct joydev *joydev, return -EFAULT; for (i = 0; i < joydev->nabs; i++) { j = joydev->abspam[i]; joydev->abs[i] = joydev_correct(dev->abs[j], &joydev->corr[i]); int val = input_abs_get_val(dev, joydev->abspam[i]); joydev->abs[i] = joydev_correct(val, &joydev->corr[i]); } return 0; Loading Loading @@ -848,24 +847,26 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, for (i = 0; i < joydev->nabs; i++) { j = joydev->abspam[i]; if (dev->absmax[j] == dev->absmin[j]) { if (input_abs_get_max(dev, j) == input_abs_get_min(dev, j)) { joydev->corr[i].type = JS_CORR_NONE; joydev->abs[i] = dev->abs[j]; joydev->abs[i] = input_abs_get_val(dev, j); continue; } joydev->corr[i].type = JS_CORR_BROKEN; joydev->corr[i].prec = dev->absfuzz[j]; joydev->corr[i].coef[0] = (dev->absmax[j] + dev->absmin[j]) / 2 - dev->absflat[j]; joydev->corr[i].coef[1] = (dev->absmax[j] + dev->absmin[j]) / 2 + dev->absflat[j]; joydev->corr[i].prec = input_abs_get_fuzz(dev, j); t = (input_abs_get_max(dev, j) + input_abs_get_min(dev, j)) / 2; joydev->corr[i].coef[0] = t - input_abs_get_flat(dev, j); joydev->corr[i].coef[1] = t + input_abs_get_flat(dev, j); t = (dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]; t = (input_abs_get_max(dev, j) - input_abs_get_min(dev, j)) / 2 - 2 * input_abs_get_flat(dev, j); if (t) { joydev->corr[i].coef[2] = (1 << 29) / t; joydev->corr[i].coef[3] = (1 << 29) / t; joydev->abs[i] = joydev_correct(dev->abs[j], joydev->abs[i] = joydev_correct(input_abs_get_val(dev, j), joydev->corr + i); } } Loading drivers/input/joystick/a3d.c +2 −1 Original line number Diff line number Diff line Loading @@ -342,7 +342,8 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv) for (i = 0; i < 4; i++) { if (i < 2) input_set_abs_params(input_dev, axes[i], 48, input_dev->abs[axes[i]] * 2 - 48, 0, 8); input_set_abs_params(input_dev, axes[i], 48, input_abs_get_val(input_dev, axes[i]) * 2 - 48, 0, 8); else input_set_abs_params(input_dev, axes[i], 2, 253, 0, 0); input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0); Loading Loading
drivers/hid/hid-wacom.c +24 −25 Original line number Diff line number Diff line Loading @@ -230,7 +230,7 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, input_report_key(input, BTN_RIGHT, 0); input_report_key(input, BTN_MIDDLE, 0); input_report_abs(input, ABS_DISTANCE, input->absmax[ABS_DISTANCE]); input_abs_get_max(input, ABS_DISTANCE)); } else { input_report_key(input, BTN_TOUCH, 0); input_report_key(input, BTN_STYLUS, 0); Loading Loading @@ -383,38 +383,37 @@ move_on: /* Basics */ input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL); input->absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE); input->relbit[0] |= BIT(REL_WHEEL); set_bit(BTN_TOOL_PEN, input->keybit); set_bit(BTN_TOUCH, input->keybit); set_bit(BTN_STYLUS, input->keybit); set_bit(BTN_STYLUS2, input->keybit); set_bit(BTN_LEFT, input->keybit); set_bit(BTN_RIGHT, input->keybit); set_bit(BTN_MIDDLE, input->keybit); __set_bit(REL_WHEEL, input->relbit); __set_bit(BTN_TOOL_PEN, input->keybit); __set_bit(BTN_TOUCH, input->keybit); __set_bit(BTN_STYLUS, input->keybit); __set_bit(BTN_STYLUS2, input->keybit); __set_bit(BTN_LEFT, input->keybit); __set_bit(BTN_RIGHT, input->keybit); __set_bit(BTN_MIDDLE, input->keybit); /* Pad */ input->evbit[0] |= BIT(EV_MSC); input->mscbit[0] |= BIT(MSC_SERIAL); set_bit(BTN_0, input->keybit); set_bit(BTN_1, input->keybit); set_bit(BTN_TOOL_FINGER, input->keybit); /* Distance, rubber and mouse */ input->absbit[0] |= BIT(ABS_DISTANCE); set_bit(BTN_TOOL_RUBBER, input->keybit); set_bit(BTN_TOOL_MOUSE, input->keybit); __set_bit(MSC_SERIAL, input->mscbit); input->absmax[ABS_PRESSURE] = 511; input->absmax[ABS_DISTANCE] = 32; __set_bit(BTN_0, input->keybit); __set_bit(BTN_1, input->keybit); __set_bit(BTN_TOOL_FINGER, input->keybit); input->absmax[ABS_X] = 16704; input->absmax[ABS_Y] = 12064; input->absfuzz[ABS_X] = 4; input->absfuzz[ABS_Y] = 4; /* Distance, rubber and mouse */ __set_bit(BTN_TOOL_RUBBER, input->keybit); __set_bit(BTN_TOOL_MOUSE, input->keybit); input_set_abs_params(input, ABS_X, 0, 16704, 4, 0); input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0); input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0); input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0); return 0; err_free: kfree(wdata); return ret; Loading
drivers/input/evdev.c +73 −79 Original line number Diff line number Diff line Loading @@ -492,13 +492,15 @@ static int str_to_user(const char *str, unsigned int maxlen, void __user *p) } #define OLD_KEY_MAX 0x1ff static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user *p, int compat_mode) static int handle_eviocgbit(struct input_dev *dev, unsigned int type, unsigned int size, void __user *p, int compat_mode) { static unsigned long keymax_warn_time; unsigned long *bits; int len; switch (_IOC_NR(cmd) & EV_MAX) { switch (type) { case 0: bits = dev->evbit; len = EV_MAX; break; case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; Loading @@ -517,7 +519,7 @@ static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user * EVIOCGBIT(EV_KEY, KEY_MAX) and not realize that 'len' * should be in bytes, not in bits. */ if ((_IOC_NR(cmd) & EV_MAX) == EV_KEY && _IOC_SIZE(cmd) == OLD_KEY_MAX) { if (type == EV_KEY && size == OLD_KEY_MAX) { len = OLD_KEY_MAX; if (printk_timed_ratelimit(&keymax_warn_time, 10 * 1000)) printk(KERN_WARNING Loading @@ -528,7 +530,7 @@ static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user BITS_TO_LONGS(OLD_KEY_MAX) * sizeof(long)); } return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode); return bits_to_user(bits, len, size, p, compat_mode); } #undef OLD_KEY_MAX Loading @@ -542,8 +544,10 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, struct ff_effect effect; int __user *ip = (int __user *)p; unsigned int i, t, u, v; unsigned int size; int error; /* First we check for fixed-length commands */ switch (cmd) { case EVIOCGVERSION: Loading Loading @@ -610,87 +614,85 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, return evdev_grab(evdev, client); else return evdev_ungrab(evdev, client); } default: size = _IOC_SIZE(cmd); if (_IOC_TYPE(cmd) != 'E') return -EINVAL; /* Now check variable-length commands */ #define EVIOC_MASK_SIZE(nr) ((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) if (_IOC_DIR(cmd) == _IOC_READ) { switch (EVIOC_MASK_SIZE(cmd)) { if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0))) return handle_eviocgbit(dev, cmd, p, compat_mode); case EVIOCGKEY(0): return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd), p, compat_mode); case EVIOCGLED(0): return bits_to_user(dev->led, LED_MAX, size, p, compat_mode); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd), p, compat_mode); case EVIOCGSND(0): return bits_to_user(dev->snd, SND_MAX, size, p, compat_mode); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd), p, compat_mode); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd), p, compat_mode); case EVIOCGSW(0): return bits_to_user(dev->sw, SW_MAX, size, p, compat_mode); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) return str_to_user(dev->name, _IOC_SIZE(cmd), p); case EVIOCGNAME(0): return str_to_user(dev->name, size, p); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) return str_to_user(dev->phys, _IOC_SIZE(cmd), p); case EVIOCGPHYS(0): return str_to_user(dev->phys, size, p); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) return str_to_user(dev->uniq, _IOC_SIZE(cmd), p); case EVIOCGUNIQ(0): return str_to_user(dev->uniq, size, p); if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { t = _IOC_NR(cmd) & ABS_MAX; case EVIOC_MASK_SIZE(EVIOCSFF): if (input_ff_effect_from_user(p, size, &effect)) return -EFAULT; abs.value = dev->abs[t]; abs.minimum = dev->absmin[t]; abs.maximum = dev->absmax[t]; abs.fuzz = dev->absfuzz[t]; abs.flat = dev->absflat[t]; abs.resolution = dev->absres[t]; error = input_ff_upload(dev, &effect, file); if (copy_to_user(p, &abs, min_t(size_t, _IOC_SIZE(cmd), sizeof(struct input_absinfo)))) if (put_user(effect.id, &(((struct ff_effect __user *)p)->id))) return -EFAULT; return 0; return error; } } /* Multi-number variable-length handlers */ if (_IOC_TYPE(cmd) != 'E') return -EINVAL; if (_IOC_DIR(cmd) == _IOC_WRITE) { if (_IOC_DIR(cmd) == _IOC_READ) { if (_IOC_NR(cmd) == _IOC_NR(EVIOCSFF)) { if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0))) return handle_eviocgbit(dev, _IOC_NR(cmd) & EV_MAX, size, p, compat_mode); if (input_ff_effect_from_user(p, _IOC_SIZE(cmd), &effect)) return -EFAULT; if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { error = input_ff_upload(dev, &effect, file); t = _IOC_NR(cmd) & ABS_MAX; abs = dev->absinfo[t]; if (put_user(effect.id, &(((struct ff_effect __user *)p)->id))) if (copy_to_user(p, &abs, min_t(size_t, size, sizeof(struct input_absinfo)))) return -EFAULT; return error; return 0; } } if (_IOC_DIR(cmd) == _IOC_READ) { if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { t = _IOC_NR(cmd) & ABS_MAX; if (copy_from_user(&abs, p, min_t(size_t, _IOC_SIZE(cmd), sizeof(struct input_absinfo)))) size, sizeof(struct input_absinfo)))) return -EFAULT; if (size < sizeof(struct input_absinfo)) abs.resolution = 0; /* We can't change number of reserved MT slots */ if (t == ABS_MT_SLOT) return -EINVAL; Loading @@ -701,21 +703,13 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, * of event. */ spin_lock_irq(&dev->event_lock); dev->abs[t] = abs.value; dev->absmin[t] = abs.minimum; dev->absmax[t] = abs.maximum; dev->absfuzz[t] = abs.fuzz; dev->absflat[t] = abs.flat; dev->absres[t] = _IOC_SIZE(cmd) < sizeof(struct input_absinfo) ? 0 : abs.resolution; dev->absinfo[t] = abs; spin_unlock_irq(&dev->event_lock); return 0; } } } return -EINVAL; } Loading
drivers/input/input.c +42 −4 Original line number Diff line number Diff line Loading @@ -182,7 +182,7 @@ static int input_handle_abs_event(struct input_dev *dev, is_mt_event = code >= ABS_MT_FIRST && code <= ABS_MT_LAST; if (!is_mt_event) { pold = &dev->abs[code]; pold = &dev->absinfo[code].value; } else if (dev->mt) { struct input_mt_slot *mtslot = &dev->mt[dev->slot]; pold = &mtslot->abs[code - ABS_MT_FIRST]; Loading @@ -196,7 +196,7 @@ static int input_handle_abs_event(struct input_dev *dev, if (pold) { *pval = input_defuzz_abs_event(*pval, *pold, dev->absfuzz[code]); dev->absinfo[code].fuzz); if (*pold == *pval) return INPUT_IGNORE_EVENT; Loading @@ -204,8 +204,8 @@ static int input_handle_abs_event(struct input_dev *dev, } /* Flush pending "slot" event */ if (is_mt_event && dev->slot != dev->abs[ABS_MT_SLOT]) { dev->abs[ABS_MT_SLOT] = dev->slot; if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_SLOT)) { input_abs_set_val(dev, ABS_MT_SLOT, dev->slot); input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot); } Loading Loading @@ -390,6 +390,43 @@ void input_inject_event(struct input_handle *handle, } EXPORT_SYMBOL(input_inject_event); /** * input_alloc_absinfo - allocates array of input_absinfo structs * @dev: the input device emitting absolute events * * If the absinfo struct the caller asked for is already allocated, this * functions will not do anything. */ void input_alloc_absinfo(struct input_dev *dev) { if (!dev->absinfo) dev->absinfo = kcalloc(ABS_CNT, sizeof(struct input_absinfo), GFP_KERNEL); WARN(!dev->absinfo, "%s(): kcalloc() failed?\n", __func__); } EXPORT_SYMBOL(input_alloc_absinfo); void input_set_abs_params(struct input_dev *dev, unsigned int axis, int min, int max, int fuzz, int flat) { struct input_absinfo *absinfo; input_alloc_absinfo(dev); if (!dev->absinfo) return; absinfo = &dev->absinfo[axis]; absinfo->minimum = min; absinfo->maximum = max; absinfo->fuzz = fuzz; absinfo->flat = flat; dev->absbit[BIT_WORD(axis)] |= BIT_MASK(axis); } EXPORT_SYMBOL(input_set_abs_params); /** * input_grab_device - grabs device for exclusive use * @handle: input handle that wants to own the device Loading Loading @@ -1308,6 +1345,7 @@ static void input_dev_release(struct device *device) input_ff_destroy(dev); input_mt_destroy_slots(dev); kfree(dev->absinfo); kfree(dev); module_put(THIS_MODULE); Loading
drivers/input/joydev.c +16 −15 Original line number Diff line number Diff line Loading @@ -530,7 +530,7 @@ static int joydev_ioctl_common(struct joydev *joydev, { struct input_dev *dev = joydev->handle.dev; size_t len; int i, j; int i; const char *name; /* Process fixed-sized commands. */ Loading Loading @@ -565,9 +565,8 @@ static int joydev_ioctl_common(struct joydev *joydev, return -EFAULT; for (i = 0; i < joydev->nabs; i++) { j = joydev->abspam[i]; joydev->abs[i] = joydev_correct(dev->abs[j], &joydev->corr[i]); int val = input_abs_get_val(dev, joydev->abspam[i]); joydev->abs[i] = joydev_correct(val, &joydev->corr[i]); } return 0; Loading Loading @@ -848,24 +847,26 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, for (i = 0; i < joydev->nabs; i++) { j = joydev->abspam[i]; if (dev->absmax[j] == dev->absmin[j]) { if (input_abs_get_max(dev, j) == input_abs_get_min(dev, j)) { joydev->corr[i].type = JS_CORR_NONE; joydev->abs[i] = dev->abs[j]; joydev->abs[i] = input_abs_get_val(dev, j); continue; } joydev->corr[i].type = JS_CORR_BROKEN; joydev->corr[i].prec = dev->absfuzz[j]; joydev->corr[i].coef[0] = (dev->absmax[j] + dev->absmin[j]) / 2 - dev->absflat[j]; joydev->corr[i].coef[1] = (dev->absmax[j] + dev->absmin[j]) / 2 + dev->absflat[j]; joydev->corr[i].prec = input_abs_get_fuzz(dev, j); t = (input_abs_get_max(dev, j) + input_abs_get_min(dev, j)) / 2; joydev->corr[i].coef[0] = t - input_abs_get_flat(dev, j); joydev->corr[i].coef[1] = t + input_abs_get_flat(dev, j); t = (dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]; t = (input_abs_get_max(dev, j) - input_abs_get_min(dev, j)) / 2 - 2 * input_abs_get_flat(dev, j); if (t) { joydev->corr[i].coef[2] = (1 << 29) / t; joydev->corr[i].coef[3] = (1 << 29) / t; joydev->abs[i] = joydev_correct(dev->abs[j], joydev->abs[i] = joydev_correct(input_abs_get_val(dev, j), joydev->corr + i); } } Loading
drivers/input/joystick/a3d.c +2 −1 Original line number Diff line number Diff line Loading @@ -342,7 +342,8 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv) for (i = 0; i < 4; i++) { if (i < 2) input_set_abs_params(input_dev, axes[i], 48, input_dev->abs[axes[i]] * 2 - 48, 0, 8); input_set_abs_params(input_dev, axes[i], 48, input_abs_get_val(input_dev, axes[i]) * 2 - 48, 0, 8); else input_set_abs_params(input_dev, axes[i], 2, 253, 0, 0); input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0); Loading