aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Lloyd <linux@sierrawireless.com>2006-10-14 02:53:21 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-10-17 17:46:34 -0400
commit033a3fb980b041c5b1c865d3e9dce9217d1dc94b (patch)
tree7e3f80114f01621e83885387b7fad80177071e48
parent5c09d144ff94706c2a5df292329ad83a27380173 (diff)
USB: Sierra Wireless driver update
The largest feature in this patch is that it adds significant throughput increase to the Sierra driver and adds support for modem status line control (e.g. the DTR line). This patch also updates the current sierra.c driver so that it supports both 3-port Sierra devices and 1-port legacy devices and removes Sierra's references in other related files (Kconfig and airprime.c). Signed-off-by: Kevin Lloyd <linux@sierrawireless.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/serial/Kconfig3
-rw-r--r--drivers/usb/serial/airprime.c5
-rw-r--r--drivers/usb/serial/sierra.c729
3 files changed, 699 insertions, 38 deletions
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 8ca6d3f01e85..9a6ec1b5e3d5 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -537,8 +537,7 @@ config USB_SERIAL_OPTION
537 The USB bus on these cards is not accessible externally. 537 The USB bus on these cards is not accessible externally.
538 538
539 Supported devices include (some of?) those made by: 539 Supported devices include (some of?) those made by:
540 Option, Huawei, Audiovox, Sierra Wireless, Novatel Wireless, or 540 Option, Huawei, Audiovox, Novatel Wireless, or Anydata.
541 Anydata.
542 541
543 To compile this driver as a module, choose M here: the 542 To compile this driver as a module, choose M here: the
544 module will be called option. 543 module will be called option.
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index ba93c72cdba0..7f5d546da39a 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -18,11 +18,6 @@
18 18
19static struct usb_device_id id_table [] = { 19static struct usb_device_id id_table [] = {
20 { USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */ 20 { USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */
21 { USB_DEVICE(0x0f3d, 0x0112) }, /* AirPrime CDMA Wireless PC Card */
22 { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */
23 { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */
24 { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless Aircard 580 */
25 { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */
26 { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */ 21 { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */
27 { USB_DEVICE(0x1410, 0x1100) }, /* ExpressCard34 Qualcomm 3G CDMA */ 22 { USB_DEVICE(0x1410, 0x1100) }, /* ExpressCard34 Qualcomm 3G CDMA */
28 { }, 23 { },
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index d29638daa987..39799d21b855 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -1,21 +1,59 @@
1/* 1/*
2 * Sierra Wireless CDMA Wireless Serial USB driver 2 USB Driver for Sierra Wireless
3 * 3
4 * Current Copy modified by: Kevin Lloyd <linux@sierrawireless.com> 4 Copyright (C) 2006 Kevin Lloyd <linux@sierrawireless.com>
5 * Original Copyright (C) 2005-2006 Greg Kroah-Hartman <gregkh@suse.de> 5
6 * 6 IMPORTANT DISCLAIMER: This driver is not commercially supported by
7 * This program is free software; you can redistribute it and/or 7 Sierra Wireless. Use at your own risk.
8 * modify it under the terms of the GNU General Public License version 8
9 * 2 as published by the Free Software Foundation. 9 This driver is free software; you can redistribute it and/or modify
10 */ 10 it under the terms of Version 2 of the GNU General Public License as
11 published by the Free Software Foundation.
12
13 Portions based on the option driver by Matthias Urlichs <smurf@smurf.noris.de>
14 Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org>
15
16 History:
17*/
18
19#define DRIVER_VERSION "v.1.0.5"
20#define DRIVER_AUTHOR "Kevin Lloyd <linux@sierrawireless.com>"
21#define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
11 22
12#include <linux/kernel.h> 23#include <linux/kernel.h>
13#include <linux/init.h> 24#include <linux/jiffies.h>
25#include <linux/errno.h>
14#include <linux/tty.h> 26#include <linux/tty.h>
27#include <linux/tty_flip.h>
15#include <linux/module.h> 28#include <linux/module.h>
16#include <linux/usb.h> 29#include <linux/usb.h>
17#include <linux/usb/serial.h> 30#include <linux/usb/serial.h>
18 31
32/* Function prototypes */
33static int sierra_open(struct usb_serial_port *port, struct file *filp);
34static void sierra_close(struct usb_serial_port *port, struct file *filp);
35static int sierra_startup(struct usb_serial *serial);
36static void sierra_shutdown(struct usb_serial *serial);
37static void sierra_rx_throttle(struct usb_serial_port *port);
38static void sierra_rx_unthrottle(struct usb_serial_port *port);
39static int sierra_write_room(struct usb_serial_port *port);
40
41static void sierra_instat_callback(struct urb *urb);
42
43static int sierra_write(struct usb_serial_port *port,
44 const unsigned char *buf, int count);
45
46static int sierra_chars_in_buffer(struct usb_serial_port *port);
47static int sierra_ioctl(struct usb_serial_port *port, struct file *file,
48 unsigned int cmd, unsigned long arg);
49static void sierra_set_termios(struct usb_serial_port *port,
50 struct termios *old);
51static void sierra_break_ctl(struct usb_serial_port *port, int break_state);
52static int sierra_tiocmget(struct usb_serial_port *port, struct file *file);
53static int sierra_tiocmset(struct usb_serial_port *port, struct file *file,
54 unsigned int set, unsigned int clear);
55static int sierra_send_setup(struct usb_serial_port *port);
56
19static struct usb_device_id id_table [] = { 57static struct usb_device_id id_table [] = {
20 { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ 58 { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */
21 { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ 59 { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */
@@ -25,51 +63,680 @@ static struct usb_device_id id_table [] = {
25 { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ 63 { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */
26 { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */ 64 { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */
27 { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ 65 { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */
28 /* Following devices are supported in the airprime.c driver */ 66
29 /* { USB_DEVICE(0x1199, 0x0112) }, */ /* Sierra Wireless AirCard 580 */ 67 { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */
30 /* { USB_DEVICE(0x0F3D, 0x0112) }, */ /* AirPrime/Sierra PC 5220 */ 68 { USB_DEVICE(0x0F3D, 0x0112) }, /* AirPrime/Sierra PC 5220 */
69 { }
70};
71
72static struct usb_device_id id_table_1port [] = {
73 { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */
74 { USB_DEVICE(0x0F3D, 0x0112) }, /* AirPrime/Sierra PC 5220 */
31 { } 75 { }
32}; 76};
77
78static struct usb_device_id id_table_3port [] = {
79 { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */
80 { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */
81 { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */
82 { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */
83 { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */
84 { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */
85 { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */
86 { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */
87 { }
88};
89
90
33MODULE_DEVICE_TABLE(usb, id_table); 91MODULE_DEVICE_TABLE(usb, id_table);
34 92
35static struct usb_driver sierra_driver = { 93static struct usb_driver sierra_driver = {
36 .name = "sierra_wireless", 94 .name = "sierra",
37 .probe = usb_serial_probe, 95 .probe = usb_serial_probe,
38 .disconnect = usb_serial_disconnect, 96 .disconnect = usb_serial_disconnect,
39 .id_table = id_table, 97 .id_table = id_table,
98 .no_dynamic_id = 3,
99};
100
101
102//static struct usb_serial_driver *sierra_device;
103
104static struct usb_serial_driver sierra_1port_device = {
105 .driver = {
106 .owner = THIS_MODULE,
107 .name = "sierra1",
108 },
109 .description = "Sierra USB modem (1 port)",
110 .id_table = id_table_1port,
111 .num_interrupt_in = NUM_DONT_CARE,
112 .num_bulk_in = 1,
113 .num_bulk_out = 1,
114 .num_ports = 1,
115 .open = sierra_open,
116 .close = sierra_close,
117 .write = sierra_write,
118 .write_room = sierra_write_room,
119 .chars_in_buffer = sierra_chars_in_buffer,
120 .throttle = sierra_rx_throttle,
121 .unthrottle = sierra_rx_unthrottle,
122 .ioctl = sierra_ioctl,
123 .set_termios = sierra_set_termios,
124 .break_ctl = sierra_break_ctl,
125 .tiocmget = sierra_tiocmget,
126 .tiocmset = sierra_tiocmset,
127 .attach = sierra_startup,
128 .shutdown = sierra_shutdown,
129 .read_int_callback = sierra_instat_callback,
40}; 130};
41 131
42static struct usb_serial_driver sierra_device = { 132static struct usb_serial_driver sierra_3port_device = {
43 .driver = { 133 .driver = {
44 .owner = THIS_MODULE, 134 .owner = THIS_MODULE,
45 .name = "Sierra_Wireless", 135 .name = "sierra3",
46 }, 136 },
47 .id_table = id_table, 137 .description = "Sierra USB modem (3 port)",
48 .num_interrupt_in = NUM_DONT_CARE, 138 .id_table = id_table_3port,
49 .num_bulk_in = NUM_DONT_CARE, 139 .num_interrupt_in = NUM_DONT_CARE,
50 .num_bulk_out = NUM_DONT_CARE, 140 .num_bulk_in = 3,
51 .num_ports = 3, 141 .num_bulk_out = 3,
142 .num_ports = 3,
143 .open = sierra_open,
144 .close = sierra_close,
145 .write = sierra_write,
146 .write_room = sierra_write_room,
147 .chars_in_buffer = sierra_chars_in_buffer,
148 .throttle = sierra_rx_throttle,
149 .unthrottle = sierra_rx_unthrottle,
150 .ioctl = sierra_ioctl,
151 .set_termios = sierra_set_termios,
152 .break_ctl = sierra_break_ctl,
153 .tiocmget = sierra_tiocmget,
154 .tiocmset = sierra_tiocmset,
155 .attach = sierra_startup,
156 .shutdown = sierra_shutdown,
157 .read_int_callback = sierra_instat_callback,
52}; 158};
53 159
160#ifdef CONFIG_USB_DEBUG
161static int debug;
162#else
163#define debug 0
164#endif
165
166/* per port private data */
167
168#define N_IN_URB 4
169#define N_OUT_URB 1
170#define IN_BUFLEN 4096
171#define OUT_BUFLEN 128
172
173struct sierra_port_private {
174 /* Input endpoints and buffer for this port */
175 struct urb *in_urbs[N_IN_URB];
176 char in_buffer[N_IN_URB][IN_BUFLEN];
177 /* Output endpoints and buffer for this port */
178 struct urb *out_urbs[N_OUT_URB];
179 char out_buffer[N_OUT_URB][OUT_BUFLEN];
180
181 /* Settings for the port */
182 int rts_state; /* Handshaking pins (outputs) */
183 int dtr_state;
184 int cts_state; /* Handshaking pins (inputs) */
185 int dsr_state;
186 int dcd_state;
187 int ri_state;
188
189 unsigned long tx_start_time[N_OUT_URB];
190};
191
192/* Functions used by new usb-serial code. */
54static int __init sierra_init(void) 193static int __init sierra_init(void)
55{ 194{
56 int retval; 195 int retval;
57 196 retval = usb_serial_register(&sierra_1port_device);
58 retval = usb_serial_register(&sierra_device); 197 if (retval)
198 goto failed_1port_device_register;
199 retval = usb_serial_register(&sierra_3port_device);
59 if (retval) 200 if (retval)
60 return retval; 201 goto failed_3port_device_register;
202
203
61 retval = usb_register(&sierra_driver); 204 retval = usb_register(&sierra_driver);
62 if (retval) 205 if (retval)
63 usb_serial_deregister(&sierra_device); 206 goto failed_driver_register;
207
208 info(DRIVER_DESC ": " DRIVER_VERSION);
209
210 return 0;
211
212failed_driver_register:
213 usb_serial_deregister(&sierra_3port_device);
214failed_3port_device_register:
215 usb_serial_deregister(&sierra_1port_device);
216failed_1port_device_register:
64 return retval; 217 return retval;
65} 218}
66 219
67static void __exit sierra_exit(void) 220static void __exit sierra_exit(void)
68{ 221{
69 usb_deregister(&sierra_driver); 222 usb_deregister (&sierra_driver);
70 usb_serial_deregister(&sierra_device); 223 usb_serial_deregister(&sierra_1port_device);
224 usb_serial_deregister(&sierra_3port_device);
71} 225}
72 226
73module_init(sierra_init); 227module_init(sierra_init);
74module_exit(sierra_exit); 228module_exit(sierra_exit);
229
230static void sierra_rx_throttle(struct usb_serial_port *port)
231{
232 dbg("%s", __FUNCTION__);
233}
234
235static void sierra_rx_unthrottle(struct usb_serial_port *port)
236{
237 dbg("%s", __FUNCTION__);
238}
239
240static void sierra_break_ctl(struct usb_serial_port *port, int break_state)
241{
242 /* Unfortunately, I don't know how to send a break */
243 dbg("%s", __FUNCTION__);
244}
245
246static void sierra_set_termios(struct usb_serial_port *port,
247 struct termios *old_termios)
248{
249 dbg("%s", __FUNCTION__);
250
251 sierra_send_setup(port);
252}
253
254static int sierra_tiocmget(struct usb_serial_port *port, struct file *file)
255{
256 unsigned int value;
257 struct sierra_port_private *portdata;
258
259 portdata = usb_get_serial_port_data(port);
260
261 value = ((portdata->rts_state) ? TIOCM_RTS : 0) |
262 ((portdata->dtr_state) ? TIOCM_DTR : 0) |
263 ((portdata->cts_state) ? TIOCM_CTS : 0) |
264 ((portdata->dsr_state) ? TIOCM_DSR : 0) |
265 ((portdata->dcd_state) ? TIOCM_CAR : 0) |
266 ((portdata->ri_state) ? TIOCM_RNG : 0);
267
268 return value;
269}
270
271static int sierra_tiocmset(struct usb_serial_port *port, struct file *file,
272 unsigned int set, unsigned int clear)
273{
274 struct sierra_port_private *portdata;
275
276 portdata = usb_get_serial_port_data(port);
277
278 if (set & TIOCM_RTS)
279 portdata->rts_state = 1;
280 if (set & TIOCM_DTR)
281 portdata->dtr_state = 1;
282
283 if (clear & TIOCM_RTS)
284 portdata->rts_state = 0;
285 if (clear & TIOCM_DTR)
286 portdata->dtr_state = 0;
287 return sierra_send_setup(port);
288}
289
290static int sierra_ioctl(struct usb_serial_port *port, struct file *file,
291 unsigned int cmd, unsigned long arg)
292{
293 return -ENOIOCTLCMD;
294}
295
296/* Write */
297static int sierra_write(struct usb_serial_port *port,
298 const unsigned char *buf, int count)
299{
300 struct sierra_port_private *portdata;
301 int i;
302 int left, todo;
303 struct urb *this_urb = NULL; /* spurious */
304 int err;
305
306 portdata = usb_get_serial_port_data(port);
307
308 dbg("%s: write (%d chars)", __FUNCTION__, count);
309
310 i = 0;
311 left = count;
312 for (i=0; left > 0 && i < N_OUT_URB; i++) {
313 todo = left;
314 if (todo > OUT_BUFLEN)
315 todo = OUT_BUFLEN;
316
317 this_urb = portdata->out_urbs[i];
318 if (this_urb->status == -EINPROGRESS) {
319 if (time_before(jiffies,
320 portdata->tx_start_time[i] + 10 * HZ))
321 continue;
322 usb_unlink_urb(this_urb);
323 continue;
324 }
325 if (this_urb->status != 0)
326 dbg("usb_write %p failed (err=%d)",
327 this_urb, this_urb->status);
328
329 dbg("%s: endpoint %d buf %d", __FUNCTION__,
330 usb_pipeendpoint(this_urb->pipe), i);
331
332 /* send the data */
333 memcpy (this_urb->transfer_buffer, buf, todo);
334 this_urb->transfer_buffer_length = todo;
335
336 this_urb->dev = port->serial->dev;
337 err = usb_submit_urb(this_urb, GFP_ATOMIC);
338 if (err) {
339 dbg("usb_submit_urb %p (write bulk) failed "
340 "(%d, has %d)", this_urb,
341 err, this_urb->status);
342 continue;
343 }
344 portdata->tx_start_time[i] = jiffies;
345 buf += todo;
346 left -= todo;
347 }
348
349 count -= left;
350 dbg("%s: wrote (did %d)", __FUNCTION__, count);
351 return count;
352}
353
354static void sierra_indat_callback(struct urb *urb)
355{
356 int err;
357 int endpoint;
358 struct usb_serial_port *port;
359 struct tty_struct *tty;
360 unsigned char *data = urb->transfer_buffer;
361
362 dbg("%s: %p", __FUNCTION__, urb);
363
364 endpoint = usb_pipeendpoint(urb->pipe);
365 port = (struct usb_serial_port *) urb->context;
366
367 if (urb->status) {
368 dbg("%s: nonzero status: %d on endpoint %02x.",
369 __FUNCTION__, urb->status, endpoint);
370 } else {
371 tty = port->tty;
372 if (urb->actual_length) {
373 tty_buffer_request_room(tty, urb->actual_length);
374 tty_insert_flip_string(tty, data, urb->actual_length);
375 tty_flip_buffer_push(tty);
376 } else {
377 dbg("%s: empty read urb received", __FUNCTION__);
378 }
379
380 /* Resubmit urb so we continue receiving */
381 if (port->open_count && urb->status != -ESHUTDOWN) {
382 err = usb_submit_urb(urb, GFP_ATOMIC);
383 if (err)
384 printk(KERN_ERR "%s: resubmit read urb failed. "
385 "(%d)", __FUNCTION__, err);
386 }
387 }
388 return;
389}
390
391static void sierra_outdat_callback(struct urb *urb)
392{
393 struct usb_serial_port *port;
394
395 dbg("%s", __FUNCTION__);
396
397 port = (struct usb_serial_port *) urb->context;
398
399 usb_serial_port_softint(port);
400}
401
402static void sierra_instat_callback(struct urb *urb)
403{
404 int err;
405 struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
406 struct sierra_port_private *portdata = usb_get_serial_port_data(port);
407 struct usb_serial *serial = port->serial;
408
409 dbg("%s", __FUNCTION__);
410 dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata);
411
412 if (urb->status == 0) {
413 struct usb_ctrlrequest *req_pkt =
414 (struct usb_ctrlrequest *)urb->transfer_buffer;
415
416 if (!req_pkt) {
417 dbg("%s: NULL req_pkt\n", __FUNCTION__);
418 return;
419 }
420 if ((req_pkt->bRequestType == 0xA1) &&
421 (req_pkt->bRequest == 0x20)) {
422 int old_dcd_state;
423 unsigned char signals = *((unsigned char *)
424 urb->transfer_buffer +
425 sizeof(struct usb_ctrlrequest));
426
427 dbg("%s: signal x%x", __FUNCTION__, signals);
428
429 old_dcd_state = portdata->dcd_state;
430 portdata->cts_state = 1;
431 portdata->dcd_state = ((signals & 0x01) ? 1 : 0);
432 portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
433 portdata->ri_state = ((signals & 0x08) ? 1 : 0);
434
435 if (port->tty && !C_CLOCAL(port->tty) &&
436 old_dcd_state && !portdata->dcd_state)
437 tty_hangup(port->tty);
438 } else {
439 dbg("%s: type %x req %x", __FUNCTION__,
440 req_pkt->bRequestType,req_pkt->bRequest);
441 }
442 } else
443 dbg("%s: error %d", __FUNCTION__, urb->status);
444
445 /* Resubmit urb so we continue receiving IRQ data */
446 if (urb->status != -ESHUTDOWN) {
447 urb->dev = serial->dev;
448 err = usb_submit_urb(urb, GFP_ATOMIC);
449 if (err)
450 dbg("%s: resubmit intr urb failed. (%d)",
451 __FUNCTION__, err);
452 }
453}
454
455static int sierra_write_room(struct usb_serial_port *port)
456{
457 struct sierra_port_private *portdata;
458 int i;
459 int data_len = 0;
460 struct urb *this_urb;
461
462 portdata = usb_get_serial_port_data(port);
463
464 for (i=0; i < N_OUT_URB; i++) {
465 this_urb = portdata->out_urbs[i];
466 if (this_urb && this_urb->status != -EINPROGRESS)
467 data_len += OUT_BUFLEN;
468 }
469
470 dbg("%s: %d", __FUNCTION__, data_len);
471 return data_len;
472}
473
474static int sierra_chars_in_buffer(struct usb_serial_port *port)
475{
476 struct sierra_port_private *portdata;
477 int i;
478 int data_len = 0;
479 struct urb *this_urb;
480
481 portdata = usb_get_serial_port_data(port);
482
483 for (i=0; i < N_OUT_URB; i++) {
484 this_urb = portdata->out_urbs[i];
485 if (this_urb && this_urb->status == -EINPROGRESS)
486 data_len += this_urb->transfer_buffer_length;
487 }
488 dbg("%s: %d", __FUNCTION__, data_len);
489 return data_len;
490}
491
492static int sierra_open(struct usb_serial_port *port, struct file *filp)
493{
494 struct sierra_port_private *portdata;
495 struct usb_serial *serial = port->serial;
496 int i, err;
497 struct urb *urb;
498
499 portdata = usb_get_serial_port_data(port);
500
501 dbg("%s", __FUNCTION__);
502
503 /* Set some sane defaults */
504 portdata->rts_state = 1;
505 portdata->dtr_state = 1;
506
507 /* Reset low level data toggle and start reading from endpoints */
508 for (i = 0; i < N_IN_URB; i++) {
509 urb = portdata->in_urbs[i];
510 if (! urb)
511 continue;
512 if (urb->dev != serial->dev) {
513 dbg("%s: dev %p != %p", __FUNCTION__,
514 urb->dev, serial->dev);
515 continue;
516 }
517
518 /*
519 * make sure endpoint data toggle is synchronized with the
520 * device
521 */
522 usb_clear_halt(urb->dev, urb->pipe);
523
524 err = usb_submit_urb(urb, GFP_KERNEL);
525 if (err) {
526 dbg("%s: submit urb %d failed (%d) %d",
527 __FUNCTION__, i, err,
528 urb->transfer_buffer_length);
529 }
530 }
531
532 /* Reset low level data toggle on out endpoints */
533 for (i = 0; i < N_OUT_URB; i++) {
534 urb = portdata->out_urbs[i];
535 if (! urb)
536 continue;
537 urb->dev = serial->dev;
538 /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
539 usb_pipeout(urb->pipe), 0); */
540 }
541
542 port->tty->low_latency = 1;
543
544 sierra_send_setup(port);
545
546 return (0);
547}
548
549static inline void stop_urb(struct urb *urb)
550{
551 if (urb && urb->status == -EINPROGRESS)
552 usb_kill_urb(urb);
553}
554
555static void sierra_close(struct usb_serial_port *port, struct file *filp)
556{
557 int i;
558 struct usb_serial *serial = port->serial;
559 struct sierra_port_private *portdata;
560
561 dbg("%s", __FUNCTION__);
562 portdata = usb_get_serial_port_data(port);
563
564 portdata->rts_state = 0;
565 portdata->dtr_state = 0;
566
567 if (serial->dev) {
568 sierra_send_setup(port);
569
570 /* Stop reading/writing urbs */
571 for (i = 0; i < N_IN_URB; i++)
572 stop_urb(portdata->in_urbs[i]);
573 for (i = 0; i < N_OUT_URB; i++)
574 stop_urb(portdata->out_urbs[i]);
575 }
576 port->tty = NULL;
577}
578
579/* Helper functions used by sierra_setup_urbs */
580static struct urb *sierra_setup_urb(struct usb_serial *serial, int endpoint,
581 int dir, void *ctx, char *buf, int len,
582 void (*callback)(struct urb *))
583{
584 struct urb *urb;
585
586 if (endpoint == -1)
587 return NULL; /* endpoint not needed */
588
589 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
590 if (urb == NULL) {
591 dbg("%s: alloc for endpoint %d failed.", __FUNCTION__, endpoint);
592 return NULL;
593 }
594
595 /* Fill URB using supplied data. */
596 usb_fill_bulk_urb(urb, serial->dev,
597 usb_sndbulkpipe(serial->dev, endpoint) | dir,
598 buf, len, callback, ctx);
599
600 return urb;
601}
602
603/* Setup urbs */
604static void sierra_setup_urbs(struct usb_serial *serial)
605{
606 int i,j;
607 struct usb_serial_port *port;
608 struct sierra_port_private *portdata;
609
610 dbg("%s", __FUNCTION__);
611
612 for (i = 0; i < serial->num_ports; i++) {
613 port = serial->port[i];
614 portdata = usb_get_serial_port_data(port);
615
616 /* Do indat endpoints first */
617 for (j = 0; j < N_IN_URB; ++j) {
618 portdata->in_urbs[j] = sierra_setup_urb (serial,
619 port->bulk_in_endpointAddress, USB_DIR_IN, port,
620 portdata->in_buffer[j], IN_BUFLEN, sierra_indat_callback);
621 }
622
623 /* outdat endpoints */
624 for (j = 0; j < N_OUT_URB; ++j) {
625 portdata->out_urbs[j] = sierra_setup_urb (serial,
626 port->bulk_out_endpointAddress, USB_DIR_OUT, port,
627 portdata->out_buffer[j], OUT_BUFLEN, sierra_outdat_callback);
628 }
629 }
630}
631
632static int sierra_send_setup(struct usb_serial_port *port)
633{
634 struct usb_serial *serial = port->serial;
635 struct sierra_port_private *portdata;
636
637 dbg("%s", __FUNCTION__);
638
639 portdata = usb_get_serial_port_data(port);
640
641 if (port->tty) {
642 int val = 0;
643 if (portdata->dtr_state)
644 val |= 0x01;
645 if (portdata->rts_state)
646 val |= 0x02;
647
648 return usb_control_msg(serial->dev,
649 usb_rcvctrlpipe(serial->dev, 0),
650 0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
651 }
652
653 return 0;
654}
655
656static int sierra_startup(struct usb_serial *serial)
657{
658 int i, err;
659 struct usb_serial_port *port;
660 struct sierra_port_private *portdata;
661
662 dbg("%s", __FUNCTION__);
663
664 /* Now setup per port private data */
665 for (i = 0; i < serial->num_ports; i++) {
666 port = serial->port[i];
667 portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
668 if (!portdata) {
669 dbg("%s: kmalloc for sierra_port_private (%d) failed!.",
670 __FUNCTION__, i);
671 return (1);
672 }
673
674 usb_set_serial_port_data(port, portdata);
675
676 if (! port->interrupt_in_urb)
677 continue;
678 err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
679 if (err)
680 dbg("%s: submit irq_in urb failed %d",
681 __FUNCTION__, err);
682 }
683
684 sierra_setup_urbs(serial);
685
686 return (0);
687}
688
689static void sierra_shutdown(struct usb_serial *serial)
690{
691 int i, j;
692 struct usb_serial_port *port;
693 struct sierra_port_private *portdata;
694
695 dbg("%s", __FUNCTION__);
696
697 /* Stop reading/writing urbs */
698 for (i = 0; i < serial->num_ports; ++i) {
699 port = serial->port[i];
700 portdata = usb_get_serial_port_data(port);
701 for (j = 0; j < N_IN_URB; j++)
702 stop_urb(portdata->in_urbs[j]);
703 for (j = 0; j < N_OUT_URB; j++)
704 stop_urb(portdata->out_urbs[j]);
705 }
706
707 /* Now free them */
708 for (i = 0; i < serial->num_ports; ++i) {
709 port = serial->port[i];
710 portdata = usb_get_serial_port_data(port);
711
712 for (j = 0; j < N_IN_URB; j++) {
713 if (portdata->in_urbs[j]) {
714 usb_free_urb(portdata->in_urbs[j]);
715 portdata->in_urbs[j] = NULL;
716 }
717 }
718 for (j = 0; j < N_OUT_URB; j++) {
719 if (portdata->out_urbs[j]) {
720 usb_free_urb(portdata->out_urbs[j]);
721 portdata->out_urbs[j] = NULL;
722 }
723 }
724 }
725
726 /* Now free per port private data */
727 for (i = 0; i < serial->num_ports; i++) {
728 port = serial->port[i];
729 kfree(usb_get_serial_port_data(port));
730 }
731}
732
733MODULE_AUTHOR(DRIVER_AUTHOR);
734MODULE_DESCRIPTION(DRIVER_DESC);
735MODULE_VERSION(DRIVER_VERSION);
75MODULE_LICENSE("GPL"); 736MODULE_LICENSE("GPL");
737
738#ifdef CONFIG_USB_DEBUG
739module_param(debug, bool, S_IRUGO | S_IWUSR);
740MODULE_PARM_DESC(debug, "Debug messages");
741#endif
742