diff options
Diffstat (limited to 'drivers/input/joydev.c')
-rw-r--r-- | drivers/input/joydev.c | 69 |
1 files changed, 45 insertions, 24 deletions
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 949bdcef8c2b..d67157513bf7 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c | |||
@@ -81,10 +81,7 @@ static int joydev_correct(int value, struct js_corr *corr) | |||
81 | return 0; | 81 | return 0; |
82 | } | 82 | } |
83 | 83 | ||
84 | if (value < -32767) return -32767; | 84 | return value < -32767 ? -32767 : (value > 32767 ? 32767 : value); |
85 | if (value > 32767) return 32767; | ||
86 | |||
87 | return value; | ||
88 | } | 85 | } |
89 | 86 | ||
90 | static void joydev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) | 87 | static void joydev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) |
@@ -96,7 +93,8 @@ static void joydev_event(struct input_handle *handle, unsigned int type, unsigne | |||
96 | switch (type) { | 93 | switch (type) { |
97 | 94 | ||
98 | case EV_KEY: | 95 | case EV_KEY: |
99 | if (code < BTN_MISC || value == 2) return; | 96 | if (code < BTN_MISC || value == 2) |
97 | return; | ||
100 | event.type = JS_EVENT_BUTTON; | 98 | event.type = JS_EVENT_BUTTON; |
101 | event.number = joydev->keymap[code - BTN_MISC]; | 99 | event.number = joydev->keymap[code - BTN_MISC]; |
102 | event.value = value; | 100 | event.value = value; |
@@ -106,7 +104,8 @@ static void joydev_event(struct input_handle *handle, unsigned int type, unsigne | |||
106 | event.type = JS_EVENT_AXIS; | 104 | event.type = JS_EVENT_AXIS; |
107 | event.number = joydev->absmap[code]; | 105 | event.number = joydev->absmap[code]; |
108 | event.value = joydev_correct(value, joydev->corr + event.number); | 106 | event.value = joydev_correct(value, joydev->corr + event.number); |
109 | if (event.value == joydev->abs[event.number]) return; | 107 | if (event.value == joydev->abs[event.number]) |
108 | return; | ||
110 | joydev->abs[event.number] = event.value; | 109 | joydev->abs[event.number] = event.value; |
111 | break; | 110 | break; |
112 | 111 | ||
@@ -134,7 +133,9 @@ static int joydev_fasync(int fd, struct file *file, int on) | |||
134 | { | 133 | { |
135 | int retval; | 134 | int retval; |
136 | struct joydev_list *list = file->private_data; | 135 | struct joydev_list *list = file->private_data; |
136 | |||
137 | retval = fasync_helper(fd, file, on, &list->fasync); | 137 | retval = fasync_helper(fd, file, on, &list->fasync); |
138 | |||
138 | return retval < 0 ? retval : 0; | 139 | return retval < 0 ? retval : 0; |
139 | } | 140 | } |
140 | 141 | ||
@@ -222,12 +223,12 @@ static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, lo | |||
222 | return sizeof(struct JS_DATA_TYPE); | 223 | return sizeof(struct JS_DATA_TYPE); |
223 | } | 224 | } |
224 | 225 | ||
225 | if (list->startup == joydev->nabs + joydev->nkey | 226 | if (list->startup == joydev->nabs + joydev->nkey && |
226 | && list->head == list->tail && (file->f_flags & O_NONBLOCK)) | 227 | list->head == list->tail && (file->f_flags & O_NONBLOCK)) |
227 | return -EAGAIN; | 228 | return -EAGAIN; |
228 | 229 | ||
229 | retval = wait_event_interruptible(list->joydev->wait, | 230 | retval = wait_event_interruptible(list->joydev->wait, |
230 | !list->joydev->exist || | 231 | !list->joydev->exist || |
231 | list->startup < joydev->nabs + joydev->nkey || | 232 | list->startup < joydev->nabs + joydev->nkey || |
232 | list->head != list->tail); | 233 | list->head != list->tail); |
233 | 234 | ||
@@ -276,8 +277,9 @@ static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, lo | |||
276 | static unsigned int joydev_poll(struct file *file, poll_table *wait) | 277 | static unsigned int joydev_poll(struct file *file, poll_table *wait) |
277 | { | 278 | { |
278 | struct joydev_list *list = file->private_data; | 279 | struct joydev_list *list = file->private_data; |
280 | |||
279 | poll_wait(file, &list->joydev->wait, wait); | 281 | poll_wait(file, &list->joydev->wait, wait); |
280 | return ((list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey) ? | 282 | return ((list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey) ? |
281 | (POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR)); | 283 | (POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR)); |
282 | } | 284 | } |
283 | 285 | ||
@@ -291,20 +293,26 @@ static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __u | |||
291 | case JS_SET_CAL: | 293 | case JS_SET_CAL: |
292 | return copy_from_user(&joydev->glue.JS_CORR, argp, | 294 | return copy_from_user(&joydev->glue.JS_CORR, argp, |
293 | sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; | 295 | sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; |
296 | |||
294 | case JS_GET_CAL: | 297 | case JS_GET_CAL: |
295 | return copy_to_user(argp, &joydev->glue.JS_CORR, | 298 | return copy_to_user(argp, &joydev->glue.JS_CORR, |
296 | sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; | 299 | sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; |
300 | |||
297 | case JS_SET_TIMEOUT: | 301 | case JS_SET_TIMEOUT: |
298 | return get_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); | 302 | return get_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); |
303 | |||
299 | case JS_GET_TIMEOUT: | 304 | case JS_GET_TIMEOUT: |
300 | return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); | 305 | return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); |
301 | 306 | ||
302 | case JSIOCGVERSION: | 307 | case JSIOCGVERSION: |
303 | return put_user(JS_VERSION, (__u32 __user *) argp); | 308 | return put_user(JS_VERSION, (__u32 __user *) argp); |
309 | |||
304 | case JSIOCGAXES: | 310 | case JSIOCGAXES: |
305 | return put_user(joydev->nabs, (__u8 __user *) argp); | 311 | return put_user(joydev->nabs, (__u8 __user *) argp); |
312 | |||
306 | case JSIOCGBUTTONS: | 313 | case JSIOCGBUTTONS: |
307 | return put_user(joydev->nkey, (__u8 __user *) argp); | 314 | return put_user(joydev->nkey, (__u8 __user *) argp); |
315 | |||
308 | case JSIOCSCORR: | 316 | case JSIOCSCORR: |
309 | if (copy_from_user(joydev->corr, argp, | 317 | if (copy_from_user(joydev->corr, argp, |
310 | sizeof(joydev->corr[0]) * joydev->nabs)) | 318 | sizeof(joydev->corr[0]) * joydev->nabs)) |
@@ -314,38 +322,49 @@ static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __u | |||
314 | joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i); | 322 | joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i); |
315 | } | 323 | } |
316 | return 0; | 324 | return 0; |
325 | |||
317 | case JSIOCGCORR: | 326 | case JSIOCGCORR: |
318 | return copy_to_user(argp, joydev->corr, | 327 | return copy_to_user(argp, joydev->corr, |
319 | sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0; | 328 | sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0; |
329 | |||
320 | case JSIOCSAXMAP: | 330 | case JSIOCSAXMAP: |
321 | if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1))) | 331 | if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1))) |
322 | return -EFAULT; | 332 | return -EFAULT; |
323 | for (i = 0; i < joydev->nabs; i++) { | 333 | for (i = 0; i < joydev->nabs; i++) { |
324 | if (joydev->abspam[i] > ABS_MAX) return -EINVAL; | 334 | if (joydev->abspam[i] > ABS_MAX) |
335 | return -EINVAL; | ||
325 | joydev->absmap[joydev->abspam[i]] = i; | 336 | joydev->absmap[joydev->abspam[i]] = i; |
326 | } | 337 | } |
327 | return 0; | 338 | return 0; |
339 | |||
328 | case JSIOCGAXMAP: | 340 | case JSIOCGAXMAP: |
329 | return copy_to_user(argp, joydev->abspam, | 341 | return copy_to_user(argp, joydev->abspam, |
330 | sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0; | 342 | sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0; |
343 | |||
331 | case JSIOCSBTNMAP: | 344 | case JSIOCSBTNMAP: |
332 | if (copy_from_user(joydev->keypam, argp, sizeof(__u16) * (KEY_MAX - BTN_MISC + 1))) | 345 | if (copy_from_user(joydev->keypam, argp, sizeof(__u16) * (KEY_MAX - BTN_MISC + 1))) |
333 | return -EFAULT; | 346 | return -EFAULT; |
334 | for (i = 0; i < joydev->nkey; i++) { | 347 | for (i = 0; i < joydev->nkey; i++) { |
335 | if (joydev->keypam[i] > KEY_MAX || joydev->keypam[i] < BTN_MISC) return -EINVAL; | 348 | if (joydev->keypam[i] > KEY_MAX || joydev->keypam[i] < BTN_MISC) |
349 | return -EINVAL; | ||
336 | joydev->keymap[joydev->keypam[i] - BTN_MISC] = i; | 350 | joydev->keymap[joydev->keypam[i] - BTN_MISC] = i; |
337 | } | 351 | } |
338 | return 0; | 352 | return 0; |
353 | |||
339 | case JSIOCGBTNMAP: | 354 | case JSIOCGBTNMAP: |
340 | return copy_to_user(argp, joydev->keypam, | 355 | return copy_to_user(argp, joydev->keypam, |
341 | sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0; | 356 | sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0; |
357 | |||
342 | default: | 358 | default: |
343 | if ((cmd & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) == JSIOCGNAME(0)) { | 359 | if ((cmd & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) == JSIOCGNAME(0)) { |
344 | int len; | 360 | int len; |
345 | if (!dev->name) return 0; | 361 | if (!dev->name) |
362 | return 0; | ||
346 | len = strlen(dev->name) + 1; | 363 | len = strlen(dev->name) + 1; |
347 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | 364 | if (len > _IOC_SIZE(cmd)) |
348 | if (copy_to_user(argp, dev->name, len)) return -EFAULT; | 365 | len = _IOC_SIZE(cmd); |
366 | if (copy_to_user(argp, dev->name, len)) | ||
367 | return -EFAULT; | ||
349 | return len; | 368 | return len; |
350 | } | 369 | } |
351 | } | 370 | } |
@@ -362,7 +381,9 @@ static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned lo | |||
362 | struct JS_DATA_SAVE_TYPE_32 ds32; | 381 | struct JS_DATA_SAVE_TYPE_32 ds32; |
363 | int err; | 382 | int err; |
364 | 383 | ||
365 | if (!joydev->exist) return -ENODEV; | 384 | if (!joydev->exist) |
385 | return -ENODEV; | ||
386 | |||
366 | switch(cmd) { | 387 | switch(cmd) { |
367 | case JS_SET_TIMELIMIT: | 388 | case JS_SET_TIMELIMIT: |
368 | err = get_user(tmp32, (s32 __user *) arg); | 389 | err = get_user(tmp32, (s32 __user *) arg); |
@@ -395,8 +416,7 @@ static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned lo | |||
395 | ds32.JS_SAVE = joydev->glue.JS_SAVE; | 416 | ds32.JS_SAVE = joydev->glue.JS_SAVE; |
396 | ds32.JS_CORR = joydev->glue.JS_CORR; | 417 | ds32.JS_CORR = joydev->glue.JS_CORR; |
397 | 418 | ||
398 | err = copy_to_user(argp, &ds32, | 419 | err = copy_to_user(argp, &ds32, sizeof(ds32)) ? -EFAULT : 0; |
399 | sizeof(ds32)) ? -EFAULT : 0; | ||
400 | break; | 420 | break; |
401 | 421 | ||
402 | default: | 422 | default: |
@@ -412,7 +432,8 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
412 | struct joydev *joydev = list->joydev; | 432 | struct joydev *joydev = list->joydev; |
413 | void __user *argp = (void __user *)arg; | 433 | void __user *argp = (void __user *)arg; |
414 | 434 | ||
415 | if (!joydev->exist) return -ENODEV; | 435 | if (!joydev->exist) |
436 | return -ENODEV; | ||
416 | 437 | ||
417 | switch(cmd) { | 438 | switch(cmd) { |
418 | case JS_SET_TIMELIMIT: | 439 | case JS_SET_TIMELIMIT: |
@@ -546,8 +567,8 @@ static struct input_device_id joydev_blacklist[] = { | |||
546 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, | 567 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, |
547 | .evbit = { BIT(EV_KEY) }, | 568 | .evbit = { BIT(EV_KEY) }, |
548 | .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) }, | 569 | .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) }, |
549 | }, /* Avoid itouchpads, touchscreens and tablets */ | 570 | }, /* Avoid itouchpads, touchscreens and tablets */ |
550 | { }, /* Terminating entry */ | 571 | { } /* Terminating entry */ |
551 | }; | 572 | }; |
552 | 573 | ||
553 | static struct input_device_id joydev_ids[] = { | 574 | static struct input_device_id joydev_ids[] = { |
@@ -566,7 +587,7 @@ static struct input_device_id joydev_ids[] = { | |||
566 | .evbit = { BIT(EV_ABS) }, | 587 | .evbit = { BIT(EV_ABS) }, |
567 | .absbit = { BIT(ABS_THROTTLE) }, | 588 | .absbit = { BIT(ABS_THROTTLE) }, |
568 | }, | 589 | }, |
569 | { }, /* Terminating entry */ | 590 | { } /* Terminating entry */ |
570 | }; | 591 | }; |
571 | 592 | ||
572 | MODULE_DEVICE_TABLE(input, joydev_ids); | 593 | MODULE_DEVICE_TABLE(input, joydev_ids); |
@@ -579,7 +600,7 @@ static struct input_handler joydev_handler = { | |||
579 | .minor = JOYDEV_MINOR_BASE, | 600 | .minor = JOYDEV_MINOR_BASE, |
580 | .name = "joydev", | 601 | .name = "joydev", |
581 | .id_table = joydev_ids, | 602 | .id_table = joydev_ids, |
582 | .blacklist = joydev_blacklist, | 603 | .blacklist = joydev_blacklist, |
583 | }; | 604 | }; |
584 | 605 | ||
585 | static int __init joydev_init(void) | 606 | static int __init joydev_init(void) |