blob: 11e439b90eacd88a2a89e1a48ee6759e7982ccc0 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 Keyspan USB to Serial Converter driver
3
4 (C) Copyright (C) 2000-2001 Hugh Blemings <hugh@blemings.org>
5 (C) Copyright (C) 2002 Greg Kroah-Hartman <greg@kroah.com>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 See http://misc.nu/hugh/keyspan.html for more information.
13
14 Code in this driver inspired by and in a number of places taken
15 from Brian Warner's original Keyspan-PDA driver.
16
17 This driver has been put together with the support of Innosys, Inc.
18 and Keyspan, Inc the manufacturers of the Keyspan USB-serial products.
19 Thanks Guys :)
20
21 Thanks to Paulus for miscellaneous tidy ups, some largish chunks
22 of much nicer and/or completely new code and (perhaps most uniquely)
23 having the patience to sit down and explain why and where he'd changed
24 stuff.
25
26 Tip 'o the hat to IBM (and previously Linuxcare :) for supporting
27 staff in their work on open source projects.
28
29 Change History
30
31 2003sep04 LPM (Keyspan) add support for new single port product USA19HS.
32 Improve setup message handling for all devices.
33
34 Wed Feb 19 22:00:00 PST 2003 (Jeffrey S. Laing <keyspan@jsl.com>)
35 Merged the current (1/31/03) Keyspan code with the current (2.4.21-pre4)
36 Linux source tree. The Linux tree lacked support for the 49WLC and
37 others. The Keyspan patches didn't work with the current kernel.
38
39 2003jan30 LPM add support for the 49WLC and MPR
40
41 Wed Apr 25 12:00:00 PST 2002 (Keyspan)
42 Started with Hugh Blemings' code dated Jan 17, 2002. All adapters
43 now supported (including QI and QW). Modified port open, port
44 close, and send setup() logic to fix various data and endpoint
45 synchronization bugs and device LED status bugs. Changed keyspan_
46 write_room() to accurately return transmit buffer availability.
47 Changed forwardingLength from 1 to 16 for all adapters.
48
49 Fri Oct 12 16:45:00 EST 2001
50 Preliminary USA-19QI and USA-28 support (both test OK for me, YMMV)
51
52 Wed Apr 25 12:00:00 PST 2002 (Keyspan)
53 Started with Hugh Blemings' code dated Jan 17, 2002. All adapters
54 now supported (including QI and QW). Modified port open, port
55 close, and send setup() logic to fix various data and endpoint
56 synchronization bugs and device LED status bugs. Changed keyspan_
57 write_room() to accurately return transmit buffer availability.
58 Changed forwardingLength from 1 to 16 for all adapters.
59
60 Fri Oct 12 16:45:00 EST 2001
61 Preliminary USA-19QI and USA-28 support (both test OK for me, YMMV)
62
63 Mon Oct 8 14:29:00 EST 2001 hugh
64 Fixed bug that prevented mulitport devices operating correctly
65 if they weren't the first unit attached.
66
67 Sat Oct 6 12:31:21 EST 2001 hugh
68 Added support for USA-28XA and -28XB, misc cleanups, break support
69 for usa26 based models thanks to David Gibson.
70
71 Thu May 31 11:56:42 PDT 2001 gkh
72 switched from using spinlock to a semaphore
73
74 (04/08/2001) gb
75 Identify version on module load.
76
77 (11/01/2000) Adam J. Richter
78 usb_device_id table support.
79
80 Tue Oct 10 23:15:33 EST 2000 Hugh
81 Merged Paul's changes with my USA-49W mods. Work in progress
82 still...
83
84 Wed Jul 19 14:00:42 EST 2000 gkh
85 Added module_init and module_exit functions to handle the fact that
86 this driver is a loadable module now.
87
88 Tue Jul 18 16:14:52 EST 2000 Hugh
89 Basic character input/output for USA-19 now mostly works,
90 fixed at 9600 baud for the moment.
91
92 Sat Jul 8 11:11:48 EST 2000 Hugh
93 First public release - nothing works except the firmware upload.
94 Tested on PPC and x86 architectures, seems to behave...
95*/
96
97
Linus Torvalds1da177e2005-04-16 15:20:36 -070098#include <linux/kernel.h>
99#include <linux/jiffies.h>
100#include <linux/errno.h>
101#include <linux/init.h>
102#include <linux/slab.h>
103#include <linux/tty.h>
104#include <linux/tty_driver.h>
105#include <linux/tty_flip.h>
106#include <linux/module.h>
107#include <linux/spinlock.h>
David Woodhouse2971c572008-05-30 14:04:03 +0300108#include <linux/firmware.h>
109#include <linux/ihex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110#include <asm/uaccess.h>
111#include <linux/usb.h>
Greg Kroah-Hartmana9698882006-07-11 21:22:58 -0700112#include <linux/usb/serial.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113#include "keyspan.h"
114
115static int debug;
116
117/*
118 * Version Information
119 */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700120#define DRIVER_VERSION "v1.1.5"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121#define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu"
122#define DRIVER_DESC "Keyspan USB to Serial Converter Driver"
123
124#define INSTAT_BUFLEN 32
125#define GLOCONT_BUFLEN 64
Lucy McCoy0ca12682007-05-18 12:10:41 -0700126#define INDAT49W_BUFLEN 512
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127
128 /* Per device and per port private data */
129struct keyspan_serial_private {
130 const struct keyspan_device_details *device_details;
131
132 struct urb *instat_urb;
133 char instat_buf[INSTAT_BUFLEN];
134
Lucy McCoy0ca12682007-05-18 12:10:41 -0700135 /* added to support 49wg, where data from all 4 ports comes in on 1 EP */
136 /* and high-speed supported */
137 struct urb *indat_urb;
138 char indat_buf[INDAT49W_BUFLEN];
139
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 /* XXX this one probably will need a lock */
141 struct urb *glocont_urb;
142 char glocont_buf[GLOCONT_BUFLEN];
Lucy McCoy0ca12682007-05-18 12:10:41 -0700143 char ctrl_buf[8]; // for EP0 control message
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144};
145
146struct keyspan_port_private {
147 /* Keep track of which input & output endpoints to use */
148 int in_flip;
149 int out_flip;
150
151 /* Keep duplicate of device details in each port
152 structure as well - simplifies some of the
153 callback functions etc. */
154 const struct keyspan_device_details *device_details;
155
156 /* Input endpoints and buffer for this port */
157 struct urb *in_urbs[2];
158 char in_buffer[2][64];
159 /* Output endpoints and buffer for this port */
160 struct urb *out_urbs[2];
161 char out_buffer[2][64];
162
163 /* Input ack endpoint */
164 struct urb *inack_urb;
165 char inack_buffer[1];
166
167 /* Output control endpoint */
168 struct urb *outcont_urb;
169 char outcont_buffer[64];
170
171 /* Settings for the port */
172 int baud;
173 int old_baud;
174 unsigned int cflag;
175 unsigned int old_cflag;
176 enum {flow_none, flow_cts, flow_xon} flow_control;
177 int rts_state; /* Handshaking pins (outputs) */
178 int dtr_state;
179 int cts_state; /* Handshaking pins (inputs) */
180 int dsr_state;
181 int dcd_state;
182 int ri_state;
183 int break_on;
184
185 unsigned long tx_start_time[2];
186 int resend_cont; /* need to resend control packet */
187};
188
189
190/* Include Keyspan message headers. All current Keyspan Adapters
Lucy McCoy0ca12682007-05-18 12:10:41 -0700191 make use of one of five message formats which are referred
192 to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and within this driver. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193#include "keyspan_usa26msg.h"
194#include "keyspan_usa28msg.h"
195#include "keyspan_usa49msg.h"
196#include "keyspan_usa90msg.h"
Lucy McCoy0ca12682007-05-18 12:10:41 -0700197#include "keyspan_usa67msg.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198
199
200/* Functions used by new usb-serial code. */
201static int __init keyspan_init (void)
202{
203 int retval;
204 retval = usb_serial_register(&keyspan_pre_device);
205 if (retval)
206 goto failed_pre_device_register;
207 retval = usb_serial_register(&keyspan_1port_device);
208 if (retval)
209 goto failed_1port_device_register;
210 retval = usb_serial_register(&keyspan_2port_device);
211 if (retval)
212 goto failed_2port_device_register;
213 retval = usb_serial_register(&keyspan_4port_device);
214 if (retval)
215 goto failed_4port_device_register;
216 retval = usb_register(&keyspan_driver);
217 if (retval)
218 goto failed_usb_register;
219
220 info(DRIVER_VERSION ":" DRIVER_DESC);
221
222 return 0;
223failed_usb_register:
224 usb_serial_deregister(&keyspan_4port_device);
225failed_4port_device_register:
226 usb_serial_deregister(&keyspan_2port_device);
227failed_2port_device_register:
228 usb_serial_deregister(&keyspan_1port_device);
229failed_1port_device_register:
230 usb_serial_deregister(&keyspan_pre_device);
231failed_pre_device_register:
232 return retval;
233}
234
235static void __exit keyspan_exit (void)
236{
237 usb_deregister (&keyspan_driver);
238 usb_serial_deregister (&keyspan_pre_device);
239 usb_serial_deregister (&keyspan_1port_device);
240 usb_serial_deregister (&keyspan_2port_device);
241 usb_serial_deregister (&keyspan_4port_device);
242}
243
244module_init(keyspan_init);
245module_exit(keyspan_exit);
246
247static void keyspan_rx_throttle (struct usb_serial_port *port)
248{
Harvey Harrison441b62c2008-03-03 16:08:34 -0800249 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250}
251
252
253static void keyspan_rx_unthrottle (struct usb_serial_port *port)
254{
Harvey Harrison441b62c2008-03-03 16:08:34 -0800255 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256}
257
258
259static void keyspan_break_ctl (struct usb_serial_port *port, int break_state)
260{
261 struct keyspan_port_private *p_priv;
262
Harvey Harrison441b62c2008-03-03 16:08:34 -0800263 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264
265 p_priv = usb_get_serial_port_data(port);
266
267 if (break_state == -1)
268 p_priv->break_on = 1;
269 else
270 p_priv->break_on = 0;
271
272 keyspan_send_setup(port, 0);
273}
274
275
276static void keyspan_set_termios (struct usb_serial_port *port,
Alan Cox606d0992006-12-08 02:38:45 -0800277 struct ktermios *old_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278{
279 int baud_rate, device_port;
280 struct keyspan_port_private *p_priv;
281 const struct keyspan_device_details *d_details;
282 unsigned int cflag;
Alan Cox74240b02007-10-18 01:24:20 -0700283 struct tty_struct *tty = port->tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284
Harvey Harrison441b62c2008-03-03 16:08:34 -0800285 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286
287 p_priv = usb_get_serial_port_data(port);
288 d_details = p_priv->device_details;
Alan Cox74240b02007-10-18 01:24:20 -0700289 cflag = tty->termios->c_cflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 device_port = port->number - port->serial->minor;
291
292 /* Baud rate calculation takes baud rate as an integer
293 so other rates can be generated if desired. */
Alan Cox74240b02007-10-18 01:24:20 -0700294 baud_rate = tty_get_baud_rate(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 /* If no match or invalid, don't change */
Alan Cox74240b02007-10-18 01:24:20 -0700296 if (d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
298 /* FIXME - more to do here to ensure rate changes cleanly */
Alan Cox74240b02007-10-18 01:24:20 -0700299 /* FIXME - calcuate exact rate from divisor ? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 p_priv->baud = baud_rate;
Alan Cox74240b02007-10-18 01:24:20 -0700301 } else
302 baud_rate = tty_termios_baud_rate(old_termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303
Alan Cox74240b02007-10-18 01:24:20 -0700304 tty_encode_baud_rate(tty, baud_rate, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 /* set CTS/RTS handshake etc. */
306 p_priv->cflag = cflag;
307 p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none;
308
Alan Cox74240b02007-10-18 01:24:20 -0700309 /* Mark/Space not supported */
310 tty->termios->c_cflag &= ~CMSPAR;
311
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 keyspan_send_setup(port, 0);
313}
314
315static int keyspan_tiocmget(struct usb_serial_port *port, struct file *file)
316{
317 unsigned int value;
318 struct keyspan_port_private *p_priv;
319
320 p_priv = usb_get_serial_port_data(port);
321
322 value = ((p_priv->rts_state) ? TIOCM_RTS : 0) |
323 ((p_priv->dtr_state) ? TIOCM_DTR : 0) |
324 ((p_priv->cts_state) ? TIOCM_CTS : 0) |
325 ((p_priv->dsr_state) ? TIOCM_DSR : 0) |
326 ((p_priv->dcd_state) ? TIOCM_CAR : 0) |
327 ((p_priv->ri_state) ? TIOCM_RNG : 0);
328
329 return value;
330}
331
332static int keyspan_tiocmset(struct usb_serial_port *port, struct file *file,
333 unsigned int set, unsigned int clear)
334{
335 struct keyspan_port_private *p_priv;
336
337 p_priv = usb_get_serial_port_data(port);
338
339 if (set & TIOCM_RTS)
340 p_priv->rts_state = 1;
341 if (set & TIOCM_DTR)
342 p_priv->dtr_state = 1;
343
344 if (clear & TIOCM_RTS)
345 p_priv->rts_state = 0;
346 if (clear & TIOCM_DTR)
347 p_priv->dtr_state = 0;
348 keyspan_send_setup(port, 0);
349 return 0;
350}
351
352static int keyspan_ioctl(struct usb_serial_port *port, struct file *file,
353 unsigned int cmd, unsigned long arg)
354{
355 return -ENOIOCTLCMD;
356}
357
358 /* Write function is similar for the four protocols used
359 with only a minor change for usa90 (usa19hs) required */
360static int keyspan_write(struct usb_serial_port *port,
361 const unsigned char *buf, int count)
362{
363 struct keyspan_port_private *p_priv;
364 const struct keyspan_device_details *d_details;
365 int flip;
366 int left, todo;
367 struct urb *this_urb;
368 int err, maxDataLen, dataOffset;
369
370 p_priv = usb_get_serial_port_data(port);
371 d_details = p_priv->device_details;
372
373 if (d_details->msg_format == msg_usa90) {
374 maxDataLen = 64;
375 dataOffset = 0;
376 } else {
377 maxDataLen = 63;
378 dataOffset = 1;
379 }
380
381 dbg("%s - for port %d (%d chars), flip=%d",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800382 __func__, port->number, count, p_priv->out_flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
384 for (left = count; left > 0; left -= todo) {
385 todo = left;
386 if (todo > maxDataLen)
387 todo = maxDataLen;
388
389 flip = p_priv->out_flip;
390
391 /* Check we have a valid urb/endpoint before we use it... */
392 if ((this_urb = p_priv->out_urbs[flip]) == NULL) {
393 /* no bulk out, so return 0 bytes written */
Harvey Harrison441b62c2008-03-03 16:08:34 -0800394 dbg("%s - no output urb :(", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 return count;
396 }
397
Harvey Harrison441b62c2008-03-03 16:08:34 -0800398 dbg("%s - endpoint %d flip %d", __func__, usb_pipeendpoint(this_urb->pipe), flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399
400 if (this_urb->status == -EINPROGRESS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 if (time_before(jiffies, p_priv->tx_start_time[flip] + 10 * HZ))
402 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 usb_unlink_urb(this_urb);
404 break;
405 }
406
407 /* First byte in buffer is "last flag" (except for usa19hx) - unused so
408 for now so set to zero */
409 ((char *)this_urb->transfer_buffer)[0] = 0;
410
411 memcpy (this_urb->transfer_buffer + dataOffset, buf, todo);
412 buf += todo;
413
414 /* send the data out the bulk port */
415 this_urb->transfer_buffer_length = todo + dataOffset;
416
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 this_urb->dev = port->serial->dev;
418 if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
419 dbg("usb_submit_urb(write bulk) failed (%d)", err);
420 }
421 p_priv->tx_start_time[flip] = jiffies;
422
423 /* Flip for next time if usa26 or usa28 interface
424 (not used on usa49) */
425 p_priv->out_flip = (flip + 1) & d_details->outdat_endp_flip;
426 }
427
428 return count - left;
429}
430
David Howells7d12e782006-10-05 14:55:46 +0100431static void usa26_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432{
433 int i, err;
434 int endpoint;
435 struct usb_serial_port *port;
436 struct tty_struct *tty;
437 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700438 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439
Harvey Harrison441b62c2008-03-03 16:08:34 -0800440 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441
442 endpoint = usb_pipeendpoint(urb->pipe);
443
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700444 if (status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 dbg("%s - nonzero status: %x on endpoint %d.",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800446 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 return;
448 }
449
Ming Leicdc97792008-02-24 18:41:47 +0800450 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 tty = port->tty;
Alan Coxa5569a52008-01-21 17:18:24 -0800452 if (tty && urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 /* 0x80 bit is error flag */
454 if ((data[0] & 0x80) == 0) {
455 /* no errors on individual bytes, only possible overrun err*/
456 if (data[0] & RXERROR_OVERRUN)
457 err = TTY_OVERRUN;
458 else err = 0;
459 for (i = 1; i < urb->actual_length ; ++i) {
460 tty_insert_flip_char(tty, data[i], err);
461 }
462 } else {
463 /* some bytes had errors, every byte has status */
Harvey Harrison441b62c2008-03-03 16:08:34 -0800464 dbg("%s - RX error!!!!", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 for (i = 0; i + 1 < urb->actual_length; i += 2) {
466 int stat = data[i], flag = 0;
467 if (stat & RXERROR_OVERRUN)
468 flag |= TTY_OVERRUN;
469 if (stat & RXERROR_FRAMING)
470 flag |= TTY_FRAME;
471 if (stat & RXERROR_PARITY)
472 flag |= TTY_PARITY;
473 /* XXX should handle break (0x10) */
474 tty_insert_flip_char(tty, data[i+1], flag);
475 }
476 }
477 tty_flip_buffer_push(tty);
478 }
479
480 /* Resubmit urb so we continue receiving */
481 urb->dev = port->serial->dev;
482 if (port->open_count)
483 if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800484 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 }
486 return;
487}
488
489 /* Outdat handling is common for all devices */
David Howells7d12e782006-10-05 14:55:46 +0100490static void usa2x_outdat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491{
492 struct usb_serial_port *port;
493 struct keyspan_port_private *p_priv;
494
Ming Leicdc97792008-02-24 18:41:47 +0800495 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 p_priv = usb_get_serial_port_data(port);
Harvey Harrison441b62c2008-03-03 16:08:34 -0800497 dbg ("%s - urb %d", __func__, urb == p_priv->out_urbs[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498
499 if (port->open_count)
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700500 usb_serial_port_softint(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501}
502
David Howells7d12e782006-10-05 14:55:46 +0100503static void usa26_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504{
Harvey Harrison441b62c2008-03-03 16:08:34 -0800505 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
507}
508
David Howells7d12e782006-10-05 14:55:46 +0100509static void usa26_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510{
511 struct usb_serial_port *port;
512 struct keyspan_port_private *p_priv;
513
Ming Leicdc97792008-02-24 18:41:47 +0800514 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 p_priv = usb_get_serial_port_data(port);
516
517 if (p_priv->resend_cont) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800518 dbg ("%s - sending setup", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 keyspan_usa26_send_setup(port->serial, port, p_priv->resend_cont - 1);
520 }
521}
522
David Howells7d12e782006-10-05 14:55:46 +0100523static void usa26_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524{
525 unsigned char *data = urb->transfer_buffer;
526 struct keyspan_usa26_portStatusMessage *msg;
527 struct usb_serial *serial;
528 struct usb_serial_port *port;
529 struct keyspan_port_private *p_priv;
530 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700531 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532
Ming Leicdc97792008-02-24 18:41:47 +0800533 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700535 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800536 dbg("%s - nonzero status: %x", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 return;
538 }
539 if (urb->actual_length != 9) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800540 dbg("%s - %d byte report??", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 goto exit;
542 }
543
544 msg = (struct keyspan_usa26_portStatusMessage *)data;
545
546#if 0
547 dbg("%s - port status: port %d cts %d dcd %d dsr %d ri %d toff %d txoff %d rxen %d cr %d",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800548 __func__, msg->port, msg->hskia_cts, msg->gpia_dcd, msg->dsr, msg->ri, msg->_txOff,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 msg->_txXoff, msg->rxEnabled, msg->controlResponse);
550#endif
551
552 /* Now do something useful with the data */
553
554
555 /* Check port number from message and retrieve private data */
556 if (msg->port >= serial->num_ports) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800557 dbg ("%s - Unexpected port number %d", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 goto exit;
559 }
560 port = serial->port[msg->port];
561 p_priv = usb_get_serial_port_data(port);
562
563 /* Update handshaking pin state information */
564 old_dcd_state = p_priv->dcd_state;
565 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
566 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
567 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
568 p_priv->ri_state = ((msg->ri) ? 1 : 0);
569
570 if (port->tty && !C_CLOCAL(port->tty)
571 && old_dcd_state != p_priv->dcd_state) {
572 if (old_dcd_state)
573 tty_hangup(port->tty);
574 /* else */
575 /* wake_up_interruptible(&p_priv->open_wait); */
576 }
577
578 /* Resubmit urb so we continue receiving */
579 urb->dev = serial->dev;
580 if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800581 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 }
583exit: ;
584}
585
David Howells7d12e782006-10-05 14:55:46 +0100586static void usa26_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587{
Harvey Harrison441b62c2008-03-03 16:08:34 -0800588 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589
590}
591
592
David Howells7d12e782006-10-05 14:55:46 +0100593static void usa28_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594{
595 int i, err;
596 struct usb_serial_port *port;
597 struct tty_struct *tty;
598 unsigned char *data;
599 struct keyspan_port_private *p_priv;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700600 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601
Harvey Harrison441b62c2008-03-03 16:08:34 -0800602 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603
Ming Leicdc97792008-02-24 18:41:47 +0800604 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 p_priv = usb_get_serial_port_data(port);
606 data = urb->transfer_buffer;
607
608 if (urb != p_priv->in_urbs[p_priv->in_flip])
609 return;
610
611 do {
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700612 if (status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 dbg("%s - nonzero status: %x on endpoint %d.",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800614 __func__, status, usb_pipeendpoint(urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 return;
616 }
617
Ming Leicdc97792008-02-24 18:41:47 +0800618 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 p_priv = usb_get_serial_port_data(port);
620 data = urb->transfer_buffer;
621
622 tty = port->tty;
623 if (urb->actual_length) {
624 for (i = 0; i < urb->actual_length ; ++i) {
625 tty_insert_flip_char(tty, data[i], 0);
626 }
627 tty_flip_buffer_push(tty);
628 }
629
630 /* Resubmit urb so we continue receiving */
631 urb->dev = port->serial->dev;
632 if (port->open_count)
633 if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800634 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 }
636 p_priv->in_flip ^= 1;
637
638 urb = p_priv->in_urbs[p_priv->in_flip];
639 } while (urb->status != -EINPROGRESS);
640}
641
David Howells7d12e782006-10-05 14:55:46 +0100642static void usa28_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643{
Harvey Harrison441b62c2008-03-03 16:08:34 -0800644 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645}
646
David Howells7d12e782006-10-05 14:55:46 +0100647static void usa28_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648{
649 struct usb_serial_port *port;
650 struct keyspan_port_private *p_priv;
651
Ming Leicdc97792008-02-24 18:41:47 +0800652 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 p_priv = usb_get_serial_port_data(port);
654
655 if (p_priv->resend_cont) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800656 dbg ("%s - sending setup", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 keyspan_usa28_send_setup(port->serial, port, p_priv->resend_cont - 1);
658 }
659}
660
David Howells7d12e782006-10-05 14:55:46 +0100661static void usa28_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662{
663 int err;
664 unsigned char *data = urb->transfer_buffer;
665 struct keyspan_usa28_portStatusMessage *msg;
666 struct usb_serial *serial;
667 struct usb_serial_port *port;
668 struct keyspan_port_private *p_priv;
669 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700670 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671
Ming Leicdc97792008-02-24 18:41:47 +0800672 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700674 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800675 dbg("%s - nonzero status: %x", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 return;
677 }
678
679 if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800680 dbg("%s - bad length %d", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681 goto exit;
682 }
683
Harvey Harrison441b62c2008-03-03 16:08:34 -0800684 /*dbg("%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 data[0], data[1], data[2], data[3], data[4], data[5],
686 data[6], data[7], data[8], data[9], data[10], data[11]);*/
687
688 /* Now do something useful with the data */
689 msg = (struct keyspan_usa28_portStatusMessage *)data;
690
691
692 /* Check port number from message and retrieve private data */
693 if (msg->port >= serial->num_ports) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800694 dbg ("%s - Unexpected port number %d", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 goto exit;
696 }
697 port = serial->port[msg->port];
698 p_priv = usb_get_serial_port_data(port);
699
700 /* Update handshaking pin state information */
701 old_dcd_state = p_priv->dcd_state;
702 p_priv->cts_state = ((msg->cts) ? 1 : 0);
703 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
704 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
705 p_priv->ri_state = ((msg->ri) ? 1 : 0);
706
707 if (port->tty && !C_CLOCAL(port->tty)
708 && old_dcd_state != p_priv->dcd_state) {
709 if (old_dcd_state)
710 tty_hangup(port->tty);
711 /* else */
712 /* wake_up_interruptible(&p_priv->open_wait); */
713 }
714
715 /* Resubmit urb so we continue receiving */
716 urb->dev = serial->dev;
717 if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800718 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 }
720exit: ;
721}
722
David Howells7d12e782006-10-05 14:55:46 +0100723static void usa28_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724{
Harvey Harrison441b62c2008-03-03 16:08:34 -0800725 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726}
727
728
David Howells7d12e782006-10-05 14:55:46 +0100729static void usa49_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730{
731 struct usb_serial *serial;
732 struct usb_serial_port *port;
733 struct keyspan_port_private *p_priv;
734 int i;
735
Harvey Harrison441b62c2008-03-03 16:08:34 -0800736 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737
Ming Leicdc97792008-02-24 18:41:47 +0800738 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 for (i = 0; i < serial->num_ports; ++i) {
740 port = serial->port[i];
741 p_priv = usb_get_serial_port_data(port);
742
743 if (p_priv->resend_cont) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800744 dbg ("%s - sending setup", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 keyspan_usa49_send_setup(serial, port, p_priv->resend_cont - 1);
746 break;
747 }
748 }
749}
750
751 /* This is actually called glostat in the Keyspan
752 doco */
David Howells7d12e782006-10-05 14:55:46 +0100753static void usa49_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754{
755 int err;
756 unsigned char *data = urb->transfer_buffer;
757 struct keyspan_usa49_portStatusMessage *msg;
758 struct usb_serial *serial;
759 struct usb_serial_port *port;
760 struct keyspan_port_private *p_priv;
761 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700762 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763
Harvey Harrison441b62c2008-03-03 16:08:34 -0800764 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765
Ming Leicdc97792008-02-24 18:41:47 +0800766 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700768 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800769 dbg("%s - nonzero status: %x", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 return;
771 }
772
773 if (urb->actual_length != sizeof(struct keyspan_usa49_portStatusMessage)) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800774 dbg("%s - bad length %d", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 goto exit;
776 }
777
Harvey Harrison441b62c2008-03-03 16:08:34 -0800778 /*dbg(" %x %x %x %x %x %x %x %x %x %x %x", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 data[0], data[1], data[2], data[3], data[4], data[5],
780 data[6], data[7], data[8], data[9], data[10]);*/
781
782 /* Now do something useful with the data */
783 msg = (struct keyspan_usa49_portStatusMessage *)data;
784
785 /* Check port number from message and retrieve private data */
786 if (msg->portNumber >= serial->num_ports) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800787 dbg ("%s - Unexpected port number %d", __func__, msg->portNumber);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 goto exit;
789 }
790 port = serial->port[msg->portNumber];
791 p_priv = usb_get_serial_port_data(port);
792
793 /* Update handshaking pin state information */
794 old_dcd_state = p_priv->dcd_state;
795 p_priv->cts_state = ((msg->cts) ? 1 : 0);
796 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
797 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
798 p_priv->ri_state = ((msg->ri) ? 1 : 0);
799
800 if (port->tty && !C_CLOCAL(port->tty)
801 && old_dcd_state != p_priv->dcd_state) {
802 if (old_dcd_state)
803 tty_hangup(port->tty);
804 /* else */
805 /* wake_up_interruptible(&p_priv->open_wait); */
806 }
807
808 /* Resubmit urb so we continue receiving */
809 urb->dev = serial->dev;
810
811 if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800812 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 }
814exit: ;
815}
816
David Howells7d12e782006-10-05 14:55:46 +0100817static void usa49_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818{
Harvey Harrison441b62c2008-03-03 16:08:34 -0800819 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820}
821
David Howells7d12e782006-10-05 14:55:46 +0100822static void usa49_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823{
824 int i, err;
825 int endpoint;
826 struct usb_serial_port *port;
827 struct tty_struct *tty;
828 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700829 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830
Harvey Harrison441b62c2008-03-03 16:08:34 -0800831 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832
833 endpoint = usb_pipeendpoint(urb->pipe);
834
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700835 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800836 dbg("%s - nonzero status: %x on endpoint %d.", __func__,
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700837 status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 return;
839 }
840
Ming Leicdc97792008-02-24 18:41:47 +0800841 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 tty = port->tty;
Alan Cox3004e532008-01-03 16:59:04 +0000843 if (tty && urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 /* 0x80 bit is error flag */
845 if ((data[0] & 0x80) == 0) {
846 /* no error on any byte */
847 for (i = 1; i < urb->actual_length ; ++i) {
848 tty_insert_flip_char(tty, data[i], 0);
849 }
850 } else {
851 /* some bytes had errors, every byte has status */
852 for (i = 0; i + 1 < urb->actual_length; i += 2) {
853 int stat = data[i], flag = 0;
854 if (stat & RXERROR_OVERRUN)
855 flag |= TTY_OVERRUN;
856 if (stat & RXERROR_FRAMING)
857 flag |= TTY_FRAME;
858 if (stat & RXERROR_PARITY)
859 flag |= TTY_PARITY;
860 /* XXX should handle break (0x10) */
861 tty_insert_flip_char(tty, data[i+1], flag);
862 }
863 }
864 tty_flip_buffer_push(tty);
865 }
866
867 /* Resubmit urb so we continue receiving */
868 urb->dev = port->serial->dev;
869 if (port->open_count)
870 if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800871 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 }
873}
874
Lucy McCoy0ca12682007-05-18 12:10:41 -0700875static void usa49wg_indat_callback(struct urb *urb)
876{
877 int i, len, x, err;
878 struct usb_serial *serial;
879 struct usb_serial_port *port;
880 struct tty_struct *tty;
881 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700882 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700883
Harvey Harrison441b62c2008-03-03 16:08:34 -0800884 dbg ("%s", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700885
886 serial = urb->context;
887
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700888 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800889 dbg("%s - nonzero status: %x", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700890 return;
891 }
892
893 /* inbound data is in the form P#, len, status, data */
894 i = 0;
895 len = 0;
896
897 if (urb->actual_length) {
898 while (i < urb->actual_length) {
899
900 /* Check port number from message*/
901 if (data[i] >= serial->num_ports) {
902 dbg ("%s - Unexpected port number %d",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800903 __func__, data[i]);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700904 return;
905 }
906 port = serial->port[data[i++]];
907 tty = port->tty;
908 len = data[i++];
909
910 /* 0x80 bit is error flag */
911 if ((data[i] & 0x80) == 0) {
912 /* no error on any byte */
913 i++;
914 for (x = 1; x < len ; ++x)
915 if (port->open_count)
916 tty_insert_flip_char(tty,
917 data[i++], 0);
918 else
919 i++;
920 } else {
921 /*
922 * some bytes had errors, every byte has status
923 */
924 for (x = 0; x + 1 < len; x += 2) {
925 int stat = data[i], flag = 0;
926 if (stat & RXERROR_OVERRUN)
927 flag |= TTY_OVERRUN;
928 if (stat & RXERROR_FRAMING)
929 flag |= TTY_FRAME;
930 if (stat & RXERROR_PARITY)
931 flag |= TTY_PARITY;
932 /* XXX should handle break (0x10) */
933 if (port->open_count)
934 tty_insert_flip_char(tty,
935 data[i+1], flag);
936 i += 2;
937 }
938 }
939 if (port->open_count)
940 tty_flip_buffer_push(tty);
941 }
942 }
943
944 /* Resubmit urb so we continue receiving */
945 urb->dev = serial->dev;
946
947 err = usb_submit_urb(urb, GFP_ATOMIC);
948 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800949 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700950}
951
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952/* not used, usa-49 doesn't have per-port control endpoints */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700953static void usa49_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954{
Harvey Harrison441b62c2008-03-03 16:08:34 -0800955 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956}
957
Lucy McCoy0ca12682007-05-18 12:10:41 -0700958static void usa90_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959{
960 int i, err;
961 int endpoint;
962 struct usb_serial_port *port;
963 struct keyspan_port_private *p_priv;
964 struct tty_struct *tty;
965 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700966 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967
Harvey Harrison441b62c2008-03-03 16:08:34 -0800968 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969
970 endpoint = usb_pipeendpoint(urb->pipe);
971
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700972 if (status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 dbg("%s - nonzero status: %x on endpoint %d.",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800974 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 return;
976 }
977
Ming Leicdc97792008-02-24 18:41:47 +0800978 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 p_priv = usb_get_serial_port_data(port);
980
981 tty = port->tty;
982 if (urb->actual_length) {
983
984 /* if current mode is DMA, looks like usa28 format
985 otherwise looks like usa26 data format */
986
987 if (p_priv->baud > 57600) {
988 for (i = 0; i < urb->actual_length ; ++i)
989 tty_insert_flip_char(tty, data[i], 0);
990 }
991 else {
992
993 /* 0x80 bit is error flag */
994 if ((data[0] & 0x80) == 0) {
995 /* no errors on individual bytes, only possible overrun err*/
996 if (data[0] & RXERROR_OVERRUN)
997 err = TTY_OVERRUN;
998 else err = 0;
999 for (i = 1; i < urb->actual_length ; ++i)
1000 tty_insert_flip_char(tty, data[i], err);
1001
1002 }
1003 else {
1004 /* some bytes had errors, every byte has status */
Harvey Harrison441b62c2008-03-03 16:08:34 -08001005 dbg("%s - RX error!!!!", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 for (i = 0; i + 1 < urb->actual_length; i += 2) {
1007 int stat = data[i], flag = 0;
1008 if (stat & RXERROR_OVERRUN)
1009 flag |= TTY_OVERRUN;
1010 if (stat & RXERROR_FRAMING)
1011 flag |= TTY_FRAME;
1012 if (stat & RXERROR_PARITY)
1013 flag |= TTY_PARITY;
1014 /* XXX should handle break (0x10) */
1015 tty_insert_flip_char(tty, data[i+1], flag);
1016 }
1017 }
1018 }
1019 tty_flip_buffer_push(tty);
1020 }
1021
1022 /* Resubmit urb so we continue receiving */
1023 urb->dev = port->serial->dev;
1024 if (port->open_count)
1025 if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001026 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 }
1028 return;
1029}
1030
1031
David Howells7d12e782006-10-05 14:55:46 +01001032static void usa90_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033{
1034 unsigned char *data = urb->transfer_buffer;
1035 struct keyspan_usa90_portStatusMessage *msg;
1036 struct usb_serial *serial;
1037 struct usb_serial_port *port;
1038 struct keyspan_port_private *p_priv;
1039 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001040 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041
Ming Leicdc97792008-02-24 18:41:47 +08001042 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001044 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001045 dbg("%s - nonzero status: %x", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 return;
1047 }
1048 if (urb->actual_length < 14) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001049 dbg("%s - %d byte report??", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 goto exit;
1051 }
1052
1053 msg = (struct keyspan_usa90_portStatusMessage *)data;
1054
1055 /* Now do something useful with the data */
1056
1057 port = serial->port[0];
1058 p_priv = usb_get_serial_port_data(port);
1059
1060 /* Update handshaking pin state information */
1061 old_dcd_state = p_priv->dcd_state;
1062 p_priv->cts_state = ((msg->cts) ? 1 : 0);
1063 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
1064 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
1065 p_priv->ri_state = ((msg->ri) ? 1 : 0);
1066
1067 if (port->tty && !C_CLOCAL(port->tty)
1068 && old_dcd_state != p_priv->dcd_state) {
1069 if (old_dcd_state)
1070 tty_hangup(port->tty);
1071 /* else */
1072 /* wake_up_interruptible(&p_priv->open_wait); */
1073 }
1074
1075 /* Resubmit urb so we continue receiving */
1076 urb->dev = serial->dev;
1077 if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001078 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 }
1080exit:
1081 ;
1082}
1083
David Howells7d12e782006-10-05 14:55:46 +01001084static void usa90_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085{
1086 struct usb_serial_port *port;
1087 struct keyspan_port_private *p_priv;
1088
Ming Leicdc97792008-02-24 18:41:47 +08001089 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 p_priv = usb_get_serial_port_data(port);
1091
1092 if (p_priv->resend_cont) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001093 dbg ("%s - sending setup", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 keyspan_usa90_send_setup(port->serial, port, p_priv->resend_cont - 1);
1095 }
1096}
1097
Lucy McCoy0ca12682007-05-18 12:10:41 -07001098/* Status messages from the 28xg */
1099static void usa67_instat_callback(struct urb *urb)
1100{
1101 int err;
1102 unsigned char *data = urb->transfer_buffer;
1103 struct keyspan_usa67_portStatusMessage *msg;
1104 struct usb_serial *serial;
1105 struct usb_serial_port *port;
1106 struct keyspan_port_private *p_priv;
1107 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001108 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001109
Harvey Harrison441b62c2008-03-03 16:08:34 -08001110 dbg ("%s", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001111
1112 serial = urb->context;
1113
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001114 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001115 dbg("%s - nonzero status: %x", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001116 return;
1117 }
1118
1119 if (urb->actual_length != sizeof(struct keyspan_usa67_portStatusMessage)) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001120 dbg("%s - bad length %d", __func__, urb->actual_length);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001121 return;
1122 }
1123
1124
1125 /* Now do something useful with the data */
1126 msg = (struct keyspan_usa67_portStatusMessage *)data;
1127
1128 /* Check port number from message and retrieve private data */
1129 if (msg->port >= serial->num_ports) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001130 dbg ("%s - Unexpected port number %d", __func__, msg->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001131 return;
1132 }
1133
1134 port = serial->port[msg->port];
1135 p_priv = usb_get_serial_port_data(port);
1136
1137 /* Update handshaking pin state information */
1138 old_dcd_state = p_priv->dcd_state;
1139 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
1140 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
1141
1142 if (port->tty && !C_CLOCAL(port->tty)
1143 && old_dcd_state != p_priv->dcd_state) {
1144 if (old_dcd_state)
1145 tty_hangup(port->tty);
1146 /* else */
1147 /* wake_up_interruptible(&p_priv->open_wait); */
1148 }
1149
1150 /* Resubmit urb so we continue receiving */
1151 urb->dev = serial->dev;
1152 err = usb_submit_urb(urb, GFP_ATOMIC);
1153 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08001154 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001155}
1156
1157static void usa67_glocont_callback(struct urb *urb)
1158{
1159 struct usb_serial *serial;
1160 struct usb_serial_port *port;
1161 struct keyspan_port_private *p_priv;
1162 int i;
1163
Harvey Harrison441b62c2008-03-03 16:08:34 -08001164 dbg ("%s", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001165
1166 serial = urb->context;
1167 for (i = 0; i < serial->num_ports; ++i) {
1168 port = serial->port[i];
1169 p_priv = usb_get_serial_port_data(port);
1170
1171 if (p_priv->resend_cont) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001172 dbg ("%s - sending setup", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001173 keyspan_usa67_send_setup(serial, port,
1174 p_priv->resend_cont - 1);
1175 break;
1176 }
1177 }
1178}
1179
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180static int keyspan_write_room (struct usb_serial_port *port)
1181{
1182 struct keyspan_port_private *p_priv;
1183 const struct keyspan_device_details *d_details;
1184 int flip;
1185 int data_len;
1186 struct urb *this_urb;
1187
Harvey Harrison441b62c2008-03-03 16:08:34 -08001188 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 p_priv = usb_get_serial_port_data(port);
1190 d_details = p_priv->device_details;
1191
Alan Coxa5b6f602008-04-08 17:16:06 +01001192 /* FIXME: locking */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193 if (d_details->msg_format == msg_usa90)
1194 data_len = 64;
1195 else
1196 data_len = 63;
1197
1198 flip = p_priv->out_flip;
1199
1200 /* Check both endpoints to see if any are available. */
1201 if ((this_urb = p_priv->out_urbs[flip]) != NULL) {
1202 if (this_urb->status != -EINPROGRESS)
1203 return (data_len);
1204 flip = (flip + 1) & d_details->outdat_endp_flip;
1205 if ((this_urb = p_priv->out_urbs[flip]) != NULL)
1206 if (this_urb->status != -EINPROGRESS)
1207 return (data_len);
1208 }
Alan Coxa5b6f602008-04-08 17:16:06 +01001209 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210}
1211
1212
1213static int keyspan_chars_in_buffer (struct usb_serial_port *port)
1214{
Alan Coxa5b6f602008-04-08 17:16:06 +01001215 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216}
1217
1218
1219static int keyspan_open (struct usb_serial_port *port, struct file *filp)
1220{
Andrew Mortonf78ba152007-11-28 16:21:54 -08001221 struct keyspan_port_private *p_priv;
1222 struct keyspan_serial_private *s_priv;
1223 struct usb_serial *serial = port->serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 const struct keyspan_device_details *d_details;
1225 int i, err;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001226 int baud_rate, device_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 struct urb *urb;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001228 unsigned int cflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229
1230 s_priv = usb_get_serial_data(serial);
1231 p_priv = usb_get_serial_port_data(port);
1232 d_details = p_priv->device_details;
Borislav Petkov7eea4362007-11-14 17:00:39 -08001233
Harvey Harrison441b62c2008-03-03 16:08:34 -08001234 dbg("%s - port%d.", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235
1236 /* Set some sane defaults */
1237 p_priv->rts_state = 1;
1238 p_priv->dtr_state = 1;
1239 p_priv->baud = 9600;
1240
1241 /* force baud and lcr to be set on open */
1242 p_priv->old_baud = 0;
1243 p_priv->old_cflag = 0;
1244
1245 p_priv->out_flip = 0;
1246 p_priv->in_flip = 0;
1247
1248 /* Reset low level data toggle and start reading from endpoints */
1249 for (i = 0; i < 2; i++) {
1250 if ((urb = p_priv->in_urbs[i]) == NULL)
1251 continue;
1252 urb->dev = serial->dev;
1253
1254 /* make sure endpoint data toggle is synchronized with the device */
Borislav Petkov7eea4362007-11-14 17:00:39 -08001255
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 usb_clear_halt(urb->dev, urb->pipe);
1257
1258 if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001259 dbg("%s - submit urb %d failed (%d)", __func__, i, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 }
1261 }
1262
1263 /* Reset low level data toggle on out endpoints */
1264 for (i = 0; i < 2; i++) {
1265 if ((urb = p_priv->out_urbs[i]) == NULL)
1266 continue;
1267 urb->dev = serial->dev;
1268 /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); */
1269 }
1270
Andrew Mortonf78ba152007-11-28 16:21:54 -08001271 /* get the terminal config for the setup message now so we don't
1272 * need to send 2 of them */
1273
1274 cflag = port->tty->termios->c_cflag;
1275 device_port = port->number - port->serial->minor;
1276
1277 /* Baud rate calculation takes baud rate as an integer
1278 so other rates can be generated if desired. */
1279 baud_rate = tty_get_baud_rate(port->tty);
1280 /* If no match or invalid, leave as default */
1281 if (baud_rate >= 0
1282 && d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
1283 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
1284 p_priv->baud = baud_rate;
1285 }
1286
1287 /* set CTS/RTS handshake etc. */
1288 p_priv->cflag = cflag;
1289 p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none;
1290
1291 keyspan_send_setup(port, 1);
1292 //mdelay(100);
1293 //keyspan_set_termios(port, NULL);
1294
Alan Coxa5b6f602008-04-08 17:16:06 +01001295 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296}
1297
1298static inline void stop_urb(struct urb *urb)
1299{
Greg Kroah-Hartman242cf672005-07-29 16:11:07 -04001300 if (urb && urb->status == -EINPROGRESS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 usb_kill_urb(urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302}
1303
1304static void keyspan_close(struct usb_serial_port *port, struct file *filp)
1305{
1306 int i;
1307 struct usb_serial *serial = port->serial;
1308 struct keyspan_serial_private *s_priv;
1309 struct keyspan_port_private *p_priv;
1310
Harvey Harrison441b62c2008-03-03 16:08:34 -08001311 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 s_priv = usb_get_serial_data(serial);
1313 p_priv = usb_get_serial_port_data(port);
1314
1315 p_priv->rts_state = 0;
1316 p_priv->dtr_state = 0;
1317
1318 if (serial->dev) {
1319 keyspan_send_setup(port, 2);
1320 /* pilot-xfer seems to work best with this delay */
1321 mdelay(100);
1322 // keyspan_set_termios(port, NULL);
1323 }
1324
1325 /*while (p_priv->outcont_urb->status == -EINPROGRESS) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001326 dbg("%s - urb in progress", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 }*/
1328
1329 p_priv->out_flip = 0;
1330 p_priv->in_flip = 0;
1331
1332 if (serial->dev) {
1333 /* Stop reading/writing urbs */
1334 stop_urb(p_priv->inack_urb);
1335 /* stop_urb(p_priv->outcont_urb); */
1336 for (i = 0; i < 2; i++) {
1337 stop_urb(p_priv->in_urbs[i]);
1338 stop_urb(p_priv->out_urbs[i]);
1339 }
1340 }
1341 port->tty = NULL;
1342}
1343
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344 /* download the firmware to a pre-renumeration device */
1345static int keyspan_fake_startup (struct usb_serial *serial)
1346{
1347 int response;
David Woodhouse2971c572008-05-30 14:04:03 +03001348 const struct ihex_binrec *record;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 char *fw_name;
David Woodhouse2971c572008-05-30 14:04:03 +03001350 const struct firmware *fw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351
1352 dbg("Keyspan startup version %04x product %04x",
1353 le16_to_cpu(serial->dev->descriptor.bcdDevice),
1354 le16_to_cpu(serial->dev->descriptor.idProduct));
1355
1356 if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000) != 0x8000) {
1357 dbg("Firmware already loaded. Quitting.");
1358 return(1);
1359 }
1360
1361 /* Select firmware image on the basis of idProduct */
1362 switch (le16_to_cpu(serial->dev->descriptor.idProduct)) {
1363 case keyspan_usa28_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001364 fw_name = "keyspan/usa28.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 break;
1366
1367 case keyspan_usa28x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001368 fw_name = "keyspan/usa28x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 break;
1370
1371 case keyspan_usa28xa_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001372 fw_name = "keyspan/usa28xa.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 break;
1374
1375 case keyspan_usa28xb_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001376 fw_name = "keyspan/usa28xb.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 break;
1378
1379 case keyspan_usa19_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001380 fw_name = "keyspan/usa19.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 break;
1382
1383 case keyspan_usa19qi_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001384 fw_name = "keyspan/usa19qi.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 break;
1386
1387 case keyspan_mpr_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001388 fw_name = "keyspan/mpr.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 break;
1390
1391 case keyspan_usa19qw_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001392 fw_name = "keyspan/usa19qw.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 break;
1394
1395 case keyspan_usa18x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001396 fw_name = "keyspan/usa18x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 break;
1398
1399 case keyspan_usa19w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001400 fw_name = "keyspan/usa19w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401 break;
1402
1403 case keyspan_usa49w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001404 fw_name = "keyspan/usa49w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 break;
1406
1407 case keyspan_usa49wlc_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001408 fw_name = "keyspan/usa49wlc.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 break;
1410
1411 default:
David Woodhouse2971c572008-05-30 14:04:03 +03001412 dev_err(&serial->dev->dev, "Unknown product ID (%04x)\n",
1413 le16_to_cpu(serial->dev->descriptor.idProduct));
1414 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 }
1416
David Woodhouse2971c572008-05-30 14:04:03 +03001417 if (request_ihex_firmware(&fw, fw_name, &serial->dev->dev)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 dev_err(&serial->dev->dev, "Required keyspan firmware image (%s) unavailable.\n", fw_name);
1419 return(1);
1420 }
1421
1422 dbg("Uploading Keyspan %s firmware.", fw_name);
1423
1424 /* download the firmware image */
1425 response = ezusb_set_reset(serial, 1);
1426
David Woodhouse2971c572008-05-30 14:04:03 +03001427 record = (const struct ihex_binrec *)fw->data;
1428
1429 while (record) {
1430 response = ezusb_writememory(serial, be32_to_cpu(record->addr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 (unsigned char *)record->data,
David Woodhouse2971c572008-05-30 14:04:03 +03001432 be16_to_cpu(record->len), 0xa0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 if (response < 0) {
1434 dev_err(&serial->dev->dev, "ezusb_writememory failed for Keyspan"
1435 "firmware (%d %04X %p %d)\n",
David Woodhouse2971c572008-05-30 14:04:03 +03001436 response, be32_to_cpu(record->addr),
1437 record->data, be16_to_cpu(record->len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 break;
1439 }
David Woodhouse2971c572008-05-30 14:04:03 +03001440 record = ihex_next_binrec(record);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 }
David Woodhouse2971c572008-05-30 14:04:03 +03001442 release_firmware(fw);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 /* bring device out of reset. Renumeration will occur in a
1444 moment and the new device will bind to the real driver */
1445 response = ezusb_set_reset(serial, 0);
1446
1447 /* we don't want this device to have a driver assigned to it. */
1448 return (1);
1449}
1450
1451/* Helper functions used by keyspan_setup_urbs */
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001452static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *serial,
1453 int endpoint)
1454{
1455 struct usb_host_interface *iface_desc;
1456 struct usb_endpoint_descriptor *ep;
1457 int i;
1458
1459 iface_desc = serial->interface->cur_altsetting;
1460 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1461 ep = &iface_desc->endpoint[i].desc;
1462 if (ep->bEndpointAddress == endpoint)
1463 return ep;
1464 }
1465 dev_warn(&serial->interface->dev, "found no endpoint descriptor for "
1466 "endpoint %x\n", endpoint);
1467 return NULL;
1468}
1469
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470static struct urb *keyspan_setup_urb (struct usb_serial *serial, int endpoint,
1471 int dir, void *ctx, char *buf, int len,
David Howells7d12e782006-10-05 14:55:46 +01001472 void (*callback)(struct urb *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473{
1474 struct urb *urb;
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001475 struct usb_endpoint_descriptor const *ep_desc;
1476 char const *ep_type_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477
1478 if (endpoint == -1)
1479 return NULL; /* endpoint not needed */
1480
Harvey Harrison441b62c2008-03-03 16:08:34 -08001481 dbg ("%s - alloc for endpoint %d.", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
1483 if (urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001484 dbg ("%s - alloc for endpoint %d failed.", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485 return NULL;
1486 }
1487
Lucy McCoy0ca12682007-05-18 12:10:41 -07001488 if (endpoint == 0) {
1489 /* control EP filled in when used */
1490 return urb;
1491 }
1492
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001493 ep_desc = find_ep(serial, endpoint);
1494 if (!ep_desc) {
1495 /* leak the urb, something's wrong and the callers don't care */
1496 return urb;
1497 }
1498 if (usb_endpoint_xfer_int(ep_desc)) {
1499 ep_type_name = "INT";
1500 usb_fill_int_urb(urb, serial->dev,
1501 usb_sndintpipe(serial->dev, endpoint) | dir,
1502 buf, len, callback, ctx,
1503 ep_desc->bInterval);
1504 } else if (usb_endpoint_xfer_bulk(ep_desc)) {
1505 ep_type_name = "BULK";
1506 usb_fill_bulk_urb(urb, serial->dev,
1507 usb_sndbulkpipe(serial->dev, endpoint) | dir,
1508 buf, len, callback, ctx);
1509 } else {
1510 dev_warn(&serial->interface->dev,
1511 "unsupported endpoint type %x\n",
1512 ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
1513 usb_free_urb(urb);
1514 return NULL;
1515 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001517 dbg("%s - using urb %p for %s endpoint %x",
1518 __func__, urb, ep_type_name, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 return urb;
1520}
1521
1522static struct callbacks {
David Howells7d12e782006-10-05 14:55:46 +01001523 void (*instat_callback)(struct urb *);
1524 void (*glocont_callback)(struct urb *);
1525 void (*indat_callback)(struct urb *);
1526 void (*outdat_callback)(struct urb *);
1527 void (*inack_callback)(struct urb *);
1528 void (*outcont_callback)(struct urb *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529} keyspan_callbacks[] = {
1530 {
1531 /* msg_usa26 callbacks */
1532 .instat_callback = usa26_instat_callback,
1533 .glocont_callback = usa26_glocont_callback,
1534 .indat_callback = usa26_indat_callback,
1535 .outdat_callback = usa2x_outdat_callback,
1536 .inack_callback = usa26_inack_callback,
1537 .outcont_callback = usa26_outcont_callback,
1538 }, {
1539 /* msg_usa28 callbacks */
1540 .instat_callback = usa28_instat_callback,
1541 .glocont_callback = usa28_glocont_callback,
1542 .indat_callback = usa28_indat_callback,
1543 .outdat_callback = usa2x_outdat_callback,
1544 .inack_callback = usa28_inack_callback,
1545 .outcont_callback = usa28_outcont_callback,
1546 }, {
1547 /* msg_usa49 callbacks */
1548 .instat_callback = usa49_instat_callback,
1549 .glocont_callback = usa49_glocont_callback,
1550 .indat_callback = usa49_indat_callback,
1551 .outdat_callback = usa2x_outdat_callback,
1552 .inack_callback = usa49_inack_callback,
1553 .outcont_callback = usa49_outcont_callback,
1554 }, {
1555 /* msg_usa90 callbacks */
1556 .instat_callback = usa90_instat_callback,
1557 .glocont_callback = usa28_glocont_callback,
1558 .indat_callback = usa90_indat_callback,
1559 .outdat_callback = usa2x_outdat_callback,
1560 .inack_callback = usa28_inack_callback,
1561 .outcont_callback = usa90_outcont_callback,
Lucy McCoy0ca12682007-05-18 12:10:41 -07001562 }, {
1563 /* msg_usa67 callbacks */
1564 .instat_callback = usa67_instat_callback,
1565 .glocont_callback = usa67_glocont_callback,
1566 .indat_callback = usa26_indat_callback,
1567 .outdat_callback = usa2x_outdat_callback,
1568 .inack_callback = usa26_inack_callback,
1569 .outcont_callback = usa26_outcont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570 }
1571};
1572
1573 /* Generic setup urbs function that uses
1574 data in device_details */
1575static void keyspan_setup_urbs(struct usb_serial *serial)
1576{
1577 int i, j;
1578 struct keyspan_serial_private *s_priv;
1579 const struct keyspan_device_details *d_details;
1580 struct usb_serial_port *port;
1581 struct keyspan_port_private *p_priv;
1582 struct callbacks *cback;
1583 int endp;
1584
Harvey Harrison441b62c2008-03-03 16:08:34 -08001585 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586
1587 s_priv = usb_get_serial_data(serial);
1588 d_details = s_priv->device_details;
1589
1590 /* Setup values for the various callback routines */
1591 cback = &keyspan_callbacks[d_details->msg_format];
1592
1593 /* Allocate and set up urbs for each one that is in use,
1594 starting with instat endpoints */
1595 s_priv->instat_urb = keyspan_setup_urb
1596 (serial, d_details->instat_endpoint, USB_DIR_IN,
1597 serial, s_priv->instat_buf, INSTAT_BUFLEN,
1598 cback->instat_callback);
1599
Lucy McCoy0ca12682007-05-18 12:10:41 -07001600 s_priv->indat_urb = keyspan_setup_urb
1601 (serial, d_details->indat_endpoint, USB_DIR_IN,
1602 serial, s_priv->indat_buf, INDAT49W_BUFLEN,
1603 usa49wg_indat_callback);
1604
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 s_priv->glocont_urb = keyspan_setup_urb
1606 (serial, d_details->glocont_endpoint, USB_DIR_OUT,
1607 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
1608 cback->glocont_callback);
1609
1610 /* Setup endpoints for each port specific thing */
1611 for (i = 0; i < d_details->num_ports; i ++) {
1612 port = serial->port[i];
1613 p_priv = usb_get_serial_port_data(port);
1614
1615 /* Do indat endpoints first, once for each flip */
1616 endp = d_details->indat_endpoints[i];
1617 for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) {
1618 p_priv->in_urbs[j] = keyspan_setup_urb
1619 (serial, endp, USB_DIR_IN, port,
1620 p_priv->in_buffer[j], 64,
1621 cback->indat_callback);
1622 }
1623 for (; j < 2; ++j)
1624 p_priv->in_urbs[j] = NULL;
1625
1626 /* outdat endpoints also have flip */
1627 endp = d_details->outdat_endpoints[i];
1628 for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) {
1629 p_priv->out_urbs[j] = keyspan_setup_urb
1630 (serial, endp, USB_DIR_OUT, port,
1631 p_priv->out_buffer[j], 64,
1632 cback->outdat_callback);
1633 }
1634 for (; j < 2; ++j)
1635 p_priv->out_urbs[j] = NULL;
1636
1637 /* inack endpoint */
1638 p_priv->inack_urb = keyspan_setup_urb
1639 (serial, d_details->inack_endpoints[i], USB_DIR_IN,
1640 port, p_priv->inack_buffer, 1, cback->inack_callback);
1641
1642 /* outcont endpoint */
1643 p_priv->outcont_urb = keyspan_setup_urb
1644 (serial, d_details->outcont_endpoints[i], USB_DIR_OUT,
1645 port, p_priv->outcont_buffer, 64,
1646 cback->outcont_callback);
1647 }
1648
1649}
1650
1651/* usa19 function doesn't require prescaler */
1652static int keyspan_usa19_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
1653 u8 *rate_low, u8 *prescaler, int portnum)
1654{
1655 u32 b16, /* baud rate times 16 (actual rate used internally) */
1656 div, /* divisor */
1657 cnt; /* inverse of divisor (programmed into 8051) */
1658
Harvey Harrison441b62c2008-03-03 16:08:34 -08001659 dbg ("%s - %d.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660
1661 /* prevent divide by zero... */
1662 if( (b16 = (baud_rate * 16L)) == 0) {
1663 return (KEYSPAN_INVALID_BAUD_RATE);
1664 }
1665
1666 /* Any "standard" rate over 57k6 is marginal on the USA-19
1667 as we run out of divisor resolution. */
1668 if (baud_rate > 57600) {
1669 return (KEYSPAN_INVALID_BAUD_RATE);
1670 }
1671
1672 /* calculate the divisor and the counter (its inverse) */
1673 if( (div = (baudclk / b16)) == 0) {
1674 return (KEYSPAN_INVALID_BAUD_RATE);
1675 }
1676 else {
1677 cnt = 0 - div;
1678 }
1679
1680 if(div > 0xffff) {
1681 return (KEYSPAN_INVALID_BAUD_RATE);
1682 }
1683
1684 /* return the counter values if non-null */
1685 if (rate_low) {
1686 *rate_low = (u8) (cnt & 0xff);
1687 }
1688 if (rate_hi) {
1689 *rate_hi = (u8) ((cnt >> 8) & 0xff);
1690 }
1691 if (rate_low && rate_hi) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001692 dbg ("%s - %d %02x %02x.", __func__, baud_rate, *rate_hi, *rate_low);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 }
1694
1695 return (KEYSPAN_BAUD_RATE_OK);
1696}
1697
1698/* usa19hs function doesn't require prescaler */
1699static int keyspan_usa19hs_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
1700 u8 *rate_low, u8 *prescaler, int portnum)
1701{
1702 u32 b16, /* baud rate times 16 (actual rate used internally) */
1703 div; /* divisor */
1704
Harvey Harrison441b62c2008-03-03 16:08:34 -08001705 dbg ("%s - %d.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706
1707 /* prevent divide by zero... */
1708 if( (b16 = (baud_rate * 16L)) == 0)
1709 return (KEYSPAN_INVALID_BAUD_RATE);
1710
1711
1712
1713 /* calculate the divisor */
1714 if( (div = (baudclk / b16)) == 0)
1715 return (KEYSPAN_INVALID_BAUD_RATE);
1716
1717 if(div > 0xffff)
1718 return (KEYSPAN_INVALID_BAUD_RATE);
1719
1720 /* return the counter values if non-null */
1721 if (rate_low)
1722 *rate_low = (u8) (div & 0xff);
1723
1724 if (rate_hi)
1725 *rate_hi = (u8) ((div >> 8) & 0xff);
1726
1727 if (rate_low && rate_hi)
Harvey Harrison441b62c2008-03-03 16:08:34 -08001728 dbg ("%s - %d %02x %02x.", __func__, baud_rate, *rate_hi, *rate_low);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729
1730 return (KEYSPAN_BAUD_RATE_OK);
1731}
1732
1733static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
1734 u8 *rate_low, u8 *prescaler, int portnum)
1735{
1736 u32 b16, /* baud rate times 16 (actual rate used internally) */
1737 clk, /* clock with 13/8 prescaler */
1738 div, /* divisor using 13/8 prescaler */
1739 res, /* resulting baud rate using 13/8 prescaler */
1740 diff, /* error using 13/8 prescaler */
1741 smallest_diff;
1742 u8 best_prescaler;
1743 int i;
1744
Harvey Harrison441b62c2008-03-03 16:08:34 -08001745 dbg ("%s - %d.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746
1747 /* prevent divide by zero */
1748 if( (b16 = baud_rate * 16L) == 0) {
1749 return (KEYSPAN_INVALID_BAUD_RATE);
1750 }
1751
1752 /* Calculate prescaler by trying them all and looking
1753 for best fit */
1754
1755 /* start with largest possible difference */
1756 smallest_diff = 0xffffffff;
1757
1758 /* 0 is an invalid prescaler, used as a flag */
1759 best_prescaler = 0;
1760
1761 for(i = 8; i <= 0xff; ++i) {
1762 clk = (baudclk * 8) / (u32) i;
1763
1764 if( (div = clk / b16) == 0) {
1765 continue;
1766 }
1767
1768 res = clk / div;
1769 diff= (res > b16) ? (res-b16) : (b16-res);
1770
1771 if(diff < smallest_diff) {
1772 best_prescaler = i;
1773 smallest_diff = diff;
1774 }
1775 }
1776
1777 if(best_prescaler == 0) {
1778 return (KEYSPAN_INVALID_BAUD_RATE);
1779 }
1780
1781 clk = (baudclk * 8) / (u32) best_prescaler;
1782 div = clk / b16;
1783
1784 /* return the divisor and prescaler if non-null */
1785 if (rate_low) {
1786 *rate_low = (u8) (div & 0xff);
1787 }
1788 if (rate_hi) {
1789 *rate_hi = (u8) ((div >> 8) & 0xff);
1790 }
1791 if (prescaler) {
1792 *prescaler = best_prescaler;
Harvey Harrison441b62c2008-03-03 16:08:34 -08001793 /* dbg("%s - %d %d", __func__, *prescaler, div); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794 }
1795 return (KEYSPAN_BAUD_RATE_OK);
1796}
1797
1798 /* USA-28 supports different maximum baud rates on each port */
1799static int keyspan_usa28_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
1800 u8 *rate_low, u8 *prescaler, int portnum)
1801{
1802 u32 b16, /* baud rate times 16 (actual rate used internally) */
1803 div, /* divisor */
1804 cnt; /* inverse of divisor (programmed into 8051) */
1805
Harvey Harrison441b62c2008-03-03 16:08:34 -08001806 dbg ("%s - %d.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807
1808 /* prevent divide by zero */
1809 if ((b16 = baud_rate * 16L) == 0)
1810 return (KEYSPAN_INVALID_BAUD_RATE);
1811
1812 /* calculate the divisor and the counter (its inverse) */
1813 if ((div = (KEYSPAN_USA28_BAUDCLK / b16)) == 0) {
1814 return (KEYSPAN_INVALID_BAUD_RATE);
1815 }
1816 else {
1817 cnt = 0 - div;
1818 }
1819
1820 /* check for out of range, based on portnum,
1821 and return result */
1822 if(portnum == 0) {
1823 if(div > 0xffff)
1824 return (KEYSPAN_INVALID_BAUD_RATE);
1825 }
1826 else {
1827 if(portnum == 1) {
1828 if(div > 0xff) {
1829 return (KEYSPAN_INVALID_BAUD_RATE);
1830 }
1831 }
1832 else {
1833 return (KEYSPAN_INVALID_BAUD_RATE);
1834 }
1835 }
1836
1837 /* return the counter values if not NULL
1838 (port 1 will ignore retHi) */
1839 if (rate_low) {
1840 *rate_low = (u8) (cnt & 0xff);
1841 }
1842 if (rate_hi) {
1843 *rate_hi = (u8) ((cnt >> 8) & 0xff);
1844 }
Harvey Harrison441b62c2008-03-03 16:08:34 -08001845 dbg ("%s - %d OK.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 return (KEYSPAN_BAUD_RATE_OK);
1847}
1848
1849static int keyspan_usa26_send_setup(struct usb_serial *serial,
1850 struct usb_serial_port *port,
1851 int reset_port)
1852{
1853 struct keyspan_usa26_portControlMessage msg;
1854 struct keyspan_serial_private *s_priv;
1855 struct keyspan_port_private *p_priv;
1856 const struct keyspan_device_details *d_details;
1857 int outcont_urb;
1858 struct urb *this_urb;
1859 int device_port, err;
1860
Harvey Harrison441b62c2008-03-03 16:08:34 -08001861 dbg ("%s reset=%d", __func__, reset_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862
1863 s_priv = usb_get_serial_data(serial);
1864 p_priv = usb_get_serial_port_data(port);
1865 d_details = s_priv->device_details;
1866 device_port = port->number - port->serial->minor;
1867
1868 outcont_urb = d_details->outcont_endpoints[port->number];
1869 this_urb = p_priv->outcont_urb;
1870
Harvey Harrison441b62c2008-03-03 16:08:34 -08001871 dbg("%s - endpoint %d", __func__, usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872
1873 /* Make sure we have an urb then send the message */
1874 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001875 dbg("%s - oops no urb.", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876 return -1;
1877 }
1878
1879 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001880 Don't overwrite resend for open/close condition. */
1881 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882 p_priv->resend_cont = reset_port + 1;
1883 if (this_urb->status == -EINPROGRESS) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001884 /* dbg ("%s - already writing", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 mdelay(5);
1886 return(-1);
1887 }
1888
1889 memset(&msg, 0, sizeof (struct keyspan_usa26_portControlMessage));
1890
1891 /* Only set baud rate if it's changed */
1892 if (p_priv->old_baud != p_priv->baud) {
1893 p_priv->old_baud = p_priv->baud;
1894 msg.setClocking = 0xff;
1895 if (d_details->calculate_baud_rate
1896 (p_priv->baud, d_details->baudclk, &msg.baudHi,
1897 &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001898 dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899 p_priv->baud);
1900 msg.baudLo = 0;
1901 msg.baudHi = 125; /* Values for 9600 baud */
1902 msg.prescaler = 10;
1903 }
1904 msg.setPrescaler = 0xff;
1905 }
1906
1907 msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
1908 switch (p_priv->cflag & CSIZE) {
1909 case CS5:
1910 msg.lcr |= USA_DATABITS_5;
1911 break;
1912 case CS6:
1913 msg.lcr |= USA_DATABITS_6;
1914 break;
1915 case CS7:
1916 msg.lcr |= USA_DATABITS_7;
1917 break;
1918 case CS8:
1919 msg.lcr |= USA_DATABITS_8;
1920 break;
1921 }
1922 if (p_priv->cflag & PARENB) {
1923 /* note USA_PARITY_NONE == 0 */
1924 msg.lcr |= (p_priv->cflag & PARODD)?
1925 USA_PARITY_ODD: USA_PARITY_EVEN;
1926 }
1927 msg.setLcr = 0xff;
1928
1929 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1930 msg.xonFlowControl = 0;
1931 msg.setFlowControl = 0xff;
1932 msg.forwardingLength = 16;
1933 msg.xonChar = 17;
1934 msg.xoffChar = 19;
1935
1936 /* Opening port */
1937 if (reset_port == 1) {
1938 msg._txOn = 1;
1939 msg._txOff = 0;
1940 msg.txFlush = 0;
1941 msg.txBreak = 0;
1942 msg.rxOn = 1;
1943 msg.rxOff = 0;
1944 msg.rxFlush = 1;
1945 msg.rxForward = 0;
1946 msg.returnStatus = 0;
1947 msg.resetDataToggle = 0xff;
1948 }
1949
1950 /* Closing port */
1951 else if (reset_port == 2) {
1952 msg._txOn = 0;
1953 msg._txOff = 1;
1954 msg.txFlush = 0;
1955 msg.txBreak = 0;
1956 msg.rxOn = 0;
1957 msg.rxOff = 1;
1958 msg.rxFlush = 1;
1959 msg.rxForward = 0;
1960 msg.returnStatus = 0;
1961 msg.resetDataToggle = 0;
1962 }
1963
1964 /* Sending intermediate configs */
1965 else {
1966 msg._txOn = (! p_priv->break_on);
1967 msg._txOff = 0;
1968 msg.txFlush = 0;
1969 msg.txBreak = (p_priv->break_on);
1970 msg.rxOn = 0;
1971 msg.rxOff = 0;
1972 msg.rxFlush = 0;
1973 msg.rxForward = 0;
1974 msg.returnStatus = 0;
1975 msg.resetDataToggle = 0x0;
1976 }
1977
1978 /* Do handshaking outputs */
1979 msg.setTxTriState_setRts = 0xff;
1980 msg.txTriState_rts = p_priv->rts_state;
1981
1982 msg.setHskoa_setDtr = 0xff;
1983 msg.hskoa_dtr = p_priv->dtr_state;
1984
1985 p_priv->resend_cont = 0;
1986 memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
1987
1988 /* send the data out the device on control endpoint */
1989 this_urb->transfer_buffer_length = sizeof(msg);
1990
1991 this_urb->dev = serial->dev;
1992 if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001993 dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994 }
1995#if 0
1996 else {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001997 dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 outcont_urb, this_urb->transfer_buffer_length,
1999 usb_pipeendpoint(this_urb->pipe));
2000 }
2001#endif
2002
Alan Coxa5b6f602008-04-08 17:16:06 +01002003 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004}
2005
2006static int keyspan_usa28_send_setup(struct usb_serial *serial,
2007 struct usb_serial_port *port,
2008 int reset_port)
2009{
2010 struct keyspan_usa28_portControlMessage msg;
2011 struct keyspan_serial_private *s_priv;
2012 struct keyspan_port_private *p_priv;
2013 const struct keyspan_device_details *d_details;
2014 struct urb *this_urb;
2015 int device_port, err;
2016
Harvey Harrison441b62c2008-03-03 16:08:34 -08002017 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018
2019 s_priv = usb_get_serial_data(serial);
2020 p_priv = usb_get_serial_port_data(port);
2021 d_details = s_priv->device_details;
2022 device_port = port->number - port->serial->minor;
2023
2024 /* only do something if we have a bulk out endpoint */
2025 if ((this_urb = p_priv->outcont_urb) == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002026 dbg("%s - oops no urb.", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 return -1;
2028 }
2029
2030 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07002031 Don't overwrite resend for open/close condition. */
2032 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 p_priv->resend_cont = reset_port + 1;
2034 if (this_urb->status == -EINPROGRESS) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002035 dbg ("%s already writing", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 mdelay(5);
2037 return(-1);
2038 }
2039
2040 memset(&msg, 0, sizeof (struct keyspan_usa28_portControlMessage));
2041
2042 msg.setBaudRate = 1;
2043 if (d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk,
2044 &msg.baudHi, &msg.baudLo, NULL, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002045 dbg("%s - Invalid baud rate requested %d.", __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046 msg.baudLo = 0xff;
2047 msg.baudHi = 0xb2; /* Values for 9600 baud */
2048 }
2049
2050 /* If parity is enabled, we must calculate it ourselves. */
2051 msg.parity = 0; /* XXX for now */
2052
2053 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2054 msg.xonFlowControl = 0;
2055
2056 /* Do handshaking outputs, DTR is inverted relative to RTS */
2057 msg.rts = p_priv->rts_state;
2058 msg.dtr = p_priv->dtr_state;
2059
2060 msg.forwardingLength = 16;
2061 msg.forwardMs = 10;
2062 msg.breakThreshold = 45;
2063 msg.xonChar = 17;
2064 msg.xoffChar = 19;
2065
2066 /*msg.returnStatus = 1;
2067 msg.resetDataToggle = 0xff;*/
2068 /* Opening port */
2069 if (reset_port == 1) {
2070 msg._txOn = 1;
2071 msg._txOff = 0;
2072 msg.txFlush = 0;
2073 msg.txForceXoff = 0;
2074 msg.txBreak = 0;
2075 msg.rxOn = 1;
2076 msg.rxOff = 0;
2077 msg.rxFlush = 1;
2078 msg.rxForward = 0;
2079 msg.returnStatus = 0;
2080 msg.resetDataToggle = 0xff;
2081 }
2082 /* Closing port */
2083 else if (reset_port == 2) {
2084 msg._txOn = 0;
2085 msg._txOff = 1;
2086 msg.txFlush = 0;
2087 msg.txForceXoff = 0;
2088 msg.txBreak = 0;
2089 msg.rxOn = 0;
2090 msg.rxOff = 1;
2091 msg.rxFlush = 1;
2092 msg.rxForward = 0;
2093 msg.returnStatus = 0;
2094 msg.resetDataToggle = 0;
2095 }
2096 /* Sending intermediate configs */
2097 else {
2098 msg._txOn = (! p_priv->break_on);
2099 msg._txOff = 0;
2100 msg.txFlush = 0;
2101 msg.txForceXoff = 0;
2102 msg.txBreak = (p_priv->break_on);
2103 msg.rxOn = 0;
2104 msg.rxOff = 0;
2105 msg.rxFlush = 0;
2106 msg.rxForward = 0;
2107 msg.returnStatus = 0;
2108 msg.resetDataToggle = 0x0;
2109 }
2110
2111 p_priv->resend_cont = 0;
2112 memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
2113
2114 /* send the data out the device on control endpoint */
2115 this_urb->transfer_buffer_length = sizeof(msg);
2116
2117 this_urb->dev = serial->dev;
2118 if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002119 dbg("%s - usb_submit_urb(setup) failed", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120 }
2121#if 0
2122 else {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002123 dbg("%s - usb_submit_urb(setup) OK %d bytes", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 this_urb->transfer_buffer_length);
2125 }
2126#endif
2127
Alan Coxa5b6f602008-04-08 17:16:06 +01002128 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129}
2130
2131static int keyspan_usa49_send_setup(struct usb_serial *serial,
2132 struct usb_serial_port *port,
2133 int reset_port)
2134{
Lucy McCoy0ca12682007-05-18 12:10:41 -07002135 struct keyspan_usa49_portControlMessage msg;
2136 struct usb_ctrlrequest *dr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137 struct keyspan_serial_private *s_priv;
2138 struct keyspan_port_private *p_priv;
2139 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140 struct urb *this_urb;
2141 int err, device_port;
2142
Harvey Harrison441b62c2008-03-03 16:08:34 -08002143 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144
2145 s_priv = usb_get_serial_data(serial);
2146 p_priv = usb_get_serial_port_data(port);
2147 d_details = s_priv->device_details;
2148
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 this_urb = s_priv->glocont_urb;
2150
Lucy McCoy0ca12682007-05-18 12:10:41 -07002151 /* Work out which port within the device is being setup */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 device_port = port->number - port->serial->minor;
2153
Harvey Harrison441b62c2008-03-03 16:08:34 -08002154 dbg("%s - endpoint %d port %d (%d)",__func__, usb_pipeendpoint(this_urb->pipe), port->number, device_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155
2156 /* Make sure we have an urb then send the message */
2157 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002158 dbg("%s - oops no urb for port %d.", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159 return -1;
2160 }
2161
2162 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07002163 Don't overwrite resend for open/close condition. */
2164 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165 p_priv->resend_cont = reset_port + 1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002166
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 if (this_urb->status == -EINPROGRESS) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002168 /* dbg ("%s - already writing", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 mdelay(5);
2170 return(-1);
2171 }
2172
2173 memset(&msg, 0, sizeof (struct keyspan_usa49_portControlMessage));
2174
2175 /*msg.portNumber = port->number;*/
2176 msg.portNumber = device_port;
2177
2178 /* Only set baud rate if it's changed */
2179 if (p_priv->old_baud != p_priv->baud) {
2180 p_priv->old_baud = p_priv->baud;
2181 msg.setClocking = 0xff;
2182 if (d_details->calculate_baud_rate
2183 (p_priv->baud, d_details->baudclk, &msg.baudHi,
2184 &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002185 dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186 p_priv->baud);
2187 msg.baudLo = 0;
2188 msg.baudHi = 125; /* Values for 9600 baud */
2189 msg.prescaler = 10;
2190 }
2191 //msg.setPrescaler = 0xff;
2192 }
2193
2194 msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
2195 switch (p_priv->cflag & CSIZE) {
2196 case CS5:
2197 msg.lcr |= USA_DATABITS_5;
2198 break;
2199 case CS6:
2200 msg.lcr |= USA_DATABITS_6;
2201 break;
2202 case CS7:
2203 msg.lcr |= USA_DATABITS_7;
2204 break;
2205 case CS8:
2206 msg.lcr |= USA_DATABITS_8;
2207 break;
2208 }
2209 if (p_priv->cflag & PARENB) {
2210 /* note USA_PARITY_NONE == 0 */
2211 msg.lcr |= (p_priv->cflag & PARODD)?
2212 USA_PARITY_ODD: USA_PARITY_EVEN;
2213 }
2214 msg.setLcr = 0xff;
2215
2216 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2217 msg.xonFlowControl = 0;
2218 msg.setFlowControl = 0xff;
2219
2220 msg.forwardingLength = 16;
2221 msg.xonChar = 17;
2222 msg.xoffChar = 19;
2223
2224 /* Opening port */
2225 if (reset_port == 1) {
2226 msg._txOn = 1;
2227 msg._txOff = 0;
2228 msg.txFlush = 0;
2229 msg.txBreak = 0;
2230 msg.rxOn = 1;
2231 msg.rxOff = 0;
2232 msg.rxFlush = 1;
2233 msg.rxForward = 0;
2234 msg.returnStatus = 0;
2235 msg.resetDataToggle = 0xff;
2236 msg.enablePort = 1;
2237 msg.disablePort = 0;
2238 }
2239 /* Closing port */
2240 else if (reset_port == 2) {
2241 msg._txOn = 0;
2242 msg._txOff = 1;
2243 msg.txFlush = 0;
2244 msg.txBreak = 0;
2245 msg.rxOn = 0;
2246 msg.rxOff = 1;
2247 msg.rxFlush = 1;
2248 msg.rxForward = 0;
2249 msg.returnStatus = 0;
2250 msg.resetDataToggle = 0;
2251 msg.enablePort = 0;
2252 msg.disablePort = 1;
2253 }
2254 /* Sending intermediate configs */
2255 else {
2256 msg._txOn = (! p_priv->break_on);
2257 msg._txOff = 0;
2258 msg.txFlush = 0;
2259 msg.txBreak = (p_priv->break_on);
2260 msg.rxOn = 0;
2261 msg.rxOff = 0;
2262 msg.rxFlush = 0;
2263 msg.rxForward = 0;
2264 msg.returnStatus = 0;
2265 msg.resetDataToggle = 0x0;
2266 msg.enablePort = 0;
2267 msg.disablePort = 0;
2268 }
2269
2270 /* Do handshaking outputs */
2271 msg.setRts = 0xff;
2272 msg.rts = p_priv->rts_state;
2273
2274 msg.setDtr = 0xff;
2275 msg.dtr = p_priv->dtr_state;
2276
2277 p_priv->resend_cont = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278
Lucy McCoy0ca12682007-05-18 12:10:41 -07002279 /* if the device is a 49wg, we send control message on usb control EP 0 */
2280
2281 if (d_details->product_id == keyspan_usa49wg_product_id) {
2282 dr = (void *)(s_priv->ctrl_buf);
2283 dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT;
2284 dr->bRequest = 0xB0; /* 49wg control message */;
2285 dr->wValue = 0;
2286 dr->wIndex = 0;
2287 dr->wLength = cpu_to_le16(sizeof(msg));
2288
2289 memcpy (s_priv->glocont_buf, &msg, sizeof(msg));
2290
2291 usb_fill_control_urb(this_urb, serial->dev, usb_sndctrlpipe(serial->dev, 0),
2292 (unsigned char *)dr, s_priv->glocont_buf, sizeof(msg),
2293 usa49_glocont_callback, serial);
2294
2295 } else {
2296 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2297
2298 /* send the data out the device on control endpoint */
2299 this_urb->transfer_buffer_length = sizeof(msg);
2300
2301 this_urb->dev = serial->dev;
2302 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002304 dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305 }
2306#if 0
2307 else {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002308 dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002309 outcont_urb, this_urb->transfer_buffer_length,
2310 usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311 }
2312#endif
2313
Alan Coxa5b6f602008-04-08 17:16:06 +01002314 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315}
2316
2317static int keyspan_usa90_send_setup(struct usb_serial *serial,
2318 struct usb_serial_port *port,
2319 int reset_port)
2320{
2321 struct keyspan_usa90_portControlMessage msg;
2322 struct keyspan_serial_private *s_priv;
2323 struct keyspan_port_private *p_priv;
2324 const struct keyspan_device_details *d_details;
2325 struct urb *this_urb;
2326 int err;
2327 u8 prescaler;
2328
Harvey Harrison441b62c2008-03-03 16:08:34 -08002329 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330
2331 s_priv = usb_get_serial_data(serial);
2332 p_priv = usb_get_serial_port_data(port);
2333 d_details = s_priv->device_details;
2334
2335 /* only do something if we have a bulk out endpoint */
2336 if ((this_urb = p_priv->outcont_urb) == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002337 dbg("%s - oops no urb.", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338 return -1;
2339 }
2340
2341 /* Save reset port val for resend.
2342 Don't overwrite resend for open/close condition. */
2343 if ((reset_port + 1) > p_priv->resend_cont)
2344 p_priv->resend_cont = reset_port + 1;
2345 if (this_urb->status == -EINPROGRESS) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002346 dbg ("%s already writing", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347 mdelay(5);
2348 return(-1);
2349 }
2350
2351 memset(&msg, 0, sizeof (struct keyspan_usa90_portControlMessage));
2352
2353 /* Only set baud rate if it's changed */
2354 if (p_priv->old_baud != p_priv->baud) {
2355 p_priv->old_baud = p_priv->baud;
2356 msg.setClocking = 0x01;
2357 if (d_details->calculate_baud_rate
2358 (p_priv->baud, d_details->baudclk, &msg.baudHi,
2359 &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE ) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002360 dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361 p_priv->baud);
2362 p_priv->baud = 9600;
2363 d_details->calculate_baud_rate (p_priv->baud, d_details->baudclk,
2364 &msg.baudHi, &msg.baudLo, &prescaler, 0);
2365 }
2366 msg.setRxMode = 1;
2367 msg.setTxMode = 1;
2368 }
2369
2370 /* modes must always be correctly specified */
2371 if (p_priv->baud > 57600)
2372 {
2373 msg.rxMode = RXMODE_DMA;
2374 msg.txMode = TXMODE_DMA;
2375 }
2376 else
2377 {
2378 msg.rxMode = RXMODE_BYHAND;
2379 msg.txMode = TXMODE_BYHAND;
2380 }
2381
2382 msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
2383 switch (p_priv->cflag & CSIZE) {
2384 case CS5:
2385 msg.lcr |= USA_DATABITS_5;
2386 break;
2387 case CS6:
2388 msg.lcr |= USA_DATABITS_6;
2389 break;
2390 case CS7:
2391 msg.lcr |= USA_DATABITS_7;
2392 break;
2393 case CS8:
2394 msg.lcr |= USA_DATABITS_8;
2395 break;
2396 }
2397 if (p_priv->cflag & PARENB) {
2398 /* note USA_PARITY_NONE == 0 */
2399 msg.lcr |= (p_priv->cflag & PARODD)?
2400 USA_PARITY_ODD: USA_PARITY_EVEN;
2401 }
2402 if (p_priv->old_cflag != p_priv->cflag) {
2403 p_priv->old_cflag = p_priv->cflag;
2404 msg.setLcr = 0x01;
2405 }
2406
2407 if (p_priv->flow_control == flow_cts)
2408 msg.txFlowControl = TXFLOW_CTS;
2409 msg.setTxFlowControl = 0x01;
2410 msg.setRxFlowControl = 0x01;
2411
2412 msg.rxForwardingLength = 16;
2413 msg.rxForwardingTimeout = 16;
2414 msg.txAckSetting = 0;
2415 msg.xonChar = 17;
2416 msg.xoffChar = 19;
2417
2418 /* Opening port */
2419 if (reset_port == 1) {
2420 msg.portEnabled = 1;
2421 msg.rxFlush = 1;
2422 msg.txBreak = (p_priv->break_on);
2423 }
2424 /* Closing port */
2425 else if (reset_port == 2) {
2426 msg.portEnabled = 0;
2427 }
2428 /* Sending intermediate configs */
2429 else {
2430 if (port->open_count)
2431 msg.portEnabled = 1;
2432 msg.txBreak = (p_priv->break_on);
2433 }
2434
2435 /* Do handshaking outputs */
2436 msg.setRts = 0x01;
2437 msg.rts = p_priv->rts_state;
2438
2439 msg.setDtr = 0x01;
2440 msg.dtr = p_priv->dtr_state;
2441
2442 p_priv->resend_cont = 0;
2443 memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
2444
2445 /* send the data out the device on control endpoint */
2446 this_urb->transfer_buffer_length = sizeof(msg);
2447
2448 this_urb->dev = serial->dev;
2449 if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002450 dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451 }
Alan Coxa5b6f602008-04-08 17:16:06 +01002452 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453}
2454
Lucy McCoy0ca12682007-05-18 12:10:41 -07002455static int keyspan_usa67_send_setup(struct usb_serial *serial,
2456 struct usb_serial_port *port,
2457 int reset_port)
2458{
2459 struct keyspan_usa67_portControlMessage msg;
2460 struct keyspan_serial_private *s_priv;
2461 struct keyspan_port_private *p_priv;
2462 const struct keyspan_device_details *d_details;
2463 struct urb *this_urb;
2464 int err, device_port;
2465
Harvey Harrison441b62c2008-03-03 16:08:34 -08002466 dbg ("%s", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002467
2468 s_priv = usb_get_serial_data(serial);
2469 p_priv = usb_get_serial_port_data(port);
2470 d_details = s_priv->device_details;
2471
2472 this_urb = s_priv->glocont_urb;
2473
2474 /* Work out which port within the device is being setup */
2475 device_port = port->number - port->serial->minor;
2476
2477 /* Make sure we have an urb then send the message */
2478 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002479 dbg("%s - oops no urb for port %d.", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002480 port->number);
2481 return -1;
2482 }
2483
2484 /* Save reset port val for resend.
2485 Don't overwrite resend for open/close condition. */
2486 if ((reset_port + 1) > p_priv->resend_cont)
2487 p_priv->resend_cont = reset_port + 1;
2488 if (this_urb->status == -EINPROGRESS) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002489 /* dbg ("%s - already writing", __func__); */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002490 mdelay(5);
2491 return(-1);
2492 }
2493
2494 memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
2495
2496 msg.port = device_port;
2497
2498 /* Only set baud rate if it's changed */
2499 if (p_priv->old_baud != p_priv->baud) {
2500 p_priv->old_baud = p_priv->baud;
2501 msg.setClocking = 0xff;
2502 if (d_details->calculate_baud_rate
2503 (p_priv->baud, d_details->baudclk, &msg.baudHi,
2504 &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002505 dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002506 p_priv->baud);
2507 msg.baudLo = 0;
2508 msg.baudHi = 125; /* Values for 9600 baud */
2509 msg.prescaler = 10;
2510 }
2511 msg.setPrescaler = 0xff;
2512 }
2513
2514 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
2515 switch (p_priv->cflag & CSIZE) {
2516 case CS5:
2517 msg.lcr |= USA_DATABITS_5;
2518 break;
2519 case CS6:
2520 msg.lcr |= USA_DATABITS_6;
2521 break;
2522 case CS7:
2523 msg.lcr |= USA_DATABITS_7;
2524 break;
2525 case CS8:
2526 msg.lcr |= USA_DATABITS_8;
2527 break;
2528 }
2529 if (p_priv->cflag & PARENB) {
2530 /* note USA_PARITY_NONE == 0 */
2531 msg.lcr |= (p_priv->cflag & PARODD)?
2532 USA_PARITY_ODD: USA_PARITY_EVEN;
2533 }
2534 msg.setLcr = 0xff;
2535
2536 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2537 msg.xonFlowControl = 0;
2538 msg.setFlowControl = 0xff;
2539 msg.forwardingLength = 16;
2540 msg.xonChar = 17;
2541 msg.xoffChar = 19;
2542
2543 if (reset_port == 1) {
2544 /* Opening port */
2545 msg._txOn = 1;
2546 msg._txOff = 0;
2547 msg.txFlush = 0;
2548 msg.txBreak = 0;
2549 msg.rxOn = 1;
2550 msg.rxOff = 0;
2551 msg.rxFlush = 1;
2552 msg.rxForward = 0;
2553 msg.returnStatus = 0;
2554 msg.resetDataToggle = 0xff;
2555 } else if (reset_port == 2) {
2556 /* Closing port */
2557 msg._txOn = 0;
2558 msg._txOff = 1;
2559 msg.txFlush = 0;
2560 msg.txBreak = 0;
2561 msg.rxOn = 0;
2562 msg.rxOff = 1;
2563 msg.rxFlush = 1;
2564 msg.rxForward = 0;
2565 msg.returnStatus = 0;
2566 msg.resetDataToggle = 0;
2567 } else {
2568 /* Sending intermediate configs */
2569 msg._txOn = (! p_priv->break_on);
2570 msg._txOff = 0;
2571 msg.txFlush = 0;
2572 msg.txBreak = (p_priv->break_on);
2573 msg.rxOn = 0;
2574 msg.rxOff = 0;
2575 msg.rxFlush = 0;
2576 msg.rxForward = 0;
2577 msg.returnStatus = 0;
2578 msg.resetDataToggle = 0x0;
2579 }
2580
2581 /* Do handshaking outputs */
2582 msg.setTxTriState_setRts = 0xff;
2583 msg.txTriState_rts = p_priv->rts_state;
2584
2585 msg.setHskoa_setDtr = 0xff;
2586 msg.hskoa_dtr = p_priv->dtr_state;
2587
2588 p_priv->resend_cont = 0;
2589
2590 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2591
2592 /* send the data out the device on control endpoint */
2593 this_urb->transfer_buffer_length = sizeof(msg);
2594 this_urb->dev = serial->dev;
2595
2596 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2597 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002598 dbg("%s - usb_submit_urb(setup) failed (%d)", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002599 err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002600 return 0;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002601}
2602
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
2604{
2605 struct usb_serial *serial = port->serial;
2606 struct keyspan_serial_private *s_priv;
2607 const struct keyspan_device_details *d_details;
2608
Harvey Harrison441b62c2008-03-03 16:08:34 -08002609 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610
2611 s_priv = usb_get_serial_data(serial);
2612 d_details = s_priv->device_details;
2613
2614 switch (d_details->msg_format) {
2615 case msg_usa26:
2616 keyspan_usa26_send_setup(serial, port, reset_port);
2617 break;
2618 case msg_usa28:
2619 keyspan_usa28_send_setup(serial, port, reset_port);
2620 break;
2621 case msg_usa49:
2622 keyspan_usa49_send_setup(serial, port, reset_port);
2623 break;
2624 case msg_usa90:
2625 keyspan_usa90_send_setup(serial, port, reset_port);
2626 break;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002627 case msg_usa67:
2628 keyspan_usa67_send_setup(serial, port, reset_port);
2629 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630 }
2631}
2632
2633
2634/* Gets called by the "real" driver (ie once firmware is loaded
2635 and renumeration has taken place. */
2636static int keyspan_startup (struct usb_serial *serial)
2637{
2638 int i, err;
2639 struct usb_serial_port *port;
2640 struct keyspan_serial_private *s_priv;
2641 struct keyspan_port_private *p_priv;
2642 const struct keyspan_device_details *d_details;
2643
Harvey Harrison441b62c2008-03-03 16:08:34 -08002644 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645
2646 for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
2647 if (d_details->product_id == le16_to_cpu(serial->dev->descriptor.idProduct))
2648 break;
2649 if (d_details == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002650 dev_err(&serial->dev->dev, "%s - unknown product id %x\n", __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651 return 1;
2652 }
2653
2654 /* Setup private data for serial driver */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01002655 s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656 if (!s_priv) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002657 dbg("%s - kmalloc for keyspan_serial_private failed.", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658 return -ENOMEM;
2659 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660
2661 s_priv->device_details = d_details;
2662 usb_set_serial_data(serial, s_priv);
2663
2664 /* Now setup per port private data */
2665 for (i = 0; i < serial->num_ports; i++) {
2666 port = serial->port[i];
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01002667 p_priv = kzalloc(sizeof(struct keyspan_port_private), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668 if (!p_priv) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002669 dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __func__, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670 return (1);
2671 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672 p_priv->device_details = d_details;
2673 usb_set_serial_port_data(port, p_priv);
2674 }
2675
2676 keyspan_setup_urbs(serial);
2677
Lucy McCoy0ca12682007-05-18 12:10:41 -07002678 if (s_priv->instat_urb != NULL) {
2679 s_priv->instat_urb->dev = serial->dev;
2680 err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
2681 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002682 dbg("%s - submit instat urb failed %d", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002683 err);
2684 }
2685 if (s_priv->indat_urb != NULL) {
2686 s_priv->indat_urb->dev = serial->dev;
2687 err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
2688 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002689 dbg("%s - submit indat urb failed %d", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002690 err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691 }
2692
Alan Coxa5b6f602008-04-08 17:16:06 +01002693 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694}
2695
2696static void keyspan_shutdown (struct usb_serial *serial)
2697{
2698 int i, j;
2699 struct usb_serial_port *port;
2700 struct keyspan_serial_private *s_priv;
2701 struct keyspan_port_private *p_priv;
2702
Harvey Harrison441b62c2008-03-03 16:08:34 -08002703 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002704
2705 s_priv = usb_get_serial_data(serial);
2706
2707 /* Stop reading/writing urbs */
2708 stop_urb(s_priv->instat_urb);
2709 stop_urb(s_priv->glocont_urb);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002710 stop_urb(s_priv->indat_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002711 for (i = 0; i < serial->num_ports; ++i) {
2712 port = serial->port[i];
2713 p_priv = usb_get_serial_port_data(port);
2714 stop_urb(p_priv->inack_urb);
2715 stop_urb(p_priv->outcont_urb);
2716 for (j = 0; j < 2; j++) {
2717 stop_urb(p_priv->in_urbs[j]);
2718 stop_urb(p_priv->out_urbs[j]);
2719 }
2720 }
2721
2722 /* Now free them */
Mariusz Kozlowski1cadc132006-11-08 15:36:34 +01002723 usb_free_urb(s_priv->instat_urb);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002724 usb_free_urb(s_priv->indat_urb);
Mariusz Kozlowski1cadc132006-11-08 15:36:34 +01002725 usb_free_urb(s_priv->glocont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726 for (i = 0; i < serial->num_ports; ++i) {
2727 port = serial->port[i];
2728 p_priv = usb_get_serial_port_data(port);
Mariusz Kozlowski1cadc132006-11-08 15:36:34 +01002729 usb_free_urb(p_priv->inack_urb);
2730 usb_free_urb(p_priv->outcont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731 for (j = 0; j < 2; j++) {
Mariusz Kozlowski1cadc132006-11-08 15:36:34 +01002732 usb_free_urb(p_priv->in_urbs[j]);
2733 usb_free_urb(p_priv->out_urbs[j]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002734 }
2735 }
2736
2737 /* dbg("Freeing serial->private."); */
2738 kfree(s_priv);
2739
2740 /* dbg("Freeing port->private."); */
2741 /* Now free per port private data */
2742 for (i = 0; i < serial->num_ports; i++) {
2743 port = serial->port[i];
2744 kfree(usb_get_serial_port_data(port));
2745 }
2746}
2747
2748MODULE_AUTHOR( DRIVER_AUTHOR );
2749MODULE_DESCRIPTION( DRIVER_DESC );
2750MODULE_LICENSE("GPL");
2751
David Woodhouse2971c572008-05-30 14:04:03 +03002752MODULE_FIRMWARE("keyspan/usa28.fw");
2753MODULE_FIRMWARE("keyspan/usa28x.fw");
2754MODULE_FIRMWARE("keyspan/usa28xa.fw");
2755MODULE_FIRMWARE("keyspan/usa28xb.fw");
2756MODULE_FIRMWARE("keyspan/usa19.fw");
2757MODULE_FIRMWARE("keyspan/usa19qi.fw");
2758MODULE_FIRMWARE("keyspan/mpr.fw");
2759MODULE_FIRMWARE("keyspan/usa19qw.fw");
2760MODULE_FIRMWARE("keyspan/usa18x.fw");
2761MODULE_FIRMWARE("keyspan/usa19w.fw");
2762MODULE_FIRMWARE("keyspan/usa49w.fw");
2763MODULE_FIRMWARE("keyspan/usa49wlc.fw");
2764
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765module_param(debug, bool, S_IRUGO | S_IWUSR);
2766MODULE_PARM_DESC(debug, "Debug enabled or not");
2767