[PATCH] USB: move usb-serial.h to include/linux/usb/
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / usb / serial / option.c
blobf0530c1d7b7a274ca7a2c69bc8a33df199a9f6c1
1 /*
2 USB Driver for GSM modems
4 Copyright (C) 2005 Matthias Urlichs <smurf@smurf.noris.de>
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.
10 Portions copied from the Keyspan driver by Hugh Blemings <hugh@blemings.org>
12 History:
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 2005-09-10 v0.4.3 added HUAWEI E600 card and Audiovox AirCard
29 2005-09-20 v0.4.4 increased recv buffer size: the card sometimes
30 wants to send >2000 bytes.
31 2006-04-10 v0.5 fixed two array overrun errors :-/
32 2006-04-21 v0.5.1 added support for Sierra Wireless MC8755
33 2006-05-15 v0.6 re-enable multi-port support
34 2006-06-01 v0.6.1 add COBRA
35 2006-06-01 v0.6.2 add backwards-compatibility stuff
36 2006-06-01 v0.6.3 add Novatel Wireless
37 2006-06-01 v0.7 Option => GSM
38 2006-06-01 v0.7.1 add COBRA2
40 Work sponsored by: Sigos GmbH, Germany <info@sigos.de>
42 This driver exists because the "normal" serial driver doesn't work too well
43 with GSM modems. Issues:
44 - data loss -- one single Receive URB is not nearly enough
45 - nonstandard flow (Option devices) and multiplex (Sierra) control
46 - controlling the baud rate doesn't make sense
48 This driver is named "option" because the most common device it's
49 used for is a PC-Card (with an internal OHCI-USB interface, behind
50 which the GSM interface sits), made by Option Inc.
52 Some of the "one port" devices actually exhibit multiple USB instances
53 on the USB bus. This is not a bug, these ports are used for different
54 device features.
57 #define DRIVER_VERSION "v0.7.1"
58 #define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"
59 #define DRIVER_DESC "USB Driver for GSM modems"
61 #include <linux/kernel.h>
62 #include <linux/jiffies.h>
63 #include <linux/errno.h>
64 #include <linux/tty.h>
65 #include <linux/tty_flip.h>
66 #include <linux/module.h>
67 #include <linux/usb.h>
68 #include <linux/usb/serial.h>
70 /* Function prototypes */
71 static int option_open(struct usb_serial_port *port, struct file *filp);
72 static void option_close(struct usb_serial_port *port, struct file *filp);
73 static int option_startup(struct usb_serial *serial);
74 static void option_shutdown(struct usb_serial *serial);
75 static void option_rx_throttle(struct usb_serial_port *port);
76 static void option_rx_unthrottle(struct usb_serial_port *port);
77 static int option_write_room(struct usb_serial_port *port);
79 static void option_instat_callback(struct urb *urb, struct pt_regs *regs);
81 static int option_write(struct usb_serial_port *port,
82 const unsigned char *buf, int count);
84 static int option_chars_in_buffer(struct usb_serial_port *port);
85 static int option_ioctl(struct usb_serial_port *port, struct file *file,
86 unsigned int cmd, unsigned long arg);
87 static void option_set_termios(struct usb_serial_port *port,
88 struct termios *old);
89 static void option_break_ctl(struct usb_serial_port *port, int break_state);
90 static int option_tiocmget(struct usb_serial_port *port, struct file *file);
91 static int option_tiocmset(struct usb_serial_port *port, struct file *file,
92 unsigned int set, unsigned int clear);
93 static int option_send_setup(struct usb_serial_port *port);
95 /* Vendor and product IDs */
96 #define OPTION_VENDOR_ID 0x0AF0
97 #define HUAWEI_VENDOR_ID 0x12D1
98 #define AUDIOVOX_VENDOR_ID 0x0F3D
99 #define SIERRAWIRELESS_VENDOR_ID 0x1199
100 #define NOVATELWIRELESS_VENDOR_ID 0x1410
102 #define OPTION_PRODUCT_OLD 0x5000
103 #define OPTION_PRODUCT_FUSION 0x6000
104 #define OPTION_PRODUCT_FUSION2 0x6300
105 #define OPTION_PRODUCT_COBRA 0x6500
106 #define OPTION_PRODUCT_COBRA2 0x6600
107 #define HUAWEI_PRODUCT_E600 0x1001
108 #define AUDIOVOX_PRODUCT_AIRCARD 0x0112
109 #define SIERRAWIRELESS_PRODUCT_MC8755 0x6802
110 #define NOVATELWIRELESS_PRODUCT_U740 0x1400
112 static struct usb_device_id option_ids[] = {
113 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) },
114 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) },
115 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
116 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
117 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) },
118 { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
119 { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
120 { USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) },
121 { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
122 { } /* Terminating entry */
125 static struct usb_device_id option_ids1[] = {
126 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) },
127 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) },
128 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
129 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
130 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) },
131 { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
132 { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
133 { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
134 { } /* Terminating entry */
136 static struct usb_device_id option_ids3[] = {
137 { USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) },
138 { } /* Terminating entry */
141 MODULE_DEVICE_TABLE(usb, option_ids);
143 static struct usb_driver option_driver = {
144 .name = "option",
145 .probe = usb_serial_probe,
146 .disconnect = usb_serial_disconnect,
147 .id_table = option_ids,
148 .no_dynamic_id = 1,
151 /* The card has three separate interfaces, which the serial driver
152 * recognizes separately, thus num_port=1.
154 static struct usb_serial_driver option_3port_device = {
155 .driver = {
156 .owner = THIS_MODULE,
157 .name = "option",
159 .description = "GSM modem (3-port)",
160 .id_table = option_ids3,
161 .num_interrupt_in = NUM_DONT_CARE,
162 .num_bulk_in = NUM_DONT_CARE,
163 .num_bulk_out = NUM_DONT_CARE,
164 .num_ports = 3,
165 .open = option_open,
166 .close = option_close,
167 .write = option_write,
168 .write_room = option_write_room,
169 .chars_in_buffer = option_chars_in_buffer,
170 .throttle = option_rx_throttle,
171 .unthrottle = option_rx_unthrottle,
172 .set_termios = option_set_termios,
173 .break_ctl = option_break_ctl,
174 .tiocmget = option_tiocmget,
175 .tiocmset = option_tiocmset,
176 .attach = option_startup,
177 .shutdown = option_shutdown,
178 .read_int_callback = option_instat_callback,
181 static struct usb_serial_driver option_1port_device = {
182 .driver = {
183 .owner = THIS_MODULE,
184 .name = "option",
186 .description = "GSM modem (1-port)",
187 .id_table = option_ids1,
188 .num_interrupt_in = NUM_DONT_CARE,
189 .num_bulk_in = NUM_DONT_CARE,
190 .num_bulk_out = NUM_DONT_CARE,
191 .num_ports = 1,
192 .open = option_open,
193 .close = option_close,
194 .write = option_write,
195 .write_room = option_write_room,
196 .chars_in_buffer = option_chars_in_buffer,
197 .throttle = option_rx_throttle,
198 .unthrottle = option_rx_unthrottle,
199 .ioctl = option_ioctl,
200 .set_termios = option_set_termios,
201 .break_ctl = option_break_ctl,
202 .tiocmget = option_tiocmget,
203 .tiocmset = option_tiocmset,
204 .attach = option_startup,
205 .shutdown = option_shutdown,
206 .read_int_callback = option_instat_callback,
209 #ifdef CONFIG_USB_DEBUG
210 static int debug;
211 #else
212 #define debug 0
213 #endif
215 /* per port private data */
217 #define N_IN_URB 4
218 #define N_OUT_URB 1
219 #define IN_BUFLEN 4096
220 #define OUT_BUFLEN 128
222 struct option_port_private {
223 /* Input endpoints and buffer for this port */
224 struct urb *in_urbs[N_IN_URB];
225 char in_buffer[N_IN_URB][IN_BUFLEN];
226 /* Output endpoints and buffer for this port */
227 struct urb *out_urbs[N_OUT_URB];
228 char out_buffer[N_OUT_URB][OUT_BUFLEN];
230 /* Settings for the port */
231 int rts_state; /* Handshaking pins (outputs) */
232 int dtr_state;
233 int cts_state; /* Handshaking pins (inputs) */
234 int dsr_state;
235 int dcd_state;
236 int ri_state;
238 unsigned long tx_start_time[N_OUT_URB];
241 /* Functions used by new usb-serial code. */
242 static int __init option_init(void)
244 int retval;
245 retval = usb_serial_register(&option_1port_device);
246 if (retval)
247 goto failed_1port_device_register;
248 retval = usb_serial_register(&option_3port_device);
249 if (retval)
250 goto failed_3port_device_register;
251 retval = usb_register(&option_driver);
252 if (retval)
253 goto failed_driver_register;
255 info(DRIVER_DESC ": " DRIVER_VERSION);
257 return 0;
259 failed_driver_register:
260 usb_serial_deregister (&option_3port_device);
261 failed_3port_device_register:
262 usb_serial_deregister (&option_1port_device);
263 failed_1port_device_register:
264 return retval;
267 static void __exit option_exit(void)
269 usb_deregister (&option_driver);
270 usb_serial_deregister (&option_3port_device);
271 usb_serial_deregister (&option_1port_device);
274 module_init(option_init);
275 module_exit(option_exit);
277 static void option_rx_throttle(struct usb_serial_port *port)
279 dbg("%s", __FUNCTION__);
282 static void option_rx_unthrottle(struct usb_serial_port *port)
284 dbg("%s", __FUNCTION__);
287 static void option_break_ctl(struct usb_serial_port *port, int break_state)
289 /* Unfortunately, I don't know how to send a break */
290 dbg("%s", __FUNCTION__);
293 static void option_set_termios(struct usb_serial_port *port,
294 struct termios *old_termios)
296 dbg("%s", __FUNCTION__);
298 option_send_setup(port);
301 static int option_tiocmget(struct usb_serial_port *port, struct file *file)
303 unsigned int value;
304 struct option_port_private *portdata;
306 portdata = usb_get_serial_port_data(port);
308 value = ((portdata->rts_state) ? TIOCM_RTS : 0) |
309 ((portdata->dtr_state) ? TIOCM_DTR : 0) |
310 ((portdata->cts_state) ? TIOCM_CTS : 0) |
311 ((portdata->dsr_state) ? TIOCM_DSR : 0) |
312 ((portdata->dcd_state) ? TIOCM_CAR : 0) |
313 ((portdata->ri_state) ? TIOCM_RNG : 0);
315 return value;
318 static int option_tiocmset(struct usb_serial_port *port, struct file *file,
319 unsigned int set, unsigned int clear)
321 struct option_port_private *portdata;
323 portdata = usb_get_serial_port_data(port);
325 if (set & TIOCM_RTS)
326 portdata->rts_state = 1;
327 if (set & TIOCM_DTR)
328 portdata->dtr_state = 1;
330 if (clear & TIOCM_RTS)
331 portdata->rts_state = 0;
332 if (clear & TIOCM_DTR)
333 portdata->dtr_state = 0;
334 return option_send_setup(port);
337 static int option_ioctl(struct usb_serial_port *port, struct file *file,
338 unsigned int cmd, unsigned long arg)
340 return -ENOIOCTLCMD;
343 /* Write */
344 static int option_write(struct usb_serial_port *port,
345 const unsigned char *buf, int count)
347 struct option_port_private *portdata;
348 int i;
349 int left, todo;
350 struct urb *this_urb = NULL; /* spurious */
351 int err;
353 portdata = usb_get_serial_port_data(port);
355 dbg("%s: write (%d chars)", __FUNCTION__, count);
357 i = 0;
358 left = count;
359 for (i=0; left > 0 && i < N_OUT_URB; i++) {
360 todo = left;
361 if (todo > OUT_BUFLEN)
362 todo = OUT_BUFLEN;
364 this_urb = portdata->out_urbs[i];
365 if (this_urb->status == -EINPROGRESS) {
366 if (time_before(jiffies,
367 portdata->tx_start_time[i] + 10 * HZ))
368 continue;
369 usb_unlink_urb(this_urb);
370 continue;
372 if (this_urb->status != 0)
373 dbg("usb_write %p failed (err=%d)",
374 this_urb, this_urb->status);
376 dbg("%s: endpoint %d buf %d", __FUNCTION__,
377 usb_pipeendpoint(this_urb->pipe), i);
379 /* send the data */
380 memcpy (this_urb->transfer_buffer, buf, todo);
381 this_urb->transfer_buffer_length = todo;
383 this_urb->dev = port->serial->dev;
384 err = usb_submit_urb(this_urb, GFP_ATOMIC);
385 if (err) {
386 dbg("usb_submit_urb %p (write bulk) failed "
387 "(%d, has %d)", this_urb,
388 err, this_urb->status);
389 continue;
391 portdata->tx_start_time[i] = jiffies;
392 buf += todo;
393 left -= todo;
396 count -= left;
397 dbg("%s: wrote (did %d)", __FUNCTION__, count);
398 return count;
401 static void option_indat_callback(struct urb *urb, struct pt_regs *regs)
403 int err;
404 int endpoint;
405 struct usb_serial_port *port;
406 struct tty_struct *tty;
407 unsigned char *data = urb->transfer_buffer;
409 dbg("%s: %p", __FUNCTION__, urb);
411 endpoint = usb_pipeendpoint(urb->pipe);
412 port = (struct usb_serial_port *) urb->context;
414 if (urb->status) {
415 dbg("%s: nonzero status: %d on endpoint %02x.",
416 __FUNCTION__, urb->status, endpoint);
417 } else {
418 tty = port->tty;
419 if (urb->actual_length) {
420 tty_buffer_request_room(tty, urb->actual_length);
421 tty_insert_flip_string(tty, data, urb->actual_length);
422 tty_flip_buffer_push(tty);
423 } else {
424 dbg("%s: empty read urb received", __FUNCTION__);
427 /* Resubmit urb so we continue receiving */
428 if (port->open_count && urb->status != -ESHUTDOWN) {
429 err = usb_submit_urb(urb, GFP_ATOMIC);
430 if (err)
431 printk(KERN_ERR "%s: resubmit read urb failed. "
432 "(%d)", __FUNCTION__, err);
435 return;
438 static void option_outdat_callback(struct urb *urb, struct pt_regs *regs)
440 struct usb_serial_port *port;
442 dbg("%s", __FUNCTION__);
444 port = (struct usb_serial_port *) urb->context;
446 usb_serial_port_softint(port);
449 static void option_instat_callback(struct urb *urb, struct pt_regs *regs)
451 int err;
452 struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
453 struct option_port_private *portdata = usb_get_serial_port_data(port);
454 struct usb_serial *serial = port->serial;
456 dbg("%s", __FUNCTION__);
457 dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata);
459 if (urb->status == 0) {
460 struct usb_ctrlrequest *req_pkt =
461 (struct usb_ctrlrequest *)urb->transfer_buffer;
463 if (!req_pkt) {
464 dbg("%s: NULL req_pkt\n", __FUNCTION__);
465 return;
467 if ((req_pkt->bRequestType == 0xA1) &&
468 (req_pkt->bRequest == 0x20)) {
469 int old_dcd_state;
470 unsigned char signals = *((unsigned char *)
471 urb->transfer_buffer +
472 sizeof(struct usb_ctrlrequest));
474 dbg("%s: signal x%x", __FUNCTION__, signals);
476 old_dcd_state = portdata->dcd_state;
477 portdata->cts_state = 1;
478 portdata->dcd_state = ((signals & 0x01) ? 1 : 0);
479 portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
480 portdata->ri_state = ((signals & 0x08) ? 1 : 0);
482 if (port->tty && !C_CLOCAL(port->tty) &&
483 old_dcd_state && !portdata->dcd_state)
484 tty_hangup(port->tty);
485 } else {
486 dbg("%s: type %x req %x", __FUNCTION__,
487 req_pkt->bRequestType,req_pkt->bRequest);
489 } else
490 dbg("%s: error %d", __FUNCTION__, urb->status);
492 /* Resubmit urb so we continue receiving IRQ data */
493 if (urb->status != -ESHUTDOWN) {
494 urb->dev = serial->dev;
495 err = usb_submit_urb(urb, GFP_ATOMIC);
496 if (err)
497 dbg("%s: resubmit intr urb failed. (%d)",
498 __FUNCTION__, err);
502 static int option_write_room(struct usb_serial_port *port)
504 struct option_port_private *portdata;
505 int i;
506 int data_len = 0;
507 struct urb *this_urb;
509 portdata = usb_get_serial_port_data(port);
511 for (i=0; i < N_OUT_URB; i++) {
512 this_urb = portdata->out_urbs[i];
513 if (this_urb && this_urb->status != -EINPROGRESS)
514 data_len += OUT_BUFLEN;
517 dbg("%s: %d", __FUNCTION__, data_len);
518 return data_len;
521 static int option_chars_in_buffer(struct usb_serial_port *port)
523 struct option_port_private *portdata;
524 int i;
525 int data_len = 0;
526 struct urb *this_urb;
528 portdata = usb_get_serial_port_data(port);
530 for (i=0; i < N_OUT_URB; i++) {
531 this_urb = portdata->out_urbs[i];
532 if (this_urb && this_urb->status == -EINPROGRESS)
533 data_len += this_urb->transfer_buffer_length;
535 dbg("%s: %d", __FUNCTION__, data_len);
536 return data_len;
539 static int option_open(struct usb_serial_port *port, struct file *filp)
541 struct option_port_private *portdata;
542 struct usb_serial *serial = port->serial;
543 int i, err;
544 struct urb *urb;
546 portdata = usb_get_serial_port_data(port);
548 dbg("%s", __FUNCTION__);
550 /* Set some sane defaults */
551 portdata->rts_state = 1;
552 portdata->dtr_state = 1;
554 /* Reset low level data toggle and start reading from endpoints */
555 for (i = 0; i < N_IN_URB; i++) {
556 urb = portdata->in_urbs[i];
557 if (! urb)
558 continue;
559 if (urb->dev != serial->dev) {
560 dbg("%s: dev %p != %p", __FUNCTION__,
561 urb->dev, serial->dev);
562 continue;
566 * make sure endpoint data toggle is synchronized with the
567 * device
569 usb_clear_halt(urb->dev, urb->pipe);
571 err = usb_submit_urb(urb, GFP_KERNEL);
572 if (err) {
573 dbg("%s: submit urb %d failed (%d) %d",
574 __FUNCTION__, i, err,
575 urb->transfer_buffer_length);
579 /* Reset low level data toggle on out endpoints */
580 for (i = 0; i < N_OUT_URB; i++) {
581 urb = portdata->out_urbs[i];
582 if (! urb)
583 continue;
584 urb->dev = serial->dev;
585 /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
586 usb_pipeout(urb->pipe), 0); */
589 port->tty->low_latency = 1;
591 option_send_setup(port);
593 return (0);
596 static inline void stop_urb(struct urb *urb)
598 if (urb && urb->status == -EINPROGRESS)
599 usb_kill_urb(urb);
602 static void option_close(struct usb_serial_port *port, struct file *filp)
604 int i;
605 struct usb_serial *serial = port->serial;
606 struct option_port_private *portdata;
608 dbg("%s", __FUNCTION__);
609 portdata = usb_get_serial_port_data(port);
611 portdata->rts_state = 0;
612 portdata->dtr_state = 0;
614 if (serial->dev) {
615 option_send_setup(port);
617 /* Stop reading/writing urbs */
618 for (i = 0; i < N_IN_URB; i++)
619 stop_urb(portdata->in_urbs[i]);
620 for (i = 0; i < N_OUT_URB; i++)
621 stop_urb(portdata->out_urbs[i]);
623 port->tty = NULL;
626 /* Helper functions used by option_setup_urbs */
627 static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint,
628 int dir, void *ctx, char *buf, int len,
629 void (*callback)(struct urb *, struct pt_regs *regs))
631 struct urb *urb;
633 if (endpoint == -1)
634 return NULL; /* endpoint not needed */
636 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
637 if (urb == NULL) {
638 dbg("%s: alloc for endpoint %d failed.", __FUNCTION__, endpoint);
639 return NULL;
642 /* Fill URB using supplied data. */
643 usb_fill_bulk_urb(urb, serial->dev,
644 usb_sndbulkpipe(serial->dev, endpoint) | dir,
645 buf, len, callback, ctx);
647 return urb;
650 /* Setup urbs */
651 static void option_setup_urbs(struct usb_serial *serial)
653 int i,j;
654 struct usb_serial_port *port;
655 struct option_port_private *portdata;
657 dbg("%s", __FUNCTION__);
660 for (i = 0; i < serial->num_ports; i++) {
661 port = serial->port[i];
662 portdata = usb_get_serial_port_data(port);
664 /* Do indat endpoints first */
665 for (j = 0; j < N_IN_URB; ++j) {
666 portdata->in_urbs[j] = option_setup_urb (serial,
667 port->bulk_in_endpointAddress, USB_DIR_IN, port,
668 portdata->in_buffer[j], IN_BUFLEN, option_indat_callback);
671 /* outdat endpoints */
672 for (j = 0; j < N_OUT_URB; ++j) {
673 portdata->out_urbs[j] = option_setup_urb (serial,
674 port->bulk_out_endpointAddress, USB_DIR_OUT, port,
675 portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback);
680 static int option_send_setup(struct usb_serial_port *port)
682 struct usb_serial *serial = port->serial;
683 struct option_port_private *portdata;
685 dbg("%s", __FUNCTION__);
687 portdata = usb_get_serial_port_data(port);
689 if (port->tty) {
690 int val = 0;
691 if (portdata->dtr_state)
692 val |= 0x01;
693 if (portdata->rts_state)
694 val |= 0x02;
696 return usb_control_msg(serial->dev,
697 usb_rcvctrlpipe(serial->dev, 0),
698 0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
701 return 0;
704 static int option_startup(struct usb_serial *serial)
706 int i, err;
707 struct usb_serial_port *port;
708 struct option_port_private *portdata;
710 dbg("%s", __FUNCTION__);
712 /* Now setup per port private data */
713 for (i = 0; i < serial->num_ports; i++) {
714 port = serial->port[i];
715 portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
716 if (!portdata) {
717 dbg("%s: kmalloc for option_port_private (%d) failed!.",
718 __FUNCTION__, i);
719 return (1);
722 usb_set_serial_port_data(port, portdata);
724 if (! port->interrupt_in_urb)
725 continue;
726 err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
727 if (err)
728 dbg("%s: submit irq_in urb failed %d",
729 __FUNCTION__, err);
732 option_setup_urbs(serial);
734 return (0);
737 static void option_shutdown(struct usb_serial *serial)
739 int i, j;
740 struct usb_serial_port *port;
741 struct option_port_private *portdata;
743 dbg("%s", __FUNCTION__);
745 /* Stop reading/writing urbs */
746 for (i = 0; i < serial->num_ports; ++i) {
747 port = serial->port[i];
748 portdata = usb_get_serial_port_data(port);
749 for (j = 0; j < N_IN_URB; j++)
750 stop_urb(portdata->in_urbs[j]);
751 for (j = 0; j < N_OUT_URB; j++)
752 stop_urb(portdata->out_urbs[j]);
755 /* Now free them */
756 for (i = 0; i < serial->num_ports; ++i) {
757 port = serial->port[i];
758 portdata = usb_get_serial_port_data(port);
760 for (j = 0; j < N_IN_URB; j++) {
761 if (portdata->in_urbs[j]) {
762 usb_free_urb(portdata->in_urbs[j]);
763 portdata->in_urbs[j] = NULL;
766 for (j = 0; j < N_OUT_URB; j++) {
767 if (portdata->out_urbs[j]) {
768 usb_free_urb(portdata->out_urbs[j]);
769 portdata->out_urbs[j] = NULL;
774 /* Now free per port private data */
775 for (i = 0; i < serial->num_ports; i++) {
776 port = serial->port[i];
777 kfree(usb_get_serial_port_data(port));
781 MODULE_AUTHOR(DRIVER_AUTHOR);
782 MODULE_DESCRIPTION(DRIVER_DESC);
783 MODULE_VERSION(DRIVER_VERSION);
784 MODULE_LICENSE("GPL");
786 #ifdef CONFIG_USB_DEBUG
787 module_param(debug, bool, S_IRUGO | S_IWUSR);
788 MODULE_PARM_DESC(debug, "Debug messages");
789 #endif