blob: a371c41bb3ab8b5cef70e1e48d1e8b2bde38fd8b [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
Alan Cox95da3102008-07-22 11:09:07 +0100247static void keyspan_break_ctl(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248{
Alan Cox95da3102008-07-22 11:09:07 +0100249 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 struct keyspan_port_private *p_priv;
251
Harvey Harrison441b62c2008-03-03 16:08:34 -0800252 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253
254 p_priv = usb_get_serial_port_data(port);
255
256 if (break_state == -1)
257 p_priv->break_on = 1;
258 else
259 p_priv->break_on = 0;
260
261 keyspan_send_setup(port, 0);
262}
263
264
Alan Cox95da3102008-07-22 11:09:07 +0100265static void keyspan_set_termios (struct tty_struct *tty,
266 struct usb_serial_port *port, struct ktermios *old_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267{
268 int baud_rate, device_port;
269 struct keyspan_port_private *p_priv;
270 const struct keyspan_device_details *d_details;
271 unsigned int cflag;
272
Harvey Harrison441b62c2008-03-03 16:08:34 -0800273 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274
275 p_priv = usb_get_serial_port_data(port);
276 d_details = p_priv->device_details;
Alan Cox74240b02007-10-18 01:24:20 -0700277 cflag = tty->termios->c_cflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 device_port = port->number - port->serial->minor;
279
280 /* Baud rate calculation takes baud rate as an integer
281 so other rates can be generated if desired. */
Alan Cox74240b02007-10-18 01:24:20 -0700282 baud_rate = tty_get_baud_rate(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 /* If no match or invalid, don't change */
Alan Cox74240b02007-10-18 01:24:20 -0700284 if (d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
286 /* FIXME - more to do here to ensure rate changes cleanly */
Alan Cox74240b02007-10-18 01:24:20 -0700287 /* FIXME - calcuate exact rate from divisor ? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 p_priv->baud = baud_rate;
Alan Cox74240b02007-10-18 01:24:20 -0700289 } else
290 baud_rate = tty_termios_baud_rate(old_termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291
Alan Cox74240b02007-10-18 01:24:20 -0700292 tty_encode_baud_rate(tty, baud_rate, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 /* set CTS/RTS handshake etc. */
294 p_priv->cflag = cflag;
295 p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none;
296
Alan Cox74240b02007-10-18 01:24:20 -0700297 /* Mark/Space not supported */
298 tty->termios->c_cflag &= ~CMSPAR;
299
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 keyspan_send_setup(port, 0);
301}
302
Alan Cox95da3102008-07-22 11:09:07 +0100303static int keyspan_tiocmget(struct tty_struct *tty, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304{
Alan Cox95da3102008-07-22 11:09:07 +0100305 struct usb_serial_port *port = tty->driver_data;
306 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 unsigned int value;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
309 value = ((p_priv->rts_state) ? TIOCM_RTS : 0) |
310 ((p_priv->dtr_state) ? TIOCM_DTR : 0) |
311 ((p_priv->cts_state) ? TIOCM_CTS : 0) |
312 ((p_priv->dsr_state) ? TIOCM_DSR : 0) |
313 ((p_priv->dcd_state) ? TIOCM_CAR : 0) |
314 ((p_priv->ri_state) ? TIOCM_RNG : 0);
315
316 return value;
317}
318
Alan Cox95da3102008-07-22 11:09:07 +0100319static int keyspan_tiocmset(struct tty_struct *tty, struct file *file,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 unsigned int set, unsigned int clear)
321{
Alan Cox95da3102008-07-22 11:09:07 +0100322 struct usb_serial_port *port = tty->driver_data;
323 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324
325 if (set & TIOCM_RTS)
326 p_priv->rts_state = 1;
327 if (set & TIOCM_DTR)
328 p_priv->dtr_state = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 if (clear & TIOCM_RTS)
330 p_priv->rts_state = 0;
331 if (clear & TIOCM_DTR)
332 p_priv->dtr_state = 0;
333 keyspan_send_setup(port, 0);
334 return 0;
335}
336
Alan Cox95da3102008-07-22 11:09:07 +0100337/* Write function is similar for the four protocols used
338 with only a minor change for usa90 (usa19hs) required */
339static int keyspan_write(struct tty_struct *tty,
340 struct usb_serial_port *port, const unsigned char *buf, int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341{
342 struct keyspan_port_private *p_priv;
343 const struct keyspan_device_details *d_details;
344 int flip;
345 int left, todo;
346 struct urb *this_urb;
347 int err, maxDataLen, dataOffset;
348
349 p_priv = usb_get_serial_port_data(port);
350 d_details = p_priv->device_details;
351
352 if (d_details->msg_format == msg_usa90) {
353 maxDataLen = 64;
354 dataOffset = 0;
355 } else {
356 maxDataLen = 63;
357 dataOffset = 1;
358 }
359
360 dbg("%s - for port %d (%d chars), flip=%d",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800361 __func__, port->number, count, p_priv->out_flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362
363 for (left = count; left > 0; left -= todo) {
364 todo = left;
365 if (todo > maxDataLen)
366 todo = maxDataLen;
367
368 flip = p_priv->out_flip;
369
370 /* Check we have a valid urb/endpoint before we use it... */
371 if ((this_urb = p_priv->out_urbs[flip]) == NULL) {
372 /* no bulk out, so return 0 bytes written */
Harvey Harrison441b62c2008-03-03 16:08:34 -0800373 dbg("%s - no output urb :(", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 return count;
375 }
376
Harvey Harrison441b62c2008-03-03 16:08:34 -0800377 dbg("%s - endpoint %d flip %d", __func__, usb_pipeendpoint(this_urb->pipe), flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378
379 if (this_urb->status == -EINPROGRESS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 if (time_before(jiffies, p_priv->tx_start_time[flip] + 10 * HZ))
381 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 usb_unlink_urb(this_urb);
383 break;
384 }
385
386 /* First byte in buffer is "last flag" (except for usa19hx) - unused so
387 for now so set to zero */
388 ((char *)this_urb->transfer_buffer)[0] = 0;
389
390 memcpy (this_urb->transfer_buffer + dataOffset, buf, todo);
391 buf += todo;
392
393 /* send the data out the bulk port */
394 this_urb->transfer_buffer_length = todo + dataOffset;
395
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 this_urb->dev = port->serial->dev;
397 if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
398 dbg("usb_submit_urb(write bulk) failed (%d)", err);
399 }
400 p_priv->tx_start_time[flip] = jiffies;
401
402 /* Flip for next time if usa26 or usa28 interface
403 (not used on usa49) */
404 p_priv->out_flip = (flip + 1) & d_details->outdat_endp_flip;
405 }
406
407 return count - left;
408}
409
David Howells7d12e782006-10-05 14:55:46 +0100410static void usa26_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411{
412 int i, err;
413 int endpoint;
414 struct usb_serial_port *port;
415 struct tty_struct *tty;
416 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700417 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418
Harvey Harrison441b62c2008-03-03 16:08:34 -0800419 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420
421 endpoint = usb_pipeendpoint(urb->pipe);
422
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700423 if (status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 dbg("%s - nonzero status: %x on endpoint %d.",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800425 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 return;
427 }
428
Ming Leicdc97792008-02-24 18:41:47 +0800429 port = urb->context;
Alan Cox95da3102008-07-22 11:09:07 +0100430 tty = port->port.tty;
Alan Coxa5569a52008-01-21 17:18:24 -0800431 if (tty && urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 /* 0x80 bit is error flag */
433 if ((data[0] & 0x80) == 0) {
434 /* no errors on individual bytes, only possible overrun err*/
435 if (data[0] & RXERROR_OVERRUN)
436 err = TTY_OVERRUN;
437 else err = 0;
438 for (i = 1; i < urb->actual_length ; ++i) {
439 tty_insert_flip_char(tty, data[i], err);
440 }
441 } else {
442 /* some bytes had errors, every byte has status */
Harvey Harrison441b62c2008-03-03 16:08:34 -0800443 dbg("%s - RX error!!!!", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 for (i = 0; i + 1 < urb->actual_length; i += 2) {
445 int stat = data[i], flag = 0;
446 if (stat & RXERROR_OVERRUN)
447 flag |= TTY_OVERRUN;
448 if (stat & RXERROR_FRAMING)
449 flag |= TTY_FRAME;
450 if (stat & RXERROR_PARITY)
451 flag |= TTY_PARITY;
452 /* XXX should handle break (0x10) */
453 tty_insert_flip_char(tty, data[i+1], flag);
454 }
455 }
456 tty_flip_buffer_push(tty);
457 }
458
459 /* Resubmit urb so we continue receiving */
460 urb->dev = port->serial->dev;
Alan Cox95da3102008-07-22 11:09:07 +0100461 if (port->port.count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800463 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 }
465 return;
466}
467
468 /* Outdat handling is common for all devices */
David Howells7d12e782006-10-05 14:55:46 +0100469static void usa2x_outdat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470{
471 struct usb_serial_port *port;
472 struct keyspan_port_private *p_priv;
473
Ming Leicdc97792008-02-24 18:41:47 +0800474 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 p_priv = usb_get_serial_port_data(port);
Harvey Harrison441b62c2008-03-03 16:08:34 -0800476 dbg ("%s - urb %d", __func__, urb == p_priv->out_urbs[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477
Alan Cox95da3102008-07-22 11:09:07 +0100478 if (port->port.count)
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700479 usb_serial_port_softint(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480}
481
David Howells7d12e782006-10-05 14:55:46 +0100482static void usa26_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483{
Harvey Harrison441b62c2008-03-03 16:08:34 -0800484 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485
486}
487
David Howells7d12e782006-10-05 14:55:46 +0100488static void usa26_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489{
490 struct usb_serial_port *port;
491 struct keyspan_port_private *p_priv;
492
Ming Leicdc97792008-02-24 18:41:47 +0800493 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 p_priv = usb_get_serial_port_data(port);
495
496 if (p_priv->resend_cont) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800497 dbg ("%s - sending setup", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 keyspan_usa26_send_setup(port->serial, port, p_priv->resend_cont - 1);
499 }
500}
501
David Howells7d12e782006-10-05 14:55:46 +0100502static void usa26_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503{
504 unsigned char *data = urb->transfer_buffer;
505 struct keyspan_usa26_portStatusMessage *msg;
506 struct usb_serial *serial;
507 struct usb_serial_port *port;
508 struct keyspan_port_private *p_priv;
509 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700510 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511
Ming Leicdc97792008-02-24 18:41:47 +0800512 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700514 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800515 dbg("%s - nonzero status: %x", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 return;
517 }
518 if (urb->actual_length != 9) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800519 dbg("%s - %d byte report??", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 goto exit;
521 }
522
523 msg = (struct keyspan_usa26_portStatusMessage *)data;
524
525#if 0
526 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 -0800527 __func__, msg->port, msg->hskia_cts, msg->gpia_dcd, msg->dsr, msg->ri, msg->_txOff,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 msg->_txXoff, msg->rxEnabled, msg->controlResponse);
529#endif
530
531 /* Now do something useful with the data */
532
533
534 /* Check port number from message and retrieve private data */
535 if (msg->port >= serial->num_ports) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800536 dbg ("%s - Unexpected port number %d", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 goto exit;
538 }
539 port = serial->port[msg->port];
540 p_priv = usb_get_serial_port_data(port);
541
542 /* Update handshaking pin state information */
543 old_dcd_state = p_priv->dcd_state;
544 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
545 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
546 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
547 p_priv->ri_state = ((msg->ri) ? 1 : 0);
548
Alan Cox95da3102008-07-22 11:09:07 +0100549 if (port->port.tty && !C_CLOCAL(port->port.tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 && old_dcd_state != p_priv->dcd_state) {
551 if (old_dcd_state)
Alan Cox95da3102008-07-22 11:09:07 +0100552 tty_hangup(port->port.tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 /* else */
554 /* wake_up_interruptible(&p_priv->open_wait); */
555 }
556
557 /* Resubmit urb so we continue receiving */
558 urb->dev = serial->dev;
559 if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800560 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 }
562exit: ;
563}
564
David Howells7d12e782006-10-05 14:55:46 +0100565static void usa26_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566{
Harvey Harrison441b62c2008-03-03 16:08:34 -0800567 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568
569}
570
571
David Howells7d12e782006-10-05 14:55:46 +0100572static void usa28_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573{
574 int i, err;
575 struct usb_serial_port *port;
576 struct tty_struct *tty;
577 unsigned char *data;
578 struct keyspan_port_private *p_priv;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700579 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580
Harvey Harrison441b62c2008-03-03 16:08:34 -0800581 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582
Ming Leicdc97792008-02-24 18:41:47 +0800583 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 p_priv = usb_get_serial_port_data(port);
585 data = urb->transfer_buffer;
586
587 if (urb != p_priv->in_urbs[p_priv->in_flip])
588 return;
589
590 do {
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700591 if (status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 dbg("%s - nonzero status: %x on endpoint %d.",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800593 __func__, status, usb_pipeendpoint(urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 return;
595 }
596
Ming Leicdc97792008-02-24 18:41:47 +0800597 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 p_priv = usb_get_serial_port_data(port);
599 data = urb->transfer_buffer;
600
Alan Cox95da3102008-07-22 11:09:07 +0100601 tty = port->port.tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 if (urb->actual_length) {
603 for (i = 0; i < urb->actual_length ; ++i) {
604 tty_insert_flip_char(tty, data[i], 0);
605 }
606 tty_flip_buffer_push(tty);
607 }
608
609 /* Resubmit urb so we continue receiving */
610 urb->dev = port->serial->dev;
Alan Cox95da3102008-07-22 11:09:07 +0100611 if (port->port.count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800613 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 }
615 p_priv->in_flip ^= 1;
616
617 urb = p_priv->in_urbs[p_priv->in_flip];
618 } while (urb->status != -EINPROGRESS);
619}
620
David Howells7d12e782006-10-05 14:55:46 +0100621static void usa28_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622{
Harvey Harrison441b62c2008-03-03 16:08:34 -0800623 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624}
625
David Howells7d12e782006-10-05 14:55:46 +0100626static void usa28_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627{
628 struct usb_serial_port *port;
629 struct keyspan_port_private *p_priv;
630
Ming Leicdc97792008-02-24 18:41:47 +0800631 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 p_priv = usb_get_serial_port_data(port);
633
634 if (p_priv->resend_cont) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800635 dbg ("%s - sending setup", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 keyspan_usa28_send_setup(port->serial, port, p_priv->resend_cont - 1);
637 }
638}
639
David Howells7d12e782006-10-05 14:55:46 +0100640static void usa28_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641{
642 int err;
643 unsigned char *data = urb->transfer_buffer;
644 struct keyspan_usa28_portStatusMessage *msg;
645 struct usb_serial *serial;
646 struct usb_serial_port *port;
647 struct keyspan_port_private *p_priv;
648 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700649 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650
Ming Leicdc97792008-02-24 18:41:47 +0800651 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700653 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800654 dbg("%s - nonzero status: %x", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 return;
656 }
657
658 if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800659 dbg("%s - bad length %d", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 goto exit;
661 }
662
Harvey Harrison441b62c2008-03-03 16:08:34 -0800663 /*dbg("%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 data[0], data[1], data[2], data[3], data[4], data[5],
665 data[6], data[7], data[8], data[9], data[10], data[11]);*/
666
667 /* Now do something useful with the data */
668 msg = (struct keyspan_usa28_portStatusMessage *)data;
669
670
671 /* Check port number from message and retrieve private data */
672 if (msg->port >= serial->num_ports) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800673 dbg ("%s - Unexpected port number %d", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 goto exit;
675 }
676 port = serial->port[msg->port];
677 p_priv = usb_get_serial_port_data(port);
678
679 /* Update handshaking pin state information */
680 old_dcd_state = p_priv->dcd_state;
681 p_priv->cts_state = ((msg->cts) ? 1 : 0);
682 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
683 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
684 p_priv->ri_state = ((msg->ri) ? 1 : 0);
685
Alan Cox95da3102008-07-22 11:09:07 +0100686 if (port->port.tty && !C_CLOCAL(port->port.tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 && old_dcd_state != p_priv->dcd_state) {
688 if (old_dcd_state)
Alan Cox95da3102008-07-22 11:09:07 +0100689 tty_hangup(port->port.tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 /* else */
691 /* wake_up_interruptible(&p_priv->open_wait); */
692 }
693
694 /* Resubmit urb so we continue receiving */
695 urb->dev = serial->dev;
696 if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800697 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 }
699exit: ;
700}
701
David Howells7d12e782006-10-05 14:55:46 +0100702static void usa28_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703{
Harvey Harrison441b62c2008-03-03 16:08:34 -0800704 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705}
706
707
David Howells7d12e782006-10-05 14:55:46 +0100708static void usa49_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709{
710 struct usb_serial *serial;
711 struct usb_serial_port *port;
712 struct keyspan_port_private *p_priv;
713 int i;
714
Harvey Harrison441b62c2008-03-03 16:08:34 -0800715 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716
Ming Leicdc97792008-02-24 18:41:47 +0800717 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 for (i = 0; i < serial->num_ports; ++i) {
719 port = serial->port[i];
720 p_priv = usb_get_serial_port_data(port);
721
722 if (p_priv->resend_cont) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800723 dbg ("%s - sending setup", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 keyspan_usa49_send_setup(serial, port, p_priv->resend_cont - 1);
725 break;
726 }
727 }
728}
729
730 /* This is actually called glostat in the Keyspan
731 doco */
David Howells7d12e782006-10-05 14:55:46 +0100732static void usa49_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733{
734 int err;
735 unsigned char *data = urb->transfer_buffer;
736 struct keyspan_usa49_portStatusMessage *msg;
737 struct usb_serial *serial;
738 struct usb_serial_port *port;
739 struct keyspan_port_private *p_priv;
740 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700741 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742
Harvey Harrison441b62c2008-03-03 16:08:34 -0800743 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744
Ming Leicdc97792008-02-24 18:41:47 +0800745 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700747 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800748 dbg("%s - nonzero status: %x", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 return;
750 }
751
752 if (urb->actual_length != sizeof(struct keyspan_usa49_portStatusMessage)) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800753 dbg("%s - bad length %d", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 goto exit;
755 }
756
Harvey Harrison441b62c2008-03-03 16:08:34 -0800757 /*dbg(" %x %x %x %x %x %x %x %x %x %x %x", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 data[0], data[1], data[2], data[3], data[4], data[5],
759 data[6], data[7], data[8], data[9], data[10]);*/
760
761 /* Now do something useful with the data */
762 msg = (struct keyspan_usa49_portStatusMessage *)data;
763
764 /* Check port number from message and retrieve private data */
765 if (msg->portNumber >= serial->num_ports) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800766 dbg ("%s - Unexpected port number %d", __func__, msg->portNumber);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767 goto exit;
768 }
769 port = serial->port[msg->portNumber];
770 p_priv = usb_get_serial_port_data(port);
771
772 /* Update handshaking pin state information */
773 old_dcd_state = p_priv->dcd_state;
774 p_priv->cts_state = ((msg->cts) ? 1 : 0);
775 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
776 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
777 p_priv->ri_state = ((msg->ri) ? 1 : 0);
778
Alan Cox95da3102008-07-22 11:09:07 +0100779 if (port->port.tty && !C_CLOCAL(port->port.tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 && old_dcd_state != p_priv->dcd_state) {
781 if (old_dcd_state)
Alan Cox95da3102008-07-22 11:09:07 +0100782 tty_hangup(port->port.tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 /* else */
784 /* wake_up_interruptible(&p_priv->open_wait); */
785 }
786
787 /* Resubmit urb so we continue receiving */
788 urb->dev = serial->dev;
789
790 if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800791 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 }
793exit: ;
794}
795
David Howells7d12e782006-10-05 14:55:46 +0100796static void usa49_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797{
Harvey Harrison441b62c2008-03-03 16:08:34 -0800798 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799}
800
David Howells7d12e782006-10-05 14:55:46 +0100801static void usa49_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802{
803 int i, err;
804 int endpoint;
805 struct usb_serial_port *port;
806 struct tty_struct *tty;
807 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700808 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809
Harvey Harrison441b62c2008-03-03 16:08:34 -0800810 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811
812 endpoint = usb_pipeendpoint(urb->pipe);
813
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700814 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800815 dbg("%s - nonzero status: %x on endpoint %d.", __func__,
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700816 status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 return;
818 }
819
Ming Leicdc97792008-02-24 18:41:47 +0800820 port = urb->context;
Alan Cox95da3102008-07-22 11:09:07 +0100821 tty = port->port.tty;
Alan Cox3004e532008-01-03 16:59:04 +0000822 if (tty && urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 /* 0x80 bit is error flag */
824 if ((data[0] & 0x80) == 0) {
825 /* no error on any byte */
826 for (i = 1; i < urb->actual_length ; ++i) {
827 tty_insert_flip_char(tty, data[i], 0);
828 }
829 } else {
830 /* some bytes had errors, every byte has status */
831 for (i = 0; i + 1 < urb->actual_length; i += 2) {
832 int stat = data[i], flag = 0;
833 if (stat & RXERROR_OVERRUN)
834 flag |= TTY_OVERRUN;
835 if (stat & RXERROR_FRAMING)
836 flag |= TTY_FRAME;
837 if (stat & RXERROR_PARITY)
838 flag |= TTY_PARITY;
839 /* XXX should handle break (0x10) */
840 tty_insert_flip_char(tty, data[i+1], flag);
841 }
842 }
843 tty_flip_buffer_push(tty);
844 }
845
846 /* Resubmit urb so we continue receiving */
847 urb->dev = port->serial->dev;
Alan Cox95da3102008-07-22 11:09:07 +0100848 if (port->port.count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800850 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 }
852}
853
Lucy McCoy0ca12682007-05-18 12:10:41 -0700854static void usa49wg_indat_callback(struct urb *urb)
855{
856 int i, len, x, err;
857 struct usb_serial *serial;
858 struct usb_serial_port *port;
859 struct tty_struct *tty;
860 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700861 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700862
Harvey Harrison441b62c2008-03-03 16:08:34 -0800863 dbg ("%s", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700864
865 serial = urb->context;
866
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700867 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800868 dbg("%s - nonzero status: %x", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700869 return;
870 }
871
872 /* inbound data is in the form P#, len, status, data */
873 i = 0;
874 len = 0;
875
876 if (urb->actual_length) {
877 while (i < urb->actual_length) {
878
879 /* Check port number from message*/
880 if (data[i] >= serial->num_ports) {
881 dbg ("%s - Unexpected port number %d",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800882 __func__, data[i]);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700883 return;
884 }
885 port = serial->port[data[i++]];
Alan Cox95da3102008-07-22 11:09:07 +0100886 tty = port->port.tty;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700887 len = data[i++];
888
889 /* 0x80 bit is error flag */
890 if ((data[i] & 0x80) == 0) {
891 /* no error on any byte */
892 i++;
893 for (x = 1; x < len ; ++x)
Alan Cox95da3102008-07-22 11:09:07 +0100894 if (port->port.count)
Lucy McCoy0ca12682007-05-18 12:10:41 -0700895 tty_insert_flip_char(tty,
896 data[i++], 0);
897 else
898 i++;
899 } else {
900 /*
901 * some bytes had errors, every byte has status
902 */
903 for (x = 0; x + 1 < len; x += 2) {
904 int stat = data[i], flag = 0;
905 if (stat & RXERROR_OVERRUN)
906 flag |= TTY_OVERRUN;
907 if (stat & RXERROR_FRAMING)
908 flag |= TTY_FRAME;
909 if (stat & RXERROR_PARITY)
910 flag |= TTY_PARITY;
911 /* XXX should handle break (0x10) */
Alan Cox95da3102008-07-22 11:09:07 +0100912 if (port->port.count)
Lucy McCoy0ca12682007-05-18 12:10:41 -0700913 tty_insert_flip_char(tty,
914 data[i+1], flag);
915 i += 2;
916 }
917 }
Alan Cox95da3102008-07-22 11:09:07 +0100918 if (port->port.count)
Lucy McCoy0ca12682007-05-18 12:10:41 -0700919 tty_flip_buffer_push(tty);
920 }
921 }
922
923 /* Resubmit urb so we continue receiving */
924 urb->dev = serial->dev;
925
926 err = usb_submit_urb(urb, GFP_ATOMIC);
927 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800928 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700929}
930
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931/* not used, usa-49 doesn't have per-port control endpoints */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700932static void usa49_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933{
Harvey Harrison441b62c2008-03-03 16:08:34 -0800934 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935}
936
Lucy McCoy0ca12682007-05-18 12:10:41 -0700937static void usa90_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938{
939 int i, err;
940 int endpoint;
941 struct usb_serial_port *port;
942 struct keyspan_port_private *p_priv;
943 struct tty_struct *tty;
944 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700945 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946
Harvey Harrison441b62c2008-03-03 16:08:34 -0800947 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948
949 endpoint = usb_pipeendpoint(urb->pipe);
950
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700951 if (status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 dbg("%s - nonzero status: %x on endpoint %d.",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800953 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 return;
955 }
956
Ming Leicdc97792008-02-24 18:41:47 +0800957 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 p_priv = usb_get_serial_port_data(port);
959
Alan Cox95da3102008-07-22 11:09:07 +0100960 tty = port->port.tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 if (urb->actual_length) {
962
963 /* if current mode is DMA, looks like usa28 format
964 otherwise looks like usa26 data format */
965
966 if (p_priv->baud > 57600) {
967 for (i = 0; i < urb->actual_length ; ++i)
968 tty_insert_flip_char(tty, data[i], 0);
969 }
970 else {
971
972 /* 0x80 bit is error flag */
973 if ((data[0] & 0x80) == 0) {
974 /* no errors on individual bytes, only possible overrun err*/
975 if (data[0] & RXERROR_OVERRUN)
976 err = TTY_OVERRUN;
977 else err = 0;
978 for (i = 1; i < urb->actual_length ; ++i)
979 tty_insert_flip_char(tty, data[i], err);
980
981 }
982 else {
983 /* some bytes had errors, every byte has status */
Harvey Harrison441b62c2008-03-03 16:08:34 -0800984 dbg("%s - RX error!!!!", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 for (i = 0; i + 1 < urb->actual_length; i += 2) {
986 int stat = data[i], flag = 0;
987 if (stat & RXERROR_OVERRUN)
988 flag |= TTY_OVERRUN;
989 if (stat & RXERROR_FRAMING)
990 flag |= TTY_FRAME;
991 if (stat & RXERROR_PARITY)
992 flag |= TTY_PARITY;
993 /* XXX should handle break (0x10) */
994 tty_insert_flip_char(tty, data[i+1], flag);
995 }
996 }
997 }
998 tty_flip_buffer_push(tty);
999 }
1000
1001 /* Resubmit urb so we continue receiving */
1002 urb->dev = port->serial->dev;
Alan Cox95da3102008-07-22 11:09:07 +01001003 if (port->port.count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001005 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 }
1007 return;
1008}
1009
1010
David Howells7d12e782006-10-05 14:55:46 +01001011static void usa90_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012{
1013 unsigned char *data = urb->transfer_buffer;
1014 struct keyspan_usa90_portStatusMessage *msg;
1015 struct usb_serial *serial;
1016 struct usb_serial_port *port;
1017 struct keyspan_port_private *p_priv;
1018 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001019 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020
Ming Leicdc97792008-02-24 18:41:47 +08001021 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001023 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001024 dbg("%s - nonzero status: %x", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 return;
1026 }
1027 if (urb->actual_length < 14) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001028 dbg("%s - %d byte report??", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 goto exit;
1030 }
1031
1032 msg = (struct keyspan_usa90_portStatusMessage *)data;
1033
1034 /* Now do something useful with the data */
1035
1036 port = serial->port[0];
1037 p_priv = usb_get_serial_port_data(port);
1038
1039 /* Update handshaking pin state information */
1040 old_dcd_state = p_priv->dcd_state;
1041 p_priv->cts_state = ((msg->cts) ? 1 : 0);
1042 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
1043 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
1044 p_priv->ri_state = ((msg->ri) ? 1 : 0);
1045
Alan Cox95da3102008-07-22 11:09:07 +01001046 if (port->port.tty && !C_CLOCAL(port->port.tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 && old_dcd_state != p_priv->dcd_state) {
1048 if (old_dcd_state)
Alan Cox95da3102008-07-22 11:09:07 +01001049 tty_hangup(port->port.tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 /* else */
1051 /* wake_up_interruptible(&p_priv->open_wait); */
1052 }
1053
1054 /* Resubmit urb so we continue receiving */
1055 urb->dev = serial->dev;
1056 if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001057 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 }
1059exit:
1060 ;
1061}
1062
David Howells7d12e782006-10-05 14:55:46 +01001063static void usa90_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064{
1065 struct usb_serial_port *port;
1066 struct keyspan_port_private *p_priv;
1067
Ming Leicdc97792008-02-24 18:41:47 +08001068 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 p_priv = usb_get_serial_port_data(port);
1070
1071 if (p_priv->resend_cont) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001072 dbg ("%s - sending setup", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 keyspan_usa90_send_setup(port->serial, port, p_priv->resend_cont - 1);
1074 }
1075}
1076
Lucy McCoy0ca12682007-05-18 12:10:41 -07001077/* Status messages from the 28xg */
1078static void usa67_instat_callback(struct urb *urb)
1079{
1080 int err;
1081 unsigned char *data = urb->transfer_buffer;
1082 struct keyspan_usa67_portStatusMessage *msg;
1083 struct usb_serial *serial;
1084 struct usb_serial_port *port;
1085 struct keyspan_port_private *p_priv;
1086 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001087 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001088
Harvey Harrison441b62c2008-03-03 16:08:34 -08001089 dbg ("%s", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001090
1091 serial = urb->context;
1092
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001093 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001094 dbg("%s - nonzero status: %x", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001095 return;
1096 }
1097
1098 if (urb->actual_length != sizeof(struct keyspan_usa67_portStatusMessage)) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001099 dbg("%s - bad length %d", __func__, urb->actual_length);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001100 return;
1101 }
1102
1103
1104 /* Now do something useful with the data */
1105 msg = (struct keyspan_usa67_portStatusMessage *)data;
1106
1107 /* Check port number from message and retrieve private data */
1108 if (msg->port >= serial->num_ports) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001109 dbg ("%s - Unexpected port number %d", __func__, msg->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001110 return;
1111 }
1112
1113 port = serial->port[msg->port];
1114 p_priv = usb_get_serial_port_data(port);
1115
1116 /* Update handshaking pin state information */
1117 old_dcd_state = p_priv->dcd_state;
1118 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
1119 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
1120
Alan Cox95da3102008-07-22 11:09:07 +01001121 if (port->port.tty && !C_CLOCAL(port->port.tty)
Lucy McCoy0ca12682007-05-18 12:10:41 -07001122 && old_dcd_state != p_priv->dcd_state) {
1123 if (old_dcd_state)
Alan Cox95da3102008-07-22 11:09:07 +01001124 tty_hangup(port->port.tty);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001125 /* else */
1126 /* wake_up_interruptible(&p_priv->open_wait); */
1127 }
1128
1129 /* Resubmit urb so we continue receiving */
1130 urb->dev = serial->dev;
1131 err = usb_submit_urb(urb, GFP_ATOMIC);
1132 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08001133 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001134}
1135
1136static void usa67_glocont_callback(struct urb *urb)
1137{
1138 struct usb_serial *serial;
1139 struct usb_serial_port *port;
1140 struct keyspan_port_private *p_priv;
1141 int i;
1142
Harvey Harrison441b62c2008-03-03 16:08:34 -08001143 dbg ("%s", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001144
1145 serial = urb->context;
1146 for (i = 0; i < serial->num_ports; ++i) {
1147 port = serial->port[i];
1148 p_priv = usb_get_serial_port_data(port);
1149
1150 if (p_priv->resend_cont) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001151 dbg ("%s - sending setup", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001152 keyspan_usa67_send_setup(serial, port,
1153 p_priv->resend_cont - 1);
1154 break;
1155 }
1156 }
1157}
1158
Alan Cox95da3102008-07-22 11:09:07 +01001159static int keyspan_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160{
Alan Cox95da3102008-07-22 11:09:07 +01001161 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 struct keyspan_port_private *p_priv;
1163 const struct keyspan_device_details *d_details;
1164 int flip;
1165 int data_len;
1166 struct urb *this_urb;
1167
Harvey Harrison441b62c2008-03-03 16:08:34 -08001168 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 p_priv = usb_get_serial_port_data(port);
1170 d_details = p_priv->device_details;
1171
Alan Coxa5b6f602008-04-08 17:16:06 +01001172 /* FIXME: locking */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 if (d_details->msg_format == msg_usa90)
1174 data_len = 64;
1175 else
1176 data_len = 63;
1177
1178 flip = p_priv->out_flip;
1179
1180 /* Check both endpoints to see if any are available. */
1181 if ((this_urb = p_priv->out_urbs[flip]) != NULL) {
1182 if (this_urb->status != -EINPROGRESS)
1183 return (data_len);
1184 flip = (flip + 1) & d_details->outdat_endp_flip;
1185 if ((this_urb = p_priv->out_urbs[flip]) != NULL)
1186 if (this_urb->status != -EINPROGRESS)
1187 return (data_len);
1188 }
Alan Coxa5b6f602008-04-08 17:16:06 +01001189 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190}
1191
1192
Alan Cox95da3102008-07-22 11:09:07 +01001193static int keyspan_open(struct tty_struct *tty,
1194 struct usb_serial_port *port, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195{
Andrew Mortonf78ba152007-11-28 16:21:54 -08001196 struct keyspan_port_private *p_priv;
1197 struct keyspan_serial_private *s_priv;
1198 struct usb_serial *serial = port->serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 const struct keyspan_device_details *d_details;
1200 int i, err;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001201 int baud_rate, device_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 struct urb *urb;
Alan Cox95da3102008-07-22 11:09:07 +01001203 unsigned int cflag = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204
1205 s_priv = usb_get_serial_data(serial);
1206 p_priv = usb_get_serial_port_data(port);
1207 d_details = p_priv->device_details;
Borislav Petkov7eea4362007-11-14 17:00:39 -08001208
Harvey Harrison441b62c2008-03-03 16:08:34 -08001209 dbg("%s - port%d.", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210
1211 /* Set some sane defaults */
1212 p_priv->rts_state = 1;
1213 p_priv->dtr_state = 1;
1214 p_priv->baud = 9600;
1215
1216 /* force baud and lcr to be set on open */
1217 p_priv->old_baud = 0;
1218 p_priv->old_cflag = 0;
1219
1220 p_priv->out_flip = 0;
1221 p_priv->in_flip = 0;
1222
1223 /* Reset low level data toggle and start reading from endpoints */
1224 for (i = 0; i < 2; i++) {
1225 if ((urb = p_priv->in_urbs[i]) == NULL)
1226 continue;
1227 urb->dev = serial->dev;
1228
1229 /* make sure endpoint data toggle is synchronized with the device */
Borislav Petkov7eea4362007-11-14 17:00:39 -08001230
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 usb_clear_halt(urb->dev, urb->pipe);
1232
1233 if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001234 dbg("%s - submit urb %d failed (%d)", __func__, i, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 }
1236 }
1237
1238 /* Reset low level data toggle on out endpoints */
1239 for (i = 0; i < 2; i++) {
1240 if ((urb = p_priv->out_urbs[i]) == NULL)
1241 continue;
1242 urb->dev = serial->dev;
1243 /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); */
1244 }
1245
Andrew Mortonf78ba152007-11-28 16:21:54 -08001246 /* get the terminal config for the setup message now so we don't
1247 * need to send 2 of them */
1248
Andrew Mortonf78ba152007-11-28 16:21:54 -08001249 device_port = port->number - port->serial->minor;
Alan Cox95da3102008-07-22 11:09:07 +01001250 if (tty) {
1251 cflag = tty->termios->c_cflag;
1252 /* Baud rate calculation takes baud rate as an integer
1253 so other rates can be generated if desired. */
1254 baud_rate = tty_get_baud_rate(tty);
1255 /* If no match or invalid, leave as default */
1256 if (baud_rate >= 0
1257 && d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
1258 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
1259 p_priv->baud = baud_rate;
1260 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001261 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001262 /* set CTS/RTS handshake etc. */
1263 p_priv->cflag = cflag;
1264 p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none;
1265
1266 keyspan_send_setup(port, 1);
1267 //mdelay(100);
1268 //keyspan_set_termios(port, NULL);
1269
Alan Coxa5b6f602008-04-08 17:16:06 +01001270 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271}
1272
1273static inline void stop_urb(struct urb *urb)
1274{
Greg Kroah-Hartman242cf672005-07-29 16:11:07 -04001275 if (urb && urb->status == -EINPROGRESS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 usb_kill_urb(urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277}
1278
Alan Cox95da3102008-07-22 11:09:07 +01001279static void keyspan_close(struct tty_struct *tty,
1280 struct usb_serial_port *port, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281{
1282 int i;
1283 struct usb_serial *serial = port->serial;
1284 struct keyspan_serial_private *s_priv;
1285 struct keyspan_port_private *p_priv;
1286
Harvey Harrison441b62c2008-03-03 16:08:34 -08001287 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 s_priv = usb_get_serial_data(serial);
1289 p_priv = usb_get_serial_port_data(port);
1290
1291 p_priv->rts_state = 0;
1292 p_priv->dtr_state = 0;
1293
1294 if (serial->dev) {
1295 keyspan_send_setup(port, 2);
1296 /* pilot-xfer seems to work best with this delay */
1297 mdelay(100);
1298 // keyspan_set_termios(port, NULL);
1299 }
1300
1301 /*while (p_priv->outcont_urb->status == -EINPROGRESS) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001302 dbg("%s - urb in progress", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 }*/
1304
1305 p_priv->out_flip = 0;
1306 p_priv->in_flip = 0;
1307
1308 if (serial->dev) {
1309 /* Stop reading/writing urbs */
1310 stop_urb(p_priv->inack_urb);
1311 /* stop_urb(p_priv->outcont_urb); */
1312 for (i = 0; i < 2; i++) {
1313 stop_urb(p_priv->in_urbs[i]);
1314 stop_urb(p_priv->out_urbs[i]);
1315 }
1316 }
Alan Cox95da3102008-07-22 11:09:07 +01001317 port->port.tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318}
1319
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 /* download the firmware to a pre-renumeration device */
1321static int keyspan_fake_startup (struct usb_serial *serial)
1322{
1323 int response;
David Woodhouse2971c572008-05-30 14:04:03 +03001324 const struct ihex_binrec *record;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 char *fw_name;
David Woodhouse2971c572008-05-30 14:04:03 +03001326 const struct firmware *fw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327
1328 dbg("Keyspan startup version %04x product %04x",
1329 le16_to_cpu(serial->dev->descriptor.bcdDevice),
1330 le16_to_cpu(serial->dev->descriptor.idProduct));
1331
1332 if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000) != 0x8000) {
1333 dbg("Firmware already loaded. Quitting.");
1334 return(1);
1335 }
1336
1337 /* Select firmware image on the basis of idProduct */
1338 switch (le16_to_cpu(serial->dev->descriptor.idProduct)) {
1339 case keyspan_usa28_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001340 fw_name = "keyspan/usa28.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 break;
1342
1343 case keyspan_usa28x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001344 fw_name = "keyspan/usa28x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 break;
1346
1347 case keyspan_usa28xa_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001348 fw_name = "keyspan/usa28xa.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 break;
1350
1351 case keyspan_usa28xb_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001352 fw_name = "keyspan/usa28xb.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 break;
1354
1355 case keyspan_usa19_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001356 fw_name = "keyspan/usa19.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 break;
1358
1359 case keyspan_usa19qi_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001360 fw_name = "keyspan/usa19qi.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 break;
1362
1363 case keyspan_mpr_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001364 fw_name = "keyspan/mpr.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 break;
1366
1367 case keyspan_usa19qw_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001368 fw_name = "keyspan/usa19qw.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 break;
1370
1371 case keyspan_usa18x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001372 fw_name = "keyspan/usa18x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 break;
1374
1375 case keyspan_usa19w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001376 fw_name = "keyspan/usa19w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 break;
1378
1379 case keyspan_usa49w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001380 fw_name = "keyspan/usa49w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 break;
1382
1383 case keyspan_usa49wlc_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001384 fw_name = "keyspan/usa49wlc.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 break;
1386
1387 default:
David Woodhouse2971c572008-05-30 14:04:03 +03001388 dev_err(&serial->dev->dev, "Unknown product ID (%04x)\n",
1389 le16_to_cpu(serial->dev->descriptor.idProduct));
1390 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 }
1392
David Woodhouse2971c572008-05-30 14:04:03 +03001393 if (request_ihex_firmware(&fw, fw_name, &serial->dev->dev)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 dev_err(&serial->dev->dev, "Required keyspan firmware image (%s) unavailable.\n", fw_name);
1395 return(1);
1396 }
1397
1398 dbg("Uploading Keyspan %s firmware.", fw_name);
1399
1400 /* download the firmware image */
1401 response = ezusb_set_reset(serial, 1);
1402
David Woodhouse2971c572008-05-30 14:04:03 +03001403 record = (const struct ihex_binrec *)fw->data;
1404
1405 while (record) {
1406 response = ezusb_writememory(serial, be32_to_cpu(record->addr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 (unsigned char *)record->data,
David Woodhouse2971c572008-05-30 14:04:03 +03001408 be16_to_cpu(record->len), 0xa0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 if (response < 0) {
1410 dev_err(&serial->dev->dev, "ezusb_writememory failed for Keyspan"
1411 "firmware (%d %04X %p %d)\n",
David Woodhouse2971c572008-05-30 14:04:03 +03001412 response, be32_to_cpu(record->addr),
1413 record->data, be16_to_cpu(record->len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 break;
1415 }
David Woodhouse2971c572008-05-30 14:04:03 +03001416 record = ihex_next_binrec(record);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 }
David Woodhouse2971c572008-05-30 14:04:03 +03001418 release_firmware(fw);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 /* bring device out of reset. Renumeration will occur in a
1420 moment and the new device will bind to the real driver */
1421 response = ezusb_set_reset(serial, 0);
1422
1423 /* we don't want this device to have a driver assigned to it. */
1424 return (1);
1425}
1426
1427/* Helper functions used by keyspan_setup_urbs */
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001428static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *serial,
1429 int endpoint)
1430{
1431 struct usb_host_interface *iface_desc;
1432 struct usb_endpoint_descriptor *ep;
1433 int i;
1434
1435 iface_desc = serial->interface->cur_altsetting;
1436 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1437 ep = &iface_desc->endpoint[i].desc;
1438 if (ep->bEndpointAddress == endpoint)
1439 return ep;
1440 }
1441 dev_warn(&serial->interface->dev, "found no endpoint descriptor for "
1442 "endpoint %x\n", endpoint);
1443 return NULL;
1444}
1445
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446static struct urb *keyspan_setup_urb (struct usb_serial *serial, int endpoint,
1447 int dir, void *ctx, char *buf, int len,
David Howells7d12e782006-10-05 14:55:46 +01001448 void (*callback)(struct urb *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449{
1450 struct urb *urb;
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001451 struct usb_endpoint_descriptor const *ep_desc;
1452 char const *ep_type_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453
1454 if (endpoint == -1)
1455 return NULL; /* endpoint not needed */
1456
Harvey Harrison441b62c2008-03-03 16:08:34 -08001457 dbg ("%s - alloc for endpoint %d.", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
1459 if (urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001460 dbg ("%s - alloc for endpoint %d failed.", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461 return NULL;
1462 }
1463
Lucy McCoy0ca12682007-05-18 12:10:41 -07001464 if (endpoint == 0) {
1465 /* control EP filled in when used */
1466 return urb;
1467 }
1468
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001469 ep_desc = find_ep(serial, endpoint);
1470 if (!ep_desc) {
1471 /* leak the urb, something's wrong and the callers don't care */
1472 return urb;
1473 }
1474 if (usb_endpoint_xfer_int(ep_desc)) {
1475 ep_type_name = "INT";
1476 usb_fill_int_urb(urb, serial->dev,
1477 usb_sndintpipe(serial->dev, endpoint) | dir,
1478 buf, len, callback, ctx,
1479 ep_desc->bInterval);
1480 } else if (usb_endpoint_xfer_bulk(ep_desc)) {
1481 ep_type_name = "BULK";
1482 usb_fill_bulk_urb(urb, serial->dev,
1483 usb_sndbulkpipe(serial->dev, endpoint) | dir,
1484 buf, len, callback, ctx);
1485 } else {
1486 dev_warn(&serial->interface->dev,
1487 "unsupported endpoint type %x\n",
1488 ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
1489 usb_free_urb(urb);
1490 return NULL;
1491 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001493 dbg("%s - using urb %p for %s endpoint %x",
1494 __func__, urb, ep_type_name, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 return urb;
1496}
1497
1498static struct callbacks {
David Howells7d12e782006-10-05 14:55:46 +01001499 void (*instat_callback)(struct urb *);
1500 void (*glocont_callback)(struct urb *);
1501 void (*indat_callback)(struct urb *);
1502 void (*outdat_callback)(struct urb *);
1503 void (*inack_callback)(struct urb *);
1504 void (*outcont_callback)(struct urb *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505} keyspan_callbacks[] = {
1506 {
1507 /* msg_usa26 callbacks */
1508 .instat_callback = usa26_instat_callback,
1509 .glocont_callback = usa26_glocont_callback,
1510 .indat_callback = usa26_indat_callback,
1511 .outdat_callback = usa2x_outdat_callback,
1512 .inack_callback = usa26_inack_callback,
1513 .outcont_callback = usa26_outcont_callback,
1514 }, {
1515 /* msg_usa28 callbacks */
1516 .instat_callback = usa28_instat_callback,
1517 .glocont_callback = usa28_glocont_callback,
1518 .indat_callback = usa28_indat_callback,
1519 .outdat_callback = usa2x_outdat_callback,
1520 .inack_callback = usa28_inack_callback,
1521 .outcont_callback = usa28_outcont_callback,
1522 }, {
1523 /* msg_usa49 callbacks */
1524 .instat_callback = usa49_instat_callback,
1525 .glocont_callback = usa49_glocont_callback,
1526 .indat_callback = usa49_indat_callback,
1527 .outdat_callback = usa2x_outdat_callback,
1528 .inack_callback = usa49_inack_callback,
1529 .outcont_callback = usa49_outcont_callback,
1530 }, {
1531 /* msg_usa90 callbacks */
1532 .instat_callback = usa90_instat_callback,
1533 .glocont_callback = usa28_glocont_callback,
1534 .indat_callback = usa90_indat_callback,
1535 .outdat_callback = usa2x_outdat_callback,
1536 .inack_callback = usa28_inack_callback,
1537 .outcont_callback = usa90_outcont_callback,
Lucy McCoy0ca12682007-05-18 12:10:41 -07001538 }, {
1539 /* msg_usa67 callbacks */
1540 .instat_callback = usa67_instat_callback,
1541 .glocont_callback = usa67_glocont_callback,
1542 .indat_callback = usa26_indat_callback,
1543 .outdat_callback = usa2x_outdat_callback,
1544 .inack_callback = usa26_inack_callback,
1545 .outcont_callback = usa26_outcont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 }
1547};
1548
1549 /* Generic setup urbs function that uses
1550 data in device_details */
1551static void keyspan_setup_urbs(struct usb_serial *serial)
1552{
1553 int i, j;
1554 struct keyspan_serial_private *s_priv;
1555 const struct keyspan_device_details *d_details;
1556 struct usb_serial_port *port;
1557 struct keyspan_port_private *p_priv;
1558 struct callbacks *cback;
1559 int endp;
1560
Harvey Harrison441b62c2008-03-03 16:08:34 -08001561 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562
1563 s_priv = usb_get_serial_data(serial);
1564 d_details = s_priv->device_details;
1565
1566 /* Setup values for the various callback routines */
1567 cback = &keyspan_callbacks[d_details->msg_format];
1568
1569 /* Allocate and set up urbs for each one that is in use,
1570 starting with instat endpoints */
1571 s_priv->instat_urb = keyspan_setup_urb
1572 (serial, d_details->instat_endpoint, USB_DIR_IN,
1573 serial, s_priv->instat_buf, INSTAT_BUFLEN,
1574 cback->instat_callback);
1575
Lucy McCoy0ca12682007-05-18 12:10:41 -07001576 s_priv->indat_urb = keyspan_setup_urb
1577 (serial, d_details->indat_endpoint, USB_DIR_IN,
1578 serial, s_priv->indat_buf, INDAT49W_BUFLEN,
1579 usa49wg_indat_callback);
1580
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 s_priv->glocont_urb = keyspan_setup_urb
1582 (serial, d_details->glocont_endpoint, USB_DIR_OUT,
1583 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
1584 cback->glocont_callback);
1585
1586 /* Setup endpoints for each port specific thing */
1587 for (i = 0; i < d_details->num_ports; i ++) {
1588 port = serial->port[i];
1589 p_priv = usb_get_serial_port_data(port);
1590
1591 /* Do indat endpoints first, once for each flip */
1592 endp = d_details->indat_endpoints[i];
1593 for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) {
1594 p_priv->in_urbs[j] = keyspan_setup_urb
1595 (serial, endp, USB_DIR_IN, port,
1596 p_priv->in_buffer[j], 64,
1597 cback->indat_callback);
1598 }
1599 for (; j < 2; ++j)
1600 p_priv->in_urbs[j] = NULL;
1601
1602 /* outdat endpoints also have flip */
1603 endp = d_details->outdat_endpoints[i];
1604 for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) {
1605 p_priv->out_urbs[j] = keyspan_setup_urb
1606 (serial, endp, USB_DIR_OUT, port,
1607 p_priv->out_buffer[j], 64,
1608 cback->outdat_callback);
1609 }
1610 for (; j < 2; ++j)
1611 p_priv->out_urbs[j] = NULL;
1612
1613 /* inack endpoint */
1614 p_priv->inack_urb = keyspan_setup_urb
1615 (serial, d_details->inack_endpoints[i], USB_DIR_IN,
1616 port, p_priv->inack_buffer, 1, cback->inack_callback);
1617
1618 /* outcont endpoint */
1619 p_priv->outcont_urb = keyspan_setup_urb
1620 (serial, d_details->outcont_endpoints[i], USB_DIR_OUT,
1621 port, p_priv->outcont_buffer, 64,
1622 cback->outcont_callback);
1623 }
1624
1625}
1626
1627/* usa19 function doesn't require prescaler */
1628static int keyspan_usa19_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
1629 u8 *rate_low, u8 *prescaler, int portnum)
1630{
1631 u32 b16, /* baud rate times 16 (actual rate used internally) */
1632 div, /* divisor */
1633 cnt; /* inverse of divisor (programmed into 8051) */
1634
Harvey Harrison441b62c2008-03-03 16:08:34 -08001635 dbg ("%s - %d.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636
1637 /* prevent divide by zero... */
1638 if( (b16 = (baud_rate * 16L)) == 0) {
1639 return (KEYSPAN_INVALID_BAUD_RATE);
1640 }
1641
1642 /* Any "standard" rate over 57k6 is marginal on the USA-19
1643 as we run out of divisor resolution. */
1644 if (baud_rate > 57600) {
1645 return (KEYSPAN_INVALID_BAUD_RATE);
1646 }
1647
1648 /* calculate the divisor and the counter (its inverse) */
1649 if( (div = (baudclk / b16)) == 0) {
1650 return (KEYSPAN_INVALID_BAUD_RATE);
1651 }
1652 else {
1653 cnt = 0 - div;
1654 }
1655
1656 if(div > 0xffff) {
1657 return (KEYSPAN_INVALID_BAUD_RATE);
1658 }
1659
1660 /* return the counter values if non-null */
1661 if (rate_low) {
1662 *rate_low = (u8) (cnt & 0xff);
1663 }
1664 if (rate_hi) {
1665 *rate_hi = (u8) ((cnt >> 8) & 0xff);
1666 }
1667 if (rate_low && rate_hi) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001668 dbg ("%s - %d %02x %02x.", __func__, baud_rate, *rate_hi, *rate_low);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669 }
1670
1671 return (KEYSPAN_BAUD_RATE_OK);
1672}
1673
1674/* usa19hs function doesn't require prescaler */
1675static int keyspan_usa19hs_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
1676 u8 *rate_low, u8 *prescaler, int portnum)
1677{
1678 u32 b16, /* baud rate times 16 (actual rate used internally) */
1679 div; /* divisor */
1680
Harvey Harrison441b62c2008-03-03 16:08:34 -08001681 dbg ("%s - %d.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682
1683 /* prevent divide by zero... */
1684 if( (b16 = (baud_rate * 16L)) == 0)
1685 return (KEYSPAN_INVALID_BAUD_RATE);
1686
1687
1688
1689 /* calculate the divisor */
1690 if( (div = (baudclk / b16)) == 0)
1691 return (KEYSPAN_INVALID_BAUD_RATE);
1692
1693 if(div > 0xffff)
1694 return (KEYSPAN_INVALID_BAUD_RATE);
1695
1696 /* return the counter values if non-null */
1697 if (rate_low)
1698 *rate_low = (u8) (div & 0xff);
1699
1700 if (rate_hi)
1701 *rate_hi = (u8) ((div >> 8) & 0xff);
1702
1703 if (rate_low && rate_hi)
Harvey Harrison441b62c2008-03-03 16:08:34 -08001704 dbg ("%s - %d %02x %02x.", __func__, baud_rate, *rate_hi, *rate_low);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705
1706 return (KEYSPAN_BAUD_RATE_OK);
1707}
1708
1709static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
1710 u8 *rate_low, u8 *prescaler, int portnum)
1711{
1712 u32 b16, /* baud rate times 16 (actual rate used internally) */
1713 clk, /* clock with 13/8 prescaler */
1714 div, /* divisor using 13/8 prescaler */
1715 res, /* resulting baud rate using 13/8 prescaler */
1716 diff, /* error using 13/8 prescaler */
1717 smallest_diff;
1718 u8 best_prescaler;
1719 int i;
1720
Harvey Harrison441b62c2008-03-03 16:08:34 -08001721 dbg ("%s - %d.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722
1723 /* prevent divide by zero */
1724 if( (b16 = baud_rate * 16L) == 0) {
1725 return (KEYSPAN_INVALID_BAUD_RATE);
1726 }
1727
1728 /* Calculate prescaler by trying them all and looking
1729 for best fit */
1730
1731 /* start with largest possible difference */
1732 smallest_diff = 0xffffffff;
1733
1734 /* 0 is an invalid prescaler, used as a flag */
1735 best_prescaler = 0;
1736
1737 for(i = 8; i <= 0xff; ++i) {
1738 clk = (baudclk * 8) / (u32) i;
1739
1740 if( (div = clk / b16) == 0) {
1741 continue;
1742 }
1743
1744 res = clk / div;
1745 diff= (res > b16) ? (res-b16) : (b16-res);
1746
1747 if(diff < smallest_diff) {
1748 best_prescaler = i;
1749 smallest_diff = diff;
1750 }
1751 }
1752
1753 if(best_prescaler == 0) {
1754 return (KEYSPAN_INVALID_BAUD_RATE);
1755 }
1756
1757 clk = (baudclk * 8) / (u32) best_prescaler;
1758 div = clk / b16;
1759
1760 /* return the divisor and prescaler if non-null */
1761 if (rate_low) {
1762 *rate_low = (u8) (div & 0xff);
1763 }
1764 if (rate_hi) {
1765 *rate_hi = (u8) ((div >> 8) & 0xff);
1766 }
1767 if (prescaler) {
1768 *prescaler = best_prescaler;
Harvey Harrison441b62c2008-03-03 16:08:34 -08001769 /* dbg("%s - %d %d", __func__, *prescaler, div); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770 }
1771 return (KEYSPAN_BAUD_RATE_OK);
1772}
1773
1774 /* USA-28 supports different maximum baud rates on each port */
1775static int keyspan_usa28_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
1776 u8 *rate_low, u8 *prescaler, int portnum)
1777{
1778 u32 b16, /* baud rate times 16 (actual rate used internally) */
1779 div, /* divisor */
1780 cnt; /* inverse of divisor (programmed into 8051) */
1781
Harvey Harrison441b62c2008-03-03 16:08:34 -08001782 dbg ("%s - %d.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783
1784 /* prevent divide by zero */
1785 if ((b16 = baud_rate * 16L) == 0)
1786 return (KEYSPAN_INVALID_BAUD_RATE);
1787
1788 /* calculate the divisor and the counter (its inverse) */
1789 if ((div = (KEYSPAN_USA28_BAUDCLK / b16)) == 0) {
1790 return (KEYSPAN_INVALID_BAUD_RATE);
1791 }
1792 else {
1793 cnt = 0 - div;
1794 }
1795
1796 /* check for out of range, based on portnum,
1797 and return result */
1798 if(portnum == 0) {
1799 if(div > 0xffff)
1800 return (KEYSPAN_INVALID_BAUD_RATE);
1801 }
1802 else {
1803 if(portnum == 1) {
1804 if(div > 0xff) {
1805 return (KEYSPAN_INVALID_BAUD_RATE);
1806 }
1807 }
1808 else {
1809 return (KEYSPAN_INVALID_BAUD_RATE);
1810 }
1811 }
1812
1813 /* return the counter values if not NULL
1814 (port 1 will ignore retHi) */
1815 if (rate_low) {
1816 *rate_low = (u8) (cnt & 0xff);
1817 }
1818 if (rate_hi) {
1819 *rate_hi = (u8) ((cnt >> 8) & 0xff);
1820 }
Harvey Harrison441b62c2008-03-03 16:08:34 -08001821 dbg ("%s - %d OK.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822 return (KEYSPAN_BAUD_RATE_OK);
1823}
1824
1825static int keyspan_usa26_send_setup(struct usb_serial *serial,
1826 struct usb_serial_port *port,
1827 int reset_port)
1828{
1829 struct keyspan_usa26_portControlMessage msg;
1830 struct keyspan_serial_private *s_priv;
1831 struct keyspan_port_private *p_priv;
1832 const struct keyspan_device_details *d_details;
1833 int outcont_urb;
1834 struct urb *this_urb;
1835 int device_port, err;
1836
Harvey Harrison441b62c2008-03-03 16:08:34 -08001837 dbg ("%s reset=%d", __func__, reset_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838
1839 s_priv = usb_get_serial_data(serial);
1840 p_priv = usb_get_serial_port_data(port);
1841 d_details = s_priv->device_details;
1842 device_port = port->number - port->serial->minor;
1843
1844 outcont_urb = d_details->outcont_endpoints[port->number];
1845 this_urb = p_priv->outcont_urb;
1846
Harvey Harrison441b62c2008-03-03 16:08:34 -08001847 dbg("%s - endpoint %d", __func__, usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848
1849 /* Make sure we have an urb then send the message */
1850 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001851 dbg("%s - oops no urb.", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 return -1;
1853 }
1854
1855 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001856 Don't overwrite resend for open/close condition. */
1857 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858 p_priv->resend_cont = reset_port + 1;
1859 if (this_urb->status == -EINPROGRESS) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001860 /* dbg ("%s - already writing", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 mdelay(5);
1862 return(-1);
1863 }
1864
1865 memset(&msg, 0, sizeof (struct keyspan_usa26_portControlMessage));
1866
1867 /* Only set baud rate if it's changed */
1868 if (p_priv->old_baud != p_priv->baud) {
1869 p_priv->old_baud = p_priv->baud;
1870 msg.setClocking = 0xff;
1871 if (d_details->calculate_baud_rate
1872 (p_priv->baud, d_details->baudclk, &msg.baudHi,
1873 &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001874 dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875 p_priv->baud);
1876 msg.baudLo = 0;
1877 msg.baudHi = 125; /* Values for 9600 baud */
1878 msg.prescaler = 10;
1879 }
1880 msg.setPrescaler = 0xff;
1881 }
1882
1883 msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
1884 switch (p_priv->cflag & CSIZE) {
1885 case CS5:
1886 msg.lcr |= USA_DATABITS_5;
1887 break;
1888 case CS6:
1889 msg.lcr |= USA_DATABITS_6;
1890 break;
1891 case CS7:
1892 msg.lcr |= USA_DATABITS_7;
1893 break;
1894 case CS8:
1895 msg.lcr |= USA_DATABITS_8;
1896 break;
1897 }
1898 if (p_priv->cflag & PARENB) {
1899 /* note USA_PARITY_NONE == 0 */
1900 msg.lcr |= (p_priv->cflag & PARODD)?
1901 USA_PARITY_ODD: USA_PARITY_EVEN;
1902 }
1903 msg.setLcr = 0xff;
1904
1905 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1906 msg.xonFlowControl = 0;
1907 msg.setFlowControl = 0xff;
1908 msg.forwardingLength = 16;
1909 msg.xonChar = 17;
1910 msg.xoffChar = 19;
1911
1912 /* Opening port */
1913 if (reset_port == 1) {
1914 msg._txOn = 1;
1915 msg._txOff = 0;
1916 msg.txFlush = 0;
1917 msg.txBreak = 0;
1918 msg.rxOn = 1;
1919 msg.rxOff = 0;
1920 msg.rxFlush = 1;
1921 msg.rxForward = 0;
1922 msg.returnStatus = 0;
1923 msg.resetDataToggle = 0xff;
1924 }
1925
1926 /* Closing port */
1927 else if (reset_port == 2) {
1928 msg._txOn = 0;
1929 msg._txOff = 1;
1930 msg.txFlush = 0;
1931 msg.txBreak = 0;
1932 msg.rxOn = 0;
1933 msg.rxOff = 1;
1934 msg.rxFlush = 1;
1935 msg.rxForward = 0;
1936 msg.returnStatus = 0;
1937 msg.resetDataToggle = 0;
1938 }
1939
1940 /* Sending intermediate configs */
1941 else {
1942 msg._txOn = (! p_priv->break_on);
1943 msg._txOff = 0;
1944 msg.txFlush = 0;
1945 msg.txBreak = (p_priv->break_on);
1946 msg.rxOn = 0;
1947 msg.rxOff = 0;
1948 msg.rxFlush = 0;
1949 msg.rxForward = 0;
1950 msg.returnStatus = 0;
1951 msg.resetDataToggle = 0x0;
1952 }
1953
1954 /* Do handshaking outputs */
1955 msg.setTxTriState_setRts = 0xff;
1956 msg.txTriState_rts = p_priv->rts_state;
1957
1958 msg.setHskoa_setDtr = 0xff;
1959 msg.hskoa_dtr = p_priv->dtr_state;
1960
1961 p_priv->resend_cont = 0;
1962 memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
1963
1964 /* send the data out the device on control endpoint */
1965 this_urb->transfer_buffer_length = sizeof(msg);
1966
1967 this_urb->dev = serial->dev;
1968 if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001969 dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 }
1971#if 0
1972 else {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001973 dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974 outcont_urb, this_urb->transfer_buffer_length,
1975 usb_pipeendpoint(this_urb->pipe));
1976 }
1977#endif
1978
Alan Coxa5b6f602008-04-08 17:16:06 +01001979 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980}
1981
1982static int keyspan_usa28_send_setup(struct usb_serial *serial,
1983 struct usb_serial_port *port,
1984 int reset_port)
1985{
1986 struct keyspan_usa28_portControlMessage msg;
1987 struct keyspan_serial_private *s_priv;
1988 struct keyspan_port_private *p_priv;
1989 const struct keyspan_device_details *d_details;
1990 struct urb *this_urb;
1991 int device_port, err;
1992
Harvey Harrison441b62c2008-03-03 16:08:34 -08001993 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994
1995 s_priv = usb_get_serial_data(serial);
1996 p_priv = usb_get_serial_port_data(port);
1997 d_details = s_priv->device_details;
1998 device_port = port->number - port->serial->minor;
1999
2000 /* only do something if we have a bulk out endpoint */
2001 if ((this_urb = p_priv->outcont_urb) == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002002 dbg("%s - oops no urb.", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003 return -1;
2004 }
2005
2006 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07002007 Don't overwrite resend for open/close condition. */
2008 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 p_priv->resend_cont = reset_port + 1;
2010 if (this_urb->status == -EINPROGRESS) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002011 dbg ("%s already writing", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012 mdelay(5);
2013 return(-1);
2014 }
2015
2016 memset(&msg, 0, sizeof (struct keyspan_usa28_portControlMessage));
2017
2018 msg.setBaudRate = 1;
2019 if (d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk,
2020 &msg.baudHi, &msg.baudLo, NULL, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002021 dbg("%s - Invalid baud rate requested %d.", __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022 msg.baudLo = 0xff;
2023 msg.baudHi = 0xb2; /* Values for 9600 baud */
2024 }
2025
2026 /* If parity is enabled, we must calculate it ourselves. */
2027 msg.parity = 0; /* XXX for now */
2028
2029 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2030 msg.xonFlowControl = 0;
2031
2032 /* Do handshaking outputs, DTR is inverted relative to RTS */
2033 msg.rts = p_priv->rts_state;
2034 msg.dtr = p_priv->dtr_state;
2035
2036 msg.forwardingLength = 16;
2037 msg.forwardMs = 10;
2038 msg.breakThreshold = 45;
2039 msg.xonChar = 17;
2040 msg.xoffChar = 19;
2041
2042 /*msg.returnStatus = 1;
2043 msg.resetDataToggle = 0xff;*/
2044 /* Opening port */
2045 if (reset_port == 1) {
2046 msg._txOn = 1;
2047 msg._txOff = 0;
2048 msg.txFlush = 0;
2049 msg.txForceXoff = 0;
2050 msg.txBreak = 0;
2051 msg.rxOn = 1;
2052 msg.rxOff = 0;
2053 msg.rxFlush = 1;
2054 msg.rxForward = 0;
2055 msg.returnStatus = 0;
2056 msg.resetDataToggle = 0xff;
2057 }
2058 /* Closing port */
2059 else if (reset_port == 2) {
2060 msg._txOn = 0;
2061 msg._txOff = 1;
2062 msg.txFlush = 0;
2063 msg.txForceXoff = 0;
2064 msg.txBreak = 0;
2065 msg.rxOn = 0;
2066 msg.rxOff = 1;
2067 msg.rxFlush = 1;
2068 msg.rxForward = 0;
2069 msg.returnStatus = 0;
2070 msg.resetDataToggle = 0;
2071 }
2072 /* Sending intermediate configs */
2073 else {
2074 msg._txOn = (! p_priv->break_on);
2075 msg._txOff = 0;
2076 msg.txFlush = 0;
2077 msg.txForceXoff = 0;
2078 msg.txBreak = (p_priv->break_on);
2079 msg.rxOn = 0;
2080 msg.rxOff = 0;
2081 msg.rxFlush = 0;
2082 msg.rxForward = 0;
2083 msg.returnStatus = 0;
2084 msg.resetDataToggle = 0x0;
2085 }
2086
2087 p_priv->resend_cont = 0;
2088 memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
2089
2090 /* send the data out the device on control endpoint */
2091 this_urb->transfer_buffer_length = sizeof(msg);
2092
2093 this_urb->dev = serial->dev;
2094 if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002095 dbg("%s - usb_submit_urb(setup) failed", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096 }
2097#if 0
2098 else {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002099 dbg("%s - usb_submit_urb(setup) OK %d bytes", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100 this_urb->transfer_buffer_length);
2101 }
2102#endif
2103
Alan Coxa5b6f602008-04-08 17:16:06 +01002104 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105}
2106
2107static int keyspan_usa49_send_setup(struct usb_serial *serial,
2108 struct usb_serial_port *port,
2109 int reset_port)
2110{
Lucy McCoy0ca12682007-05-18 12:10:41 -07002111 struct keyspan_usa49_portControlMessage msg;
2112 struct usb_ctrlrequest *dr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113 struct keyspan_serial_private *s_priv;
2114 struct keyspan_port_private *p_priv;
2115 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 struct urb *this_urb;
2117 int err, device_port;
2118
Harvey Harrison441b62c2008-03-03 16:08:34 -08002119 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120
2121 s_priv = usb_get_serial_data(serial);
2122 p_priv = usb_get_serial_port_data(port);
2123 d_details = s_priv->device_details;
2124
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 this_urb = s_priv->glocont_urb;
2126
Lucy McCoy0ca12682007-05-18 12:10:41 -07002127 /* Work out which port within the device is being setup */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128 device_port = port->number - port->serial->minor;
2129
Harvey Harrison441b62c2008-03-03 16:08:34 -08002130 dbg("%s - endpoint %d port %d (%d)",__func__, usb_pipeendpoint(this_urb->pipe), port->number, device_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131
2132 /* Make sure we have an urb then send the message */
2133 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002134 dbg("%s - oops no urb for port %d.", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135 return -1;
2136 }
2137
2138 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07002139 Don't overwrite resend for open/close condition. */
2140 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141 p_priv->resend_cont = reset_port + 1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002142
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143 if (this_urb->status == -EINPROGRESS) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002144 /* dbg ("%s - already writing", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145 mdelay(5);
2146 return(-1);
2147 }
2148
2149 memset(&msg, 0, sizeof (struct keyspan_usa49_portControlMessage));
2150
2151 /*msg.portNumber = port->number;*/
2152 msg.portNumber = device_port;
2153
2154 /* Only set baud rate if it's changed */
2155 if (p_priv->old_baud != p_priv->baud) {
2156 p_priv->old_baud = p_priv->baud;
2157 msg.setClocking = 0xff;
2158 if (d_details->calculate_baud_rate
2159 (p_priv->baud, d_details->baudclk, &msg.baudHi,
2160 &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002161 dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 p_priv->baud);
2163 msg.baudLo = 0;
2164 msg.baudHi = 125; /* Values for 9600 baud */
2165 msg.prescaler = 10;
2166 }
2167 //msg.setPrescaler = 0xff;
2168 }
2169
2170 msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
2171 switch (p_priv->cflag & CSIZE) {
2172 case CS5:
2173 msg.lcr |= USA_DATABITS_5;
2174 break;
2175 case CS6:
2176 msg.lcr |= USA_DATABITS_6;
2177 break;
2178 case CS7:
2179 msg.lcr |= USA_DATABITS_7;
2180 break;
2181 case CS8:
2182 msg.lcr |= USA_DATABITS_8;
2183 break;
2184 }
2185 if (p_priv->cflag & PARENB) {
2186 /* note USA_PARITY_NONE == 0 */
2187 msg.lcr |= (p_priv->cflag & PARODD)?
2188 USA_PARITY_ODD: USA_PARITY_EVEN;
2189 }
2190 msg.setLcr = 0xff;
2191
2192 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2193 msg.xonFlowControl = 0;
2194 msg.setFlowControl = 0xff;
2195
2196 msg.forwardingLength = 16;
2197 msg.xonChar = 17;
2198 msg.xoffChar = 19;
2199
2200 /* Opening port */
2201 if (reset_port == 1) {
2202 msg._txOn = 1;
2203 msg._txOff = 0;
2204 msg.txFlush = 0;
2205 msg.txBreak = 0;
2206 msg.rxOn = 1;
2207 msg.rxOff = 0;
2208 msg.rxFlush = 1;
2209 msg.rxForward = 0;
2210 msg.returnStatus = 0;
2211 msg.resetDataToggle = 0xff;
2212 msg.enablePort = 1;
2213 msg.disablePort = 0;
2214 }
2215 /* Closing port */
2216 else if (reset_port == 2) {
2217 msg._txOn = 0;
2218 msg._txOff = 1;
2219 msg.txFlush = 0;
2220 msg.txBreak = 0;
2221 msg.rxOn = 0;
2222 msg.rxOff = 1;
2223 msg.rxFlush = 1;
2224 msg.rxForward = 0;
2225 msg.returnStatus = 0;
2226 msg.resetDataToggle = 0;
2227 msg.enablePort = 0;
2228 msg.disablePort = 1;
2229 }
2230 /* Sending intermediate configs */
2231 else {
2232 msg._txOn = (! p_priv->break_on);
2233 msg._txOff = 0;
2234 msg.txFlush = 0;
2235 msg.txBreak = (p_priv->break_on);
2236 msg.rxOn = 0;
2237 msg.rxOff = 0;
2238 msg.rxFlush = 0;
2239 msg.rxForward = 0;
2240 msg.returnStatus = 0;
2241 msg.resetDataToggle = 0x0;
2242 msg.enablePort = 0;
2243 msg.disablePort = 0;
2244 }
2245
2246 /* Do handshaking outputs */
2247 msg.setRts = 0xff;
2248 msg.rts = p_priv->rts_state;
2249
2250 msg.setDtr = 0xff;
2251 msg.dtr = p_priv->dtr_state;
2252
2253 p_priv->resend_cont = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254
Lucy McCoy0ca12682007-05-18 12:10:41 -07002255 /* if the device is a 49wg, we send control message on usb control EP 0 */
2256
2257 if (d_details->product_id == keyspan_usa49wg_product_id) {
2258 dr = (void *)(s_priv->ctrl_buf);
2259 dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT;
2260 dr->bRequest = 0xB0; /* 49wg control message */;
2261 dr->wValue = 0;
2262 dr->wIndex = 0;
2263 dr->wLength = cpu_to_le16(sizeof(msg));
2264
2265 memcpy (s_priv->glocont_buf, &msg, sizeof(msg));
2266
2267 usb_fill_control_urb(this_urb, serial->dev, usb_sndctrlpipe(serial->dev, 0),
2268 (unsigned char *)dr, s_priv->glocont_buf, sizeof(msg),
2269 usa49_glocont_callback, serial);
2270
2271 } else {
2272 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2273
2274 /* send the data out the device on control endpoint */
2275 this_urb->transfer_buffer_length = sizeof(msg);
2276
2277 this_urb->dev = serial->dev;
2278 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279 if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002280 dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281 }
2282#if 0
2283 else {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002284 dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002285 outcont_urb, this_urb->transfer_buffer_length,
2286 usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 }
2288#endif
2289
Alan Coxa5b6f602008-04-08 17:16:06 +01002290 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291}
2292
2293static int keyspan_usa90_send_setup(struct usb_serial *serial,
2294 struct usb_serial_port *port,
2295 int reset_port)
2296{
2297 struct keyspan_usa90_portControlMessage msg;
2298 struct keyspan_serial_private *s_priv;
2299 struct keyspan_port_private *p_priv;
2300 const struct keyspan_device_details *d_details;
2301 struct urb *this_urb;
2302 int err;
2303 u8 prescaler;
2304
Harvey Harrison441b62c2008-03-03 16:08:34 -08002305 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306
2307 s_priv = usb_get_serial_data(serial);
2308 p_priv = usb_get_serial_port_data(port);
2309 d_details = s_priv->device_details;
2310
2311 /* only do something if we have a bulk out endpoint */
2312 if ((this_urb = p_priv->outcont_urb) == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002313 dbg("%s - oops no urb.", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 return -1;
2315 }
2316
2317 /* Save reset port val for resend.
2318 Don't overwrite resend for open/close condition. */
2319 if ((reset_port + 1) > p_priv->resend_cont)
2320 p_priv->resend_cont = reset_port + 1;
2321 if (this_urb->status == -EINPROGRESS) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002322 dbg ("%s already writing", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323 mdelay(5);
2324 return(-1);
2325 }
2326
2327 memset(&msg, 0, sizeof (struct keyspan_usa90_portControlMessage));
2328
2329 /* Only set baud rate if it's changed */
2330 if (p_priv->old_baud != p_priv->baud) {
2331 p_priv->old_baud = p_priv->baud;
2332 msg.setClocking = 0x01;
2333 if (d_details->calculate_baud_rate
2334 (p_priv->baud, d_details->baudclk, &msg.baudHi,
2335 &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE ) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002336 dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 p_priv->baud);
2338 p_priv->baud = 9600;
2339 d_details->calculate_baud_rate (p_priv->baud, d_details->baudclk,
2340 &msg.baudHi, &msg.baudLo, &prescaler, 0);
2341 }
2342 msg.setRxMode = 1;
2343 msg.setTxMode = 1;
2344 }
2345
2346 /* modes must always be correctly specified */
2347 if (p_priv->baud > 57600)
2348 {
2349 msg.rxMode = RXMODE_DMA;
2350 msg.txMode = TXMODE_DMA;
2351 }
2352 else
2353 {
2354 msg.rxMode = RXMODE_BYHAND;
2355 msg.txMode = TXMODE_BYHAND;
2356 }
2357
2358 msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
2359 switch (p_priv->cflag & CSIZE) {
2360 case CS5:
2361 msg.lcr |= USA_DATABITS_5;
2362 break;
2363 case CS6:
2364 msg.lcr |= USA_DATABITS_6;
2365 break;
2366 case CS7:
2367 msg.lcr |= USA_DATABITS_7;
2368 break;
2369 case CS8:
2370 msg.lcr |= USA_DATABITS_8;
2371 break;
2372 }
2373 if (p_priv->cflag & PARENB) {
2374 /* note USA_PARITY_NONE == 0 */
2375 msg.lcr |= (p_priv->cflag & PARODD)?
2376 USA_PARITY_ODD: USA_PARITY_EVEN;
2377 }
2378 if (p_priv->old_cflag != p_priv->cflag) {
2379 p_priv->old_cflag = p_priv->cflag;
2380 msg.setLcr = 0x01;
2381 }
2382
2383 if (p_priv->flow_control == flow_cts)
2384 msg.txFlowControl = TXFLOW_CTS;
2385 msg.setTxFlowControl = 0x01;
2386 msg.setRxFlowControl = 0x01;
2387
2388 msg.rxForwardingLength = 16;
2389 msg.rxForwardingTimeout = 16;
2390 msg.txAckSetting = 0;
2391 msg.xonChar = 17;
2392 msg.xoffChar = 19;
2393
2394 /* Opening port */
2395 if (reset_port == 1) {
2396 msg.portEnabled = 1;
2397 msg.rxFlush = 1;
2398 msg.txBreak = (p_priv->break_on);
2399 }
2400 /* Closing port */
2401 else if (reset_port == 2) {
2402 msg.portEnabled = 0;
2403 }
2404 /* Sending intermediate configs */
2405 else {
Alan Cox95da3102008-07-22 11:09:07 +01002406 if (port->port.count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407 msg.portEnabled = 1;
2408 msg.txBreak = (p_priv->break_on);
2409 }
2410
2411 /* Do handshaking outputs */
2412 msg.setRts = 0x01;
2413 msg.rts = p_priv->rts_state;
2414
2415 msg.setDtr = 0x01;
2416 msg.dtr = p_priv->dtr_state;
2417
2418 p_priv->resend_cont = 0;
2419 memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
2420
2421 /* send the data out the device on control endpoint */
2422 this_urb->transfer_buffer_length = sizeof(msg);
2423
2424 this_urb->dev = serial->dev;
2425 if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002426 dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427 }
Alan Coxa5b6f602008-04-08 17:16:06 +01002428 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429}
2430
Lucy McCoy0ca12682007-05-18 12:10:41 -07002431static int keyspan_usa67_send_setup(struct usb_serial *serial,
2432 struct usb_serial_port *port,
2433 int reset_port)
2434{
2435 struct keyspan_usa67_portControlMessage msg;
2436 struct keyspan_serial_private *s_priv;
2437 struct keyspan_port_private *p_priv;
2438 const struct keyspan_device_details *d_details;
2439 struct urb *this_urb;
2440 int err, device_port;
2441
Harvey Harrison441b62c2008-03-03 16:08:34 -08002442 dbg ("%s", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002443
2444 s_priv = usb_get_serial_data(serial);
2445 p_priv = usb_get_serial_port_data(port);
2446 d_details = s_priv->device_details;
2447
2448 this_urb = s_priv->glocont_urb;
2449
2450 /* Work out which port within the device is being setup */
2451 device_port = port->number - port->serial->minor;
2452
2453 /* Make sure we have an urb then send the message */
2454 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002455 dbg("%s - oops no urb for port %d.", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002456 port->number);
2457 return -1;
2458 }
2459
2460 /* Save reset port val for resend.
2461 Don't overwrite resend for open/close condition. */
2462 if ((reset_port + 1) > p_priv->resend_cont)
2463 p_priv->resend_cont = reset_port + 1;
2464 if (this_urb->status == -EINPROGRESS) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002465 /* dbg ("%s - already writing", __func__); */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002466 mdelay(5);
2467 return(-1);
2468 }
2469
2470 memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
2471
2472 msg.port = device_port;
2473
2474 /* Only set baud rate if it's changed */
2475 if (p_priv->old_baud != p_priv->baud) {
2476 p_priv->old_baud = p_priv->baud;
2477 msg.setClocking = 0xff;
2478 if (d_details->calculate_baud_rate
2479 (p_priv->baud, d_details->baudclk, &msg.baudHi,
2480 &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002481 dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002482 p_priv->baud);
2483 msg.baudLo = 0;
2484 msg.baudHi = 125; /* Values for 9600 baud */
2485 msg.prescaler = 10;
2486 }
2487 msg.setPrescaler = 0xff;
2488 }
2489
2490 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
2491 switch (p_priv->cflag & CSIZE) {
2492 case CS5:
2493 msg.lcr |= USA_DATABITS_5;
2494 break;
2495 case CS6:
2496 msg.lcr |= USA_DATABITS_6;
2497 break;
2498 case CS7:
2499 msg.lcr |= USA_DATABITS_7;
2500 break;
2501 case CS8:
2502 msg.lcr |= USA_DATABITS_8;
2503 break;
2504 }
2505 if (p_priv->cflag & PARENB) {
2506 /* note USA_PARITY_NONE == 0 */
2507 msg.lcr |= (p_priv->cflag & PARODD)?
2508 USA_PARITY_ODD: USA_PARITY_EVEN;
2509 }
2510 msg.setLcr = 0xff;
2511
2512 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2513 msg.xonFlowControl = 0;
2514 msg.setFlowControl = 0xff;
2515 msg.forwardingLength = 16;
2516 msg.xonChar = 17;
2517 msg.xoffChar = 19;
2518
2519 if (reset_port == 1) {
2520 /* Opening port */
2521 msg._txOn = 1;
2522 msg._txOff = 0;
2523 msg.txFlush = 0;
2524 msg.txBreak = 0;
2525 msg.rxOn = 1;
2526 msg.rxOff = 0;
2527 msg.rxFlush = 1;
2528 msg.rxForward = 0;
2529 msg.returnStatus = 0;
2530 msg.resetDataToggle = 0xff;
2531 } else if (reset_port == 2) {
2532 /* Closing port */
2533 msg._txOn = 0;
2534 msg._txOff = 1;
2535 msg.txFlush = 0;
2536 msg.txBreak = 0;
2537 msg.rxOn = 0;
2538 msg.rxOff = 1;
2539 msg.rxFlush = 1;
2540 msg.rxForward = 0;
2541 msg.returnStatus = 0;
2542 msg.resetDataToggle = 0;
2543 } else {
2544 /* Sending intermediate configs */
2545 msg._txOn = (! p_priv->break_on);
2546 msg._txOff = 0;
2547 msg.txFlush = 0;
2548 msg.txBreak = (p_priv->break_on);
2549 msg.rxOn = 0;
2550 msg.rxOff = 0;
2551 msg.rxFlush = 0;
2552 msg.rxForward = 0;
2553 msg.returnStatus = 0;
2554 msg.resetDataToggle = 0x0;
2555 }
2556
2557 /* Do handshaking outputs */
2558 msg.setTxTriState_setRts = 0xff;
2559 msg.txTriState_rts = p_priv->rts_state;
2560
2561 msg.setHskoa_setDtr = 0xff;
2562 msg.hskoa_dtr = p_priv->dtr_state;
2563
2564 p_priv->resend_cont = 0;
2565
2566 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2567
2568 /* send the data out the device on control endpoint */
2569 this_urb->transfer_buffer_length = sizeof(msg);
2570 this_urb->dev = serial->dev;
2571
2572 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2573 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002574 dbg("%s - usb_submit_urb(setup) failed (%d)", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002575 err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002576 return 0;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002577}
2578
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
2580{
2581 struct usb_serial *serial = port->serial;
2582 struct keyspan_serial_private *s_priv;
2583 const struct keyspan_device_details *d_details;
2584
Harvey Harrison441b62c2008-03-03 16:08:34 -08002585 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586
2587 s_priv = usb_get_serial_data(serial);
2588 d_details = s_priv->device_details;
2589
2590 switch (d_details->msg_format) {
2591 case msg_usa26:
2592 keyspan_usa26_send_setup(serial, port, reset_port);
2593 break;
2594 case msg_usa28:
2595 keyspan_usa28_send_setup(serial, port, reset_port);
2596 break;
2597 case msg_usa49:
2598 keyspan_usa49_send_setup(serial, port, reset_port);
2599 break;
2600 case msg_usa90:
2601 keyspan_usa90_send_setup(serial, port, reset_port);
2602 break;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002603 case msg_usa67:
2604 keyspan_usa67_send_setup(serial, port, reset_port);
2605 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606 }
2607}
2608
2609
2610/* Gets called by the "real" driver (ie once firmware is loaded
2611 and renumeration has taken place. */
2612static int keyspan_startup (struct usb_serial *serial)
2613{
2614 int i, err;
2615 struct usb_serial_port *port;
2616 struct keyspan_serial_private *s_priv;
2617 struct keyspan_port_private *p_priv;
2618 const struct keyspan_device_details *d_details;
2619
Harvey Harrison441b62c2008-03-03 16:08:34 -08002620 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621
2622 for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
2623 if (d_details->product_id == le16_to_cpu(serial->dev->descriptor.idProduct))
2624 break;
2625 if (d_details == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002626 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 -07002627 return 1;
2628 }
2629
2630 /* Setup private data for serial driver */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01002631 s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632 if (!s_priv) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002633 dbg("%s - kmalloc for keyspan_serial_private failed.", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634 return -ENOMEM;
2635 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636
2637 s_priv->device_details = d_details;
2638 usb_set_serial_data(serial, s_priv);
2639
2640 /* Now setup per port private data */
2641 for (i = 0; i < serial->num_ports; i++) {
2642 port = serial->port[i];
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01002643 p_priv = kzalloc(sizeof(struct keyspan_port_private), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644 if (!p_priv) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002645 dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __func__, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646 return (1);
2647 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648 p_priv->device_details = d_details;
2649 usb_set_serial_port_data(port, p_priv);
2650 }
2651
2652 keyspan_setup_urbs(serial);
2653
Lucy McCoy0ca12682007-05-18 12:10:41 -07002654 if (s_priv->instat_urb != NULL) {
2655 s_priv->instat_urb->dev = serial->dev;
2656 err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
2657 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002658 dbg("%s - submit instat urb failed %d", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002659 err);
2660 }
2661 if (s_priv->indat_urb != NULL) {
2662 s_priv->indat_urb->dev = serial->dev;
2663 err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
2664 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002665 dbg("%s - submit indat urb failed %d", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002666 err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667 }
2668
Alan Coxa5b6f602008-04-08 17:16:06 +01002669 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670}
2671
2672static void keyspan_shutdown (struct usb_serial *serial)
2673{
2674 int i, j;
2675 struct usb_serial_port *port;
2676 struct keyspan_serial_private *s_priv;
2677 struct keyspan_port_private *p_priv;
2678
Harvey Harrison441b62c2008-03-03 16:08:34 -08002679 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680
2681 s_priv = usb_get_serial_data(serial);
2682
2683 /* Stop reading/writing urbs */
2684 stop_urb(s_priv->instat_urb);
2685 stop_urb(s_priv->glocont_urb);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002686 stop_urb(s_priv->indat_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687 for (i = 0; i < serial->num_ports; ++i) {
2688 port = serial->port[i];
2689 p_priv = usb_get_serial_port_data(port);
2690 stop_urb(p_priv->inack_urb);
2691 stop_urb(p_priv->outcont_urb);
2692 for (j = 0; j < 2; j++) {
2693 stop_urb(p_priv->in_urbs[j]);
2694 stop_urb(p_priv->out_urbs[j]);
2695 }
2696 }
2697
2698 /* Now free them */
Mariusz Kozlowski1cadc132006-11-08 15:36:34 +01002699 usb_free_urb(s_priv->instat_urb);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002700 usb_free_urb(s_priv->indat_urb);
Mariusz Kozlowski1cadc132006-11-08 15:36:34 +01002701 usb_free_urb(s_priv->glocont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702 for (i = 0; i < serial->num_ports; ++i) {
2703 port = serial->port[i];
2704 p_priv = usb_get_serial_port_data(port);
Mariusz Kozlowski1cadc132006-11-08 15:36:34 +01002705 usb_free_urb(p_priv->inack_urb);
2706 usb_free_urb(p_priv->outcont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707 for (j = 0; j < 2; j++) {
Mariusz Kozlowski1cadc132006-11-08 15:36:34 +01002708 usb_free_urb(p_priv->in_urbs[j]);
2709 usb_free_urb(p_priv->out_urbs[j]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002710 }
2711 }
2712
2713 /* dbg("Freeing serial->private."); */
2714 kfree(s_priv);
2715
2716 /* dbg("Freeing port->private."); */
2717 /* Now free per port private data */
2718 for (i = 0; i < serial->num_ports; i++) {
2719 port = serial->port[i];
2720 kfree(usb_get_serial_port_data(port));
2721 }
2722}
2723
2724MODULE_AUTHOR( DRIVER_AUTHOR );
2725MODULE_DESCRIPTION( DRIVER_DESC );
2726MODULE_LICENSE("GPL");
2727
David Woodhouse2971c572008-05-30 14:04:03 +03002728MODULE_FIRMWARE("keyspan/usa28.fw");
2729MODULE_FIRMWARE("keyspan/usa28x.fw");
2730MODULE_FIRMWARE("keyspan/usa28xa.fw");
2731MODULE_FIRMWARE("keyspan/usa28xb.fw");
2732MODULE_FIRMWARE("keyspan/usa19.fw");
2733MODULE_FIRMWARE("keyspan/usa19qi.fw");
2734MODULE_FIRMWARE("keyspan/mpr.fw");
2735MODULE_FIRMWARE("keyspan/usa19qw.fw");
2736MODULE_FIRMWARE("keyspan/usa18x.fw");
2737MODULE_FIRMWARE("keyspan/usa19w.fw");
2738MODULE_FIRMWARE("keyspan/usa49w.fw");
2739MODULE_FIRMWARE("keyspan/usa49wlc.fw");
2740
Linus Torvalds1da177e2005-04-16 15:20:36 -07002741module_param(debug, bool, S_IRUGO | S_IWUSR);
2742MODULE_PARM_DESC(debug, "Debug enabled or not");
2743