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 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; 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; }