- pre5:
[davej-history.git] / drivers / usb / dabusb.c
bloba9982288bbca67c73c03df6488d938d789e0d129
1 /*****************************************************************************/
3 /*
4 * dabusb.c -- dab usb driver.
6 * Copyright (C) 1999 Deti Fliegl (deti@fliegl.de)
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 * $Id: dabusb.c,v 1.54 2000/07/24 21:39:39 deti Exp $
28 /*****************************************************************************/
30 #include <linux/module.h>
31 #include <linux/socket.h>
32 #include <linux/miscdevice.h>
33 #include <linux/list.h>
34 #include <linux/vmalloc.h>
35 #include <linux/slab.h>
36 #include <linux/init.h>
37 #include <asm/uaccess.h>
38 #include <asm/atomic.h>
39 #include <linux/delay.h>
40 #include <linux/usb.h>
41 #include <linux/smp_lock.h>
43 #include "dabusb.h"
44 #include "dabfirmware.h"
46 /* --------------------------------------------------------------------- */
48 #define NRDABUSB 4
50 /*-------------------------------------------------------------------*/
52 static dabusb_t dabusb[NRDABUSB];
53 static int buffers = 256;
55 /*-------------------------------------------------------------------*/
57 static int dabusb_add_buf_tail (pdabusb_t s, struct list_head *dst, struct list_head *src)
59 unsigned long flags;
60 struct list_head *tmp;
61 int ret = 0;
63 spin_lock_irqsave (&s->lock, flags);
65 if (list_empty (src)) {
66 // no elements in source buffer
67 ret = -1;
68 goto err;
70 tmp = src->next;
71 list_del (tmp);
72 list_add_tail (tmp, dst);
74 err: spin_unlock_irqrestore (&s->lock, flags);
75 return ret;
77 /*-------------------------------------------------------------------*/
78 #ifdef DEBUG
79 static void dump_urb (purb_t purb)
81 dbg("urb :%p", purb);
82 dbg("next :%p", purb->next);
83 dbg("dev :%p", purb->dev);
84 dbg("pipe :%08X", purb->pipe);
85 dbg("status :%d", purb->status);
86 dbg("transfer_flags :%08X", purb->transfer_flags);
87 dbg("transfer_buffer :%p", purb->transfer_buffer);
88 dbg("transfer_buffer_length:%d", purb->transfer_buffer_length);
89 dbg("actual_length :%d", purb->actual_length);
90 dbg("setup_packet :%p", purb->setup_packet);
91 dbg("start_frame :%d", purb->start_frame);
92 dbg("number_of_packets :%d", purb->number_of_packets);
93 dbg("interval :%d", purb->interval);
94 dbg("error_count :%d", purb->error_count);
95 dbg("context :%p", purb->context);
96 dbg("complete :%p", purb->complete);
98 #endif
99 /*-------------------------------------------------------------------*/
100 static int dabusb_cancel_queue (pdabusb_t s, struct list_head *q)
102 unsigned long flags;
103 struct list_head *p;
104 pbuff_t b;
106 dbg("dabusb_cancel_queue");
108 spin_lock_irqsave (&s->lock, flags);
110 for (p = q->next; p != q; p = p->next) {
111 b = list_entry (p, buff_t, buff_list);
113 #ifdef DEBUG
114 dump_urb(b->purb);
115 #endif
116 usb_unlink_urb (b->purb);
118 spin_unlock_irqrestore (&s->lock, flags);
119 return 0;
121 /*-------------------------------------------------------------------*/
122 static int dabusb_free_queue (struct list_head *q)
124 struct list_head *tmp;
125 struct list_head *p;
126 pbuff_t b;
128 dbg("dabusb_free_queue");
129 for (p = q->next; p != q;) {
130 b = list_entry (p, buff_t, buff_list);
132 #ifdef DEBUG
133 dump_urb(b->purb);
134 #endif
135 if (b->purb->transfer_buffer)
136 kfree (b->purb->transfer_buffer);
137 usb_free_urb(b->purb);
138 tmp = p->next;
139 list_del (p);
140 kfree (b);
141 p = tmp;
144 return 0;
146 /*-------------------------------------------------------------------*/
147 static int dabusb_free_buffers (pdabusb_t s)
149 unsigned long flags;
150 dbg("dabusb_free_buffers");
152 spin_lock_irqsave(&s->lock, flags);
154 dabusb_free_queue (&s->free_buff_list);
155 dabusb_free_queue (&s->rec_buff_list);
157 spin_unlock_irqrestore(&s->lock, flags);
159 s->got_mem = 0;
160 return 0;
162 /*-------------------------------------------------------------------*/
163 static void dabusb_iso_complete (purb_t purb)
165 pbuff_t b = purb->context;
166 pdabusb_t s = b->s;
167 int i;
168 int len;
169 int dst = 0;
170 void *buf = purb->transfer_buffer;
172 dbg("dabusb_iso_complete");
174 // process if URB was not killed
175 if (purb->status != -ENOENT) {
176 unsigned int pipe = usb_rcvisocpipe (purb->dev, _DABUSB_ISOPIPE);
177 int pipesize = usb_maxpacket (purb->dev, pipe, usb_pipeout (pipe));
178 for (i = 0; i < purb->number_of_packets; i++)
179 if (!purb->iso_frame_desc[i].status) {
180 len = purb->iso_frame_desc[i].actual_length;
181 if (len <= pipesize) {
182 memcpy (buf + dst, buf + purb->iso_frame_desc[i].offset, len);
183 dst += len;
185 else
186 err("dabusb_iso_complete: invalid len %d", len);
188 else
189 warn("dabusb_iso_complete: corrupted packet status: %d", purb->iso_frame_desc[i].status);
190 if (dst != purb->actual_length)
191 err("dst!=purb->actual_length:%d!=%d", dst, purb->actual_length);
194 if (atomic_dec_and_test (&s->pending_io) && !s->remove_pending && s->state != _stopped) {
195 s->overruns++;
196 err("overrun (%d)", s->overruns);
198 wake_up (&s->wait);
200 /*-------------------------------------------------------------------*/
201 static int dabusb_alloc_buffers (pdabusb_t s)
203 int buffers = 0;
204 pbuff_t b;
205 unsigned int pipe = usb_rcvisocpipe (s->usbdev, _DABUSB_ISOPIPE);
206 int pipesize = usb_maxpacket (s->usbdev, pipe, usb_pipeout (pipe));
207 int packets = _ISOPIPESIZE / pipesize;
208 int transfer_buffer_length = packets * pipesize;
209 int i;
211 dbg("dabusb_alloc_buffers pipesize:%d packets:%d transfer_buffer_len:%d",
212 pipesize, packets, transfer_buffer_length);
214 while (buffers < (s->total_buffer_size << 10)) {
215 b = (pbuff_t) kmalloc (sizeof (buff_t), GFP_KERNEL);
216 if (!b) {
217 err("kmalloc(sizeof(buff_t))==NULL");
218 goto err;
220 memset (b, sizeof (buff_t), 0);
221 b->s = s;
222 b->purb = usb_alloc_urb(packets);
223 if (!b->purb) {
224 err("usb_alloc_urb == NULL");
225 kfree (b);
226 goto err;
229 b->purb->transfer_buffer = kmalloc (transfer_buffer_length, GFP_KERNEL);
230 if (!b->purb->transfer_buffer) {
231 kfree (b->purb);
232 kfree (b);
233 err("kmalloc(%d)==NULL", transfer_buffer_length);
234 goto err;
237 b->purb->transfer_buffer_length = transfer_buffer_length;
238 b->purb->number_of_packets = packets;
239 b->purb->complete = dabusb_iso_complete;
240 b->purb->context = b;
241 b->purb->dev = s->usbdev;
242 b->purb->pipe = pipe;
243 b->purb->transfer_flags = USB_ISO_ASAP;
245 for (i = 0; i < packets; i++) {
246 b->purb->iso_frame_desc[i].offset = i * pipesize;
247 b->purb->iso_frame_desc[i].length = pipesize;
250 buffers += transfer_buffer_length;
251 list_add_tail (&b->buff_list, &s->free_buff_list);
253 s->got_mem = buffers;
255 return 0;
257 err:
258 dabusb_free_buffers (s);
259 return -ENOMEM;
261 /*-------------------------------------------------------------------*/
262 static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb)
264 int ret;
265 unsigned int pipe;
266 int actual_length;
268 dbg("dabusb_bulk");
270 if (!pb->pipe)
271 pipe = usb_rcvbulkpipe (s->usbdev, 2);
272 else
273 pipe = usb_sndbulkpipe (s->usbdev, 2);
275 ret=usb_bulk_msg(s->usbdev, pipe, pb->data, pb->size, &actual_length, 100);
276 if(ret<0) {
277 err("dabusb: usb_bulk_msg failed(%d)",ret);
279 if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
280 err("set_interface failed");
281 return -EINVAL;
286 if( ret == -EPIPE ) {
287 warn("CLEAR_FEATURE request to remove STALL condition.");
288 if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe)))
289 err("request failed");
292 pb->size = actual_length;
293 return ret;
295 /* --------------------------------------------------------------------- */
296 static int dabusb_writemem (pdabusb_t s, int pos, unsigned char *data, int len)
298 int ret;
299 unsigned char *transfer_buffer = kmalloc (len, GFP_KERNEL);
301 if (!transfer_buffer) {
302 err("dabusb_writemem: kmalloc(%d) failed.", len);
303 return -ENOMEM;
306 memcpy (transfer_buffer, data, len);
308 ret=usb_control_msg(s->usbdev, usb_sndctrlpipe( s->usbdev, 0 ), 0xa0, 0x40, pos, 0, transfer_buffer, len, 300);
310 kfree (transfer_buffer);
311 return ret;
313 /* --------------------------------------------------------------------- */
314 static int dabusb_8051_reset (pdabusb_t s, unsigned char reset_bit)
316 dbg("dabusb_8051_reset: %d",reset_bit);
317 return dabusb_writemem (s, CPUCS_REG, &reset_bit, 1);
319 /* --------------------------------------------------------------------- */
320 static int dabusb_loadmem (pdabusb_t s, const char *fname)
322 int ret;
323 PINTEL_HEX_RECORD ptr = firmware;
325 dbg("Enter dabusb_loadmem (internal)");
327 ret = dabusb_8051_reset (s, 1);
328 while (ptr->Type == 0) {
330 dbg("dabusb_writemem: %04X %p %d)", ptr->Address, ptr->Data, ptr->Length);
332 ret = dabusb_writemem (s, ptr->Address, ptr->Data, ptr->Length);
333 if (ret < 0) {
334 err("dabusb_writemem failed (%d %04X %p %d)", ret, ptr->Address, ptr->Data, ptr->Length);
335 break;
337 ptr++;
339 ret = dabusb_8051_reset (s, 0);
341 dbg("dabusb_loadmem: exit");
343 return ret;
345 /* --------------------------------------------------------------------- */
346 static int dabusb_fpga_clear (pdabusb_t s, pbulk_transfer_t b)
348 b->size = 4;
349 b->data[0] = 0x2a;
350 b->data[1] = 0;
351 b->data[2] = 0;
352 b->data[3] = 0;
354 dbg("dabusb_fpga_clear");
356 return dabusb_bulk (s, b);
358 /* --------------------------------------------------------------------- */
359 static int dabusb_fpga_init (pdabusb_t s, pbulk_transfer_t b)
361 b->size = 4;
362 b->data[0] = 0x2c;
363 b->data[1] = 0;
364 b->data[2] = 0;
365 b->data[3] = 0;
367 dbg("dabusb_fpga_init");
369 return dabusb_bulk (s, b);
371 /* --------------------------------------------------------------------- */
372 static int dabusb_fpga_download (pdabusb_t s, const char *fname)
374 pbulk_transfer_t b = kmalloc (sizeof (bulk_transfer_t), GFP_KERNEL);
375 unsigned int blen, n;
376 int ret;
377 unsigned char *buf = bitstream;
379 dbg("Enter dabusb_fpga_download (internal)");
381 if (!b) {
382 err("kmalloc(sizeof(bulk_transfer_t))==NULL");
383 return -ENOMEM;
386 b->pipe = 1;
387 ret = dabusb_fpga_clear (s, b);
388 mdelay (10);
389 blen = buf[73] + (buf[72] << 8);
391 dbg("Bitstream len: %i", blen);
393 b->data[0] = 0x2b;
394 b->data[1] = 0;
395 b->data[2] = 0;
396 b->data[3] = 60;
398 for (n = 0; n <= blen + 60; n += 60) {
399 // some cclks for startup
400 b->size = 64;
401 memcpy (b->data + 4, buf + 74 + n, 60);
402 ret = dabusb_bulk (s, b);
403 if (ret < 0) {
404 err("dabusb_bulk failed.");
405 break;
407 mdelay (1);
410 ret = dabusb_fpga_init (s, b);
411 kfree (b);
413 dbg("exit dabusb_fpga_download");
415 return ret;
418 static loff_t dabusb_llseek (struct file *file, loff_t offset, int origin)
420 return -ESPIPE;
423 static int dabusb_stop (pdabusb_t s)
425 dbg("dabusb_stop");
427 s->state = _stopped;
428 dabusb_cancel_queue (s, &s->rec_buff_list);
430 dbg("pending_io: %d", s->pending_io.counter);
432 s->pending_io.counter = 0;
433 return 0;
436 static int dabusb_startrek (pdabusb_t s)
438 if (!s->got_mem && s->state != _started) {
440 dbg("dabusb_startrek");
442 if (dabusb_alloc_buffers (s) < 0)
443 return -ENOMEM;
444 dabusb_stop (s);
445 s->state = _started;
446 s->readptr = 0;
449 if (!list_empty (&s->free_buff_list)) {
450 pbuff_t end;
451 int ret;
453 while (!dabusb_add_buf_tail (s, &s->rec_buff_list, &s->free_buff_list)) {
455 dbg("submitting: end:%p s->rec_buff_list:%p", s->rec_buff_list.prev, &s->rec_buff_list);
457 end = list_entry (s->rec_buff_list.prev, buff_t, buff_list);
459 ret = usb_submit_urb (end->purb);
460 if (ret) {
461 err("usb_submit_urb returned:%d", ret);
462 if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list))
463 err("startrek: dabusb_add_buf_tail failed");
464 break;
466 else
467 atomic_inc (&s->pending_io);
469 dbg("pending_io: %d",s->pending_io.counter);
472 return 0;
475 static ssize_t dabusb_read (struct file *file, char *buf, size_t count, loff_t * ppos)
477 pdabusb_t s = (pdabusb_t) file->private_data;
478 unsigned long flags;
479 unsigned ret = 0;
480 int rem;
481 int cnt;
482 pbuff_t b;
483 purb_t purb = NULL;
485 dbg("dabusb_read");
487 if (*ppos)
488 return -ESPIPE;
490 if (s->remove_pending)
491 return -EIO;
494 if (!s->usbdev)
495 return -EIO;
497 while (count > 0) {
498 dabusb_startrek (s);
500 spin_lock_irqsave (&s->lock, flags);
502 if (list_empty (&s->rec_buff_list)) {
504 spin_unlock_irqrestore(&s->lock, flags);
506 err("error: rec_buf_list is empty");
507 goto err;
510 b = list_entry (s->rec_buff_list.next, buff_t, buff_list);
511 purb = b->purb;
513 spin_unlock_irqrestore(&s->lock, flags);
515 if (purb->status == -EINPROGRESS) {
516 if (file->f_flags & O_NONBLOCK) // return nonblocking
518 if (!ret)
519 ret = -EAGAIN;
520 goto err;
523 interruptible_sleep_on (&s->wait);
525 if (signal_pending (current)) {
526 if (!ret)
527 ret = -ERESTARTSYS;
528 goto err;
531 spin_lock_irqsave (&s->lock, flags);
533 if (list_empty (&s->rec_buff_list)) {
534 spin_unlock_irqrestore(&s->lock, flags);
535 err("error: still no buffer available.");
536 goto err;
538 spin_unlock_irqrestore(&s->lock, flags);
539 s->readptr = 0;
541 if (s->remove_pending) {
542 ret = -EIO;
543 goto err;
546 rem = purb->actual_length - s->readptr; // set remaining bytes to copy
548 if (count >= rem)
549 cnt = rem;
550 else
551 cnt = count;
553 dbg("copy_to_user:%p %p %d",buf, purb->transfer_buffer + s->readptr, cnt);
555 if (copy_to_user (buf, purb->transfer_buffer + s->readptr, cnt)) {
556 err("read: copy_to_user failed");
557 if (!ret)
558 ret = -EFAULT;
559 goto err;
562 s->readptr += cnt;
563 count -= cnt;
564 buf += cnt;
565 ret += cnt;
567 if (s->readptr == purb->actual_length) {
568 // finished, take next buffer
569 if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list))
570 err("read: dabusb_add_buf_tail failed");
571 s->readptr = 0;
574 err: //up(&s->mutex);
575 return ret;
578 static int dabusb_open (struct inode *inode, struct file *file)
580 int devnum = MINOR (inode->i_rdev);
581 pdabusb_t s;
583 if (devnum < DABUSB_MINOR || devnum >= (DABUSB_MINOR + NRDABUSB))
584 return -EIO;
586 s = &dabusb[devnum - DABUSB_MINOR];
588 dbg("dabusb_open");
589 down (&s->mutex);
591 while (!s->usbdev || s->opened) {
592 up (&s->mutex);
594 if (file->f_flags & O_NONBLOCK) {
595 return -EBUSY;
597 schedule_timeout (HZ / 2);
599 if (signal_pending (current)) {
600 return -EAGAIN;
602 down (&s->mutex);
604 if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
605 err("set_interface failed");
606 return -EINVAL;
608 s->opened = 1;
609 up (&s->mutex);
611 file->f_pos = 0;
612 file->private_data = s;
614 return 0;
617 static int dabusb_release (struct inode *inode, struct file *file)
619 pdabusb_t s = (pdabusb_t) file->private_data;
621 dbg("dabusb_release");
623 lock_kernel();
624 down (&s->mutex);
625 dabusb_stop (s);
626 dabusb_free_buffers (s);
627 up (&s->mutex);
629 if (!s->remove_pending) {
630 if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0)
631 err("set_interface failed");
633 else
634 wake_up (&s->remove_ok);
636 s->opened = 0;
637 unlock_kernel();
638 return 0;
641 static int dabusb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
643 pdabusb_t s = (pdabusb_t) file->private_data;
644 pbulk_transfer_t pbulk;
645 int ret = 0;
646 int version = DABUSB_VERSION;
648 dbg("dabusb_ioctl");
650 if (s->remove_pending)
651 return -EIO;
653 down (&s->mutex);
655 if (!s->usbdev) {
656 up (&s->mutex);
657 return -EIO;
660 switch (cmd) {
662 case IOCTL_DAB_BULK:
663 pbulk = (pbulk_transfer_t) kmalloc (sizeof (bulk_transfer_t), GFP_KERNEL);
665 if (!pbulk) {
666 ret = -ENOMEM;
667 break;
670 if (copy_from_user (pbulk, (void *) arg, sizeof (bulk_transfer_t))) {
671 ret = -EFAULT;
672 kfree (pbulk);
673 break;
676 ret=dabusb_bulk (s, pbulk);
677 if(ret==0)
678 ret = copy_to_user ((void *) arg, pbulk, sizeof (bulk_transfer_t));
679 kfree (pbulk);
680 break;
682 case IOCTL_DAB_OVERRUNS:
683 ret = put_user (s->overruns, (unsigned int *) arg);
684 break;
686 case IOCTL_DAB_VERSION:
687 ret = put_user (version, (unsigned int *) arg);
688 break;
690 default:
691 ret = -ENOIOCTLCMD;
692 break;
694 up (&s->mutex);
695 return ret;
698 static struct file_operations dabusb_fops =
700 owner: THIS_MODULE,
701 llseek: dabusb_llseek,
702 read: dabusb_read,
703 ioctl: dabusb_ioctl,
704 open: dabusb_open,
705 release: dabusb_release,
708 static int dabusb_find_struct (void)
710 int u;
712 for (u = 0; u < NRDABUSB; u++) {
713 pdabusb_t s = &dabusb[u];
714 if (!s->usbdev)
715 return u;
717 return -1;
720 /* --------------------------------------------------------------------- */
721 static void *dabusb_probe (struct usb_device *usbdev, unsigned int ifnum)
723 int devnum;
724 pdabusb_t s;
726 dbg("dabusb: probe: vendor id 0x%x, device id 0x%x ifnum:%d",
727 usbdev->descriptor.idVendor, usbdev->descriptor.idProduct, ifnum);
729 /* the 1234:5678 is just a self assigned test ID */
730 if ((usbdev->descriptor.idVendor != 0x0547 || usbdev->descriptor.idProduct != 0x2131) &&
731 (usbdev->descriptor.idVendor != 0x0547 || usbdev->descriptor.idProduct != 0x9999))
732 return NULL;
734 /* We don't handle multiple configurations */
735 if (usbdev->descriptor.bNumConfigurations != 1)
736 return NULL;
738 if (ifnum != _DABUSB_IF && usbdev->descriptor.idProduct == 0x9999)
739 return NULL;
741 devnum = dabusb_find_struct ();
742 if (devnum == -1)
743 return NULL;
745 s = &dabusb[devnum];
747 down (&s->mutex);
748 s->remove_pending = 0;
749 s->usbdev = usbdev;
751 if (usb_set_configuration (usbdev, usbdev->config[0].bConfigurationValue) < 0) {
752 err("set_configuration failed");
753 goto reject;
755 if (usbdev->descriptor.idProduct == 0x2131) {
756 dabusb_loadmem (s, NULL);
757 goto reject;
759 else {
760 dabusb_fpga_download (s, NULL);
762 if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) {
763 err("set_interface failed");
764 goto reject;
767 dbg("bound to interface: %d", ifnum);
768 up (&s->mutex);
769 MOD_INC_USE_COUNT;
770 return s;
772 reject:
773 up (&s->mutex);
774 s->usbdev = NULL;
775 return NULL;
778 static void dabusb_disconnect (struct usb_device *usbdev, void *ptr)
780 pdabusb_t s = (pdabusb_t) ptr;
782 dbg("dabusb_disconnect");
784 s->remove_pending = 1;
785 wake_up (&s->wait);
786 if (s->state == _started)
787 sleep_on (&s->remove_ok);
788 s->usbdev = NULL;
789 s->overruns = 0;
790 MOD_DEC_USE_COUNT;
793 static struct usb_driver dabusb_driver =
795 "dabusb",
796 dabusb_probe,
797 dabusb_disconnect,
798 {NULL, NULL},
799 &dabusb_fops,
800 DABUSB_MINOR
803 /* --------------------------------------------------------------------- */
805 static int __init dabusb_init (void)
807 unsigned u;
809 /* initialize struct */
810 for (u = 0; u < NRDABUSB; u++) {
811 pdabusb_t s = &dabusb[u];
812 memset (s, 0, sizeof (dabusb_t));
813 init_MUTEX (&s->mutex);
814 s->usbdev = NULL;
815 s->total_buffer_size = buffers;
816 init_waitqueue_head (&s->wait);
817 init_waitqueue_head (&s->remove_ok);
818 spin_lock_init (&s->lock);
819 INIT_LIST_HEAD (&s->free_buff_list);
820 INIT_LIST_HEAD (&s->rec_buff_list);
823 /* register misc device */
824 if (usb_register(&dabusb_driver))
825 return -1;
827 dbg("dabusb_init: driver registered");
828 return 0;
831 static void __exit dabusb_cleanup (void)
833 dbg("dabusb_cleanup");
835 usb_deregister (&dabusb_driver);
838 /* --------------------------------------------------------------------- */
840 #ifdef MODULE
841 MODULE_AUTHOR ("Deti Fliegl, deti@fliegl.de");
842 MODULE_DESCRIPTION ("DAB-USB Interface Driver for Linux (c)1999");
843 MODULE_PARM (buffers, "i");
844 MODULE_PARM_DESC (buffers, "Number of buffers (default=256)");
846 module_init (dabusb_init);
847 module_exit (dabusb_cleanup);
850 #endif
852 /* --------------------------------------------------------------------- */