diff options
Diffstat (limited to 'drivers/staging/comedi/comedi_compat32.c')
-rw-r--r-- | drivers/staging/comedi/comedi_compat32.c | 99 |
1 files changed, 54 insertions, 45 deletions
diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c index 5a4c74f703b3..25848244c4b1 100644 --- a/drivers/staging/comedi/comedi_compat32.c +++ b/drivers/staging/comedi/comedi_compat32.c @@ -1,23 +1,23 @@ /* - comedi/comedi_compat32.c - 32-bit ioctl compatibility for 64-bit comedi kernel module. - - Author: Ian Abbott, MEV Ltd. <abbotti@mev.co.uk> - Copyright (C) 2007 MEV Ltd. <http://www.mev.co.uk/> - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-2007 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * comedi/comedi_compat32.c + * 32-bit ioctl compatibility for 64-bit comedi kernel module. + * + * Author: Ian Abbott, MEV Ltd. <abbotti@mev.co.uk> + * Copyright (C) 2007 MEV Ltd. <http://www.mev.co.uk/> + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-2007 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #include <linux/uaccess.h> #include <linux/compat.h> @@ -27,11 +27,15 @@ #define COMEDI32_CHANINFO _IOR(CIO, 3, struct comedi32_chaninfo_struct) #define COMEDI32_RANGEINFO _IOR(CIO, 8, struct comedi32_rangeinfo_struct) -/* N.B. COMEDI32_CMD and COMEDI_CMD ought to use _IOWR, not _IOR. - * It's too late to change it now, but it only affects the command number. */ +/* + * N.B. COMEDI32_CMD and COMEDI_CMD ought to use _IOWR, not _IOR. + * It's too late to change it now, but it only affects the command number. + */ #define COMEDI32_CMD _IOR(CIO, 9, struct comedi32_cmd_struct) -/* N.B. COMEDI32_CMDTEST and COMEDI_CMDTEST ought to use _IOWR, not _IOR. - * It's too late to change it now, but it only affects the command number. */ +/* + * N.B. COMEDI32_CMDTEST and COMEDI_CMDTEST ought to use _IOWR, not _IOR. + * It's too late to change it now, but it only affects the command number. + */ #define COMEDI32_CMDTEST _IOR(CIO, 10, struct comedi32_cmd_struct) #define COMEDI32_INSNLIST _IOR(CIO, 11, struct comedi32_insnlist_struct) #define COMEDI32_INSN _IOR(CIO, 12, struct comedi32_insn_struct) @@ -39,7 +43,7 @@ struct comedi32_chaninfo_struct { unsigned int subdev; compat_uptr_t maxdata_list; /* 32-bit 'unsigned int *' */ - compat_uptr_t flaglist; /* 32-bit 'unsigned int *' */ + compat_uptr_t flaglist; /* 32-bit 'unsigned int *' */ compat_uptr_t rangelist; /* 32-bit 'unsigned int *' */ unsigned int unused[4]; }; @@ -62,16 +66,16 @@ struct comedi32_cmd_struct { unsigned int scan_end_arg; unsigned int stop_src; unsigned int stop_arg; - compat_uptr_t chanlist; /* 32-bit 'unsigned int *' */ + compat_uptr_t chanlist; /* 32-bit 'unsigned int *' */ unsigned int chanlist_len; - compat_uptr_t data; /* 32-bit 'short *' */ + compat_uptr_t data; /* 32-bit 'short *' */ unsigned int data_len; }; struct comedi32_insn_struct { unsigned int insn; unsigned int n; - compat_uptr_t data; /* 32-bit 'unsigned int *' */ + compat_uptr_t data; /* 32-bit 'unsigned int *' */ unsigned int subdev; unsigned int chanspec; unsigned int unused[3]; @@ -79,7 +83,7 @@ struct comedi32_insn_struct { struct comedi32_insnlist_struct { unsigned int n_insns; - compat_uptr_t insns; /* 32-bit 'struct comedi_insn *' */ + compat_uptr_t insns; /* 32-bit 'struct comedi_insn *' */ }; /* Handle translated ioctl. */ @@ -215,10 +219,12 @@ static int put_compat_cmd(struct comedi32_cmd_struct __user *cmd32, int err; unsigned int temp; - /* Copy back most of cmd structure. */ - /* Assume the pointer values are already valid. */ - /* (Could use ptr_to_compat() to set them, but that wasn't implemented - * until kernel version 2.6.11.) */ + /* + * Copy back most of cmd structure. + * + * Assume the pointer values are already valid. + * (Could use ptr_to_compat() to set them.) + */ if (!access_ok(VERIFY_READ, cmd, sizeof(*cmd)) || !access_ok(VERIFY_WRITE, cmd32, sizeof(*cmd32))) return -EFAULT; @@ -262,7 +268,7 @@ static int compat_cmd(struct file *file, unsigned long arg) { struct comedi_cmd __user *cmd; struct comedi32_cmd_struct __user *cmd32; - int rc; + int rc, err; cmd32 = compat_ptr(arg); cmd = compat_alloc_user_space(sizeof(*cmd)); @@ -271,7 +277,15 @@ static int compat_cmd(struct file *file, unsigned long arg) if (rc) return rc; - return translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd); + rc = translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd); + if (rc == -EAGAIN) { + /* Special case: copy cmd back to user. */ + err = put_compat_cmd(cmd32, cmd); + if (err) + rc = err; + } + + return rc; } /* Handle 32-bit COMEDI_CMDTEST ioctl. */ @@ -395,10 +409,12 @@ static int compat_insn(struct file *file, unsigned long arg) return translated_ioctl(file, COMEDI_INSN, (unsigned long)insn); } -/* Process untranslated ioctl. */ -/* Returns -ENOIOCTLCMD for unrecognised ioctl codes. */ -static inline int raw_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) +/* + * compat_ioctl file operation. + * + * Returns -ENOIOCTLCMD for unrecognised ioctl codes. + */ +long comedi_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int rc; @@ -445,10 +461,3 @@ static inline int raw_ioctl(struct file *file, unsigned int cmd, } return rc; } - -/* compat_ioctl file operation. */ -/* Returns -ENOIOCTLCMD for unrecognised ioctl codes. */ -long comedi_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - return raw_ioctl(file, cmd, arg); -} |