diff options
Diffstat (limited to 'drivers/input/joydev.c')
-rw-r--r-- | drivers/input/joydev.c | 116 |
1 files changed, 91 insertions, 25 deletions
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 39775fc380c7..ff8e1bbd0e13 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c | |||
@@ -285,48 +285,33 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait) | |||
285 | (POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR)); | 285 | (POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR)); |
286 | } | 286 | } |
287 | 287 | ||
288 | static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 288 | static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __user *argp) |
289 | { | 289 | { |
290 | struct joydev_list *list = file->private_data; | ||
291 | struct joydev *joydev = list->joydev; | ||
292 | struct input_dev *dev = joydev->handle.dev; | 290 | struct input_dev *dev = joydev->handle.dev; |
293 | void __user *argp = (void __user *)arg; | ||
294 | int i, j; | 291 | int i, j; |
295 | 292 | ||
296 | if (!joydev->exist) return -ENODEV; | ||
297 | |||
298 | switch (cmd) { | 293 | switch (cmd) { |
299 | 294 | ||
300 | case JS_SET_CAL: | 295 | case JS_SET_CAL: |
301 | return copy_from_user(&joydev->glue.JS_CORR, argp, | 296 | return copy_from_user(&joydev->glue.JS_CORR, argp, |
302 | sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0; | 297 | sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; |
303 | case JS_GET_CAL: | 298 | case JS_GET_CAL: |
304 | return copy_to_user(argp, &joydev->glue.JS_CORR, | 299 | return copy_to_user(argp, &joydev->glue.JS_CORR, |
305 | sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0; | 300 | sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; |
306 | case JS_SET_TIMEOUT: | 301 | case JS_SET_TIMEOUT: |
307 | return get_user(joydev->glue.JS_TIMEOUT, (int __user *) arg); | 302 | return get_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); |
308 | case JS_GET_TIMEOUT: | 303 | case JS_GET_TIMEOUT: |
309 | return put_user(joydev->glue.JS_TIMEOUT, (int __user *) arg); | 304 | return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); |
310 | case JS_SET_TIMELIMIT: | ||
311 | return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); | ||
312 | case JS_GET_TIMELIMIT: | ||
313 | return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); | ||
314 | case JS_SET_ALL: | ||
315 | return copy_from_user(&joydev->glue, argp, | ||
316 | sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0; | ||
317 | case JS_GET_ALL: | ||
318 | return copy_to_user(argp, &joydev->glue, | ||
319 | sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0; | ||
320 | 305 | ||
321 | case JSIOCGVERSION: | 306 | case JSIOCGVERSION: |
322 | return put_user(JS_VERSION, (__u32 __user *) arg); | 307 | return put_user(JS_VERSION, (__u32 __user *) argp); |
323 | case JSIOCGAXES: | 308 | case JSIOCGAXES: |
324 | return put_user(joydev->nabs, (__u8 __user *) arg); | 309 | return put_user(joydev->nabs, (__u8 __user *) argp); |
325 | case JSIOCGBUTTONS: | 310 | case JSIOCGBUTTONS: |
326 | return put_user(joydev->nkey, (__u8 __user *) arg); | 311 | return put_user(joydev->nkey, (__u8 __user *) argp); |
327 | case JSIOCSCORR: | 312 | case JSIOCSCORR: |
328 | if (copy_from_user(joydev->corr, argp, | 313 | if (copy_from_user(joydev->corr, argp, |
329 | sizeof(struct js_corr) * joydev->nabs)) | 314 | sizeof(joydev->corr[0]) * joydev->nabs)) |
330 | return -EFAULT; | 315 | return -EFAULT; |
331 | for (i = 0; i < joydev->nabs; i++) { | 316 | for (i = 0; i < joydev->nabs; i++) { |
332 | j = joydev->abspam[i]; | 317 | j = joydev->abspam[i]; |
@@ -335,7 +320,7 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
335 | return 0; | 320 | return 0; |
336 | case JSIOCGCORR: | 321 | case JSIOCGCORR: |
337 | return copy_to_user(argp, joydev->corr, | 322 | return copy_to_user(argp, joydev->corr, |
338 | sizeof(struct js_corr) * joydev->nabs) ? -EFAULT : 0; | 323 | sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0; |
339 | case JSIOCSAXMAP: | 324 | case JSIOCSAXMAP: |
340 | if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1))) | 325 | if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1))) |
341 | return -EFAULT; | 326 | return -EFAULT; |
@@ -371,6 +356,84 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
371 | return -EINVAL; | 356 | return -EINVAL; |
372 | } | 357 | } |
373 | 358 | ||
359 | #ifdef CONFIG_COMPAT | ||
360 | static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
361 | { | ||
362 | struct joydev_list *list = file->private_data; | ||
363 | struct joydev *joydev = list->joydev; | ||
364 | void __user *argp = (void __user *)arg; | ||
365 | s32 tmp32; | ||
366 | struct JS_DATA_SAVE_TYPE_32 ds32; | ||
367 | int err; | ||
368 | |||
369 | if (!joydev->exist) return -ENODEV; | ||
370 | switch(cmd) { | ||
371 | case JS_SET_TIMELIMIT: | ||
372 | err = get_user(tmp32, (s32 __user *) arg); | ||
373 | if (err == 0) | ||
374 | joydev->glue.JS_TIMELIMIT = tmp32; | ||
375 | break; | ||
376 | case JS_GET_TIMELIMIT: | ||
377 | tmp32 = joydev->glue.JS_TIMELIMIT; | ||
378 | err = put_user(tmp32, (s32 __user *) arg); | ||
379 | break; | ||
380 | |||
381 | case JS_SET_ALL: | ||
382 | err = copy_from_user(&ds32, argp, | ||
383 | sizeof(ds32)) ? -EFAULT : 0; | ||
384 | if (err == 0) { | ||
385 | joydev->glue.JS_TIMEOUT = ds32.JS_TIMEOUT; | ||
386 | joydev->glue.BUSY = ds32.BUSY; | ||
387 | joydev->glue.JS_EXPIRETIME = ds32.JS_EXPIRETIME; | ||
388 | joydev->glue.JS_TIMELIMIT = ds32.JS_TIMELIMIT; | ||
389 | joydev->glue.JS_SAVE = ds32.JS_SAVE; | ||
390 | joydev->glue.JS_CORR = ds32.JS_CORR; | ||
391 | } | ||
392 | break; | ||
393 | |||
394 | case JS_GET_ALL: | ||
395 | ds32.JS_TIMEOUT = joydev->glue.JS_TIMEOUT; | ||
396 | ds32.BUSY = joydev->glue.BUSY; | ||
397 | ds32.JS_EXPIRETIME = joydev->glue.JS_EXPIRETIME; | ||
398 | ds32.JS_TIMELIMIT = joydev->glue.JS_TIMELIMIT; | ||
399 | ds32.JS_SAVE = joydev->glue.JS_SAVE; | ||
400 | ds32.JS_CORR = joydev->glue.JS_CORR; | ||
401 | |||
402 | err = copy_to_user(argp, &ds32, | ||
403 | sizeof(ds32)) ? -EFAULT : 0; | ||
404 | break; | ||
405 | |||
406 | default: | ||
407 | err = joydev_ioctl_common(joydev, cmd, argp); | ||
408 | } | ||
409 | return err; | ||
410 | } | ||
411 | #endif /* CONFIG_COMPAT */ | ||
412 | |||
413 | static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | ||
414 | { | ||
415 | struct joydev_list *list = file->private_data; | ||
416 | struct joydev *joydev = list->joydev; | ||
417 | void __user *argp = (void __user *)arg; | ||
418 | |||
419 | if (!joydev->exist) return -ENODEV; | ||
420 | |||
421 | switch(cmd) { | ||
422 | case JS_SET_TIMELIMIT: | ||
423 | return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); | ||
424 | case JS_GET_TIMELIMIT: | ||
425 | return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); | ||
426 | case JS_SET_ALL: | ||
427 | return copy_from_user(&joydev->glue, argp, | ||
428 | sizeof(joydev->glue)) ? -EFAULT : 0; | ||
429 | case JS_GET_ALL: | ||
430 | return copy_to_user(argp, &joydev->glue, | ||
431 | sizeof(joydev->glue)) ? -EFAULT : 0; | ||
432 | default: | ||
433 | return joydev_ioctl_common(joydev, cmd, argp); | ||
434 | } | ||
435 | } | ||
436 | |||
374 | static struct file_operations joydev_fops = { | 437 | static struct file_operations joydev_fops = { |
375 | .owner = THIS_MODULE, | 438 | .owner = THIS_MODULE, |
376 | .read = joydev_read, | 439 | .read = joydev_read, |
@@ -379,6 +442,9 @@ static struct file_operations joydev_fops = { | |||
379 | .open = joydev_open, | 442 | .open = joydev_open, |
380 | .release = joydev_release, | 443 | .release = joydev_release, |
381 | .ioctl = joydev_ioctl, | 444 | .ioctl = joydev_ioctl, |
445 | #ifdef CONFIG_COMPAT | ||
446 | .compat_ioctl = joydev_compat_ioctl, | ||
447 | #endif | ||
382 | .fasync = joydev_fasync, | 448 | .fasync = joydev_fasync, |
383 | }; | 449 | }; |
384 | 450 | ||