static int uinput_setup_device(struct uinput_device *udev, const char __user *buffer, size_t count) { struct uinput_user_dev *user_dev; struct input_dev *dev; char *name; int i, size; int retval; if (count != sizeof(struct uinput_user_dev)) return -EINVAL; if (!udev->dev) { retval = uinput_allocate_device(udev); if (retval) return retval; } dev = udev->dev; user_dev = kmalloc(sizeof(struct uinput_user_dev), GFP_KERNEL); if (!user_dev) return -ENOMEM; if (copy_from_user(user_dev, buffer, sizeof(struct uinput_user_dev))) { retval = -EFAULT; goto exit; } udev->ff_effects_max = user_dev->ff_effects_max; size = strnlen(user_dev->name, UINPUT_MAX_NAME_SIZE) + 1; if (!size) { retval = -EINVAL; goto exit; } kfree(dev->name); dev->name = name = kmalloc(size, GFP_KERNEL); if (!name) { retval = -ENOMEM; goto exit; } strlcpy(name, user_dev->name, size); dev->id.bustype = user_dev->id.bustype; dev->id.vendor = user_dev->id.vendor; dev->id.product = user_dev->id.product; dev->id.version = user_dev->id.version; for (i = 0; i < ABS_CNT; i++) { input_abs_set_max(dev, i, user_dev->absmax[i]); input_abs_set_min(dev, i, user_dev->absmin[i]); input_abs_set_fuzz(dev, i, user_dev->absfuzz[i]); input_abs_set_flat(dev, i, user_dev->absflat[i]); } /* check if absmin/absmax/absfuzz/absflat are filled as * told in Documentation/input/input-programming.txt */ if (test_bit(EV_ABS, dev->evbit)) { retval = uinput_validate_absbits(dev); if (retval < 0) goto exit; } udev->state = UIST_SETUP_COMPLETE; retval = count; exit: kfree(user_dev); return retval; }
static int uinput_setup_device(struct uinput_device *udev, const char __user *buffer, size_t count) { struct uinput_user_dev *user_dev; struct input_dev *dev; int i; int retval; if (count != sizeof(struct uinput_user_dev)) return -EINVAL; if (!udev->dev) { retval = uinput_allocate_device(udev); if (retval) return retval; } dev = udev->dev; user_dev = memdup_user(buffer, sizeof(struct uinput_user_dev)); if (IS_ERR(user_dev)) return PTR_ERR(user_dev); udev->ff_effects_max = user_dev->ff_effects_max; /* Ensure name is filled in */ if (!user_dev->name[0]) { retval = -EINVAL; goto exit; } kfree(dev->name); dev->name = kstrndup(user_dev->name, UINPUT_MAX_NAME_SIZE, GFP_KERNEL); if (!dev->name) { retval = -ENOMEM; goto exit; } dev->id.bustype = user_dev->id.bustype; dev->id.vendor = user_dev->id.vendor; dev->id.product = user_dev->id.product; dev->id.version = user_dev->id.version; for (i = 0; i < ABS_CNT; i++) { input_abs_set_max(dev, i, user_dev->absmax[i]); input_abs_set_min(dev, i, user_dev->absmin[i]); input_abs_set_fuzz(dev, i, user_dev->absfuzz[i]); input_abs_set_flat(dev, i, user_dev->absflat[i]); } /* check if absmin/absmax/absfuzz/absflat are filled as * told in Documentation/input/input-programming.txt */ if (test_bit(EV_ABS, dev->evbit)) { retval = uinput_validate_absbits(dev); if (retval < 0) goto exit; if (test_bit(ABS_MT_SLOT, dev->absbit)) { int nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1; input_mt_init_slots(dev, nslot, 0); } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) { input_set_events_per_packet(dev, 60); } } udev->state = UIST_SETUP_COMPLETE; retval = count; exit: kfree(user_dev); return retval; }
static void hil_dev_handle_ptr_events(struct hil_dev *ptr) { struct input_dev *dev = ptr->dev; int idx = ptr->idx4 / 4; hil_packet p = ptr->data[idx - 1]; int i, cnt, laxis; bool absdev, ax16; if ((p & HIL_CMDCT_POL) != idx - 1) { printk(KERN_WARNING PREFIX "Malformed poll packet %x (idx = %i)\n", p, idx); return; } i = (p & HIL_POL_AXIS_ALT) ? 3 : 0; laxis = (p & HIL_POL_NUM_AXES_MASK) + i; ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */ absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS; for (cnt = 1; i < laxis; i++) { unsigned int lo, hi, val; lo = ptr->data[cnt++] & HIL_PKT_DATA_MASK; hi = ax16 ? (ptr->data[cnt++] & HIL_PKT_DATA_MASK) : 0; if (absdev) { val = lo + (hi << 8); #ifdef TABLET_AUTOADJUST if (val < input_abs_get_min(dev, ABS_X + i)) input_abs_set_min(dev, ABS_X + i, val); if (val > input_abs_get_max(dev, ABS_X + i)) input_abs_set_max(dev, ABS_X + i, val); #endif if (i % 3) val = input_abs_get_max(dev, ABS_X + i) - val; input_report_abs(dev, ABS_X + i, val); } else { val = (int) (((int8_t) lo) | ((int8_t) hi << 8)); if (i % 3) val *= -1; input_report_rel(dev, REL_X + i, val); } } while (cnt < idx - 1) { unsigned int btn = ptr->data[cnt++]; int up = btn & 1; btn &= 0xfe; if (btn == 0x8e) continue; /* TODO: proximity == touch? */ if (btn > 0x8c || btn < 0x80) continue; btn = (btn - 0x80) >> 1; btn = ptr->btnmap[btn]; input_report_key(dev, btn, !up); } input_sync(dev); }
static void hil_dev_pointer_setup(struct hil_dev *ptr) { struct input_dev *input_dev = ptr->dev; uint8_t did = ptr->idd[0]; uint8_t *idd = ptr->idd + 1; unsigned int naxsets = HIL_IDD_NUM_AXSETS(*idd); unsigned int i, btntype; const char *txt; ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd); switch (did & HIL_IDD_DID_TYPE_MASK) { case HIL_IDD_DID_TYPE_REL: input_dev->evbit[0] = BIT_MASK(EV_REL); for (i = 0; i < ptr->naxes; i++) __set_bit(REL_X + i, input_dev->relbit); for (i = 3; naxsets > 1 && i < ptr->naxes + 3; i++) __set_bit(REL_X + i, input_dev->relbit); txt = "relative"; break; case HIL_IDD_DID_TYPE_ABS: input_dev->evbit[0] = BIT_MASK(EV_ABS); for (i = 0; i < ptr->naxes; i++) input_set_abs_params(input_dev, ABS_X + i, 0, HIL_IDD_AXIS_MAX(idd, i), 0, 0); for (i = 3; naxsets > 1 && i < ptr->naxes + 3; i++) input_set_abs_params(input_dev, ABS_X + i, 0, HIL_IDD_AXIS_MAX(idd, i - 3), 0, 0); #ifdef TABLET_AUTOADJUST for (i = 0; i < ABS_MAX; i++) { int diff = input_abs_get_max(input_dev, ABS_X + i) / 10; input_abs_set_min(input_dev, ABS_X + i, input_abs_get_min(input_dev, ABS_X + i) + diff); input_abs_set_max(input_dev, ABS_X + i, input_abs_get_max(input_dev, ABS_X + i) - diff); } #endif txt = "absolute"; break; default: BUG(); } ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd); if (ptr->nbtn) input_dev->evbit[0] |= BIT_MASK(EV_KEY); btntype = BTN_MISC; if ((did & HIL_IDD_DID_ABS_TABLET_MASK) == HIL_IDD_DID_ABS_TABLET) #ifdef TABLET_SIMULATES_MOUSE btntype = BTN_TOUCH; #else btntype = BTN_DIGI; #endif if ((did & HIL_IDD_DID_ABS_TSCREEN_MASK) == HIL_IDD_DID_ABS_TSCREEN) btntype = BTN_TOUCH; if ((did & HIL_IDD_DID_REL_MOUSE_MASK) == HIL_IDD_DID_REL_MOUSE) btntype = BTN_MOUSE; for (i = 0; i < ptr->nbtn; i++) { __set_bit(btntype | i, input_dev->keybit); ptr->btnmap[i] = btntype | i; } if (btntype == BTN_MOUSE) { /* Swap buttons 2 and 3 */ ptr->btnmap[1] = BTN_MIDDLE; ptr->btnmap[2] = BTN_RIGHT; } input_dev->name = strlen(ptr->rnm) ? ptr->rnm : "HIL pointer device"; printk(KERN_INFO PREFIX "HIL pointer device found (did: 0x%02x, axis: %s)\n", did, txt); printk(KERN_INFO PREFIX "HIL pointer has %i buttons and %i sets of %i axes\n", ptr->nbtn, naxsets, ptr->naxes); }
static int uinput_setup_device(struct uinput_device *udev, const char __user *buffer, size_t count) { struct uinput_user_dev *user_dev; struct input_dev *dev; int i; int retval; size_t size; size = min_t(size_t, count, sizeof(struct uinput_user_dev)); if (!udev->dev) { retval = uinput_allocate_device(udev); if (retval) return retval; } dev = udev->dev; user_dev = kzalloc(sizeof(struct uinput_user_dev), GFP_KERNEL); if (!user_dev) return -ENOMEM; if (copy_from_user(user_dev, buffer, size)) { retval = -EFAULT; goto exit; } udev->ff_effects_max = user_dev->ff_effects_max; /* Ensure name is filled in */ if (!user_dev->name[0]) { retval = -EINVAL; goto exit; } kfree(dev->name); dev->name = kstrndup(user_dev->name, UINPUT_MAX_NAME_SIZE, GFP_KERNEL); if (!dev->name) { retval = -ENOMEM; goto exit; } dev->id.bustype = user_dev->id.bustype; dev->id.vendor = user_dev->id.vendor; dev->id.product = user_dev->id.product; dev->id.version = user_dev->id.version; for (i = 0; i < ABS_CNT; i++) { input_abs_set_max(dev, i, user_dev->absmax[i]); input_abs_set_min(dev, i, user_dev->absmin[i]); input_abs_set_fuzz(dev, i, user_dev->absfuzz[i]); input_abs_set_flat(dev, i, user_dev->absflat[i]); input_abs_set_res(dev, i, user_dev->absres[i]); } /* check if absmin/absmax/absfuzz/absflat are filled as * told in Documentation/input/input-programming.txt */ if (test_bit(EV_ABS, dev->evbit)) { retval = uinput_validate_absbits(dev); if (retval < 0) goto exit; if (test_bit(ABS_MT_SLOT, dev->absbit)) { int nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1; #ifdef INPUT_MT_POINTER input_mt_init_slots(dev, nslot, 0); #else /* INPUT_MT_POINTER */ input_mt_init_slots(dev, nslot); #endif /* INPUT_MT_POINTER */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) { input_set_events_per_packet(dev, 60); #endif /* LINUX_VERSION_CODE >= 2.6.36 */ } } udev->state = UIST_SETUP_COMPLETE; retval = count; exit: kfree(user_dev); return retval; }