[PATCH] USB: add support for WiseGroup., Ltd SmartJoy Dual PLUS Adapter
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / usb / serial / option.c
CommitLineData
58cfe911 1/*
14f76cc7 2 USB Driver for GSM modems
58cfe911
MU
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
ba460e48 15 and analysis of misbehavior with the standard driver
58cfe911
MU
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
ba460e48
MU
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
b6137383 28 2005-09-10 v0.4.3 added HUAWEI E600 card and Audiovox AirCard
b27c73dc
MU
29 2005-09-20 v0.4.4 increased recv buffer size: the card sometimes
30 wants to send >2000 bytes.
14f76cc7
MU
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
ba460e48
MU
38
39 Work sponsored by: Sigos GmbH, Germany <info@sigos.de>
40
14f76cc7
MU
41 This driver exists because the "normal" serial driver doesn't work too well
42 with GSM modems. Issues:
43 - data loss -- one single Receive URB is not nearly enough
44 - nonstandard flow (Option devices) and multiplex (Sierra) control
45 - controlling the baud rate doesn't make sense
46
47 This driver is named "option" because the most common device it's
48 used for is a PC-Card (with an internal OHCI-USB interface, behind
49 which the GSM interface sits), made by Option Inc.
50
51 Some of the "one port" devices actually exhibit multiple USB instances
52 on the USB bus. This is not a bug, these ports are used for different
53 device features.
58cfe911 54*/
ba460e48 55
14f76cc7 56#define DRIVER_VERSION "v0.7.0"
58cfe911 57#define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"
14f76cc7 58#define DRIVER_DESC "USB Driver for GSM modems"
58cfe911 59
58cfe911
MU
60#include <linux/kernel.h>
61#include <linux/jiffies.h>
62#include <linux/errno.h>
63#include <linux/tty.h>
64#include <linux/tty_flip.h>
65#include <linux/module.h>
66#include <linux/usb.h>
67#include "usb-serial.h"
68
69/* Function prototypes */
7bb75aee
AM
70static int option_open(struct usb_serial_port *port, struct file *filp);
71static void option_close(struct usb_serial_port *port, struct file *filp);
72static int option_startup(struct usb_serial *serial);
73static void option_shutdown(struct usb_serial *serial);
74static void option_rx_throttle(struct usb_serial_port *port);
75static void option_rx_unthrottle(struct usb_serial_port *port);
76static int option_write_room(struct usb_serial_port *port);
58cfe911
MU
77
78static void option_instat_callback(struct urb *urb, struct pt_regs *regs);
79
7bb75aee
AM
80static int option_write(struct usb_serial_port *port,
81 const unsigned char *buf, int count);
58cfe911 82
7bb75aee
AM
83static int option_chars_in_buffer(struct usb_serial_port *port);
84static int option_ioctl(struct usb_serial_port *port, struct file *file,
85 unsigned int cmd, unsigned long arg);
86static void option_set_termios(struct usb_serial_port *port,
87 struct termios *old);
88static void option_break_ctl(struct usb_serial_port *port, int break_state);
89static int option_tiocmget(struct usb_serial_port *port, struct file *file);
90static int option_tiocmset(struct usb_serial_port *port, struct file *file,
91 unsigned int set, unsigned int clear);
92static int option_send_setup(struct usb_serial_port *port);
58cfe911
MU
93
94/* Vendor and product IDs */
14f76cc7
MU
95#define OPTION_VENDOR_ID 0x0AF0
96#define HUAWEI_VENDOR_ID 0x12D1
97#define AUDIOVOX_VENDOR_ID 0x0F3D
98#define SIERRAWIRELESS_VENDOR_ID 0x1199
99#define NOVATELWIRELESS_VENDOR_ID 0x1410
100
101#define OPTION_PRODUCT_OLD 0x5000
102#define OPTION_PRODUCT_FUSION 0x6000
103#define OPTION_PRODUCT_FUSION2 0x6300
104#define OPTION_PRODUCT_COBRA 0x6500
105#define HUAWEI_PRODUCT_E600 0x1001
106#define AUDIOVOX_PRODUCT_AIRCARD 0x0112
107#define SIERRAWIRELESS_PRODUCT_MC8755 0x6802
108#define NOVATELWIRELESS_PRODUCT_U740 0x1400
58cfe911 109
58cfe911
MU
110static struct usb_device_id option_ids[] = {
111 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) },
ba460e48
MU
112 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) },
113 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
14f76cc7 114 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
b6137383
MU
115 { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
116 { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
14f76cc7
MU
117 { USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) },
118 { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
119 { } /* Terminating entry */
120};
121
122static struct usb_device_id option_ids1[] = {
123 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) },
124 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) },
125 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
126 { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
127 { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
128 { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
129 { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
130 { } /* Terminating entry */
131};
132static struct usb_device_id option_ids3[] = {
133 { USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) },
58cfe911
MU
134 { } /* Terminating entry */
135};
136
137MODULE_DEVICE_TABLE(usb, option_ids);
138
139static struct usb_driver option_driver = {
58cfe911
MU
140 .name = "option",
141 .probe = usb_serial_probe,
142 .disconnect = usb_serial_disconnect,
143 .id_table = option_ids,
ba9dc657 144 .no_dynamic_id = 1,
58cfe911
MU
145};
146
c30fe7f7 147/* The card has three separate interfaces, which the serial driver
58cfe911
MU
148 * recognizes separately, thus num_port=1.
149 */
ea65370d 150static struct usb_serial_driver option_3port_device = {
18fcac35
GKH
151 .driver = {
152 .owner = THIS_MODULE,
269bda1c 153 .name = "option",
18fcac35 154 },
14f76cc7
MU
155 .description = "GSM modem (3-port)",
156 .id_table = option_ids3,
157 .num_interrupt_in = NUM_DONT_CARE,
158 .num_bulk_in = NUM_DONT_CARE,
159 .num_bulk_out = NUM_DONT_CARE,
160 .num_ports = 3,
161 .open = option_open,
162 .close = option_close,
163 .write = option_write,
164 .write_room = option_write_room,
165 .chars_in_buffer = option_chars_in_buffer,
166 .throttle = option_rx_throttle,
167 .unthrottle = option_rx_unthrottle,
168 .set_termios = option_set_termios,
169 .break_ctl = option_break_ctl,
170 .tiocmget = option_tiocmget,
171 .tiocmset = option_tiocmset,
172 .attach = option_startup,
173 .shutdown = option_shutdown,
174 .read_int_callback = option_instat_callback,
175};
176
177static struct usb_serial_driver option_1port_device = {
178 .driver = {
179 .owner = THIS_MODULE,
180 .name = "option",
181 },
182 .description = "GSM modem (1-port)",
183 .id_table = option_ids1,
ba460e48
MU
184 .num_interrupt_in = NUM_DONT_CARE,
185 .num_bulk_in = NUM_DONT_CARE,
186 .num_bulk_out = NUM_DONT_CARE,
14f76cc7 187 .num_ports = 1,
ba460e48
MU
188 .open = option_open,
189 .close = option_close,
190 .write = option_write,
191 .write_room = option_write_room,
192 .chars_in_buffer = option_chars_in_buffer,
193 .throttle = option_rx_throttle,
194 .unthrottle = option_rx_unthrottle,
195 .ioctl = option_ioctl,
196 .set_termios = option_set_termios,
197 .break_ctl = option_break_ctl,
198 .tiocmget = option_tiocmget,
199 .tiocmset = option_tiocmset,
200 .attach = option_startup,
201 .shutdown = option_shutdown,
202 .read_int_callback = option_instat_callback,
58cfe911
MU
203};
204
ba460e48 205#ifdef CONFIG_USB_DEBUG
58cfe911 206static int debug;
ba460e48
MU
207#else
208#define debug 0
209#endif
210
58cfe911
MU
211/* per port private data */
212
ba460e48
MU
213#define N_IN_URB 4
214#define N_OUT_URB 1
b27c73dc 215#define IN_BUFLEN 4096
ba460e48 216#define OUT_BUFLEN 128
58cfe911
MU
217
218struct option_port_private {
219 /* Input endpoints and buffer for this port */
ba460e48
MU
220 struct urb *in_urbs[N_IN_URB];
221 char in_buffer[N_IN_URB][IN_BUFLEN];
58cfe911 222 /* Output endpoints and buffer for this port */
ba460e48
MU
223 struct urb *out_urbs[N_OUT_URB];
224 char out_buffer[N_OUT_URB][OUT_BUFLEN];
58cfe911
MU
225
226 /* Settings for the port */
ba460e48
MU
227 int rts_state; /* Handshaking pins (outputs) */
228 int dtr_state;
229 int cts_state; /* Handshaking pins (inputs) */
230 int dsr_state;
231 int dcd_state;
232 int ri_state;
233
234 unsigned long tx_start_time[N_OUT_URB];
58cfe911
MU
235};
236
58cfe911 237/* Functions used by new usb-serial code. */
7bb75aee 238static int __init option_init(void)
58cfe911
MU
239{
240 int retval;
14f76cc7
MU
241 retval = usb_serial_register(&option_1port_device);
242 if (retval)
243 goto failed_1port_device_register;
58cfe911
MU
244 retval = usb_serial_register(&option_3port_device);
245 if (retval)
246 goto failed_3port_device_register;
247 retval = usb_register(&option_driver);
248 if (retval)
249 goto failed_driver_register;
250
251 info(DRIVER_DESC ": " DRIVER_VERSION);
252
253 return 0;
254
255failed_driver_register:
256 usb_serial_deregister (&option_3port_device);
257failed_3port_device_register:
14f76cc7
MU
258 usb_serial_deregister (&option_1port_device);
259failed_1port_device_register:
58cfe911
MU
260 return retval;
261}
262
7bb75aee 263static void __exit option_exit(void)
58cfe911
MU
264{
265 usb_deregister (&option_driver);
266 usb_serial_deregister (&option_3port_device);
14f76cc7 267 usb_serial_deregister (&option_1port_device);
58cfe911
MU
268}
269
270module_init(option_init);
271module_exit(option_exit);
272
7bb75aee 273static void option_rx_throttle(struct usb_serial_port *port)
58cfe911
MU
274{
275 dbg("%s", __FUNCTION__);
276}
277
7bb75aee 278static void option_rx_unthrottle(struct usb_serial_port *port)
58cfe911
MU
279{
280 dbg("%s", __FUNCTION__);
281}
282
7bb75aee 283static void option_break_ctl(struct usb_serial_port *port, int break_state)
58cfe911
MU
284{
285 /* Unfortunately, I don't know how to send a break */
ba460e48 286 dbg("%s", __FUNCTION__);
58cfe911
MU
287}
288
7bb75aee
AM
289static void option_set_termios(struct usb_serial_port *port,
290 struct termios *old_termios)
58cfe911
MU
291{
292 dbg("%s", __FUNCTION__);
293
294 option_send_setup(port);
295}
296
7bb75aee 297static int option_tiocmget(struct usb_serial_port *port, struct file *file)
58cfe911 298{
ba460e48
MU
299 unsigned int value;
300 struct option_port_private *portdata;
58cfe911
MU
301
302 portdata = usb_get_serial_port_data(port);
303
304 value = ((portdata->rts_state) ? TIOCM_RTS : 0) |
305 ((portdata->dtr_state) ? TIOCM_DTR : 0) |
306 ((portdata->cts_state) ? TIOCM_CTS : 0) |
307 ((portdata->dsr_state) ? TIOCM_DSR : 0) |
308 ((portdata->dcd_state) ? TIOCM_CAR : 0) |
309 ((portdata->ri_state) ? TIOCM_RNG : 0);
310
311 return value;
312}
313
7bb75aee
AM
314static int option_tiocmset(struct usb_serial_port *port, struct file *file,
315 unsigned int set, unsigned int clear)
58cfe911 316{
ba460e48 317 struct option_port_private *portdata;
58cfe911
MU
318
319 portdata = usb_get_serial_port_data(port);
320
321 if (set & TIOCM_RTS)
322 portdata->rts_state = 1;
323 if (set & TIOCM_DTR)
324 portdata->dtr_state = 1;
325
326 if (clear & TIOCM_RTS)
327 portdata->rts_state = 0;
328 if (clear & TIOCM_DTR)
329 portdata->dtr_state = 0;
330 return option_send_setup(port);
331}
332
7bb75aee
AM
333static int option_ioctl(struct usb_serial_port *port, struct file *file,
334 unsigned int cmd, unsigned long arg)
58cfe911
MU
335{
336 return -ENOIOCTLCMD;
337}
338
339/* Write */
7bb75aee
AM
340static int option_write(struct usb_serial_port *port,
341 const unsigned char *buf, int count)
58cfe911 342{
ba460e48
MU
343 struct option_port_private *portdata;
344 int i;
345 int left, todo;
346 struct urb *this_urb = NULL; /* spurious */
347 int err;
58cfe911
MU
348
349 portdata = usb_get_serial_port_data(port);
350
351 dbg("%s: write (%d chars)", __FUNCTION__, count);
352
58cfe911
MU
353 i = 0;
354 left = count;
ba460e48 355 for (i=0; left > 0 && i < N_OUT_URB; i++) {
58cfe911
MU
356 todo = left;
357 if (todo > OUT_BUFLEN)
358 todo = OUT_BUFLEN;
359
ba460e48
MU
360 this_urb = portdata->out_urbs[i];
361 if (this_urb->status == -EINPROGRESS) {
7bb75aee
AM
362 if (time_before(jiffies,
363 portdata->tx_start_time[i] + 10 * HZ))
58cfe911 364 continue;
58cfe911 365 usb_unlink_urb(this_urb);
ba460e48 366 continue;
58cfe911 367 }
ba460e48 368 if (this_urb->status != 0)
7bb75aee
AM
369 dbg("usb_write %p failed (err=%d)",
370 this_urb, this_urb->status);
58cfe911 371
7bb75aee
AM
372 dbg("%s: endpoint %d buf %d", __FUNCTION__,
373 usb_pipeendpoint(this_urb->pipe), i);
58cfe911 374
ba460e48 375 /* send the data */
58cfe911 376 memcpy (this_urb->transfer_buffer, buf, todo);
58cfe911
MU
377 this_urb->transfer_buffer_length = todo;
378
58cfe911
MU
379 this_urb->dev = port->serial->dev;
380 err = usb_submit_urb(this_urb, GFP_ATOMIC);
381 if (err) {
7bb75aee
AM
382 dbg("usb_submit_urb %p (write bulk) failed "
383 "(%d, has %d)", this_urb,
384 err, this_urb->status);
58cfe911
MU
385 continue;
386 }
387 portdata->tx_start_time[i] = jiffies;
388 buf += todo;
389 left -= todo;
390 }
391
392 count -= left;
58cfe911
MU
393 dbg("%s: wrote (did %d)", __FUNCTION__, count);
394 return count;
395}
396
7bb75aee 397static void option_indat_callback(struct urb *urb, struct pt_regs *regs)
58cfe911 398{
33f0f88f 399 int err;
58cfe911
MU
400 int endpoint;
401 struct usb_serial_port *port;
402 struct tty_struct *tty;
403 unsigned char *data = urb->transfer_buffer;
404
405 dbg("%s: %p", __FUNCTION__, urb);
406
407 endpoint = usb_pipeendpoint(urb->pipe);
408 port = (struct usb_serial_port *) urb->context;
409
410 if (urb->status) {
411 dbg("%s: nonzero status: %d on endpoint %02x.",
412 __FUNCTION__, urb->status, endpoint);
413 } else {
414 tty = port->tty;
415 if (urb->actual_length) {
33f0f88f
AC
416 tty_buffer_request_room(tty, urb->actual_length);
417 tty_insert_flip_string(tty, data, urb->actual_length);
58cfe911
MU
418 tty_flip_buffer_push(tty);
419 } else {
420 dbg("%s: empty read urb received", __FUNCTION__);
421 }
422
423 /* Resubmit urb so we continue receiving */
424 if (port->open_count && urb->status != -ESHUTDOWN) {
425 err = usb_submit_urb(urb, GFP_ATOMIC);
426 if (err)
7bb75aee
AM
427 printk(KERN_ERR "%s: resubmit read urb failed. "
428 "(%d)", __FUNCTION__, err);
58cfe911
MU
429 }
430 }
431 return;
432}
433
7bb75aee 434static void option_outdat_callback(struct urb *urb, struct pt_regs *regs)
58cfe911
MU
435{
436 struct usb_serial_port *port;
437
438 dbg("%s", __FUNCTION__);
439
440 port = (struct usb_serial_port *) urb->context;
441
cf2c7481 442 usb_serial_port_softint(port);
58cfe911
MU
443}
444
7bb75aee 445static void option_instat_callback(struct urb *urb, struct pt_regs *regs)
58cfe911
MU
446{
447 int err;
448 struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
449 struct option_port_private *portdata = usb_get_serial_port_data(port);
450 struct usb_serial *serial = port->serial;
451
452 dbg("%s", __FUNCTION__);
453 dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata);
454
455 if (urb->status == 0) {
456 struct usb_ctrlrequest *req_pkt =
457 (struct usb_ctrlrequest *)urb->transfer_buffer;
458
459 if (!req_pkt) {
460 dbg("%s: NULL req_pkt\n", __FUNCTION__);
461 return;
462 }
7bb75aee
AM
463 if ((req_pkt->bRequestType == 0xA1) &&
464 (req_pkt->bRequest == 0x20)) {
58cfe911
MU
465 int old_dcd_state;
466 unsigned char signals = *((unsigned char *)
7bb75aee
AM
467 urb->transfer_buffer +
468 sizeof(struct usb_ctrlrequest));
58cfe911
MU
469
470 dbg("%s: signal x%x", __FUNCTION__, signals);
471
472 old_dcd_state = portdata->dcd_state;
473 portdata->cts_state = 1;
474 portdata->dcd_state = ((signals & 0x01) ? 1 : 0);
475 portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
476 portdata->ri_state = ((signals & 0x08) ? 1 : 0);
477
7bb75aee
AM
478 if (port->tty && !C_CLOCAL(port->tty) &&
479 old_dcd_state && !portdata->dcd_state)
58cfe911 480 tty_hangup(port->tty);
7bb75aee
AM
481 } else {
482 dbg("%s: type %x req %x", __FUNCTION__,
483 req_pkt->bRequestType,req_pkt->bRequest);
484 }
58cfe911
MU
485 } else
486 dbg("%s: error %d", __FUNCTION__, urb->status);
487
488 /* Resubmit urb so we continue receiving IRQ data */
489 if (urb->status != -ESHUTDOWN) {
490 urb->dev = serial->dev;
491 err = usb_submit_urb(urb, GFP_ATOMIC);
492 if (err)
7bb75aee
AM
493 dbg("%s: resubmit intr urb failed. (%d)",
494 __FUNCTION__, err);
58cfe911
MU
495 }
496}
497
7bb75aee 498static int option_write_room(struct usb_serial_port *port)
58cfe911
MU
499{
500 struct option_port_private *portdata;
501 int i;
502 int data_len = 0;
503 struct urb *this_urb;
504
505 portdata = usb_get_serial_port_data(port);
506
ba460e48 507 for (i=0; i < N_OUT_URB; i++) {
58cfe911
MU
508 this_urb = portdata->out_urbs[i];
509 if (this_urb && this_urb->status != -EINPROGRESS)
510 data_len += OUT_BUFLEN;
ba460e48 511 }
58cfe911
MU
512
513 dbg("%s: %d", __FUNCTION__, data_len);
514 return data_len;
515}
516
7bb75aee 517static int option_chars_in_buffer(struct usb_serial_port *port)
58cfe911
MU
518{
519 struct option_port_private *portdata;
520 int i;
521 int data_len = 0;
522 struct urb *this_urb;
523
524 portdata = usb_get_serial_port_data(port);
525
ba460e48 526 for (i=0; i < N_OUT_URB; i++) {
58cfe911
MU
527 this_urb = portdata->out_urbs[i];
528 if (this_urb && this_urb->status == -EINPROGRESS)
529 data_len += this_urb->transfer_buffer_length;
ba460e48 530 }
58cfe911
MU
531 dbg("%s: %d", __FUNCTION__, data_len);
532 return data_len;
533}
534
7bb75aee 535static int option_open(struct usb_serial_port *port, struct file *filp)
58cfe911 536{
ba460e48
MU
537 struct option_port_private *portdata;
538 struct usb_serial *serial = port->serial;
539 int i, err;
540 struct urb *urb;
58cfe911
MU
541
542 portdata = usb_get_serial_port_data(port);
543
544 dbg("%s", __FUNCTION__);
545
546 /* Set some sane defaults */
547 portdata->rts_state = 1;
548 portdata->dtr_state = 1;
549
550 /* Reset low level data toggle and start reading from endpoints */
551 for (i = 0; i < N_IN_URB; i++) {
552 urb = portdata->in_urbs[i];
553 if (! urb)
554 continue;
555 if (urb->dev != serial->dev) {
7bb75aee
AM
556 dbg("%s: dev %p != %p", __FUNCTION__,
557 urb->dev, serial->dev);
58cfe911
MU
558 continue;
559 }
560
7bb75aee
AM
561 /*
562 * make sure endpoint data toggle is synchronized with the
563 * device
564 */
58cfe911
MU
565 usb_clear_halt(urb->dev, urb->pipe);
566
567 err = usb_submit_urb(urb, GFP_KERNEL);
568 if (err) {
7bb75aee
AM
569 dbg("%s: submit urb %d failed (%d) %d",
570 __FUNCTION__, i, err,
58cfe911
MU
571 urb->transfer_buffer_length);
572 }
573 }
574
575 /* Reset low level data toggle on out endpoints */
576 for (i = 0; i < N_OUT_URB; i++) {
577 urb = portdata->out_urbs[i];
578 if (! urb)
579 continue;
580 urb->dev = serial->dev;
7bb75aee
AM
581 /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
582 usb_pipeout(urb->pipe), 0); */
58cfe911
MU
583 }
584
585 port->tty->low_latency = 1;
586
587 option_send_setup(port);
588
589 return (0);
590}
591
7bb75aee 592static inline void stop_urb(struct urb *urb)
58cfe911 593{
242cf670 594 if (urb && urb->status == -EINPROGRESS)
58cfe911 595 usb_kill_urb(urb);
58cfe911
MU
596}
597
7bb75aee 598static void option_close(struct usb_serial_port *port, struct file *filp)
58cfe911 599{
ba460e48
MU
600 int i;
601 struct usb_serial *serial = port->serial;
602 struct option_port_private *portdata;
58cfe911
MU
603
604 dbg("%s", __FUNCTION__);
605 portdata = usb_get_serial_port_data(port);
606
607 portdata->rts_state = 0;
608 portdata->dtr_state = 0;
609
610 if (serial->dev) {
611 option_send_setup(port);
612
613 /* Stop reading/writing urbs */
614 for (i = 0; i < N_IN_URB; i++)
615 stop_urb(portdata->in_urbs[i]);
616 for (i = 0; i < N_OUT_URB; i++)
617 stop_urb(portdata->out_urbs[i]);
618 }
619 port->tty = NULL;
620}
621
58cfe911 622/* Helper functions used by option_setup_urbs */
7bb75aee
AM
623static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint,
624 int dir, void *ctx, char *buf, int len,
625 void (*callback)(struct urb *, struct pt_regs *regs))
58cfe911
MU
626{
627 struct urb *urb;
628
629 if (endpoint == -1)
630 return NULL; /* endpoint not needed */
631
632 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
633 if (urb == NULL) {
634 dbg("%s: alloc for endpoint %d failed.", __FUNCTION__, endpoint);
635 return NULL;
636 }
637
638 /* Fill URB using supplied data. */
639 usb_fill_bulk_urb(urb, serial->dev,
640 usb_sndbulkpipe(serial->dev, endpoint) | dir,
641 buf, len, callback, ctx);
642
643 return urb;
644}
645
646/* Setup urbs */
7bb75aee 647static void option_setup_urbs(struct usb_serial *serial)
58cfe911 648{
14f76cc7 649 int i,j;
ba460e48
MU
650 struct usb_serial_port *port;
651 struct option_port_private *portdata;
58cfe911
MU
652
653 dbg("%s", __FUNCTION__);
654
14f76cc7
MU
655
656 for (i = 0; i < serial->num_ports; i++) {
657 port = serial->port[i];
658 portdata = usb_get_serial_port_data(port);
58cfe911
MU
659
660 /* Do indat endpoints first */
14f76cc7
MU
661 for (j = 0; j < N_IN_URB; ++j) {
662 portdata->in_urbs[j] = option_setup_urb (serial,
663 port->bulk_in_endpointAddress, USB_DIR_IN, port,
664 portdata->in_buffer[j], IN_BUFLEN, option_indat_callback);
665 }
58cfe911 666
14f76cc7
MU
667 /* outdat endpoints */
668 for (j = 0; j < N_OUT_URB; ++j) {
669 portdata->out_urbs[j] = option_setup_urb (serial,
670 port->bulk_out_endpointAddress, USB_DIR_OUT, port,
671 portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback);
672 }
58cfe911
MU
673 }
674}
675
7bb75aee 676static int option_send_setup(struct usb_serial_port *port)
58cfe911
MU
677{
678 struct usb_serial *serial = port->serial;
679 struct option_port_private *portdata;
680
681 dbg("%s", __FUNCTION__);
682
683 portdata = usb_get_serial_port_data(port);
684
685 if (port->tty) {
686 int val = 0;
687 if (portdata->dtr_state)
688 val |= 0x01;
689 if (portdata->rts_state)
690 val |= 0x02;
691
7bb75aee
AM
692 return usb_control_msg(serial->dev,
693 usb_rcvctrlpipe(serial->dev, 0),
694 0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
58cfe911
MU
695 }
696
697 return 0;
698}
699
7bb75aee 700static int option_startup(struct usb_serial *serial)
58cfe911 701{
ba460e48
MU
702 int i, err;
703 struct usb_serial_port *port;
704 struct option_port_private *portdata;
58cfe911
MU
705
706 dbg("%s", __FUNCTION__);
707
708 /* Now setup per port private data */
709 for (i = 0; i < serial->num_ports; i++) {
710 port = serial->port[i];
80b6ca48 711 portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
58cfe911 712 if (!portdata) {
7bb75aee
AM
713 dbg("%s: kmalloc for option_port_private (%d) failed!.",
714 __FUNCTION__, i);
58cfe911
MU
715 return (1);
716 }
58cfe911
MU
717
718 usb_set_serial_port_data(port, portdata);
719
720 if (! port->interrupt_in_urb)
721 continue;
722 err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
723 if (err)
7bb75aee
AM
724 dbg("%s: submit irq_in urb failed %d",
725 __FUNCTION__, err);
58cfe911
MU
726 }
727
728 option_setup_urbs(serial);
729
730 return (0);
731}
732
7bb75aee 733static void option_shutdown(struct usb_serial *serial)
58cfe911 734{
ba460e48
MU
735 int i, j;
736 struct usb_serial_port *port;
737 struct option_port_private *portdata;
58cfe911
MU
738
739 dbg("%s", __FUNCTION__);
740
741 /* Stop reading/writing urbs */
742 for (i = 0; i < serial->num_ports; ++i) {
743 port = serial->port[i];
744 portdata = usb_get_serial_port_data(port);
745 for (j = 0; j < N_IN_URB; j++)
746 stop_urb(portdata->in_urbs[j]);
747 for (j = 0; j < N_OUT_URB; j++)
748 stop_urb(portdata->out_urbs[j]);
749 }
750
751 /* Now free them */
752 for (i = 0; i < serial->num_ports; ++i) {
753 port = serial->port[i];
754 portdata = usb_get_serial_port_data(port);
755
756 for (j = 0; j < N_IN_URB; j++) {
757 if (portdata->in_urbs[j]) {
758 usb_free_urb(portdata->in_urbs[j]);
759 portdata->in_urbs[j] = NULL;
760 }
761 }
762 for (j = 0; j < N_OUT_URB; j++) {
763 if (portdata->out_urbs[j]) {
764 usb_free_urb(portdata->out_urbs[j]);
765 portdata->out_urbs[j] = NULL;
766 }
767 }
768 }
769
770 /* Now free per port private data */
771 for (i = 0; i < serial->num_ports; i++) {
772 port = serial->port[i];
773 kfree(usb_get_serial_port_data(port));
774 }
775}
776
777MODULE_AUTHOR(DRIVER_AUTHOR);
778MODULE_DESCRIPTION(DRIVER_DESC);
779MODULE_VERSION(DRIVER_VERSION);
780MODULE_LICENSE("GPL");
781
ba460e48 782#ifdef CONFIG_USB_DEBUG
58cfe911
MU
783module_param(debug, bool, S_IRUGO | S_IWUSR);
784MODULE_PARM_DESC(debug, "Debug messages");
ba460e48 785#endif
58cfe911 786