diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-14 18:07:18 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-14 18:07:18 -0800 |
commit | 9f7a9b1191b0252184b1971c7248c304d4e38e5e (patch) | |
tree | d946c6bddc459a76b79b6effc01160c4536fa460 /drivers/input | |
parent | 4e4510fec4af08ead21f6934c1410af1f19a8cad (diff) | |
parent | c25141062a82ae8bddced1b3ce2b57a1c0efabe0 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov:
- three new touchscreen drivers: EETI EXC3000, HiDeep, and Samsung
S6SY761
- the timer API conversion (setup_timer() -> timer_setup())
- a few drivers swiytched to using managed API for creating custom
device attributes
- other assorted fixed and cleanups.
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (50 commits)
Input: gamecon - mark expected switch fall-throughs
Input: sidewinder - mark expected switch fall-throughs
Input: spaceball - mark expected switch fall-throughs
Input: uinput - unlock on allocation failure in ioctl
Input: add support for the Samsung S6SY761 touchscreen
Input: add support for HiDeep touchscreen
Input: st1232 - remove obsolete platform device support
Input: convert autorepeat timer to use timer_setup()
media: ttpci: remove autorepeat handling and use timer_setup
Input: cyttsp4 - avoid overflows when calculating memory sizes
Input: mxs-lradc - remove redundant assignment to pointer input
Input: add I2C attached EETI EXC3000 multi touch driver
Input: goodix - support gt1151 touchpanel
Input: ps2-gpio - actually abort probe when connected to sleeping GPIOs
Input: hil_mlc - convert to using timer_setup()
Input: hp_sdc - convert to using timer_setup()
Input: touchsceen - convert timers to use timer_setup()
Input: keyboard - convert timers to use timer_setup()
Input: uinput - fold header into the driver proper
Input: uinput - remove uinput_allocate_device()
...
Diffstat (limited to 'drivers/input')
44 files changed, 2617 insertions, 537 deletions
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c index fcc6c3368182..2743ed4656e4 100644 --- a/drivers/input/ff-memless.c +++ b/drivers/input/ff-memless.c @@ -412,10 +412,10 @@ static void ml_play_effects(struct ml_device *ml) ml_schedule_timer(ml); } -static void ml_effect_timer(unsigned long timer_data) +static void ml_effect_timer(struct timer_list *t) { - struct input_dev *dev = (struct input_dev *)timer_data; - struct ml_device *ml = dev->ff->private; + struct ml_device *ml = from_timer(ml, t, timer); + struct input_dev *dev = ml->dev; unsigned long flags; pr_debug("timer: updating effects\n"); @@ -526,7 +526,7 @@ int input_ff_create_memless(struct input_dev *dev, void *data, ml->private = data; ml->play_effect = play_effect; ml->gain = 0xffff; - setup_timer(&ml->timer, ml_effect_timer, (unsigned long)dev); + timer_setup(&ml->timer, ml_effect_timer, 0); set_bit(FF_GAIN, dev->ffbit); diff --git a/drivers/input/input.c b/drivers/input/input.c index 762bfb9487dc..44916ef4a424 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -76,7 +76,7 @@ static void input_start_autorepeat(struct input_dev *dev, int code) { if (test_bit(EV_REP, dev->evbit) && dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] && - dev->timer.data) { + dev->timer.function) { dev->repeat_key = code; mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_DELAY])); @@ -179,9 +179,9 @@ static void input_pass_event(struct input_dev *dev, * dev->event_lock here to avoid racing with input_event * which may cause keys get "stuck". */ -static void input_repeat_key(unsigned long data) +static void input_repeat_key(struct timer_list *t) { - struct input_dev *dev = (void *) data; + struct input_dev *dev = from_timer(dev, t, timer); unsigned long flags; spin_lock_irqsave(&dev->event_lock, flags); @@ -1784,7 +1784,7 @@ struct input_dev *input_allocate_device(void) device_initialize(&dev->dev); mutex_init(&dev->mutex); spin_lock_init(&dev->event_lock); - init_timer(&dev->timer); + timer_setup(&dev->timer, NULL, 0); INIT_LIST_HEAD(&dev->h_list); INIT_LIST_HEAD(&dev->node); @@ -2047,8 +2047,7 @@ static void devm_input_device_unregister(struct device *dev, void *res) */ void input_enable_softrepeat(struct input_dev *dev, int delay, int period) { - dev->timer.data = (unsigned long) dev; - dev->timer.function = input_repeat_key; + dev->timer.function = (TIMER_FUNC_TYPE)input_repeat_key; dev->rep[REP_DELAY] = delay; dev->rep[REP_PERIOD] = period; } diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index c43f087a496d..ca734ea97e53 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -654,6 +654,7 @@ static void gc_psx_report_one(struct gc_pad *pad, unsigned char psx_type, input_report_key(dev, BTN_THUMBL, ~data[0] & 0x04); input_report_key(dev, BTN_THUMBR, ~data[0] & 0x02); + /* fall through */ case GC_PSX_NEGCON: case GC_PSX_ANALOG: @@ -887,6 +888,7 @@ static int gc_setup_pad(struct gc *gc, int idx, int pad_type) case GC_SNES: for (i = 4; i < 8; i++) __set_bit(gc_snes_btn[i], input_dev->keybit); + /* fall through */ case GC_NES: for (i = 0; i < 4; i++) __set_bit(gc_snes_btn[i], input_dev->keybit); @@ -894,6 +896,7 @@ static int gc_setup_pad(struct gc *gc, int idx, int pad_type) case GC_MULTI2: __set_bit(BTN_THUMB, input_dev->keybit); + /* fall through */ case GC_MULTI: __set_bit(BTN_TRIGGER, input_dev->keybit); break; diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c index 4a95b224169f..5e602a6852b7 100644 --- a/drivers/input/joystick/sidewinder.c +++ b/drivers/input/joystick/sidewinder.c @@ -672,16 +672,16 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv) switch (i * m) { case 60: - sw->number++; + sw->number++; /* fall through */ case 45: /* Ambiguous packet length */ if (j <= 40) { /* ID length less or eq 40 -> FSP */ case 43: sw->type = SW_ID_FSP; break; } - sw->number++; + sw->number++; /* fall through */ case 30: - sw->number++; + sw->number++; /* fall through */ case 15: sw->type = SW_ID_GP; break; @@ -697,9 +697,9 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv) sw->type = SW_ID_PP; break; case 66: - sw->bits = 3; + sw->bits = 3; /* fall through */ case 198: - sw->length = 22; + sw->length = 22; /* fall through */ case 64: sw->type = SW_ID_3DP; if (j == 160) diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c index e9712a1b7cad..bb3faeff8cac 100644 --- a/drivers/input/joystick/spaceball.c +++ b/drivers/input/joystick/spaceball.c @@ -162,6 +162,7 @@ static irqreturn_t spaceball_interrupt(struct serio *serio, break; } spaceball->escape = 0; + /* fall through */ case 'M': case 'Q': case 'S': @@ -169,6 +170,7 @@ static irqreturn_t spaceball_interrupt(struct serio *serio, spaceball->escape = 0; data &= 0x1f; } + /* fall through */ default: if (spaceball->escape) spaceball->escape = 0; @@ -234,11 +236,13 @@ static int spaceball_connect(struct serio *serio, struct serio_driver *drv) input_dev->keybit[BIT_WORD(BTN_A)] |= BIT_MASK(BTN_A) | BIT_MASK(BTN_B) | BIT_MASK(BTN_C) | BIT_MASK(BTN_MODE); + /* fall through */ default: input_dev->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_2) | BIT_MASK(BTN_3) | BIT_MASK(BTN_4) | BIT_MASK(BTN_5) | BIT_MASK(BTN_6) | BIT_MASK(BTN_7) | BIT_MASK(BTN_8); + /* fall through */ case SPACEBALL_3003C: input_dev->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_1) | BIT_MASK(BTN_8); diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index 39bcbc38997f..8a07a426f88e 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c @@ -127,10 +127,9 @@ static inline void bfin_kpad_clear_irq(void) bfin_write_KPAD_ROWCOL(0xFFFF); } -static void bfin_kpad_timer(unsigned long data) +static void bfin_kpad_timer(struct timer_list *t) { - struct platform_device *pdev = (struct platform_device *) data; - struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); + struct bf54x_kpad *bf54x_kpad = from_timer(bf54x_kpad, t, timer); if (bfin_kpad_get_keypressed(bf54x_kpad)) { /* Try again later */ @@ -298,7 +297,7 @@ static int bfin_kpad_probe(struct platform_device *pdev) /* Init Keypad Key Up/Release test timer */ - setup_timer(&bf54x_kpad->timer, bfin_kpad_timer, (unsigned long) pdev); + timer_setup(&bf54x_kpad->timer, bfin_kpad_timer, 0); bfin_write_KPAD_PRESCALE(bfin_kpad_get_prescale(TIME_SCALE)); diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index e9f0ebf3267a..87e613dc33b8 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -419,9 +419,9 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static void gpio_keys_irq_timer(unsigned long _data) +static void gpio_keys_irq_timer(struct timer_list *t) { - struct gpio_button_data *bdata = (struct gpio_button_data *)_data; + struct gpio_button_data *bdata = from_timer(bdata, t, release_timer); struct input_dev *input = bdata->input; unsigned long flags; @@ -582,8 +582,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev, } bdata->release_delay = button->debounce_interval; - setup_timer(&bdata->release_timer, - gpio_keys_irq_timer, (unsigned long)bdata); + timer_setup(&bdata->release_timer, gpio_keys_irq_timer, 0); isr = gpio_keys_irq_isr; irqflags = 0; diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index 2165f3dd328b..25d61d8d4fc4 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c @@ -184,9 +184,9 @@ static void imx_keypad_fire_events(struct imx_keypad *keypad, /* * imx_keypad_check_for_events is the timer handler. */ -static void imx_keypad_check_for_events(unsigned long data) +static void imx_keypad_check_for_events(struct timer_list *t) { - struct imx_keypad *keypad = (struct imx_keypad *) data; + struct imx_keypad *keypad = from_timer(keypad, t, check_matrix_timer); unsigned short matrix_volatile_state[MAX_MATRIX_KEY_COLS]; unsigned short reg_val; bool state_changed, is_zero_matrix; @@ -456,8 +456,8 @@ static int imx_keypad_probe(struct platform_device *pdev) keypad->irq = irq; keypad->stable_count = 0; - setup_timer(&keypad->check_matrix_timer, - imx_keypad_check_for_events, (unsigned long) keypad); + timer_setup(&keypad->check_matrix_timer, + imx_keypad_check_for_events, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); keypad->mmio_base = devm_ioremap_resource(&pdev->dev, res); diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c index 0d74312d5b02..30d610758595 100644 --- a/drivers/input/keyboard/locomokbd.c +++ b/drivers/input/keyboard/locomokbd.c @@ -210,9 +210,9 @@ static irqreturn_t locomokbd_interrupt(int irq, void *dev_id) /* * LoCoMo timer checking for released keys */ -static void locomokbd_timer_callback(unsigned long data) +static void locomokbd_timer_callback(struct timer_list *t) { - struct locomokbd *locomokbd = (struct locomokbd *) data; + struct locomokbd *locomokbd = from_timer(locomokbd, t, timer); locomokbd_scankeyboard(locomokbd); } @@ -264,8 +264,7 @@ static int locomokbd_probe(struct locomo_dev *dev) spin_lock_init(&locomokbd->lock); - setup_timer(&locomokbd->timer, locomokbd_timer_callback, - (unsigned long)locomokbd); + timer_setup(&locomokbd->timer, locomokbd_timer_callback, 0); locomokbd->suspend_jiffies = jiffies; diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index 146b26f665f6..7bd107910a6e 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c @@ -41,7 +41,7 @@ #undef NEW_BOARD_LEARNING_MODE static void omap_kp_tasklet(unsigned long); -static void omap_kp_timer(unsigned long); +static void omap_kp_timer(struct timer_list *); static unsigned char keypad_state[8]; static DEFINE_MUTEX(kp_enable_mutex); @@ -74,7 +74,7 @@ static irqreturn_t omap_kp_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static void omap_kp_timer(unsigned long data) +static void omap_kp_timer(struct timer_list *unused) { tasklet_schedule(&kp_tasklet); } @@ -233,7 +233,7 @@ static int omap_kp_probe(struct platform_device *pdev) col_idx = 0; row_idx = 0; - setup_timer(&omap_kp->timer, omap_kp_timer, (unsigned long)omap_kp); + timer_setup(&omap_kp->timer, omap_kp_timer, 0); /* get the irq and init timer*/ kp_tasklet.data = (unsigned long) omap_kp; diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c index 7544888c4749..53c768b95939 100644 --- a/drivers/input/keyboard/snvs_pwrkey.c +++ b/drivers/input/keyboard/snvs_pwrkey.c @@ -45,9 +45,9 @@ struct pwrkey_drv_data { struct input_dev *input; }; -static void imx_imx_snvs_check_for_events(unsigned long data) +static void imx_imx_snvs_check_for_events(struct timer_list *t) { - struct pwrkey_drv_data *pdata = (struct pwrkey_drv_data *) data; + struct pwrkey_drv_data *pdata = from_timer(pdata, t, check_timer); struct input_dev *input = pdata->input; u32 state; @@ -134,8 +134,7 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev) /* clear the unexpected interrupt before driver ready */ regmap_write(pdata->snvs, SNVS_LPSR_REG, SNVS_LPSR_SPO); - setup_timer(&pdata->check_timer, - imx_imx_snvs_check_for_events, (unsigned long) pdata); + timer_setup(&pdata->check_timer, imx_imx_snvs_check_for_events, 0); input = devm_input_allocate_device(&pdev->dev); if (!input) { diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index edc1385ca00b..875205f445b5 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -251,9 +251,9 @@ static void tegra_kbc_set_fifo_interrupt(struct tegra_kbc *kbc, bool enable) writel(val, kbc->mmio + KBC_CONTROL_0); } -static void tegra_kbc_keypress_timer(unsigned long data) +static void tegra_kbc_keypress_timer(struct timer_list *t) { - struct tegra_kbc *kbc = (struct tegra_kbc *)data; + struct tegra_kbc *kbc = from_timer(kbc, t, timer); unsigned long flags; u32 val; unsigned int i; @@ -655,7 +655,7 @@ static int tegra_kbc_probe(struct platform_device *pdev) return -ENOMEM; } - setup_timer(&kbc->timer, tegra_kbc_keypress_timer, (unsigned long)kbc); + timer_setup(&kbc->timer, tegra_kbc_keypress_timer, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); kbc->mmio = devm_ioremap_resource(&pdev->dev, res); diff --git a/drivers/input/misc/adxl34x.c b/drivers/input/misc/adxl34x.c index 2b2d02f408bb..a3e79bf5a04b 100644 --- a/drivers/input/misc/adxl34x.c +++ b/drivers/input/misc/adxl34x.c @@ -796,7 +796,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, if (pdata->watermark) { ac->int_mask |= WATERMARK; - if (!FIFO_MODE(pdata->fifo_mode)) + if (FIFO_MODE(pdata->fifo_mode) == FIFO_BYPASS) ac->pdata.fifo_mode |= FIFO_STREAM; } else { ac->int_mask |= DATA_READY; diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 443151de90c6..39ddd9a73feb 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -31,6 +31,7 @@ * 0.1 20/06/2002 * - first public version */ +#include <uapi/linux/uinput.h> #include <linux/poll.h> #include <linux/sched.h> #include <linux/slab.h> @@ -38,10 +39,47 @@ #include <linux/init.h> #include <linux/fs.h> #include <linux/miscdevice.h> -#include <linux/uinput.h> #include <linux/input/mt.h> #include "../input-compat.h" +#define UINPUT_NAME "uinput" +#define UINPUT_BUFFER_SIZE 16 +#define UINPUT_NUM_REQUESTS 16 + +enum uinput_state { UIST_NEW_DEVICE, UIST_SETUP_COMPLETE, UIST_CREATED }; + +struct uinput_request { + unsigned int id; + unsigned int code; /* UI_FF_UPLOAD, UI_FF_ERASE */ + + int retval; + struct completion done; + + union { + unsigned int effect_id; + struct { + struct ff_effect *effect; + struct ff_effect *old; + } upload; + } u; +}; + +struct uinput_device { + struct input_dev *dev; + struct mutex mutex; + enum uinput_state state; + wait_queue_head_t waitq; + unsigned char ready; + unsigned char head; + unsigned char tail; + struct input_event buff[UINPUT_BUFFER_SIZE]; + unsigned int ff_effects_max; + + struct uinput_request *requests[UINPUT_NUM_REQUESTS]; + wait_queue_head_t requests_waitq; + spinlock_t requests_lock; +}; + static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { @@ -149,7 +187,11 @@ static int uinput_request_submit(struct uinput_device *udev, if (retval) goto out; - wait_for_completion(&request->done); + if (!wait_for_completion_timeout(&request->done, 30 * HZ)) { + retval = -ETIMEDOUT; + goto out; + } + retval = request->retval; out: @@ -320,6 +362,10 @@ static int uinput_create_device(struct uinput_device *udev) dev->flush = uinput_dev_flush; } + dev->event = uinput_dev_event; + + input_set_drvdata(udev->dev, udev); + error = input_register_device(udev->dev); if (error) goto fail2; @@ -402,18 +448,6 @@ static int uinput_validate_absbits(struct input_dev *dev) return 0; } -static int uinput_allocate_device(struct uinput_device *udev) -{ - udev->dev = input_allocate_device(); - if (!udev->dev) - return -ENOMEM; - - udev->dev->event = uinput_dev_event; - input_set_drvdata(udev->dev, udev); - - return 0; -} - static int uinput_dev_setup(struct uinput_device *udev, struct uinput_setup __user *arg) { @@ -489,9 +523,9 @@ static int uinput_setup_device_legacy(struct uinput_device *udev, return -EINVAL; if (!udev->dev) { - retval = uinput_allocate_device(udev); - if (retval) - return retval; + udev->dev = input_allocate_device(); + if (!udev->dev) + return -ENOMEM; } dev = udev->dev; @@ -822,162 +856,163 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, return retval; if (!udev->dev) { - retval = uinput_allocate_device(udev); - if (retval) + udev->dev = input_allocate_device(); + if (!udev->dev) { + retval = -ENOMEM; goto out; + } } switch (cmd) { - case UI_GET_VERSION: - if (put_user(UINPUT_VERSION, - (unsigned int __user *)p)) - retval = -EFAULT; - goto out; + case UI_GET_VERSION: + if (put_user(UINPUT_VERSION, (unsigned int __user *)p)) + retval = -EFAULT; + goto out; - case UI_DEV_CREATE: - retval = uinput_create_device(udev); - goto out; + case UI_DEV_CREATE: + retval = uinput_create_device(udev); + goto out; - case UI_DEV_DESTROY: - uinput_destroy_device(udev); - goto out; + case UI_DEV_DESTROY: + uinput_destroy_device(udev); + goto out; - case UI_DEV_SETUP: - retval = uinput_dev_setup(udev, p); - goto out; + case UI_DEV_SETUP: + retval = uinput_dev_setup(udev, p); + goto out; - /* UI_ABS_SETUP is handled in the variable size ioctls */ + /* UI_ABS_SETUP is handled in the variable size ioctls */ - case UI_SET_EVBIT: - retval = uinput_set_bit(arg, evbit, EV_MAX); - goto out; + case UI_SET_EVBIT: + retval = uinput_set_bit(arg, evbit, EV_MAX); + goto out; - case UI_SET_KEYBIT: - retval = uinput_set_bit(arg, keybit, KEY_MAX); - goto out; + case UI_SET_KEYBIT: + retval = uinput_set_bit(arg, keybit, KEY_MAX); + goto out; - case UI_SET_RELBIT: - retval = uinput_set_bit(arg, relbit, REL_MAX); - goto out; + case UI_SET_RELBIT: + retval = uinput_set_bit(arg, relbit, REL_MAX); + goto out; - case UI_SET_ABSBIT: - retval = uinput_set_bit(arg, absbit, ABS_MAX); - goto out; + case UI_SET_ABSBIT: + retval = uinput_set_bit(arg, absbit, ABS_MAX); + goto out; - case UI_SET_MSCBIT: - retval = uinput_set_bit(arg, mscbit, MSC_MAX); - goto out; + case UI_SET_MSCBIT: + retval = uinput_set_bit(arg, mscbit, MSC_MAX); + goto out; - case UI_SET_LEDBIT: - retval = uinput_set_bit(arg, ledbit, LED_MAX); - goto out; + case UI_SET_LEDBIT: + retval = uinput_set_bit(arg, ledbit, LED_MAX); + goto out; + + case UI_SET_SNDBIT: + retval = uinput_set_bit(arg, sndbit, SND_MAX); + goto out; - case UI_SET_SNDBIT: - retval = uinput_set_bit(arg, sndbit, SND_MAX); + case UI_SET_FFBIT: + retval = uinput_set_bit(arg, ffbit, FF_MAX); + goto out; + + case UI_SET_SWBIT: + retval = uinput_set_bit(arg, swbit, SW_MAX); + goto out; + + case UI_SET_PROPBIT: + retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX); + goto out; + + case UI_SET_PHYS: + if (udev->state == UIST_CREATED) { + retval = -EINVAL; goto out; + } - case UI_SET_FFBIT: - retval = uinput_set_bit(arg, ffbit, FF_MAX); + phys = strndup_user(p, 1024); + if (IS_ERR(phys)) { + retval = PTR_ERR(phys); goto out; + } + + kfree(udev->dev->phys); + udev->dev->phys = phys; + goto out; - case UI_SET_SWBIT: - retval = uinput_set_bit(arg, swbit, SW_MAX); + case UI_BEGIN_FF_UPLOAD: + retval = uinput_ff_upload_from_user(p, &ff_up); + if (retval) goto out; - case UI_SET_PROPBIT: - retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX); + req = uinput_request_find(udev, ff_up.request_id); + if (!req || req->code != UI_FF_UPLOAD || + !req->u.upload.effect) { + retval = -EINVAL; goto out; + } - case UI_SET_PHYS: - if (udev->state == UIST_CREATED) { - retval = -EINVAL; - goto out; - } + ff_up.retval = 0; + ff_up.effect = *req->u.upload.effect; + if (req->u.upload.old) + ff_up.old = *req->u.upload.old; + else + memset(&ff_up.old, 0, sizeof(struct ff_effect)); - phys = strndup_user(p, 1024); - if (IS_ERR(phys)) { - retval = PTR_ERR(phys); - goto out; - } + retval = uinput_ff_upload_to_user(p, &ff_up); + goto out; - kfree(udev->dev->phys); - udev->dev->phys = phys; + case UI_BEGIN_FF_ERASE: + if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) { + retval = -EFAULT; goto out; + } - case UI_BEGIN_FF_UPLOAD: - retval = uinput_ff_upload_from_user(p, &ff_up); - if (retval) - goto out; - - req = uinput_request_find(udev, ff_up.request_id); - if (!req || req->code != UI_FF_UPLOAD || - !req->u.upload.effect) { - retval = -EINVAL; - goto out; - } - - ff_up.retval = 0; - ff_up.effect = *req->u.upload.effect; - if (req->u.upload.old) - ff_up.old = *req->u.upload.old; - else - memset(&ff_up.old, 0, sizeof(struct ff_effect)); - - retval = uinput_ff_upload_to_user(p, &ff_up); + req = uinput_request_find(udev, ff_erase.request_id); + if (!req || req->code != UI_FF_ERASE) { + retval = -EINVAL; goto out; + } - case UI_BEGIN_FF_ERASE: |