Merge branch 'topic/hda' into for-linus
[linux-2.6] / drivers / staging / comedi / comedi_compat32.c
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
40 #define COMEDI32_CHANINFO _IOR(CIO, 3, struct comedi32_chaninfo_struct)
41 #define COMEDI32_RANGEINFO _IOR(CIO, 8, struct comedi32_rangeinfo_struct)
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. */
44 #define COMEDI32_CMD _IOR(CIO, 9, struct comedi32_cmd_struct)
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. */
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)
50
51 struct comedi32_chaninfo_struct {
52         unsigned int subdev;
53         compat_uptr_t maxdata_list;     /* 32-bit 'unsigned int *' */
54         compat_uptr_t flaglist;         /* 32-bit 'unsigned int *' */
55         compat_uptr_t rangelist;        /* 32-bit 'unsigned int *' */
56         unsigned int unused[4];
57 };
58
59 struct comedi32_rangeinfo_struct {
60         unsigned int range_type;
61         compat_uptr_t range_ptr;        /* 32-bit 'void *' */
62 };
63
64 struct comedi32_cmd_struct {
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;
79         compat_uptr_t data;             /* 32-bit 'short *' */
80         unsigned int data_len;
81 };
82
83 struct comedi32_insn_struct {
84         unsigned int insn;
85         unsigned int n;
86         compat_uptr_t data;             /* 32-bit 'unsigned int *' */
87         unsigned int subdev;
88         unsigned int chanspec;
89         unsigned int unused[3];
90 };
91
92 struct comedi32_insnlist_struct {
93         unsigned int n_insns;
94         compat_uptr_t insns;            /* 32-bit 'struct comedi_insn *' */
95 };
96
97 /* Handle translated ioctl. */
98 static int translated_ioctl(struct file *file, unsigned int cmd,
99                 unsigned long arg)
100 {
101         if (!file->f_op)
102                 return -ENOTTY;
103
104 #ifdef HAVE_UNLOCKED_IOCTL
105         if (file->f_op->unlocked_ioctl) {
106                 int rc = (int)(*file->f_op->unlocked_ioctl)(file, cmd, arg);
107                 if (rc == -ENOIOCTLCMD)
108                         rc = -ENOTTY;
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. */
124 static int compat_chaninfo(struct file *file, unsigned long arg)
125 {
126         struct comedi_chaninfo __user *chaninfo;
127         struct comedi32_chaninfo_struct __user *chaninfo32;
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);
152         if (err)
153                 return -EFAULT;
154
155         return translated_ioctl(file, COMEDI_CHANINFO, (unsigned long)chaninfo);
156 }
157
158 /* Handle 32-bit COMEDI_RANGEINFO ioctl. */
159 static int compat_rangeinfo(struct file *file, unsigned long arg)
160 {
161         struct comedi_rangeinfo __user *rangeinfo;
162         struct comedi32_rangeinfo_struct __user *rangeinfo32;
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);
183         if (err)
184                 return -EFAULT;
185
186         return translated_ioctl(file, COMEDI_RANGEINFO,
187                         (unsigned long)rangeinfo);
188 }
189
190 /* Copy 32-bit cmd structure to native cmd structure. */
191 static int get_compat_cmd(struct comedi_cmd __user *cmd,
192                 struct comedi32_cmd_struct __user *cmd32)
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. */
242 static int put_compat_cmd(struct comedi32_cmd_struct __user *cmd32, struct comedi_cmd __user *cmd)
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. */
290 static int compat_cmd(struct file *file, unsigned long arg)
291 {
292         struct comedi_cmd __user *cmd;
293         struct comedi32_cmd_struct __user *cmd32;
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);
300         if (rc)
301                 return rc;
302
303         return translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd);
304 }
305
306 /* Handle 32-bit COMEDI_CMDTEST ioctl. */
307 static int compat_cmdtest(struct file *file, unsigned long arg)
308 {
309         struct comedi_cmd __user *cmd;
310         struct comedi32_cmd_struct __user *cmd32;
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);
317         if (rc)
318                 return rc;
319
320         rc = translated_ioctl(file, COMEDI_CMDTEST, (unsigned long)cmd);
321         if (rc < 0)
322                 return rc;
323
324         err = put_compat_cmd(cmd32, cmd);
325         if (err)
326                 rc = err;
327
328         return rc;
329 }
330
331 /* Copy 32-bit insn structure to native insn structure. */
332 static int get_compat_insn(struct comedi_insn __user *insn,
333                 struct comedi32_insn_struct __user *insn32)
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))
344                         || !access_ok(VERIFY_WRITE, insn, sizeof(*insn)))
345                 return -EFAULT;
346
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. */
361 static int compat_insnlist(struct file *file, unsigned long arg)
362 {
363         struct combined_insnlist {
364                 struct comedi_insnlist insnlist;
365                 struct comedi_insn insn[1];
366         } __user *s;
367         struct comedi32_insnlist_struct __user *insnlist32;
368         struct comedi32_insn_struct __user *insn32;
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);
383         if (err)
384                 return -EFAULT;
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);
396         if (err)
397                 return -EFAULT;
398
399         /* Copy insn structures. */
400         for (n = 0; n < n_insns; n++) {
401                 rc = get_compat_insn(&s->insn[n], &insn32[n]);
402                 if (rc)
403                         return rc;
404         }
405
406         return translated_ioctl(file, COMEDI_INSNLIST,
407                         (unsigned long)&s->insnlist);
408 }
409
410 /* Handle 32-bit COMEDI_INSN ioctl. */
411 static int compat_insn(struct file *file, unsigned long arg)
412 {
413         struct comedi_insn __user *insn;
414         struct comedi32_insn_struct __user *insn32;
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);
421         if (rc)
422                 return rc;
423
424         return translated_ioctl(file, COMEDI_INSN, (unsigned long)insn);
425 }
426
427 /* Process untranslated ioctl. */
428 /* Returns -ENOIOCTLCMD for unrecognised ioctl codes. */
429 static 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. */
480 long 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. */
499 static 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. */
505         if (imajor(file->f_dentry->d_inode) != COMEDI_MAJOR)
506                 return -ENOTTY;
507
508         rc = raw_ioctl(file, cmd, arg);
509         /* Do not return -ENOIOCTLCMD. */
510         if (rc == -ENOIOCTLCMD)
511                 rc = -ENOTTY;
512
513         return rc;
514 }
515
516 struct ioctl32_map {
517         unsigned int cmd;
518         int (*handler)(unsigned int, unsigned int, unsigned long,
519                         struct file *);
520         int registered;
521 };
522
523 static 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. */
544 void 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. */
563 void 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 */