Staging: comedi: Remove lsampl_t and sampl_t typedefs
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / comedi / comedi_compat32.c
CommitLineData
ed9eccbe
DS
1/*
2 comedi/comedi_compat32.c
3 32-bit ioctl compatibility for 64-bit comedi kernel module.
4
5 Author: Ian Abbott, MEV Ltd. <abbotti@mev.co.uk>
6 Copyright (C) 2007 MEV Ltd. <http://www.mev.co.uk/>
7
8 COMEDI - Linux Control and Measurement Device Interface
9 Copyright (C) 1997-2007 David A. Schleef <ds@schleef.org>
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24
25*/
26
27#define __NO_VERSION__
28#include "comedi.h"
29#include <linux/smp_lock.h>
30#include <asm/uaccess.h>
31
32#include "comedi_compat32.h"
33
34#ifdef CONFIG_COMPAT
35
36#ifndef HAVE_COMPAT_IOCTL
37#include <linux/ioctl32.h> /* for (un)register_ioctl32_conversion */
38#endif
39
8086fff8 40#define COMEDI32_CHANINFO _IOR(CIO, 3, comedi32_chaninfo)
bf8db92e 41#define COMEDI32_RANGEINFO _IOR(CIO, 8, (struct comedi32_rangeinfo_struct))
ed9eccbe
DS
42/* N.B. COMEDI32_CMD and COMEDI_CMD ought to use _IOWR, not _IOR.
43 * It's too late to change it now, but it only affects the command number. */
bf8db92e 44#define COMEDI32_CMD _IOR(CIO, 9, (struct comedi32_cmd_struct))
ed9eccbe
DS
45/* N.B. COMEDI32_CMDTEST and COMEDI_CMDTEST ought to use _IOWR, not _IOR.
46 * It's too late to change it now, but it only affects the command number. */
bf8db92e
BP
47#define COMEDI32_CMDTEST _IOR(CIO, 10, (struct comedi32_cmd_struct))
48#define COMEDI32_INSNLIST _IOR(CIO, 11, (struct comedi32_insnlist_struct))
49#define COMEDI32_INSN _IOR(CIO, 12, (struct comedi32_insn_struct))
ed9eccbe 50
bf8db92e 51struct comedi32_chaninfo_struct {
ed9eccbe 52 unsigned int subdev;
790c5541 53 compat_uptr_t maxdata_list; /* 32-bit 'unsigned int *' */
ed9eccbe
DS
54 compat_uptr_t flaglist; /* 32-bit 'unsigned int *' */
55 compat_uptr_t rangelist; /* 32-bit 'unsigned int *' */
56 unsigned int unused[4];
bf8db92e 57};
ed9eccbe 58
bf8db92e 59struct comedi32_rangeinfo_struct {
ed9eccbe
DS
60 unsigned int range_type;
61 compat_uptr_t range_ptr; /* 32-bit 'void *' */
bf8db92e 62};
ed9eccbe 63
bf8db92e 64struct comedi32_cmd_struct {
ed9eccbe
DS
65 unsigned int subdev;
66 unsigned int flags;
67 unsigned int start_src;
68 unsigned int start_arg;
69 unsigned int scan_begin_src;
70 unsigned int scan_begin_arg;
71 unsigned int convert_src;
72 unsigned int convert_arg;
73 unsigned int scan_end_src;
74 unsigned int scan_end_arg;
75 unsigned int stop_src;
76 unsigned int stop_arg;
77 compat_uptr_t chanlist; /* 32-bit 'unsigned int *' */
78 unsigned int chanlist_len;
790c5541 79 compat_uptr_t data; /* 32-bit 'short *' */
ed9eccbe 80 unsigned int data_len;
bf8db92e 81};
ed9eccbe 82
bf8db92e 83struct comedi32_insn_struct {
ed9eccbe
DS
84 unsigned int insn;
85 unsigned int n;
790c5541 86 compat_uptr_t data; /* 32-bit 'unsigned int *' */
ed9eccbe
DS
87 unsigned int subdev;
88 unsigned int chanspec;
89 unsigned int unused[3];
bf8db92e 90};
ed9eccbe 91
bf8db92e 92struct comedi32_insnlist_struct {
ed9eccbe
DS
93 unsigned int n_insns;
94 compat_uptr_t insns; /* 32-bit 'comedi_insn *' */
bf8db92e 95};
ed9eccbe
DS
96
97/* Handle translated ioctl. */
98static int translated_ioctl(struct file *file, unsigned int cmd,
99 unsigned long arg)
100{
82675f35 101 if (!file->f_op)
ed9eccbe 102 return -ENOTTY;
82675f35 103
ed9eccbe
DS
104#ifdef HAVE_UNLOCKED_IOCTL
105 if (file->f_op->unlocked_ioctl) {
106 int rc = (int)(*file->f_op->unlocked_ioctl)(file, cmd, arg);
82675f35 107 if (rc == -ENOIOCTLCMD)
ed9eccbe 108 rc = -ENOTTY;
ed9eccbe
DS
109 return rc;
110 }
111#endif
112 if (file->f_op->ioctl) {
113 int rc;
114 lock_kernel();
115 rc = (*file->f_op->ioctl)(file->f_dentry->d_inode,
116 file, cmd, arg);
117 unlock_kernel();
118 return rc;
119 }
120 return -ENOTTY;
121}
122
123/* Handle 32-bit COMEDI_CHANINFO ioctl. */
124static int compat_chaninfo(struct file *file, unsigned long arg)
125{
bf8db92e
BP
126 struct comedi_chaninfo_struct __user *chaninfo;
127 struct comedi32_chaninfo_struct __user *chaninfo32;
ed9eccbe
DS
128 int err;
129 union {
130 unsigned int uint;
131 compat_uptr_t uptr;
132 } temp;
133
134 chaninfo32 = compat_ptr(arg);
135 chaninfo = compat_alloc_user_space(sizeof(*chaninfo));
136
137 /* Copy chaninfo structure. Ignore unused members. */
138 if (!access_ok(VERIFY_READ, chaninfo32, sizeof(*chaninfo32))
139 || !access_ok(VERIFY_WRITE, chaninfo,
140 sizeof(*chaninfo))) {
141 return -EFAULT;
142 }
143 err = 0;
144 err |= __get_user(temp.uint, &chaninfo32->subdev);
145 err |= __put_user(temp.uint, &chaninfo->subdev);
146 err |= __get_user(temp.uptr, &chaninfo32->maxdata_list);
147 err |= __put_user(compat_ptr(temp.uptr), &chaninfo->maxdata_list);
148 err |= __get_user(temp.uptr, &chaninfo32->flaglist);
149 err |= __put_user(compat_ptr(temp.uptr), &chaninfo->flaglist);
150 err |= __get_user(temp.uptr, &chaninfo32->rangelist);
151 err |= __put_user(compat_ptr(temp.uptr), &chaninfo->rangelist);
82675f35 152 if (err)
ed9eccbe 153 return -EFAULT;
ed9eccbe
DS
154
155 return translated_ioctl(file, COMEDI_CHANINFO, (unsigned long)chaninfo);
156}
157
158/* Handle 32-bit COMEDI_RANGEINFO ioctl. */
159static int compat_rangeinfo(struct file *file, unsigned long arg)
160{
161 comedi_rangeinfo __user *rangeinfo;
bf8db92e 162 struct comedi32_rangeinfo_struct __user *rangeinfo32;
ed9eccbe
DS
163 int err;
164 union {
165 unsigned int uint;
166 compat_uptr_t uptr;
167 } temp;
168
169 rangeinfo32 = compat_ptr(arg);
170 rangeinfo = compat_alloc_user_space(sizeof(*rangeinfo));
171
172 /* Copy rangeinfo structure. */
173 if (!access_ok(VERIFY_READ, rangeinfo32, sizeof(*rangeinfo32))
174 || !access_ok(VERIFY_WRITE, rangeinfo,
175 sizeof(*rangeinfo))) {
176 return -EFAULT;
177 }
178 err = 0;
179 err |= __get_user(temp.uint, &rangeinfo32->range_type);
180 err |= __put_user(temp.uint, &rangeinfo->range_type);
181 err |= __get_user(temp.uptr, &rangeinfo32->range_ptr);
182 err |= __put_user(compat_ptr(temp.uptr), &rangeinfo->range_ptr);
82675f35 183 if (err)
ed9eccbe 184 return -EFAULT;
ed9eccbe
DS
185
186 return translated_ioctl(file, COMEDI_RANGEINFO,
187 (unsigned long)rangeinfo);
188}
189
190/* Copy 32-bit cmd structure to native cmd structure. */
191static int get_compat_cmd(comedi_cmd __user *cmd,
bf8db92e 192 struct comedi32_cmd_struct __user *cmd32)
ed9eccbe
DS
193{
194 int err;
195 union {
196 unsigned int uint;
197 compat_uptr_t uptr;
198 } temp;
199
200 /* Copy cmd structure. */
201 if (!access_ok(VERIFY_READ, cmd32, sizeof(*cmd32))
202 || !access_ok(VERIFY_WRITE, cmd, sizeof(*cmd))) {
203 return -EFAULT;
204 }
205 err = 0;
206 err |= __get_user(temp.uint, &cmd32->subdev);
207 err |= __put_user(temp.uint, &cmd->subdev);
208 err |= __get_user(temp.uint, &cmd32->flags);
209 err |= __put_user(temp.uint, &cmd->flags);
210 err |= __get_user(temp.uint, &cmd32->start_src);
211 err |= __put_user(temp.uint, &cmd->start_src);
212 err |= __get_user(temp.uint, &cmd32->start_arg);
213 err |= __put_user(temp.uint, &cmd->start_arg);
214 err |= __get_user(temp.uint, &cmd32->scan_begin_src);
215 err |= __put_user(temp.uint, &cmd->scan_begin_src);
216 err |= __get_user(temp.uint, &cmd32->scan_begin_arg);
217 err |= __put_user(temp.uint, &cmd->scan_begin_arg);
218 err |= __get_user(temp.uint, &cmd32->convert_src);
219 err |= __put_user(temp.uint, &cmd->convert_src);
220 err |= __get_user(temp.uint, &cmd32->convert_arg);
221 err |= __put_user(temp.uint, &cmd->convert_arg);
222 err |= __get_user(temp.uint, &cmd32->scan_end_src);
223 err |= __put_user(temp.uint, &cmd->scan_end_src);
224 err |= __get_user(temp.uint, &cmd32->scan_end_arg);
225 err |= __put_user(temp.uint, &cmd->scan_end_arg);
226 err |= __get_user(temp.uint, &cmd32->stop_src);
227 err |= __put_user(temp.uint, &cmd->stop_src);
228 err |= __get_user(temp.uint, &cmd32->stop_arg);
229 err |= __put_user(temp.uint, &cmd->stop_arg);
230 err |= __get_user(temp.uptr, &cmd32->chanlist);
231 err |= __put_user(compat_ptr(temp.uptr), &cmd->chanlist);
232 err |= __get_user(temp.uint, &cmd32->chanlist_len);
233 err |= __put_user(temp.uint, &cmd->chanlist_len);
234 err |= __get_user(temp.uptr, &cmd32->data);
235 err |= __put_user(compat_ptr(temp.uptr), &cmd->data);
236 err |= __get_user(temp.uint, &cmd32->data_len);
237 err |= __put_user(temp.uint, &cmd->data_len);
238 return err ? -EFAULT : 0;
239}
240
241/* Copy native cmd structure to 32-bit cmd structure. */
bf8db92e 242static int put_compat_cmd(struct comedi32_cmd_struct __user *cmd32, comedi_cmd __user *cmd)
ed9eccbe
DS
243{
244 int err;
245 unsigned int temp;
246
247 /* Copy back most of cmd structure. */
248 /* Assume the pointer values are already valid. */
249 /* (Could use ptr_to_compat() to set them, but that wasn't implemented
250 * until kernel version 2.6.11.) */
251 if (!access_ok(VERIFY_READ, cmd, sizeof(*cmd))
252 || !access_ok(VERIFY_WRITE, cmd32, sizeof(*cmd32))) {
253 return -EFAULT;
254 }
255 err = 0;
256 err |= __get_user(temp, &cmd->subdev);
257 err |= __put_user(temp, &cmd32->subdev);
258 err |= __get_user(temp, &cmd->flags);
259 err |= __put_user(temp, &cmd32->flags);
260 err |= __get_user(temp, &cmd->start_src);
261 err |= __put_user(temp, &cmd32->start_src);
262 err |= __get_user(temp, &cmd->start_arg);
263 err |= __put_user(temp, &cmd32->start_arg);
264 err |= __get_user(temp, &cmd->scan_begin_src);
265 err |= __put_user(temp, &cmd32->scan_begin_src);
266 err |= __get_user(temp, &cmd->scan_begin_arg);
267 err |= __put_user(temp, &cmd32->scan_begin_arg);
268 err |= __get_user(temp, &cmd->convert_src);
269 err |= __put_user(temp, &cmd32->convert_src);
270 err |= __get_user(temp, &cmd->convert_arg);
271 err |= __put_user(temp, &cmd32->convert_arg);
272 err |= __get_user(temp, &cmd->scan_end_src);
273 err |= __put_user(temp, &cmd32->scan_end_src);
274 err |= __get_user(temp, &cmd->scan_end_arg);
275 err |= __put_user(temp, &cmd32->scan_end_arg);
276 err |= __get_user(temp, &cmd->stop_src);
277 err |= __put_user(temp, &cmd32->stop_src);
278 err |= __get_user(temp, &cmd->stop_arg);
279 err |= __put_user(temp, &cmd32->stop_arg);
280 /* Assume chanlist pointer is unchanged. */
281 err |= __get_user(temp, &cmd->chanlist_len);
282 err |= __put_user(temp, &cmd32->chanlist_len);
283 /* Assume data pointer is unchanged. */
284 err |= __get_user(temp, &cmd->data_len);
285 err |= __put_user(temp, &cmd32->data_len);
286 return err ? -EFAULT : 0;
287}
288
289/* Handle 32-bit COMEDI_CMD ioctl. */
290static int compat_cmd(struct file *file, unsigned long arg)
291{
292 comedi_cmd __user *cmd;
bf8db92e 293 struct comedi32_cmd_struct __user *cmd32;
ed9eccbe
DS
294 int rc;
295
296 cmd32 = compat_ptr(arg);
297 cmd = compat_alloc_user_space(sizeof(*cmd));
298
299 rc = get_compat_cmd(cmd, cmd32);
82675f35 300 if (rc)
ed9eccbe 301 return rc;
ed9eccbe
DS
302
303 return translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd);
304}
305
306/* Handle 32-bit COMEDI_CMDTEST ioctl. */
307static int compat_cmdtest(struct file *file, unsigned long arg)
308{
309 comedi_cmd __user *cmd;
bf8db92e 310 struct comedi32_cmd_struct __user *cmd32;
ed9eccbe
DS
311 int rc, err;
312
313 cmd32 = compat_ptr(arg);
314 cmd = compat_alloc_user_space(sizeof(*cmd));
315
316 rc = get_compat_cmd(cmd, cmd32);
82675f35 317 if (rc)
ed9eccbe 318 return rc;
ed9eccbe
DS
319
320 rc = translated_ioctl(file, COMEDI_CMDTEST, (unsigned long)cmd);
82675f35 321 if (rc < 0)
ed9eccbe 322 return rc;
ed9eccbe
DS
323
324 err = put_compat_cmd(cmd32, cmd);
82675f35 325 if (err)
ed9eccbe 326 rc = err;
82675f35 327
ed9eccbe
DS
328 return rc;
329}
330
331/* Copy 32-bit insn structure to native insn structure. */
332static int get_compat_insn(comedi_insn __user *insn,
bf8db92e 333 struct comedi32_insn_struct __user *insn32)
ed9eccbe
DS
334{
335 int err;
336 union {
337 unsigned int uint;
338 compat_uptr_t uptr;
339 } temp;
340
341 /* Copy insn structure. Ignore the unused members. */
342 err = 0;
343 if (!access_ok(VERIFY_READ, insn32, sizeof(*insn32))
82675f35 344 || !access_ok(VERIFY_WRITE, insn, sizeof(*insn)))
ed9eccbe 345 return -EFAULT;
82675f35 346
ed9eccbe
DS
347 err |= __get_user(temp.uint, &insn32->insn);
348 err |= __put_user(temp.uint, &insn->insn);
349 err |= __get_user(temp.uint, &insn32->n);
350 err |= __put_user(temp.uint, &insn->n);
351 err |= __get_user(temp.uptr, &insn32->data);
352 err |= __put_user(compat_ptr(temp.uptr), &insn->data);
353 err |= __get_user(temp.uint, &insn32->subdev);
354 err |= __put_user(temp.uint, &insn->subdev);
355 err |= __get_user(temp.uint, &insn32->chanspec);
356 err |= __put_user(temp.uint, &insn->chanspec);
357 return err ? -EFAULT : 0;
358}
359
360/* Handle 32-bit COMEDI_INSNLIST ioctl. */
361static int compat_insnlist(struct file *file, unsigned long arg)
362{
363 struct combined_insnlist {
364 comedi_insnlist insnlist;
365 comedi_insn insn[1];
366 } __user *s;
bf8db92e
BP
367 struct comedi32_insnlist_struct __user *insnlist32;
368 struct comedi32_insn_struct __user *insn32;
ed9eccbe
DS
369 compat_uptr_t uptr;
370 unsigned int n_insns, n;
371 int err, rc;
372
373 insnlist32 = compat_ptr(arg);
374
375 /* Get 32-bit insnlist structure. */
376 if (!access_ok(VERIFY_READ, insnlist32, sizeof(*insnlist32))) {
377 return -EFAULT;
378 }
379 err = 0;
380 err |= __get_user(n_insns, &insnlist32->n_insns);
381 err |= __get_user(uptr, &insnlist32->insns);
382 insn32 = compat_ptr(uptr);
82675f35 383 if (err)
ed9eccbe 384 return -EFAULT;
ed9eccbe
DS
385
386 /* Allocate user memory to copy insnlist and insns into. */
387 s = compat_alloc_user_space(offsetof(struct combined_insnlist,
388 insn[n_insns]));
389
390 /* Set native insnlist structure. */
391 if (!access_ok(VERIFY_WRITE, &s->insnlist, sizeof(s->insnlist))) {
392 return -EFAULT;
393 }
394 err |= __put_user(n_insns, &s->insnlist.n_insns);
395 err |= __put_user(&s->insn[0], &s->insnlist.insns);
82675f35 396 if (err)
ed9eccbe 397 return -EFAULT;
ed9eccbe
DS
398
399 /* Copy insn structures. */
400 for (n = 0; n < n_insns; n++) {
401 rc = get_compat_insn(&s->insn[n], &insn32[n]);
82675f35 402 if (rc)
ed9eccbe 403 return rc;
ed9eccbe
DS
404 }
405
406 return translated_ioctl(file, COMEDI_INSNLIST,
407 (unsigned long)&s->insnlist);
408}
409
410/* Handle 32-bit COMEDI_INSN ioctl. */
411static int compat_insn(struct file *file, unsigned long arg)
412{
413 comedi_insn __user *insn;
bf8db92e 414 struct comedi32_insn_struct __user *insn32;
ed9eccbe
DS
415 int rc;
416
417 insn32 = compat_ptr(arg);
418 insn = compat_alloc_user_space(sizeof(*insn));
419
420 rc = get_compat_insn(insn, insn32);
82675f35 421 if (rc)
ed9eccbe 422 return rc;
ed9eccbe
DS
423
424 return translated_ioctl(file, COMEDI_INSN, (unsigned long)insn);
425}
426
427/* Process untranslated ioctl. */
428/* Returns -ENOIOCTLCMD for unrecognised ioctl codes. */
429static inline int raw_ioctl(struct file *file, unsigned int cmd,
430 unsigned long arg)
431{
432 int rc;
433
434 switch (cmd) {
435 case COMEDI_DEVCONFIG:
436 case COMEDI_DEVINFO:
437 case COMEDI_SUBDINFO:
438 case COMEDI_BUFCONFIG:
439 case COMEDI_BUFINFO:
440 /* Just need to translate the pointer argument. */
441 arg = (unsigned long)compat_ptr(arg);
442 rc = translated_ioctl(file, cmd, arg);
443 break;
444 case COMEDI_LOCK:
445 case COMEDI_UNLOCK:
446 case COMEDI_CANCEL:
447 case COMEDI_POLL:
448 /* No translation needed. */
449 rc = translated_ioctl(file, cmd, arg);
450 break;
451 case COMEDI32_CHANINFO:
452 rc = compat_chaninfo(file, arg);
453 break;
454 case COMEDI32_RANGEINFO:
455 rc = compat_rangeinfo(file, arg);
456 break;
457 case COMEDI32_CMD:
458 rc = compat_cmd(file, arg);
459 break;
460 case COMEDI32_CMDTEST:
461 rc = compat_cmdtest(file, arg);
462 break;
463 case COMEDI32_INSNLIST:
464 rc = compat_insnlist(file, arg);
465 break;
466 case COMEDI32_INSN:
467 rc = compat_insn(file, arg);
468 break;
469 default:
470 rc = -ENOIOCTLCMD;
471 break;
472 }
473 return rc;
474}
475
476#ifdef HAVE_COMPAT_IOCTL /* defined in <linux/fs.h> 2.6.11 onwards */
477
478/* compat_ioctl file operation. */
479/* Returns -ENOIOCTLCMD for unrecognised ioctl codes. */
480long comedi_compat_ioctl(struct file *file, unsigned int cmd,
481 unsigned long arg)
482{
483 return raw_ioctl(file, cmd, arg);
484}
485
486#else /* HAVE_COMPAT_IOCTL */
487
488/*
489 * Brain-dead ioctl compatibility for 2.6.10 and earlier.
490 *
491 * It's brain-dead because cmd numbers need to be unique system-wide!
492 * The comedi driver could end up attempting to execute ioctls for non-Comedi
493 * devices because it registered the system-wide cmd code first. Similarly,
494 * another driver could end up attempting to execute ioctls for a Comedi
495 * device because it registered the cmd code first. Chaos ensues.
496 */
497
498/* Handler for all 32-bit ioctl codes registered by this driver. */
499static int mapped_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg,
500 struct file *file)
501{
502 int rc;
503
504 /* Make sure we are dealing with a Comedi device. */
82675f35 505 if (imajor(file->f_dentry->d_inode) != COMEDI_MAJOR)
ed9eccbe 506 return -ENOTTY;
82675f35 507
ed9eccbe
DS
508 rc = raw_ioctl(file, cmd, arg);
509 /* Do not return -ENOIOCTLCMD. */
82675f35 510 if (rc == -ENOIOCTLCMD)
ed9eccbe 511 rc = -ENOTTY;
82675f35 512
ed9eccbe
DS
513 return rc;
514}
515
516struct ioctl32_map {
517 unsigned int cmd;
518 int (*handler)(unsigned int, unsigned int, unsigned long,
519 struct file *);
520 int registered;
521};
522
523static struct ioctl32_map comedi_ioctl32_map[] = {
524 { COMEDI_DEVCONFIG, mapped_ioctl, 0 },
525 { COMEDI_DEVINFO, mapped_ioctl, 0 },
526 { COMEDI_SUBDINFO, mapped_ioctl, 0 },
527 { COMEDI_BUFCONFIG, mapped_ioctl, 0 },
528 { COMEDI_BUFINFO, mapped_ioctl, 0 },
529 { COMEDI_LOCK, mapped_ioctl, 0 },
530 { COMEDI_UNLOCK, mapped_ioctl, 0 },
531 { COMEDI_CANCEL, mapped_ioctl, 0 },
532 { COMEDI_POLL, mapped_ioctl, 0 },
533 { COMEDI32_CHANINFO, mapped_ioctl, 0 },
534 { COMEDI32_RANGEINFO, mapped_ioctl, 0 },
535 { COMEDI32_CMD, mapped_ioctl, 0 },
536 { COMEDI32_CMDTEST, mapped_ioctl, 0 },
537 { COMEDI32_INSNLIST, mapped_ioctl, 0 },
538 { COMEDI32_INSN, mapped_ioctl, 0 },
539};
540
541#define NUM_IOCTL32_MAPS ARRAY_SIZE(comedi_ioctl32_map)
542
543/* Register system-wide 32-bit ioctl handlers. */
544void comedi_register_ioctl32(void)
545{
546 int n, rc;
547
548 for (n = 0; n < NUM_IOCTL32_MAPS; n++) {
549 rc = register_ioctl32_conversion(comedi_ioctl32_map[n].cmd,
550 comedi_ioctl32_map[n].handler);
551 if (rc) {
552 printk(KERN_WARNING
553 "comedi: failed to register 32-bit "
554 "compatible ioctl handler for 0x%X - "
555 "expect bad things to happen!\n",
556 comedi_ioctl32_map[n].cmd);
557 }
558 comedi_ioctl32_map[n].registered = !rc;
559 }
560}
561
562/* Unregister system-wide 32-bit ioctl translations. */
563void comedi_unregister_ioctl32(void)
564{
565 int n, rc;
566
567 for (n = 0; n < NUM_IOCTL32_MAPS; n++) {
568 if (comedi_ioctl32_map[n].registered) {
569 rc = unregister_ioctl32_conversion(
570 comedi_ioctl32_map[n].cmd,
571 comedi_ioctl32_map[n].handler);
572 if (rc) {
573 printk(KERN_ERR
574 "comedi: failed to unregister 32-bit "
575 "compatible ioctl handler for 0x%X - "
576 "expect kernel Oops!\n",
577 comedi_ioctl32_map[n].cmd);
578 } else {
579 comedi_ioctl32_map[n].registered = 0;
580 }
581 }
582 }
583}
584
585#endif /* HAVE_COMPAT_IOCTL */
586
587#endif /* CONFIG_COMPAT */