Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: This patch implements compat_ioctl for joydev.

I've tested it with a Logitech WingMan Rumblepad on an x86-64
machine, and on an ia32 machine to make sure I didn't break
anything.

Signed-off-by: Jeremy Fitzhardinge <jeremy@goop.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

authored by

Jeremy Fitzhardinge and committed by
Dmitry Torokhov
024ac44c f23488b2

+116 -33
+91 -25
drivers/input/joydev.c
··· 285 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 290 struct input_dev *dev = joydev->handle.dev; 293 - void __user *argp = (void __user *)arg; 294 291 int i, j; 295 - 296 - if (!joydev->exist) return -ENODEV; 297 292 298 293 switch (cmd) { 299 294 300 295 case JS_SET_CAL: 301 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 298 case JS_GET_CAL: 304 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 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 303 case JS_GET_TIMEOUT: 309 - return put_user(joydev->glue.JS_TIMEOUT, (int __user *) arg); 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; 304 + return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); 320 305 321 306 case JSIOCGVERSION: 322 - return put_user(JS_VERSION, (__u32 __user *) arg); 307 + return put_user(JS_VERSION, (__u32 __user *) argp); 323 308 case JSIOCGAXES: 324 - return put_user(joydev->nabs, (__u8 __user *) arg); 309 + return put_user(joydev->nabs, (__u8 __user *) argp); 325 310 case JSIOCGBUTTONS: 326 - return put_user(joydev->nkey, (__u8 __user *) arg); 311 + return put_user(joydev->nkey, (__u8 __user *) argp); 327 312 case JSIOCSCORR: 328 313 if (copy_from_user(joydev->corr, argp, 329 - sizeof(struct js_corr) * joydev->nabs)) 314 + sizeof(joydev->corr[0]) * joydev->nabs)) 330 315 return -EFAULT; 331 316 for (i = 0; i < joydev->nabs; i++) { 332 317 j = joydev->abspam[i]; ··· 320 335 return 0; 321 336 case JSIOCGCORR: 322 337 return copy_to_user(argp, joydev->corr, 323 - sizeof(struct js_corr) * joydev->nabs) ? -EFAULT : 0; 338 + sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0; 324 339 case JSIOCSAXMAP: 325 340 if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1))) 326 341 return -EFAULT; ··· 356 371 return -EINVAL; 357 372 } 358 373 374 + #ifdef CONFIG_COMPAT 375 + static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 376 + { 377 + struct joydev_list *list = file->private_data; 378 + struct joydev *joydev = list->joydev; 379 + void __user *argp = (void __user *)arg; 380 + s32 tmp32; 381 + struct JS_DATA_SAVE_TYPE_32 ds32; 382 + int err; 383 + 384 + if (!joydev->exist) return -ENODEV; 385 + switch(cmd) { 386 + case JS_SET_TIMELIMIT: 387 + err = get_user(tmp32, (s32 __user *) arg); 388 + if (err == 0) 389 + joydev->glue.JS_TIMELIMIT = tmp32; 390 + break; 391 + case JS_GET_TIMELIMIT: 392 + tmp32 = joydev->glue.JS_TIMELIMIT; 393 + err = put_user(tmp32, (s32 __user *) arg); 394 + break; 395 + 396 + case JS_SET_ALL: 397 + err = copy_from_user(&ds32, argp, 398 + sizeof(ds32)) ? -EFAULT : 0; 399 + if (err == 0) { 400 + joydev->glue.JS_TIMEOUT = ds32.JS_TIMEOUT; 401 + joydev->glue.BUSY = ds32.BUSY; 402 + joydev->glue.JS_EXPIRETIME = ds32.JS_EXPIRETIME; 403 + joydev->glue.JS_TIMELIMIT = ds32.JS_TIMELIMIT; 404 + joydev->glue.JS_SAVE = ds32.JS_SAVE; 405 + joydev->glue.JS_CORR = ds32.JS_CORR; 406 + } 407 + break; 408 + 409 + case JS_GET_ALL: 410 + ds32.JS_TIMEOUT = joydev->glue.JS_TIMEOUT; 411 + ds32.BUSY = joydev->glue.BUSY; 412 + ds32.JS_EXPIRETIME = joydev->glue.JS_EXPIRETIME; 413 + ds32.JS_TIMELIMIT = joydev->glue.JS_TIMELIMIT; 414 + ds32.JS_SAVE = joydev->glue.JS_SAVE; 415 + ds32.JS_CORR = joydev->glue.JS_CORR; 416 + 417 + err = copy_to_user(argp, &ds32, 418 + sizeof(ds32)) ? -EFAULT : 0; 419 + break; 420 + 421 + default: 422 + err = joydev_ioctl_common(joydev, cmd, argp); 423 + } 424 + return err; 425 + } 426 + #endif /* CONFIG_COMPAT */ 427 + 428 + static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) 429 + { 430 + struct joydev_list *list = file->private_data; 431 + struct joydev *joydev = list->joydev; 432 + void __user *argp = (void __user *)arg; 433 + 434 + if (!joydev->exist) return -ENODEV; 435 + 436 + switch(cmd) { 437 + case JS_SET_TIMELIMIT: 438 + return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); 439 + case JS_GET_TIMELIMIT: 440 + return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); 441 + case JS_SET_ALL: 442 + return copy_from_user(&joydev->glue, argp, 443 + sizeof(joydev->glue)) ? -EFAULT : 0; 444 + case JS_GET_ALL: 445 + return copy_to_user(argp, &joydev->glue, 446 + sizeof(joydev->glue)) ? -EFAULT : 0; 447 + default: 448 + return joydev_ioctl_common(joydev, cmd, argp); 449 + } 450 + } 451 + 359 452 static struct file_operations joydev_fops = { 360 453 .owner = THIS_MODULE, 361 454 .read = joydev_read, ··· 442 379 .open = joydev_open, 443 380 .release = joydev_release, 444 381 .ioctl = joydev_ioctl, 382 + #ifdef CONFIG_COMPAT 383 + .compat_ioctl = joydev_compat_ioctl, 384 + #endif 445 385 .fasync = joydev_fasync, 446 386 }; 447 387
+25 -8
include/linux/joystick.h
··· 111 111 #define JS_SET_ALL 8 112 112 113 113 struct JS_DATA_TYPE { 114 - int buttons; 115 - int x; 116 - int y; 114 + __s32 buttons; 115 + __s32 x; 116 + __s32 y; 117 117 }; 118 118 119 - struct JS_DATA_SAVE_TYPE { 120 - int JS_TIMEOUT; 121 - int BUSY; 122 - long JS_EXPIRETIME; 123 - long JS_TIMELIMIT; 119 + struct JS_DATA_SAVE_TYPE_32 { 120 + __s32 JS_TIMEOUT; 121 + __s32 BUSY; 122 + __s32 JS_EXPIRETIME; 123 + __s32 JS_TIMELIMIT; 124 124 struct JS_DATA_TYPE JS_SAVE; 125 125 struct JS_DATA_TYPE JS_CORR; 126 126 }; 127 + 128 + struct JS_DATA_SAVE_TYPE_64 { 129 + __s32 JS_TIMEOUT; 130 + __s32 BUSY; 131 + __s64 JS_EXPIRETIME; 132 + __s64 JS_TIMELIMIT; 133 + struct JS_DATA_TYPE JS_SAVE; 134 + struct JS_DATA_TYPE JS_CORR; 135 + }; 136 + 137 + #if BITS_PER_LONG == 64 138 + #define JS_DATA_SAVE_TYPE JS_DATA_SAVE_TYPE_64 139 + #elif BITS_PER_LONG == 32 140 + #define JS_DATA_SAVE_TYPE JS_DATA_SAVE_TYPE_32 141 + #else 142 + #error Unexpected BITS_PER_LONG 143 + #endif 127 144 128 145 #endif /* _LINUX_JOYSTICK_H */