]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/usb/serial/option.c
92d0f925d053c64326878afc14704b9d2877cdd7
[linux-2.6-omap-h63xx.git] / drivers / usb / serial / option.c
1 /*
2   Option Card (PCMCIA to) USB to Serial Driver
3
4   Copyright (C) 2005  Matthias Urlichs <smurf@smurf.noris.de>
5
6   This driver is free software; you can redistribute it and/or modify
7   it under the terms of Version 2 of the GNU General Public License as
8   published by the Free Software Foundation.
9
10   Portions copied from the Keyspan driver by Hugh Blemings <hugh@blemings.org>
11
12   History:
13
14   2005-05-19  v0.1   Initial version, based on incomplete docs
15                      and analysis of misbehavior with the standard driver
16   2005-05-20  v0.2   Extended the input buffer to avoid losing
17                      random 64-byte chunks of data
18   2005-05-21  v0.3   implemented chars_in_buffer()
19                      turned on low_latency
20                      simplified the code somewhat
21   2005-05-24  v0.4   option_write() sometimes deadlocked under heavy load
22                      removed some dead code
23                      added sponsor notice
24                      coding style clean-up
25   2005-06-20  v0.4.1 add missing braces :-/
26                      killed end-of-line whitespace
27   2005-07-15  v0.4.2 rename WLAN product to FUSION, add FUSION2
28
29   Work sponsored by: Sigos GmbH, Germany <info@sigos.de>
30
31 */
32
33 #define DRIVER_VERSION "v0.4"
34 #define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"
35 #define DRIVER_DESC "Option Card (PC-Card to) USB to Serial Driver"
36
37 #include <linux/config.h>
38 #include <linux/kernel.h>
39 #include <linux/jiffies.h>
40 #include <linux/errno.h>
41 #include <linux/tty.h>
42 #include <linux/tty_flip.h>
43 #include <linux/module.h>
44 #include <linux/usb.h>
45 #include "usb-serial.h"
46
47 /* Function prototypes */
48 static int  option_open(struct usb_serial_port *port, struct file *filp);
49 static void option_close(struct usb_serial_port *port, struct file *filp);
50 static int  option_startup(struct usb_serial *serial);
51 static void option_shutdown(struct usb_serial *serial);
52 static void option_rx_throttle(struct usb_serial_port *port);
53 static void option_rx_unthrottle(struct usb_serial_port *port);
54 static int  option_write_room(struct usb_serial_port *port);
55
56 static void option_instat_callback(struct urb *urb, struct pt_regs *regs);
57
58 static int option_write(struct usb_serial_port *port,
59                         const unsigned char *buf, int count);
60
61 static int  option_chars_in_buffer(struct usb_serial_port *port);
62 static int  option_ioctl(struct usb_serial_port *port, struct file *file,
63                         unsigned int cmd, unsigned long arg);
64 static void option_set_termios(struct usb_serial_port *port,
65                                 struct termios *old);
66 static void option_break_ctl(struct usb_serial_port *port, int break_state);
67 static int  option_tiocmget(struct usb_serial_port *port, struct file *file);
68 static int  option_tiocmset(struct usb_serial_port *port, struct file *file,
69                                 unsigned int set, unsigned int clear);
70 static int  option_send_setup(struct usb_serial_port *port);
71
72 /* Vendor and product IDs */
73 #define OPTION_VENDOR_ID                        0x0AF0
74
75 #define OPTION_PRODUCT_OLD              0x5000
76 #define OPTION_PRODUCT_FUSION   0x6000
77 #define OPTION_PRODUCT_FUSION2  0x6300
78
79 static struct usb_device_id option_ids[] = {
80         { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) },
81         { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) },
82         { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
83         { } /* Terminating entry */
84 };
85
86 MODULE_DEVICE_TABLE(usb, option_ids);
87
88 static struct usb_driver option_driver = {
89         .owner      = THIS_MODULE,
90         .name       = "option",
91         .probe      = usb_serial_probe,
92         .disconnect = usb_serial_disconnect,
93         .id_table   = option_ids,
94 };
95
96 /* The card has three separate interfaces, wich the serial driver
97  * recognizes separately, thus num_port=1.
98  */
99 static struct usb_serial_device_type option_3port_device = {
100         .owner             = THIS_MODULE,
101         .name              = "Option 3G data card",
102         .short_name        = "option",
103         .id_table          = option_ids,
104         .num_interrupt_in  = NUM_DONT_CARE,
105         .num_bulk_in       = NUM_DONT_CARE,
106         .num_bulk_out      = NUM_DONT_CARE,
107         .num_ports         = 1, /* 3, but the card reports its ports separately */
108         .open              = option_open,
109         .close             = option_close,
110         .write             = option_write,
111         .write_room        = option_write_room,
112         .chars_in_buffer   = option_chars_in_buffer,
113         .throttle          = option_rx_throttle,
114         .unthrottle        = option_rx_unthrottle,
115         .ioctl             = option_ioctl,
116         .set_termios       = option_set_termios,
117         .break_ctl         = option_break_ctl,
118         .tiocmget          = option_tiocmget,
119         .tiocmset          = option_tiocmset,
120         .attach            = option_startup,
121         .shutdown          = option_shutdown,
122         .read_int_callback = option_instat_callback,
123 };
124
125 #ifdef CONFIG_USB_DEBUG
126 static int debug;
127 #else
128 #define debug 0
129 #endif
130
131 /* per port private data */
132
133 #define N_IN_URB 4
134 #define N_OUT_URB 1
135 #define IN_BUFLEN 1024
136 #define OUT_BUFLEN 128
137
138 struct option_port_private {
139         /* Input endpoints and buffer for this port */
140         struct urb *in_urbs[N_IN_URB];
141         char in_buffer[N_IN_URB][IN_BUFLEN];
142         /* Output endpoints and buffer for this port */
143         struct urb *out_urbs[N_OUT_URB];
144         char out_buffer[N_OUT_URB][OUT_BUFLEN];
145
146         /* Settings for the port */
147         int rts_state;  /* Handshaking pins (outputs) */
148         int dtr_state;
149         int cts_state;  /* Handshaking pins (inputs) */
150         int dsr_state;
151         int dcd_state;
152         int ri_state;
153
154         unsigned long tx_start_time[N_OUT_URB];
155 };
156
157 /* Functions used by new usb-serial code. */
158 static int __init option_init(void)
159 {
160         int retval;
161         retval = usb_serial_register(&option_3port_device);
162         if (retval)
163                 goto failed_3port_device_register;
164         retval = usb_register(&option_driver);
165         if (retval)
166                 goto failed_driver_register;
167
168         info(DRIVER_DESC ": " DRIVER_VERSION);
169
170         return 0;
171
172 failed_driver_register:
173         usb_serial_deregister (&option_3port_device);
174 failed_3port_device_register:
175         return retval;
176 }
177
178 static void __exit option_exit(void)
179 {
180         usb_deregister (&option_driver);
181         usb_serial_deregister (&option_3port_device);
182 }
183
184 module_init(option_init);
185 module_exit(option_exit);
186
187 static void option_rx_throttle(struct usb_serial_port *port)
188 {
189         dbg("%s", __FUNCTION__);
190 }
191
192 static void option_rx_unthrottle(struct usb_serial_port *port)
193 {
194         dbg("%s", __FUNCTION__);
195 }
196
197 static void option_break_ctl(struct usb_serial_port *port, int break_state)
198 {
199         /* Unfortunately, I don't know how to send a break */
200         dbg("%s", __FUNCTION__);
201 }
202
203 static void option_set_termios(struct usb_serial_port *port,
204                         struct termios *old_termios)
205 {
206         dbg("%s", __FUNCTION__);
207
208         option_send_setup(port);
209 }
210
211 static int option_tiocmget(struct usb_serial_port *port, struct file *file)
212 {
213         unsigned int value;
214         struct option_port_private *portdata;
215
216         portdata = usb_get_serial_port_data(port);
217
218         value = ((portdata->rts_state) ? TIOCM_RTS : 0) |
219                 ((portdata->dtr_state) ? TIOCM_DTR : 0) |
220                 ((portdata->cts_state) ? TIOCM_CTS : 0) |
221                 ((portdata->dsr_state) ? TIOCM_DSR : 0) |
222                 ((portdata->dcd_state) ? TIOCM_CAR : 0) |
223                 ((portdata->ri_state) ? TIOCM_RNG : 0);
224
225         return value;
226 }
227
228 static int option_tiocmset(struct usb_serial_port *port, struct file *file,
229                         unsigned int set, unsigned int clear)
230 {
231         struct option_port_private *portdata;
232
233         portdata = usb_get_serial_port_data(port);
234
235         if (set & TIOCM_RTS)
236                 portdata->rts_state = 1;
237         if (set & TIOCM_DTR)
238                 portdata->dtr_state = 1;
239
240         if (clear & TIOCM_RTS)
241                 portdata->rts_state = 0;
242         if (clear & TIOCM_DTR)
243                 portdata->dtr_state = 0;
244         return option_send_setup(port);
245 }
246
247 static int option_ioctl(struct usb_serial_port *port, struct file *file,
248                         unsigned int cmd, unsigned long arg)
249 {
250         return -ENOIOCTLCMD;
251 }
252
253 /* Write */
254 static int option_write(struct usb_serial_port *port,
255                         const unsigned char *buf, int count)
256 {
257         struct option_port_private *portdata;
258         int i;
259         int left, todo;
260         struct urb *this_urb = NULL; /* spurious */
261         int err;
262
263         portdata = usb_get_serial_port_data(port);
264
265         dbg("%s: write (%d chars)", __FUNCTION__, count);
266
267         i = 0;
268         left = count;
269         for (i=0; left > 0 && i < N_OUT_URB; i++) {
270                 todo = left;
271                 if (todo > OUT_BUFLEN)
272                         todo = OUT_BUFLEN;
273
274                 this_urb = portdata->out_urbs[i];
275                 if (this_urb->status == -EINPROGRESS) {
276                         if (time_before(jiffies,
277                                         portdata->tx_start_time[i] + 10 * HZ))
278                                 continue;
279                         usb_unlink_urb(this_urb);
280                         continue;
281                 }
282                 if (this_urb->status != 0)
283                         dbg("usb_write %p failed (err=%d)",
284                                 this_urb, this_urb->status);
285
286                 dbg("%s: endpoint %d buf %d", __FUNCTION__,
287                         usb_pipeendpoint(this_urb->pipe), i);
288
289                 /* send the data */
290                 memcpy (this_urb->transfer_buffer, buf, todo);
291                 this_urb->transfer_buffer_length = todo;
292
293                 this_urb->dev = port->serial->dev;
294                 err = usb_submit_urb(this_urb, GFP_ATOMIC);
295                 if (err) {
296                         dbg("usb_submit_urb %p (write bulk) failed "
297                                 "(%d, has %d)", this_urb,
298                                 err, this_urb->status);
299                         continue;
300                 }
301                 portdata->tx_start_time[i] = jiffies;
302                 buf += todo;
303                 left -= todo;
304         }
305
306         count -= left;
307         dbg("%s: wrote (did %d)", __FUNCTION__, count);
308         return count;
309 }
310
311 static void option_indat_callback(struct urb *urb, struct pt_regs *regs)
312 {
313         int i, err;
314         int endpoint;
315         struct usb_serial_port *port;
316         struct tty_struct *tty;
317         unsigned char *data = urb->transfer_buffer;
318
319         dbg("%s: %p", __FUNCTION__, urb);
320
321         endpoint = usb_pipeendpoint(urb->pipe);
322         port = (struct usb_serial_port *) urb->context;
323
324         if (urb->status) {
325                 dbg("%s: nonzero status: %d on endpoint %02x.",
326                     __FUNCTION__, urb->status, endpoint);
327         } else {
328                 tty = port->tty;
329                 if (urb->actual_length) {
330                         for (i = 0; i < urb->actual_length ; ++i) {
331                                 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
332                                         tty_flip_buffer_push(tty);
333                                 tty_insert_flip_char(tty, data[i], 0);
334                         }
335                         tty_flip_buffer_push(tty);
336                 } else {
337                         dbg("%s: empty read urb received", __FUNCTION__);
338                 }
339
340                 /* Resubmit urb so we continue receiving */
341                 if (port->open_count && urb->status != -ESHUTDOWN) {
342                         err = usb_submit_urb(urb, GFP_ATOMIC);
343                         if (err)
344                                 printk(KERN_ERR "%s: resubmit read urb failed. "
345                                         "(%d)", __FUNCTION__, err);
346                 }
347         }
348         return;
349 }
350
351 static void option_outdat_callback(struct urb *urb, struct pt_regs *regs)
352 {
353         struct usb_serial_port *port;
354
355         dbg("%s", __FUNCTION__);
356
357         port = (struct usb_serial_port *) urb->context;
358
359         if (port->open_count)
360                 schedule_work(&port->work);
361 }
362
363 static void option_instat_callback(struct urb *urb, struct pt_regs *regs)
364 {
365         int err;
366         struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
367         struct option_port_private *portdata = usb_get_serial_port_data(port);
368         struct usb_serial *serial = port->serial;
369
370         dbg("%s", __FUNCTION__);
371         dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata);
372
373         if (urb->status == 0) {
374                 struct usb_ctrlrequest *req_pkt =
375                                 (struct usb_ctrlrequest *)urb->transfer_buffer;
376
377                 if (!req_pkt) {
378                         dbg("%s: NULL req_pkt\n", __FUNCTION__);
379                         return;
380                 }
381                 if ((req_pkt->bRequestType == 0xA1) &&
382                                 (req_pkt->bRequest == 0x20)) {
383                         int old_dcd_state;
384                         unsigned char signals = *((unsigned char *)
385                                         urb->transfer_buffer +
386                                         sizeof(struct usb_ctrlrequest));
387
388                         dbg("%s: signal x%x", __FUNCTION__, signals);
389
390                         old_dcd_state = portdata->dcd_state;
391                         portdata->cts_state = 1;
392                         portdata->dcd_state = ((signals & 0x01) ? 1 : 0);
393                         portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
394                         portdata->ri_state = ((signals & 0x08) ? 1 : 0);
395
396                         if (port->tty && !C_CLOCAL(port->tty) &&
397                                         old_dcd_state && !portdata->dcd_state)
398                                 tty_hangup(port->tty);
399                 } else {
400                         dbg("%s: type %x req %x", __FUNCTION__,
401                                 req_pkt->bRequestType,req_pkt->bRequest);
402                 }
403         } else
404                 dbg("%s: error %d", __FUNCTION__, urb->status);
405
406         /* Resubmit urb so we continue receiving IRQ data */
407         if (urb->status != -ESHUTDOWN) {
408                 urb->dev = serial->dev;
409                 err = usb_submit_urb(urb, GFP_ATOMIC);
410                 if (err)
411                         dbg("%s: resubmit intr urb failed. (%d)",
412                                 __FUNCTION__, err);
413         }
414 }
415
416 static int option_write_room(struct usb_serial_port *port)
417 {
418         struct option_port_private *portdata;
419         int i;
420         int data_len = 0;
421         struct urb *this_urb;
422
423         portdata = usb_get_serial_port_data(port);
424
425         for (i=0; i < N_OUT_URB; i++) {
426                 this_urb = portdata->out_urbs[i];
427                 if (this_urb && this_urb->status != -EINPROGRESS)
428                         data_len += OUT_BUFLEN;
429         }
430
431         dbg("%s: %d", __FUNCTION__, data_len);
432         return data_len;
433 }
434
435 static int option_chars_in_buffer(struct usb_serial_port *port)
436 {
437         struct option_port_private *portdata;
438         int i;
439         int data_len = 0;
440         struct urb *this_urb;
441
442         portdata = usb_get_serial_port_data(port);
443
444         for (i=0; i < N_OUT_URB; i++) {
445                 this_urb = portdata->out_urbs[i];
446                 if (this_urb && this_urb->status == -EINPROGRESS)
447                         data_len += this_urb->transfer_buffer_length;
448         }
449         dbg("%s: %d", __FUNCTION__, data_len);
450         return data_len;
451 }
452
453 static int option_open(struct usb_serial_port *port, struct file *filp)
454 {
455         struct option_port_private *portdata;
456         struct usb_serial *serial = port->serial;
457         int i, err;
458         struct urb *urb;
459
460         portdata = usb_get_serial_port_data(port);
461
462         dbg("%s", __FUNCTION__);
463
464         /* Set some sane defaults */
465         portdata->rts_state = 1;
466         portdata->dtr_state = 1;
467
468         /* Reset low level data toggle and start reading from endpoints */
469         for (i = 0; i < N_IN_URB; i++) {
470                 urb = portdata->in_urbs[i];
471                 if (! urb)
472                         continue;
473                 if (urb->dev != serial->dev) {
474                         dbg("%s: dev %p != %p", __FUNCTION__,
475                                 urb->dev, serial->dev);
476                         continue;
477                 }
478
479                 /*
480                  * make sure endpoint data toggle is synchronized with the
481                  * device
482                  */
483                 usb_clear_halt(urb->dev, urb->pipe);
484
485                 err = usb_submit_urb(urb, GFP_KERNEL);
486                 if (err) {
487                         dbg("%s: submit urb %d failed (%d) %d",
488                                 __FUNCTION__, i, err,
489                                 urb->transfer_buffer_length);
490                 }
491         }
492
493         /* Reset low level data toggle on out endpoints */
494         for (i = 0; i < N_OUT_URB; i++) {
495                 urb = portdata->out_urbs[i];
496                 if (! urb)
497                         continue;
498                 urb->dev = serial->dev;
499                 /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
500                                 usb_pipeout(urb->pipe), 0); */
501         }
502
503         port->tty->low_latency = 1;
504
505         option_send_setup(port);
506
507         return (0);
508 }
509
510 static inline void stop_urb(struct urb *urb)
511 {
512         if (urb && urb->status == -EINPROGRESS)
513                 usb_kill_urb(urb);
514 }
515
516 static void option_close(struct usb_serial_port *port, struct file *filp)
517 {
518         int i;
519         struct usb_serial *serial = port->serial;
520         struct option_port_private *portdata;
521
522         dbg("%s", __FUNCTION__);
523         portdata = usb_get_serial_port_data(port);
524
525         portdata->rts_state = 0;
526         portdata->dtr_state = 0;
527
528         if (serial->dev) {
529                 option_send_setup(port);
530
531                 /* Stop reading/writing urbs */
532                 for (i = 0; i < N_IN_URB; i++)
533                         stop_urb(portdata->in_urbs[i]);
534                 for (i = 0; i < N_OUT_URB; i++)
535                         stop_urb(portdata->out_urbs[i]);
536         }
537         port->tty = NULL;
538 }
539
540 /* Helper functions used by option_setup_urbs */
541 static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint,
542                 int dir, void *ctx, char *buf, int len,
543                 void (*callback)(struct urb *, struct pt_regs *regs))
544 {
545         struct urb *urb;
546
547         if (endpoint == -1)
548                 return NULL;            /* endpoint not needed */
549
550         urb = usb_alloc_urb(0, GFP_KERNEL);             /* No ISO */
551         if (urb == NULL) {
552                 dbg("%s: alloc for endpoint %d failed.", __FUNCTION__, endpoint);
553                 return NULL;
554         }
555
556                 /* Fill URB using supplied data. */
557         usb_fill_bulk_urb(urb, serial->dev,
558                       usb_sndbulkpipe(serial->dev, endpoint) | dir,
559                       buf, len, callback, ctx);
560
561         return urb;
562 }
563
564 /* Setup urbs */
565 static void option_setup_urbs(struct usb_serial *serial)
566 {
567         int j;
568         struct usb_serial_port *port;
569         struct option_port_private *portdata;
570
571         dbg("%s", __FUNCTION__);
572
573         port = serial->port[0];
574         portdata = usb_get_serial_port_data(port);
575
576         /* Do indat endpoints first */
577         for (j = 0; j <= N_IN_URB; ++j) {
578                 portdata->in_urbs[j] = option_setup_urb (serial,
579                   port->bulk_in_endpointAddress, USB_DIR_IN, port,
580                   portdata->in_buffer[j], IN_BUFLEN, option_indat_callback);
581         }
582
583         /* outdat endpoints */
584         for (j = 0; j <= N_OUT_URB; ++j) {
585                 portdata->out_urbs[j] = option_setup_urb (serial,
586                   port->bulk_out_endpointAddress, USB_DIR_OUT, port,
587                   portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback);
588         }
589 }
590
591 static int option_send_setup(struct usb_serial_port *port)
592 {
593         struct usb_serial *serial = port->serial;
594         struct option_port_private *portdata;
595
596         dbg("%s", __FUNCTION__);
597
598         portdata = usb_get_serial_port_data(port);
599
600         if (port->tty) {
601                 int val = 0;
602                 if (portdata->dtr_state)
603                         val |= 0x01;
604                 if (portdata->rts_state)
605                         val |= 0x02;
606
607                 return usb_control_msg(serial->dev,
608                                 usb_rcvctrlpipe(serial->dev, 0),
609                                 0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
610         }
611
612         return 0;
613 }
614
615 static int option_startup(struct usb_serial *serial)
616 {
617         int i, err;
618         struct usb_serial_port *port;
619         struct option_port_private *portdata;
620
621         dbg("%s", __FUNCTION__);
622
623         /* Now setup per port private data */
624         for (i = 0; i < serial->num_ports; i++) {
625                 port = serial->port[i];
626                 portdata = kmalloc(sizeof(*portdata), GFP_KERNEL);
627                 if (!portdata) {
628                         dbg("%s: kmalloc for option_port_private (%d) failed!.",
629                                         __FUNCTION__, i);
630                         return (1);
631                 }
632                 memset(portdata, 0, sizeof(struct option_port_private));
633
634                 usb_set_serial_port_data(port, portdata);
635
636                 if (! port->interrupt_in_urb)
637                         continue;
638                 err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
639                 if (err)
640                         dbg("%s: submit irq_in urb failed %d",
641                                 __FUNCTION__, err);
642         }
643
644         option_setup_urbs(serial);
645
646         return (0);
647 }
648
649 static void option_shutdown(struct usb_serial *serial)
650 {
651         int i, j;
652         struct usb_serial_port *port;
653         struct option_port_private *portdata;
654
655         dbg("%s", __FUNCTION__);
656
657         /* Stop reading/writing urbs */
658         for (i = 0; i < serial->num_ports; ++i) {
659                 port = serial->port[i];
660                 portdata = usb_get_serial_port_data(port);
661                 for (j = 0; j < N_IN_URB; j++)
662                         stop_urb(portdata->in_urbs[j]);
663                 for (j = 0; j < N_OUT_URB; j++)
664                         stop_urb(portdata->out_urbs[j]);
665         }
666
667         /* Now free them */
668         for (i = 0; i < serial->num_ports; ++i) {
669                 port = serial->port[i];
670                 portdata = usb_get_serial_port_data(port);
671
672                 for (j = 0; j < N_IN_URB; j++) {
673                         if (portdata->in_urbs[j]) {
674                                 usb_free_urb(portdata->in_urbs[j]);
675                                 portdata->in_urbs[j] = NULL;
676                         }
677                 }
678                 for (j = 0; j < N_OUT_URB; j++) {
679                         if (portdata->out_urbs[j]) {
680                                 usb_free_urb(portdata->out_urbs[j]);
681                                 portdata->out_urbs[j] = NULL;
682                         }
683                 }
684         }
685
686         /* Now free per port private data */
687         for (i = 0; i < serial->num_ports; i++) {
688                 port = serial->port[i];
689                 kfree(usb_get_serial_port_data(port));
690         }
691 }
692
693 MODULE_AUTHOR(DRIVER_AUTHOR);
694 MODULE_DESCRIPTION(DRIVER_DESC);
695 MODULE_VERSION(DRIVER_VERSION);
696 MODULE_LICENSE("GPL");
697
698 #ifdef CONFIG_USB_DEBUG
699 module_param(debug, bool, S_IRUGO | S_IWUSR);
700 MODULE_PARM_DESC(debug, "Debug messages");
701 #endif
702