blob: 4e23d3841b43df3a2ddd914181f6ccb581715c78 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* -*- linux-c -*- */
2
3/*
4 * Driver for USB Rio 500
5 *
6 * Cesar Miquel (miquel@df.uba.ar)
7 *
8 * based on hp_scanner.c by David E. Nelson (dnelson@jump.net)
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of the
13 * License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 * Based upon mouse.c (Brad Keryan) and printer.c (Michael Gee).
25 *
26 * Changelog:
27 * 30/05/2003 replaced lock/unlock kernel with up/down
28 * Daniele Bellucci bellucda@tiscali.it
29 * */
30
31#include <linux/module.h>
32#include <linux/kernel.h>
33#include <linux/signal.h>
34#include <linux/sched.h>
Arnd Bergmann925ce682010-07-11 23:18:56 +020035#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <linux/errno.h>
37#include <linux/random.h>
38#include <linux/poll.h>
39#include <linux/init.h>
40#include <linux/slab.h>
41#include <linux/spinlock.h>
42#include <linux/usb.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/wait.h>
44
45#include "rio500_usb.h"
46
47/*
48 * Version Information
49 */
50#define DRIVER_VERSION "v1.1"
51#define DRIVER_AUTHOR "Cesar Miquel <miquel@df.uba.ar>"
52#define DRIVER_DESC "USB Rio 500 driver"
53
54#define RIO_MINOR 64
55
56/* stall/wait timeout for rio */
57#define NAK_TIMEOUT (HZ)
58
59#define IBUF_SIZE 0x1000
60
61/* Size of the rio buffer */
62#define OBUF_SIZE 0x10000
63
64struct rio_usb_data {
65 struct usb_device *rio_dev; /* init: probe_rio */
66 unsigned int ifnum; /* Interface number of the USB device */
67 int isopen; /* nz if open */
68 int present; /* Device is present on the bus */
69 char *obuf, *ibuf; /* transfer buffers */
70 char bulk_in_ep, bulk_out_ep; /* Endpoint assignments */
71 wait_queue_head_t wait_q; /* for timeouts */
Oliver Neukum2cba72f2006-12-15 23:48:56 +010072 struct mutex lock; /* general race avoidance */
Linus Torvalds1da177e2005-04-16 15:20:36 -070073};
74
Arnd Bergmann925ce682010-07-11 23:18:56 +020075static DEFINE_MUTEX(rio500_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070076static struct rio_usb_data rio_instance;
77
78static int open_rio(struct inode *inode, struct file *file)
79{
80 struct rio_usb_data *rio = &rio_instance;
Oliver Neukum511e2d02010-01-14 16:10:38 +010081
82 /* against disconnect() */
Arnd Bergmann925ce682010-07-11 23:18:56 +020083 mutex_lock(&rio500_mutex);
Oliver Neukum2cba72f2006-12-15 23:48:56 +010084 mutex_lock(&(rio->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -070085
86 if (rio->isopen || !rio->present) {
Oliver Neukum2cba72f2006-12-15 23:48:56 +010087 mutex_unlock(&(rio->lock));
Arnd Bergmann925ce682010-07-11 23:18:56 +020088 mutex_unlock(&rio500_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070089 return -EBUSY;
90 }
91 rio->isopen = 1;
92
93 init_waitqueue_head(&rio->wait_q);
94
Oliver Neukum2cba72f2006-12-15 23:48:56 +010095 mutex_unlock(&(rio->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
Greg Kroah-Hartman1b29a372008-08-18 13:21:04 -070097 dev_info(&rio->rio_dev->dev, "Rio opened.\n");
Arnd Bergmann925ce682010-07-11 23:18:56 +020098 mutex_unlock(&rio500_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
100 return 0;
101}
102
103static int close_rio(struct inode *inode, struct file *file)
104{
105 struct rio_usb_data *rio = &rio_instance;
106
107 rio->isopen = 0;
108
Greg Kroah-Hartman1b29a372008-08-18 13:21:04 -0700109 dev_info(&rio->rio_dev->dev, "Rio closed.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 return 0;
111}
112
Alan Cox54592152008-05-22 22:47:31 +0100113static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114{
115 struct RioCommand rio_cmd;
116 struct rio_usb_data *rio = &rio_instance;
117 void __user *data;
118 unsigned char *buffer;
119 int result, requesttype;
120 int retries;
121 int retval=0;
122
Oliver Neukum2cba72f2006-12-15 23:48:56 +0100123 mutex_lock(&(rio->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 /* Sanity check to make sure rio is connected, powered, etc */
Adrian Bunk3328d972007-10-18 12:53:07 +0200125 if (rio->present == 0 || rio->rio_dev == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 retval = -ENODEV;
127 goto err_out;
128 }
129
130 switch (cmd) {
131 case RIO_RECV_COMMAND:
132 data = (void __user *) arg;
133 if (data == NULL)
134 break;
135 if (copy_from_user(&rio_cmd, data, sizeof(struct RioCommand))) {
136 retval = -EFAULT;
137 goto err_out;
138 }
139 if (rio_cmd.length < 0 || rio_cmd.length > PAGE_SIZE) {
140 retval = -EINVAL;
141 goto err_out;
142 }
143 buffer = (unsigned char *) __get_free_page(GFP_KERNEL);
144 if (buffer == NULL) {
145 retval = -ENOMEM;
146 goto err_out;
147 }
148 if (copy_from_user(buffer, rio_cmd.buffer, rio_cmd.length)) {
149 retval = -EFAULT;
150 free_page((unsigned long) buffer);
151 goto err_out;
152 }
153
154 requesttype = rio_cmd.requesttype | USB_DIR_IN |
155 USB_TYPE_VENDOR | USB_RECIP_DEVICE;
156 dbg
157 ("sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x",
158 requesttype, rio_cmd.request, rio_cmd.value,
159 rio_cmd.index, rio_cmd.length);
160 /* Send rio control message */
161 retries = 3;
162 while (retries) {
163 result = usb_control_msg(rio->rio_dev,
164 usb_rcvctrlpipe(rio-> rio_dev, 0),
165 rio_cmd.request,
166 requesttype,
167 rio_cmd.value,
168 rio_cmd.index, buffer,
169 rio_cmd.length,
170 jiffies_to_msecs(rio_cmd.timeout));
171 if (result == -ETIMEDOUT)
172 retries--;
173 else if (result < 0) {
174 err("Error executing ioctrl. code = %d", result);
175 retries = 0;
176 } else {
177 dbg("Executed ioctl. Result = %d (data=%02x)",
178 result, buffer[0]);
179 if (copy_to_user(rio_cmd.buffer, buffer,
180 rio_cmd.length)) {
181 free_page((unsigned long) buffer);
182 retval = -EFAULT;
183 goto err_out;
184 }
185 retries = 0;
186 }
187
188 /* rio_cmd.buffer contains a raw stream of single byte
189 data which has been returned from rio. Data is
190 interpreted at application level. For data that
191 will be cast to data types longer than 1 byte, data
192 will be little_endian and will potentially need to
193 be swapped at the app level */
194
195 }
196 free_page((unsigned long) buffer);
197 break;
198
199 case RIO_SEND_COMMAND:
200 data = (void __user *) arg;
201 if (data == NULL)
202 break;
203 if (copy_from_user(&rio_cmd, data, sizeof(struct RioCommand))) {
204 retval = -EFAULT;
205 goto err_out;
206 }
207 if (rio_cmd.length < 0 || rio_cmd.length > PAGE_SIZE) {
208 retval = -EINVAL;
209 goto err_out;
210 }
211 buffer = (unsigned char *) __get_free_page(GFP_KERNEL);
212 if (buffer == NULL) {
213 retval = -ENOMEM;
214 goto err_out;
215 }
216 if (copy_from_user(buffer, rio_cmd.buffer, rio_cmd.length)) {
217 free_page((unsigned long)buffer);
218 retval = -EFAULT;
219 goto err_out;
220 }
221
222 requesttype = rio_cmd.requesttype | USB_DIR_OUT |
223 USB_TYPE_VENDOR | USB_RECIP_DEVICE;
224 dbg("sending command: reqtype=%0x req=%0x value=%0x index=%0x len=%0x",
225 requesttype, rio_cmd.request, rio_cmd.value,
226 rio_cmd.index, rio_cmd.length);
227 /* Send rio control message */
228 retries = 3;
229 while (retries) {
230 result = usb_control_msg(rio->rio_dev,
231 usb_sndctrlpipe(rio-> rio_dev, 0),
232 rio_cmd.request,
233 requesttype,
234 rio_cmd.value,
235 rio_cmd.index, buffer,
236 rio_cmd.length,
237 jiffies_to_msecs(rio_cmd.timeout));
238 if (result == -ETIMEDOUT)
239 retries--;
240 else if (result < 0) {
241 err("Error executing ioctrl. code = %d", result);
242 retries = 0;
243 } else {
244 dbg("Executed ioctl. Result = %d", result);
245 retries = 0;
246
247 }
248
249 }
250 free_page((unsigned long) buffer);
251 break;
252
253 default:
254 retval = -ENOTTY;
255 break;
256 }
257
258
259err_out:
Oliver Neukum2cba72f2006-12-15 23:48:56 +0100260 mutex_unlock(&(rio->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 return retval;
262}
263
264static ssize_t
265write_rio(struct file *file, const char __user *buffer,
266 size_t count, loff_t * ppos)
267{
268 DEFINE_WAIT(wait);
269 struct rio_usb_data *rio = &rio_instance;
270
271 unsigned long copy_size;
272 unsigned long bytes_written = 0;
273 unsigned int partial;
274
275 int result = 0;
276 int maxretry;
277 int errn = 0;
Oliver Neukum2cba72f2006-12-15 23:48:56 +0100278 int intr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
Oliver Neukum2cba72f2006-12-15 23:48:56 +0100280 intr = mutex_lock_interruptible(&(rio->lock));
281 if (intr)
282 return -EINTR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 /* Sanity check to make sure rio is connected, powered, etc */
Adrian Bunk3328d972007-10-18 12:53:07 +0200284 if (rio->present == 0 || rio->rio_dev == NULL) {
Oliver Neukum2cba72f2006-12-15 23:48:56 +0100285 mutex_unlock(&(rio->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 return -ENODEV;
287 }
288
289
290
291 do {
292 unsigned long thistime;
293 char *obuf = rio->obuf;
294
295 thistime = copy_size =
296 (count >= OBUF_SIZE) ? OBUF_SIZE : count;
297 if (copy_from_user(rio->obuf, buffer, copy_size)) {
298 errn = -EFAULT;
299 goto error;
300 }
301 maxretry = 5;
302 while (thistime) {
303 if (!rio->rio_dev) {
304 errn = -ENODEV;
305 goto error;
306 }
307 if (signal_pending(current)) {
Oliver Neukum2cba72f2006-12-15 23:48:56 +0100308 mutex_unlock(&(rio->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 return bytes_written ? bytes_written : -EINTR;
310 }
311
312 result = usb_bulk_msg(rio->rio_dev,
313 usb_sndbulkpipe(rio->rio_dev, 2),
314 obuf, thistime, &partial, 5000);
315
316 dbg("write stats: result:%d thistime:%lu partial:%u",
317 result, thistime, partial);
318
319 if (result == -ETIMEDOUT) { /* NAK - so hold for a while */
320 if (!maxretry--) {
321 errn = -ETIME;
322 goto error;
323 }
324 prepare_to_wait(&rio->wait_q, &wait, TASK_INTERRUPTIBLE);
325 schedule_timeout(NAK_TIMEOUT);
326 finish_wait(&rio->wait_q, &wait);
327 continue;
328 } else if (!result && partial) {
329 obuf += partial;
330 thistime -= partial;
331 } else
332 break;
333 };
334 if (result) {
335 err("Write Whoops - %x", result);
336 errn = -EIO;
337 goto error;
338 }
339 bytes_written += copy_size;
340 count -= copy_size;
341 buffer += copy_size;
342 } while (count > 0);
343
Oliver Neukum2cba72f2006-12-15 23:48:56 +0100344 mutex_unlock(&(rio->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345
346 return bytes_written ? bytes_written : -EIO;
347
348error:
Oliver Neukum2cba72f2006-12-15 23:48:56 +0100349 mutex_unlock(&(rio->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 return errn;
351}
352
353static ssize_t
354read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
355{
356 DEFINE_WAIT(wait);
357 struct rio_usb_data *rio = &rio_instance;
358 ssize_t read_count;
359 unsigned int partial;
360 int this_read;
361 int result;
362 int maxretry = 10;
363 char *ibuf;
Oliver Neukum2cba72f2006-12-15 23:48:56 +0100364 int intr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365
Oliver Neukum2cba72f2006-12-15 23:48:56 +0100366 intr = mutex_lock_interruptible(&(rio->lock));
367 if (intr)
368 return -EINTR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 /* Sanity check to make sure rio is connected, powered, etc */
Adrian Bunk3328d972007-10-18 12:53:07 +0200370 if (rio->present == 0 || rio->rio_dev == NULL) {
Oliver Neukum2cba72f2006-12-15 23:48:56 +0100371 mutex_unlock(&(rio->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 return -ENODEV;
373 }
374
375 ibuf = rio->ibuf;
376
377 read_count = 0;
378
379
380 while (count > 0) {
381 if (signal_pending(current)) {
Oliver Neukum2cba72f2006-12-15 23:48:56 +0100382 mutex_unlock(&(rio->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 return read_count ? read_count : -EINTR;
384 }
385 if (!rio->rio_dev) {
Oliver Neukum2cba72f2006-12-15 23:48:56 +0100386 mutex_unlock(&(rio->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 return -ENODEV;
388 }
389 this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count;
390
391 result = usb_bulk_msg(rio->rio_dev,
392 usb_rcvbulkpipe(rio->rio_dev, 1),
393 ibuf, this_read, &partial,
394 8000);
395
Greg Kroah-Hartman654f3112005-11-17 09:48:09 -0800396 dbg("read stats: result:%d this_read:%u partial:%u",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 result, this_read, partial);
398
399 if (partial) {
400 count = this_read = partial;
401 } else if (result == -ETIMEDOUT || result == 15) { /* FIXME: 15 ??? */
402 if (!maxretry--) {
Oliver Neukum2cba72f2006-12-15 23:48:56 +0100403 mutex_unlock(&(rio->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404 err("read_rio: maxretry timeout");
405 return -ETIME;
406 }
407 prepare_to_wait(&rio->wait_q, &wait, TASK_INTERRUPTIBLE);
408 schedule_timeout(NAK_TIMEOUT);
409 finish_wait(&rio->wait_q, &wait);
410 continue;
411 } else if (result != -EREMOTEIO) {
Oliver Neukum2cba72f2006-12-15 23:48:56 +0100412 mutex_unlock(&(rio->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 err("Read Whoops - result:%u partial:%u this_read:%u",
414 result, partial, this_read);
415 return -EIO;
416 } else {
Oliver Neukum2cba72f2006-12-15 23:48:56 +0100417 mutex_unlock(&(rio->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 return (0);
419 }
420
421 if (this_read) {
422 if (copy_to_user(buffer, ibuf, this_read)) {
Oliver Neukum2cba72f2006-12-15 23:48:56 +0100423 mutex_unlock(&(rio->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 return -EFAULT;
425 }
426 count -= this_read;
427 read_count += this_read;
428 buffer += this_read;
429 }
430 }
Oliver Neukum2cba72f2006-12-15 23:48:56 +0100431 mutex_unlock(&(rio->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 return read_count;
433}
434
Alexey Dobriyan828c0952009-10-01 15:43:56 -0700435static const struct file_operations usb_rio_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 .owner = THIS_MODULE,
437 .read = read_rio,
438 .write = write_rio,
Alan Cox54592152008-05-22 22:47:31 +0100439 .unlocked_ioctl = ioctl_rio,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 .open = open_rio,
441 .release = close_rio,
Arnd Bergmann6038f372010-08-15 18:52:59 +0200442 .llseek = noop_llseek,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443};
444
445static struct usb_class_driver usb_rio_class = {
Greg Kroah-Hartmand6e5bcf2005-06-20 21:15:16 -0700446 .name = "rio500%d",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 .fops = &usb_rio_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 .minor_base = RIO_MINOR,
449};
450
451static int probe_rio(struct usb_interface *intf,
452 const struct usb_device_id *id)
453{
454 struct usb_device *dev = interface_to_usbdev(intf);
455 struct rio_usb_data *rio = &rio_instance;
456 int retval;
457
Greg Kroah-Hartman1b29a372008-08-18 13:21:04 -0700458 dev_info(&intf->dev, "USB Rio found at address %d\n", dev->devnum);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459
460 retval = usb_register_dev(intf, &usb_rio_class);
461 if (retval) {
462 err("Not able to get a minor for this device.");
463 return -ENOMEM;
464 }
465
466 rio->rio_dev = dev;
467
Jesper Juhl0e8eb0f2005-12-11 20:34:02 +0100468 if (!(rio->obuf = kmalloc(OBUF_SIZE, GFP_KERNEL))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 err("probe_rio: Not enough memory for the output buffer");
470 usb_deregister_dev(intf, &usb_rio_class);
471 return -ENOMEM;
472 }
473 dbg("probe_rio: obuf address:%p", rio->obuf);
474
Jesper Juhl0e8eb0f2005-12-11 20:34:02 +0100475 if (!(rio->ibuf = kmalloc(IBUF_SIZE, GFP_KERNEL))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 err("probe_rio: Not enough memory for the input buffer");
477 usb_deregister_dev(intf, &usb_rio_class);
478 kfree(rio->obuf);
479 return -ENOMEM;
480 }
481 dbg("probe_rio: ibuf address:%p", rio->ibuf);
482
Oliver Neukum2cba72f2006-12-15 23:48:56 +0100483 mutex_init(&(rio->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484
485 usb_set_intfdata (intf, rio);
486 rio->present = 1;
487
488 return 0;
489}
490
491static void disconnect_rio(struct usb_interface *intf)
492{
493 struct rio_usb_data *rio = usb_get_intfdata (intf);
494
495 usb_set_intfdata (intf, NULL);
Arnd Bergmann925ce682010-07-11 23:18:56 +0200496 mutex_lock(&rio500_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 if (rio) {
498 usb_deregister_dev(intf, &usb_rio_class);
499
Oliver Neukum2cba72f2006-12-15 23:48:56 +0100500 mutex_lock(&(rio->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 if (rio->isopen) {
502 rio->isopen = 0;
503 /* better let it finish - the release will do whats needed */
504 rio->rio_dev = NULL;
Oliver Neukum2cba72f2006-12-15 23:48:56 +0100505 mutex_unlock(&(rio->lock));
Arnd Bergmann925ce682010-07-11 23:18:56 +0200506 mutex_unlock(&rio500_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 return;
508 }
509 kfree(rio->ibuf);
510 kfree(rio->obuf);
511
Greg Kroah-Hartman1b29a372008-08-18 13:21:04 -0700512 dev_info(&intf->dev, "USB Rio disconnected.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513
514 rio->present = 0;
Oliver Neukum2cba72f2006-12-15 23:48:56 +0100515 mutex_unlock(&(rio->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 }
Arnd Bergmann925ce682010-07-11 23:18:56 +0200517 mutex_unlock(&rio500_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518}
519
Németh Márton33b9e162010-01-10 15:34:45 +0100520static const struct usb_device_id rio_table[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 { USB_DEVICE(0x0841, 1) }, /* Rio 500 */
522 { } /* Terminating entry */
523};
524
525MODULE_DEVICE_TABLE (usb, rio_table);
526
527static struct usb_driver rio_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 .name = "rio500",
529 .probe = probe_rio,
530 .disconnect = disconnect_rio,
531 .id_table = rio_table,
532};
533
534static int __init usb_rio_init(void)
535{
536 int retval;
537 retval = usb_register(&rio_driver);
538 if (retval)
539 goto out;
540
Greg Kroah-Hartman1b29a372008-08-18 13:21:04 -0700541 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
542 DRIVER_DESC "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543
544out:
545 return retval;
546}
547
548
549static void __exit usb_rio_cleanup(void)
550{
551 struct rio_usb_data *rio = &rio_instance;
552
553 rio->present = 0;
554 usb_deregister(&rio_driver);
555
556
557}
558
559module_init(usb_rio_init);
560module_exit(usb_rio_cleanup);
561
562MODULE_AUTHOR( DRIVER_AUTHOR );
563MODULE_DESCRIPTION( DRIVER_DESC );
564MODULE_LICENSE("GPL");
565