blob: 15447af48691b5b79140c3303744b868359b1390 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 Keyspan USB to Serial Converter driver
Alan Coxdeb91682008-07-22 11:13:08 +01003
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 (C) Copyright (C) 2000-2001 Hugh Blemings <hugh@blemings.org>
5 (C) Copyright (C) 2002 Greg Kroah-Hartman <greg@kroah.com>
Alan Coxdeb91682008-07-22 11:13:08 +01006
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 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.
Alan Coxdeb91682008-07-22 11:13:08 +010013
Linus Torvalds1da177e2005-04-16 15:20:36 -070014 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 :)
Alan Coxdeb91682008-07-22 11:13:08 +010020
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 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
Alan Coxdeb91682008-07-22 11:13:08 +010024 stuff.
25
26 Tip 'o the hat to IBM (and previously Linuxcare :) for supporting
Linus Torvalds1da177e2005-04-16 15:20:36 -070027 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
Alan Coxdeb91682008-07-22 11:13:08 +010073
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 (04/08/2001) gb
75 Identify version on module load.
Alan Coxdeb91682008-07-22 11:13:08 +010076
Linus Torvalds1da177e2005-04-16 15:20:36 -070077 (11/01/2000) Adam J. Richter
78 usb_device_id table support.
Alan Coxdeb91682008-07-22 11:13:08 +010079
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 Tue Oct 10 23:15:33 EST 2000 Hugh
81 Merged Paul's changes with my USA-49W mods. Work in progress
82 still...
Alan Coxdeb91682008-07-22 11:13:08 +010083
Linus Torvalds1da177e2005-04-16 15:20:36 -070084 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.
Alan Coxdeb91682008-07-22 11:13:08 +010087
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 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>
Alan Coxdeb91682008-07-22 11:13:08 +0100110#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111#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
Alan Coxdeb91682008-07-22 11:13:08 +0100135 /* added to support 49wg, where data from all 4 ports comes in
136 on 1 EP and high-speed supported */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700137 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];
Alan Coxdeb91682008-07-22 11:13:08 +0100143 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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189/* Include Keyspan message headers. All current Keyspan Adapters
Lucy McCoy0ca12682007-05-18 12:10:41 -0700190 make use of one of five message formats which are referred
Alan Coxdeb91682008-07-22 11:13:08 +0100191 to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and
192 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"
Alan Coxdeb91682008-07-22 11:13:08 +0100198
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199
200/* Functions used by new usb-serial code. */
Alan Coxdeb91682008-07-22 11:13:08 +0100201static int __init keyspan_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202{
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);
Alan Coxdeb91682008-07-22 11:13:08 +0100217 if (retval)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 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
Alan Coxdeb91682008-07-22 11:13:08 +0100235static void __exit keyspan_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236{
Alan Coxdeb91682008-07-22 11:13:08 +0100237 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);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242}
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
Alan Coxdeb91682008-07-22 11:13:08 +0100252 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 Coxdeb91682008-07-22 11:13:08 +0100265static void keyspan_set_termios(struct tty_struct *tty,
Alan Cox95da3102008-07-22 11:09:07 +0100266 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);
Alan Coxdeb91682008-07-22 11:13:08 +0100283 /* 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;
Alan Coxdeb91682008-07-22 11:13:08 +0100308
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 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) |
Alan Coxdeb91682008-07-22 11:13:08 +0100314 ((p_priv->ri_state) ? TIOCM_RNG : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315
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);
Alan Coxdeb91682008-07-22 11:13:08 +0100324
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 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;
Alan Coxdeb91682008-07-22 11:13:08 +0100347 int err, maxDataLen, dataOffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348
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) {
Alan Coxdeb91682008-07-22 11:13:08 +0100353 maxDataLen = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 dataOffset = 0;
355 } else {
356 maxDataLen = 63;
357 dataOffset = 1;
358 }
Alan Coxdeb91682008-07-22 11:13:08 +0100359
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 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;
Alan Coxdeb91682008-07-22 11:13:08 +0100369
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 /* Check we have a valid urb/endpoint before we use it... */
Alan Coxdeb91682008-07-22 11:13:08 +0100371 this_urb = p_priv->out_urbs[flip];
372 if (this_urb == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 /* no bulk out, so return 0 bytes written */
Harvey Harrison441b62c2008-03-03 16:08:34 -0800374 dbg("%s - no output urb :(", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 return count;
376 }
377
Alan Coxdeb91682008-07-22 11:13:08 +0100378 dbg("%s - endpoint %d flip %d",
379 __func__, usb_pipeendpoint(this_urb->pipe), flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380
381 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +0100382 if (time_before(jiffies,
383 p_priv->tx_start_time[flip] + 10 * HZ))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 usb_unlink_urb(this_urb);
386 break;
387 }
388
Alan Coxdeb91682008-07-22 11:13:08 +0100389 /* First byte in buffer is "last flag" (except for usa19hx)
390 - unused so for now so set to zero */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 ((char *)this_urb->transfer_buffer)[0] = 0;
392
Alan Coxdeb91682008-07-22 11:13:08 +0100393 memcpy(this_urb->transfer_buffer + dataOffset, buf, todo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 buf += todo;
395
396 /* send the data out the bulk port */
397 this_urb->transfer_buffer_length = todo + dataOffset;
398
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 this_urb->dev = port->serial->dev;
Alan Coxdeb91682008-07-22 11:13:08 +0100400 err = usb_submit_urb(this_urb, GFP_ATOMIC);
401 if (err != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 dbg("usb_submit_urb(write bulk) failed (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 p_priv->tx_start_time[flip] = jiffies;
404
405 /* Flip for next time if usa26 or usa28 interface
406 (not used on usa49) */
407 p_priv->out_flip = (flip + 1) & d_details->outdat_endp_flip;
408 }
409
410 return count - left;
411}
412
David Howells7d12e782006-10-05 14:55:46 +0100413static void usa26_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414{
415 int i, err;
416 int endpoint;
417 struct usb_serial_port *port;
418 struct tty_struct *tty;
419 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700420 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
Alan Coxdeb91682008-07-22 11:13:08 +0100422 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423
424 endpoint = usb_pipeendpoint(urb->pipe);
425
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700426 if (status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 dbg("%s - nonzero status: %x on endpoint %d.",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800428 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 return;
430 }
431
Ming Leicdc97792008-02-24 18:41:47 +0800432 port = urb->context;
Alan Cox4a90f092008-10-13 10:39:46 +0100433 tty = tty_port_tty_get(&port->port);
Alan Coxa5569a52008-01-21 17:18:24 -0800434 if (tty && urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 /* 0x80 bit is error flag */
436 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100437 /* no errors on individual bytes, only
438 possible overrun err */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 if (data[0] & RXERROR_OVERRUN)
Alan Coxdeb91682008-07-22 11:13:08 +0100440 err = TTY_OVERRUN;
441 else
442 err = 0;
443 for (i = 1; i < urb->actual_length ; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 tty_insert_flip_char(tty, data[i], err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 } else {
446 /* some bytes had errors, every byte has status */
Harvey Harrison441b62c2008-03-03 16:08:34 -0800447 dbg("%s - RX error!!!!", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 for (i = 0; i + 1 < urb->actual_length; i += 2) {
449 int stat = data[i], flag = 0;
450 if (stat & RXERROR_OVERRUN)
451 flag |= TTY_OVERRUN;
452 if (stat & RXERROR_FRAMING)
453 flag |= TTY_FRAME;
454 if (stat & RXERROR_PARITY)
455 flag |= TTY_PARITY;
456 /* XXX should handle break (0x10) */
457 tty_insert_flip_char(tty, data[i+1], flag);
458 }
459 }
460 tty_flip_buffer_push(tty);
461 }
Alan Cox4a90f092008-10-13 10:39:46 +0100462 tty_kref_put(tty);
Alan Coxdeb91682008-07-22 11:13:08 +0100463
464 /* Resubmit urb so we continue receiving */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 urb->dev = port->serial->dev;
Alan Coxdeb91682008-07-22 11:13:08 +0100466 if (port->port.count) {
467 err = usb_submit_urb(urb, GFP_ATOMIC);
468 if (err != 0)
469 dbg("%s - resubmit read urb failed. (%d)",
470 __func__, err);
471 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 return;
473}
474
Alan Coxdeb91682008-07-22 11:13:08 +0100475/* Outdat handling is common for all devices */
David Howells7d12e782006-10-05 14:55:46 +0100476static void usa2x_outdat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477{
478 struct usb_serial_port *port;
479 struct keyspan_port_private *p_priv;
480
Ming Leicdc97792008-02-24 18:41:47 +0800481 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100483 dbg("%s - urb %d", __func__, urb == p_priv->out_urbs[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484
Alan Cox95da3102008-07-22 11:09:07 +0100485 if (port->port.count)
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700486 usb_serial_port_softint(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487}
488
David Howells7d12e782006-10-05 14:55:46 +0100489static void usa26_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490{
Alan Coxdeb91682008-07-22 11:13:08 +0100491 dbg("%s", __func__);
492
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493}
494
David Howells7d12e782006-10-05 14:55:46 +0100495static void usa26_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496{
497 struct usb_serial_port *port;
498 struct keyspan_port_private *p_priv;
499
Ming Leicdc97792008-02-24 18:41:47 +0800500 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 p_priv = usb_get_serial_port_data(port);
502
503 if (p_priv->resend_cont) {
Alan Coxdeb91682008-07-22 11:13:08 +0100504 dbg("%s - sending setup", __func__);
505 keyspan_usa26_send_setup(port->serial, port,
506 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 }
508}
509
David Howells7d12e782006-10-05 14:55:46 +0100510static void usa26_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511{
512 unsigned char *data = urb->transfer_buffer;
513 struct keyspan_usa26_portStatusMessage *msg;
514 struct usb_serial *serial;
515 struct usb_serial_port *port;
516 struct keyspan_port_private *p_priv;
Alan Cox4a90f092008-10-13 10:39:46 +0100517 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700519 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520
Ming Leicdc97792008-02-24 18:41:47 +0800521 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700523 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800524 dbg("%s - nonzero status: %x", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 return;
526 }
527 if (urb->actual_length != 9) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800528 dbg("%s - %d byte report??", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 goto exit;
530 }
531
532 msg = (struct keyspan_usa26_portStatusMessage *)data;
533
534#if 0
535 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 -0800536 __func__, msg->port, msg->hskia_cts, msg->gpia_dcd, msg->dsr, msg->ri, msg->_txOff,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 msg->_txXoff, msg->rxEnabled, msg->controlResponse);
538#endif
539
540 /* Now do something useful with the data */
541
542
Alan Coxdeb91682008-07-22 11:13:08 +0100543 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 if (msg->port >= serial->num_ports) {
Alan Coxdeb91682008-07-22 11:13:08 +0100545 dbg("%s - Unexpected port number %d", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 goto exit;
547 }
548 port = serial->port[msg->port];
549 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100550
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 /* Update handshaking pin state information */
552 old_dcd_state = p_priv->dcd_state;
553 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
554 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
555 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
556 p_priv->ri_state = ((msg->ri) ? 1 : 0);
557
Alan Cox4a90f092008-10-13 10:39:46 +0100558 if (old_dcd_state != p_priv->dcd_state) {
559 tty = tty_port_tty_get(&port->port);
560 if (tty && !C_CLOCAL(tty))
561 tty_hangup(tty);
562 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 }
Alan Coxdeb91682008-07-22 11:13:08 +0100564
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 /* Resubmit urb so we continue receiving */
566 urb->dev = serial->dev;
Alan Coxdeb91682008-07-22 11:13:08 +0100567 err = usb_submit_urb(urb, GFP_ATOMIC);
568 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800569 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570exit: ;
571}
572
David Howells7d12e782006-10-05 14:55:46 +0100573static void usa26_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574{
Alan Coxdeb91682008-07-22 11:13:08 +0100575 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576}
577
578
David Howells7d12e782006-10-05 14:55:46 +0100579static void usa28_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580{
Alan Coxf035a8a2008-07-22 11:13:32 +0100581 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 struct usb_serial_port *port;
583 struct tty_struct *tty;
584 unsigned char *data;
585 struct keyspan_port_private *p_priv;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700586 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587
Alan Coxdeb91682008-07-22 11:13:08 +0100588 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589
Ming Leicdc97792008-02-24 18:41:47 +0800590 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 p_priv = usb_get_serial_port_data(port);
592 data = urb->transfer_buffer;
593
594 if (urb != p_priv->in_urbs[p_priv->in_flip])
595 return;
596
597 do {
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700598 if (status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599 dbg("%s - nonzero status: %x on endpoint %d.",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800600 __func__, status, usb_pipeendpoint(urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 return;
602 }
603
Ming Leicdc97792008-02-24 18:41:47 +0800604 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 p_priv = usb_get_serial_port_data(port);
606 data = urb->transfer_buffer;
607
Alan Cox4a90f092008-10-13 10:39:46 +0100608 tty =tty_port_tty_get(&port->port);
609 if (tty && urb->actual_length) {
Alan Coxf035a8a2008-07-22 11:13:32 +0100610 tty_insert_flip_string(tty, data, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 tty_flip_buffer_push(tty);
612 }
Alan Cox4a90f092008-10-13 10:39:46 +0100613 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614
615 /* Resubmit urb so we continue receiving */
616 urb->dev = port->serial->dev;
Alan Coxdeb91682008-07-22 11:13:08 +0100617 if (port->port.count) {
618 err = usb_submit_urb(urb, GFP_ATOMIC);
619 if (err != 0)
620 dbg("%s - resubmit read urb failed. (%d)",
621 __func__, err);
622 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 p_priv->in_flip ^= 1;
624
625 urb = p_priv->in_urbs[p_priv->in_flip];
626 } while (urb->status != -EINPROGRESS);
627}
628
David Howells7d12e782006-10-05 14:55:46 +0100629static void usa28_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630{
Alan Coxdeb91682008-07-22 11:13:08 +0100631 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632}
633
David Howells7d12e782006-10-05 14:55:46 +0100634static void usa28_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635{
636 struct usb_serial_port *port;
637 struct keyspan_port_private *p_priv;
638
Ming Leicdc97792008-02-24 18:41:47 +0800639 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 p_priv = usb_get_serial_port_data(port);
641
642 if (p_priv->resend_cont) {
Alan Coxdeb91682008-07-22 11:13:08 +0100643 dbg("%s - sending setup", __func__);
644 keyspan_usa28_send_setup(port->serial, port,
645 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 }
647}
648
David Howells7d12e782006-10-05 14:55:46 +0100649static void usa28_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650{
651 int err;
652 unsigned char *data = urb->transfer_buffer;
653 struct keyspan_usa28_portStatusMessage *msg;
654 struct usb_serial *serial;
655 struct usb_serial_port *port;
656 struct keyspan_port_private *p_priv;
Alan Cox4a90f092008-10-13 10:39:46 +0100657 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700659 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660
Ming Leicdc97792008-02-24 18:41:47 +0800661 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700663 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800664 dbg("%s - nonzero status: %x", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 return;
666 }
667
668 if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800669 dbg("%s - bad length %d", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 goto exit;
671 }
672
Harvey Harrison441b62c2008-03-03 16:08:34 -0800673 /*dbg("%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 data[0], data[1], data[2], data[3], data[4], data[5],
675 data[6], data[7], data[8], data[9], data[10], data[11]);*/
Alan Coxdeb91682008-07-22 11:13:08 +0100676
677 /* Now do something useful with the data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 msg = (struct keyspan_usa28_portStatusMessage *)data;
679
Alan Coxdeb91682008-07-22 11:13:08 +0100680 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681 if (msg->port >= serial->num_ports) {
Alan Coxdeb91682008-07-22 11:13:08 +0100682 dbg("%s - Unexpected port number %d", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683 goto exit;
684 }
685 port = serial->port[msg->port];
686 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100687
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 /* Update handshaking pin state information */
689 old_dcd_state = p_priv->dcd_state;
690 p_priv->cts_state = ((msg->cts) ? 1 : 0);
691 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
692 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
693 p_priv->ri_state = ((msg->ri) ? 1 : 0);
694
Alan Cox4a90f092008-10-13 10:39:46 +0100695 if( old_dcd_state != p_priv->dcd_state && old_dcd_state) {
696 tty = tty_port_tty_get(&port->port);
697 if (tty && !C_CLOCAL(tty))
698 tty_hangup(tty);
699 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 }
701
702 /* Resubmit urb so we continue receiving */
703 urb->dev = serial->dev;
Alan Coxdeb91682008-07-22 11:13:08 +0100704 err = usb_submit_urb(urb, GFP_ATOMIC);
705 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800706 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707exit: ;
708}
709
David Howells7d12e782006-10-05 14:55:46 +0100710static void usa28_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711{
Alan Coxdeb91682008-07-22 11:13:08 +0100712 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713}
714
715
David Howells7d12e782006-10-05 14:55:46 +0100716static void usa49_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717{
718 struct usb_serial *serial;
719 struct usb_serial_port *port;
720 struct keyspan_port_private *p_priv;
721 int i;
722
Alan Coxdeb91682008-07-22 11:13:08 +0100723 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724
Ming Leicdc97792008-02-24 18:41:47 +0800725 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 for (i = 0; i < serial->num_ports; ++i) {
727 port = serial->port[i];
728 p_priv = usb_get_serial_port_data(port);
729
730 if (p_priv->resend_cont) {
Alan Coxdeb91682008-07-22 11:13:08 +0100731 dbg("%s - sending setup", __func__);
732 keyspan_usa49_send_setup(serial, port,
733 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 break;
735 }
736 }
737}
738
739 /* This is actually called glostat in the Keyspan
740 doco */
David Howells7d12e782006-10-05 14:55:46 +0100741static void usa49_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742{
743 int err;
744 unsigned char *data = urb->transfer_buffer;
745 struct keyspan_usa49_portStatusMessage *msg;
746 struct usb_serial *serial;
747 struct usb_serial_port *port;
748 struct keyspan_port_private *p_priv;
749 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700750 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751
Alan Coxdeb91682008-07-22 11:13:08 +0100752 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753
Ming Leicdc97792008-02-24 18:41:47 +0800754 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700756 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800757 dbg("%s - nonzero status: %x", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 return;
759 }
760
Alan Coxdeb91682008-07-22 11:13:08 +0100761 if (urb->actual_length !=
762 sizeof(struct keyspan_usa49_portStatusMessage)) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800763 dbg("%s - bad length %d", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 goto exit;
765 }
766
Harvey Harrison441b62c2008-03-03 16:08:34 -0800767 /*dbg(" %x %x %x %x %x %x %x %x %x %x %x", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 data[0], data[1], data[2], data[3], data[4], data[5],
769 data[6], data[7], data[8], data[9], data[10]);*/
Alan Coxdeb91682008-07-22 11:13:08 +0100770
771 /* Now do something useful with the data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 msg = (struct keyspan_usa49_portStatusMessage *)data;
773
Alan Coxdeb91682008-07-22 11:13:08 +0100774 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 if (msg->portNumber >= serial->num_ports) {
Alan Coxdeb91682008-07-22 11:13:08 +0100776 dbg("%s - Unexpected port number %d",
777 __func__, msg->portNumber);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 goto exit;
779 }
780 port = serial->port[msg->portNumber];
781 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100782
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 /* Update handshaking pin state information */
784 old_dcd_state = p_priv->dcd_state;
785 p_priv->cts_state = ((msg->cts) ? 1 : 0);
786 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
787 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
788 p_priv->ri_state = ((msg->ri) ? 1 : 0);
789
Alan Cox4a90f092008-10-13 10:39:46 +0100790 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
791 struct tty_struct *tty = tty_port_tty_get(&port->port);
792 if (tty && !C_CLOCAL(tty))
793 tty_hangup(tty);
794 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 }
796
Alan Coxdeb91682008-07-22 11:13:08 +0100797 /* Resubmit urb so we continue receiving */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 urb->dev = serial->dev;
799
Alan Coxdeb91682008-07-22 11:13:08 +0100800 err = usb_submit_urb(urb, GFP_ATOMIC);
801 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800802 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803exit: ;
804}
805
David Howells7d12e782006-10-05 14:55:46 +0100806static void usa49_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807{
Alan Coxdeb91682008-07-22 11:13:08 +0100808 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809}
810
David Howells7d12e782006-10-05 14:55:46 +0100811static void usa49_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812{
813 int i, err;
814 int endpoint;
815 struct usb_serial_port *port;
816 struct tty_struct *tty;
817 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700818 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819
Alan Coxdeb91682008-07-22 11:13:08 +0100820 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821
822 endpoint = usb_pipeendpoint(urb->pipe);
823
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700824 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800825 dbg("%s - nonzero status: %x on endpoint %d.", __func__,
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700826 status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 return;
828 }
829
Ming Leicdc97792008-02-24 18:41:47 +0800830 port = urb->context;
Alan Cox4a90f092008-10-13 10:39:46 +0100831 tty = tty_port_tty_get(&port->port);
Alan Cox3004e532008-01-03 16:59:04 +0000832 if (tty && urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 /* 0x80 bit is error flag */
834 if ((data[0] & 0x80) == 0) {
835 /* no error on any byte */
Alan Coxf035a8a2008-07-22 11:13:32 +0100836 tty_insert_flip_string(tty, data + 1,
837 urb->actual_length - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 } else {
839 /* some bytes had errors, every byte has status */
840 for (i = 0; i + 1 < urb->actual_length; i += 2) {
841 int stat = data[i], flag = 0;
842 if (stat & RXERROR_OVERRUN)
843 flag |= TTY_OVERRUN;
844 if (stat & RXERROR_FRAMING)
845 flag |= TTY_FRAME;
846 if (stat & RXERROR_PARITY)
847 flag |= TTY_PARITY;
848 /* XXX should handle break (0x10) */
849 tty_insert_flip_char(tty, data[i+1], flag);
850 }
851 }
852 tty_flip_buffer_push(tty);
853 }
Alan Cox4a90f092008-10-13 10:39:46 +0100854 tty_kref_put(tty);
Alan Coxdeb91682008-07-22 11:13:08 +0100855
856 /* Resubmit urb so we continue receiving */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 urb->dev = port->serial->dev;
Alan Coxdeb91682008-07-22 11:13:08 +0100858 if (port->port.count) {
859 err = usb_submit_urb(urb, GFP_ATOMIC);
860 if (err != 0)
861 dbg("%s - resubmit read urb failed. (%d)",
862 __func__, err);
863 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864}
865
Lucy McCoy0ca12682007-05-18 12:10:41 -0700866static void usa49wg_indat_callback(struct urb *urb)
867{
868 int i, len, x, err;
869 struct usb_serial *serial;
870 struct usb_serial_port *port;
871 struct tty_struct *tty;
872 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700873 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700874
Alan Coxdeb91682008-07-22 11:13:08 +0100875 dbg("%s", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700876
877 serial = urb->context;
878
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700879 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800880 dbg("%s - nonzero status: %x", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700881 return;
882 }
883
884 /* inbound data is in the form P#, len, status, data */
885 i = 0;
886 len = 0;
887
888 if (urb->actual_length) {
889 while (i < urb->actual_length) {
890
891 /* Check port number from message*/
892 if (data[i] >= serial->num_ports) {
Alan Coxdeb91682008-07-22 11:13:08 +0100893 dbg("%s - Unexpected port number %d",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800894 __func__, data[i]);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700895 return;
896 }
897 port = serial->port[data[i++]];
Alan Cox4a90f092008-10-13 10:39:46 +0100898 tty = tty_port_tty_get(&port->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700899 len = data[i++];
900
901 /* 0x80 bit is error flag */
902 if ((data[i] & 0x80) == 0) {
903 /* no error on any byte */
904 i++;
905 for (x = 1; x < len ; ++x)
Alan Cox95da3102008-07-22 11:09:07 +0100906 if (port->port.count)
Lucy McCoy0ca12682007-05-18 12:10:41 -0700907 tty_insert_flip_char(tty,
908 data[i++], 0);
909 else
910 i++;
911 } else {
912 /*
913 * some bytes had errors, every byte has status
914 */
915 for (x = 0; x + 1 < len; x += 2) {
916 int stat = data[i], flag = 0;
917 if (stat & RXERROR_OVERRUN)
918 flag |= TTY_OVERRUN;
919 if (stat & RXERROR_FRAMING)
920 flag |= TTY_FRAME;
921 if (stat & RXERROR_PARITY)
922 flag |= TTY_PARITY;
923 /* XXX should handle break (0x10) */
Alan Cox95da3102008-07-22 11:09:07 +0100924 if (port->port.count)
Lucy McCoy0ca12682007-05-18 12:10:41 -0700925 tty_insert_flip_char(tty,
926 data[i+1], flag);
927 i += 2;
928 }
929 }
Alan Cox95da3102008-07-22 11:09:07 +0100930 if (port->port.count)
Lucy McCoy0ca12682007-05-18 12:10:41 -0700931 tty_flip_buffer_push(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100932 tty_kref_put(tty);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700933 }
934 }
935
936 /* Resubmit urb so we continue receiving */
937 urb->dev = serial->dev;
938
939 err = usb_submit_urb(urb, GFP_ATOMIC);
940 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800941 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700942}
943
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944/* not used, usa-49 doesn't have per-port control endpoints */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700945static void usa49_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946{
Alan Coxdeb91682008-07-22 11:13:08 +0100947 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948}
949
Lucy McCoy0ca12682007-05-18 12:10:41 -0700950static void usa90_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951{
952 int i, err;
953 int endpoint;
954 struct usb_serial_port *port;
955 struct keyspan_port_private *p_priv;
956 struct tty_struct *tty;
957 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700958 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959
Alan Coxdeb91682008-07-22 11:13:08 +0100960 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961
962 endpoint = usb_pipeendpoint(urb->pipe);
963
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700964 if (status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 dbg("%s - nonzero status: %x on endpoint %d.",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800966 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 return;
968 }
969
Ming Leicdc97792008-02-24 18:41:47 +0800970 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 p_priv = usb_get_serial_port_data(port);
972
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 if (urb->actual_length) {
Alan Cox4a90f092008-10-13 10:39:46 +0100974 tty = tty_port_tty_get(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 /* if current mode is DMA, looks like usa28 format
Alan Coxdeb91682008-07-22 11:13:08 +0100976 otherwise looks like usa26 data format */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977
Alan Coxf035a8a2008-07-22 11:13:32 +0100978 if (p_priv->baud > 57600)
979 tty_insert_flip_string(tty, data, urb->actual_length);
980 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 /* 0x80 bit is error flag */
982 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100983 /* no errors on individual bytes, only
984 possible overrun err*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 if (data[0] & RXERROR_OVERRUN)
Alan Coxdeb91682008-07-22 11:13:08 +0100986 err = TTY_OVERRUN;
987 else
988 err = 0;
989 for (i = 1; i < urb->actual_length ; ++i)
990 tty_insert_flip_char(tty, data[i],
991 err);
992 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 /* some bytes had errors, every byte has status */
Harvey Harrison441b62c2008-03-03 16:08:34 -0800994 dbg("%s - RX error!!!!", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 for (i = 0; i + 1 < urb->actual_length; i += 2) {
996 int stat = data[i], flag = 0;
997 if (stat & RXERROR_OVERRUN)
998 flag |= TTY_OVERRUN;
999 if (stat & RXERROR_FRAMING)
1000 flag |= TTY_FRAME;
1001 if (stat & RXERROR_PARITY)
1002 flag |= TTY_PARITY;
1003 /* XXX should handle break (0x10) */
Alan Coxdeb91682008-07-22 11:13:08 +01001004 tty_insert_flip_char(tty, data[i+1],
1005 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 }
1007 }
1008 }
1009 tty_flip_buffer_push(tty);
Alan Cox4a90f092008-10-13 10:39:46 +01001010 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 }
Alan Coxdeb91682008-07-22 11:13:08 +01001012
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 /* Resubmit urb so we continue receiving */
1014 urb->dev = port->serial->dev;
Alan Coxdeb91682008-07-22 11:13:08 +01001015 if (port->port.count) {
1016 err = usb_submit_urb(urb, GFP_ATOMIC);
1017 if (err != 0)
1018 dbg("%s - resubmit read urb failed. (%d)",
1019 __func__, err);
1020 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 return;
1022}
1023
1024
David Howells7d12e782006-10-05 14:55:46 +01001025static void usa90_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026{
1027 unsigned char *data = urb->transfer_buffer;
1028 struct keyspan_usa90_portStatusMessage *msg;
1029 struct usb_serial *serial;
1030 struct usb_serial_port *port;
1031 struct keyspan_port_private *p_priv;
Alan Cox4a90f092008-10-13 10:39:46 +01001032 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001034 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035
Ming Leicdc97792008-02-24 18:41:47 +08001036 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001038 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001039 dbg("%s - nonzero status: %x", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 return;
1041 }
1042 if (urb->actual_length < 14) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001043 dbg("%s - %d byte report??", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 goto exit;
1045 }
1046
1047 msg = (struct keyspan_usa90_portStatusMessage *)data;
1048
1049 /* Now do something useful with the data */
1050
1051 port = serial->port[0];
1052 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +01001053
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 /* Update handshaking pin state information */
1055 old_dcd_state = p_priv->dcd_state;
1056 p_priv->cts_state = ((msg->cts) ? 1 : 0);
1057 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
1058 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
1059 p_priv->ri_state = ((msg->ri) ? 1 : 0);
1060
Alan Cox4a90f092008-10-13 10:39:46 +01001061 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
1062 tty = tty_port_tty_get(&port->port);
1063 if (tty && !C_CLOCAL(tty))
1064 tty_hangup(tty);
1065 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 }
Alan Coxdeb91682008-07-22 11:13:08 +01001067
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 /* Resubmit urb so we continue receiving */
1069 urb->dev = serial->dev;
Alan Coxdeb91682008-07-22 11:13:08 +01001070 err = usb_submit_urb(urb, GFP_ATOMIC);
1071 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08001072 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073exit:
1074 ;
1075}
1076
David Howells7d12e782006-10-05 14:55:46 +01001077static void usa90_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078{
1079 struct usb_serial_port *port;
1080 struct keyspan_port_private *p_priv;
1081
Ming Leicdc97792008-02-24 18:41:47 +08001082 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 p_priv = usb_get_serial_port_data(port);
1084
1085 if (p_priv->resend_cont) {
Alan Coxdeb91682008-07-22 11:13:08 +01001086 dbg("%s - sending setup", __func__);
1087 keyspan_usa90_send_setup(port->serial, port,
1088 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 }
1090}
1091
Lucy McCoy0ca12682007-05-18 12:10:41 -07001092/* Status messages from the 28xg */
1093static void usa67_instat_callback(struct urb *urb)
1094{
1095 int err;
1096 unsigned char *data = urb->transfer_buffer;
1097 struct keyspan_usa67_portStatusMessage *msg;
1098 struct usb_serial *serial;
1099 struct usb_serial_port *port;
1100 struct keyspan_port_private *p_priv;
1101 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001102 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001103
Alan Coxdeb91682008-07-22 11:13:08 +01001104 dbg("%s", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001105
1106 serial = urb->context;
1107
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001108 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001109 dbg("%s - nonzero status: %x", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001110 return;
1111 }
1112
Alan Coxdeb91682008-07-22 11:13:08 +01001113 if (urb->actual_length !=
1114 sizeof(struct keyspan_usa67_portStatusMessage)) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001115 dbg("%s - bad length %d", __func__, urb->actual_length);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001116 return;
1117 }
1118
1119
1120 /* Now do something useful with the data */
1121 msg = (struct keyspan_usa67_portStatusMessage *)data;
1122
1123 /* Check port number from message and retrieve private data */
1124 if (msg->port >= serial->num_ports) {
Alan Coxdeb91682008-07-22 11:13:08 +01001125 dbg("%s - Unexpected port number %d", __func__, msg->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001126 return;
1127 }
1128
1129 port = serial->port[msg->port];
1130 p_priv = usb_get_serial_port_data(port);
1131
1132 /* Update handshaking pin state information */
1133 old_dcd_state = p_priv->dcd_state;
1134 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
1135 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
1136
Alan Cox4a90f092008-10-13 10:39:46 +01001137 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
1138 struct tty_struct *tty = tty_port_tty_get(&port->port);
1139 if (tty && !C_CLOCAL(tty))
1140 tty_hangup(tty);
1141 tty_kref_put(tty);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001142 }
1143
1144 /* Resubmit urb so we continue receiving */
1145 urb->dev = serial->dev;
1146 err = usb_submit_urb(urb, GFP_ATOMIC);
1147 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08001148 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001149}
1150
1151static void usa67_glocont_callback(struct urb *urb)
1152{
1153 struct usb_serial *serial;
1154 struct usb_serial_port *port;
1155 struct keyspan_port_private *p_priv;
1156 int i;
1157
Alan Coxdeb91682008-07-22 11:13:08 +01001158 dbg("%s", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001159
1160 serial = urb->context;
1161 for (i = 0; i < serial->num_ports; ++i) {
1162 port = serial->port[i];
1163 p_priv = usb_get_serial_port_data(port);
1164
1165 if (p_priv->resend_cont) {
Alan Coxdeb91682008-07-22 11:13:08 +01001166 dbg("%s - sending setup", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001167 keyspan_usa67_send_setup(serial, port,
1168 p_priv->resend_cont - 1);
1169 break;
1170 }
1171 }
1172}
1173
Alan Cox95da3102008-07-22 11:09:07 +01001174static int keyspan_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175{
Alan Cox95da3102008-07-22 11:09:07 +01001176 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 struct keyspan_port_private *p_priv;
1178 const struct keyspan_device_details *d_details;
1179 int flip;
1180 int data_len;
1181 struct urb *this_urb;
1182
Harvey Harrison441b62c2008-03-03 16:08:34 -08001183 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 p_priv = usb_get_serial_port_data(port);
1185 d_details = p_priv->device_details;
1186
Alan Coxa5b6f602008-04-08 17:16:06 +01001187 /* FIXME: locking */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 if (d_details->msg_format == msg_usa90)
Alan Coxdeb91682008-07-22 11:13:08 +01001189 data_len = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 else
1191 data_len = 63;
1192
1193 flip = p_priv->out_flip;
1194
1195 /* Check both endpoints to see if any are available. */
Alan Coxdeb91682008-07-22 11:13:08 +01001196 this_urb = p_priv->out_urbs[flip];
1197 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001199 return data_len;
1200 flip = (flip + 1) & d_details->outdat_endp_flip;
1201 this_urb = p_priv->out_urbs[flip];
1202 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001204 return data_len;
1205 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 }
Alan Coxa5b6f602008-04-08 17:16:06 +01001207 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208}
1209
1210
Alan Cox95da3102008-07-22 11:09:07 +01001211static int keyspan_open(struct tty_struct *tty,
1212 struct usb_serial_port *port, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213{
Andrew Mortonf78ba152007-11-28 16:21:54 -08001214 struct keyspan_port_private *p_priv;
1215 struct keyspan_serial_private *s_priv;
1216 struct usb_serial *serial = port->serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 const struct keyspan_device_details *d_details;
1218 int i, err;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001219 int baud_rate, device_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 struct urb *urb;
Alan Cox95da3102008-07-22 11:09:07 +01001221 unsigned int cflag = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222
1223 s_priv = usb_get_serial_data(serial);
1224 p_priv = usb_get_serial_port_data(port);
1225 d_details = p_priv->device_details;
Borislav Petkov7eea4362007-11-14 17:00:39 -08001226
Harvey Harrison441b62c2008-03-03 16:08:34 -08001227 dbg("%s - port%d.", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228
1229 /* Set some sane defaults */
1230 p_priv->rts_state = 1;
1231 p_priv->dtr_state = 1;
1232 p_priv->baud = 9600;
1233
1234 /* force baud and lcr to be set on open */
1235 p_priv->old_baud = 0;
1236 p_priv->old_cflag = 0;
1237
1238 p_priv->out_flip = 0;
1239 p_priv->in_flip = 0;
1240
1241 /* Reset low level data toggle and start reading from endpoints */
1242 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001243 urb = p_priv->in_urbs[i];
1244 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245 continue;
1246 urb->dev = serial->dev;
1247
Alan Coxdeb91682008-07-22 11:13:08 +01001248 /* make sure endpoint data toggle is synchronized
1249 with the device */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 usb_clear_halt(urb->dev, urb->pipe);
Alan Coxdeb91682008-07-22 11:13:08 +01001251 err = usb_submit_urb(urb, GFP_KERNEL);
1252 if (err != 0)
1253 dbg("%s - submit urb %d failed (%d)",
1254 __func__, i, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 }
1256
1257 /* Reset low level data toggle on out endpoints */
1258 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001259 urb = p_priv->out_urbs[i];
1260 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 continue;
1262 urb->dev = serial->dev;
Alan Coxdeb91682008-07-22 11:13:08 +01001263 /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
1264 usb_pipeout(urb->pipe), 0); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 }
1266
Andrew Mortonf78ba152007-11-28 16:21:54 -08001267 /* get the terminal config for the setup message now so we don't
1268 * need to send 2 of them */
1269
Andrew Mortonf78ba152007-11-28 16:21:54 -08001270 device_port = port->number - port->serial->minor;
Alan Cox95da3102008-07-22 11:09:07 +01001271 if (tty) {
1272 cflag = tty->termios->c_cflag;
1273 /* Baud rate calculation takes baud rate as an integer
1274 so other rates can be generated if desired. */
1275 baud_rate = tty_get_baud_rate(tty);
1276 /* If no match or invalid, leave as default */
1277 if (baud_rate >= 0
1278 && d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
1279 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
1280 p_priv->baud = baud_rate;
1281 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001282 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001283 /* set CTS/RTS handshake etc. */
1284 p_priv->cflag = cflag;
1285 p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none;
1286
1287 keyspan_send_setup(port, 1);
Alan Coxdeb91682008-07-22 11:13:08 +01001288 /* mdelay(100); */
1289 /* keyspan_set_termios(port, NULL); */
Andrew Mortonf78ba152007-11-28 16:21:54 -08001290
Alan Coxa5b6f602008-04-08 17:16:06 +01001291 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292}
1293
1294static inline void stop_urb(struct urb *urb)
1295{
Greg Kroah-Hartman242cf672005-07-29 16:11:07 -04001296 if (urb && urb->status == -EINPROGRESS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 usb_kill_urb(urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298}
1299
Alan Cox95da3102008-07-22 11:09:07 +01001300static void keyspan_close(struct tty_struct *tty,
1301 struct usb_serial_port *port, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302{
1303 int i;
1304 struct usb_serial *serial = port->serial;
1305 struct keyspan_serial_private *s_priv;
1306 struct keyspan_port_private *p_priv;
1307
Harvey Harrison441b62c2008-03-03 16:08:34 -08001308 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 s_priv = usb_get_serial_data(serial);
1310 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +01001311
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 p_priv->rts_state = 0;
1313 p_priv->dtr_state = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001314
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315 if (serial->dev) {
1316 keyspan_send_setup(port, 2);
1317 /* pilot-xfer seems to work best with this delay */
1318 mdelay(100);
Alan Coxdeb91682008-07-22 11:13:08 +01001319 /* keyspan_set_termios(port, NULL); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 }
1321
1322 /*while (p_priv->outcont_urb->status == -EINPROGRESS) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001323 dbg("%s - urb in progress", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 }*/
1325
1326 p_priv->out_flip = 0;
1327 p_priv->in_flip = 0;
1328
1329 if (serial->dev) {
1330 /* Stop reading/writing urbs */
1331 stop_urb(p_priv->inack_urb);
1332 /* stop_urb(p_priv->outcont_urb); */
1333 for (i = 0; i < 2; i++) {
1334 stop_urb(p_priv->in_urbs[i]);
1335 stop_urb(p_priv->out_urbs[i]);
1336 }
1337 }
Alan Cox4a90f092008-10-13 10:39:46 +01001338 tty_port_tty_set(&port->port, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339}
1340
Alan Coxdeb91682008-07-22 11:13:08 +01001341/* download the firmware to a pre-renumeration device */
1342static int keyspan_fake_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343{
1344 int response;
David Woodhouse2971c572008-05-30 14:04:03 +03001345 const struct ihex_binrec *record;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 char *fw_name;
David Woodhouse2971c572008-05-30 14:04:03 +03001347 const struct firmware *fw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348
1349 dbg("Keyspan startup version %04x product %04x",
1350 le16_to_cpu(serial->dev->descriptor.bcdDevice),
1351 le16_to_cpu(serial->dev->descriptor.idProduct));
Alan Coxdeb91682008-07-22 11:13:08 +01001352
1353 if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000)
1354 != 0x8000) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 dbg("Firmware already loaded. Quitting.");
Alan Coxdeb91682008-07-22 11:13:08 +01001356 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 }
1358
1359 /* Select firmware image on the basis of idProduct */
1360 switch (le16_to_cpu(serial->dev->descriptor.idProduct)) {
1361 case keyspan_usa28_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001362 fw_name = "keyspan/usa28.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 break;
1364
1365 case keyspan_usa28x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001366 fw_name = "keyspan/usa28x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 break;
1368
1369 case keyspan_usa28xa_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001370 fw_name = "keyspan/usa28xa.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 break;
1372
1373 case keyspan_usa28xb_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001374 fw_name = "keyspan/usa28xb.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 break;
1376
1377 case keyspan_usa19_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001378 fw_name = "keyspan/usa19.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001380
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 case keyspan_usa19qi_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001382 fw_name = "keyspan/usa19qi.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001384
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 case keyspan_mpr_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001386 fw_name = "keyspan/mpr.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 break;
1388
1389 case keyspan_usa19qw_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001390 fw_name = "keyspan/usa19qw.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001392
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 case keyspan_usa18x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001394 fw_name = "keyspan/usa18x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001396
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 case keyspan_usa19w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001398 fw_name = "keyspan/usa19w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001400
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401 case keyspan_usa49w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001402 fw_name = "keyspan/usa49w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 break;
1404
1405 case keyspan_usa49wlc_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001406 fw_name = "keyspan/usa49wlc.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 break;
1408
1409 default:
David Woodhouse2971c572008-05-30 14:04:03 +03001410 dev_err(&serial->dev->dev, "Unknown product ID (%04x)\n",
1411 le16_to_cpu(serial->dev->descriptor.idProduct));
1412 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 }
1414
David Woodhouse2971c572008-05-30 14:04:03 +03001415 if (request_ihex_firmware(&fw, fw_name, &serial->dev->dev)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 dev_err(&serial->dev->dev, "Required keyspan firmware image (%s) unavailable.\n", fw_name);
1417 return(1);
1418 }
1419
1420 dbg("Uploading Keyspan %s firmware.", fw_name);
1421
1422 /* download the firmware image */
1423 response = ezusb_set_reset(serial, 1);
1424
David Woodhouse2971c572008-05-30 14:04:03 +03001425 record = (const struct ihex_binrec *)fw->data;
1426
1427 while (record) {
1428 response = ezusb_writememory(serial, be32_to_cpu(record->addr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 (unsigned char *)record->data,
David Woodhouse2971c572008-05-30 14:04:03 +03001430 be16_to_cpu(record->len), 0xa0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 if (response < 0) {
Alan Coxdeb91682008-07-22 11:13:08 +01001432 dev_err(&serial->dev->dev, "ezusb_writememory failed for Keyspan firmware (%d %04X %p %d)\n",
David Woodhouse2971c572008-05-30 14:04:03 +03001433 response, be32_to_cpu(record->addr),
1434 record->data, be16_to_cpu(record->len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435 break;
1436 }
David Woodhouse2971c572008-05-30 14:04:03 +03001437 record = ihex_next_binrec(record);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 }
David Woodhouse2971c572008-05-30 14:04:03 +03001439 release_firmware(fw);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 /* bring device out of reset. Renumeration will occur in a
1441 moment and the new device will bind to the real driver */
1442 response = ezusb_set_reset(serial, 0);
1443
1444 /* we don't want this device to have a driver assigned to it. */
Alan Coxdeb91682008-07-22 11:13:08 +01001445 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446}
1447
1448/* Helper functions used by keyspan_setup_urbs */
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001449static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *serial,
1450 int endpoint)
1451{
1452 struct usb_host_interface *iface_desc;
1453 struct usb_endpoint_descriptor *ep;
1454 int i;
1455
1456 iface_desc = serial->interface->cur_altsetting;
1457 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1458 ep = &iface_desc->endpoint[i].desc;
1459 if (ep->bEndpointAddress == endpoint)
1460 return ep;
1461 }
1462 dev_warn(&serial->interface->dev, "found no endpoint descriptor for "
1463 "endpoint %x\n", endpoint);
1464 return NULL;
1465}
1466
Alan Coxdeb91682008-07-22 11:13:08 +01001467static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 int dir, void *ctx, char *buf, int len,
David Howells7d12e782006-10-05 14:55:46 +01001469 void (*callback)(struct urb *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470{
1471 struct urb *urb;
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001472 struct usb_endpoint_descriptor const *ep_desc;
1473 char const *ep_type_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474
1475 if (endpoint == -1)
1476 return NULL; /* endpoint not needed */
1477
Alan Coxdeb91682008-07-22 11:13:08 +01001478 dbg("%s - alloc for endpoint %d.", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
1480 if (urb == NULL) {
Alan Coxdeb91682008-07-22 11:13:08 +01001481 dbg("%s - alloc for endpoint %d failed.", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482 return NULL;
1483 }
1484
Lucy McCoy0ca12682007-05-18 12:10:41 -07001485 if (endpoint == 0) {
1486 /* control EP filled in when used */
1487 return urb;
1488 }
1489
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001490 ep_desc = find_ep(serial, endpoint);
1491 if (!ep_desc) {
1492 /* leak the urb, something's wrong and the callers don't care */
1493 return urb;
1494 }
1495 if (usb_endpoint_xfer_int(ep_desc)) {
1496 ep_type_name = "INT";
1497 usb_fill_int_urb(urb, serial->dev,
1498 usb_sndintpipe(serial->dev, endpoint) | dir,
1499 buf, len, callback, ctx,
1500 ep_desc->bInterval);
1501 } else if (usb_endpoint_xfer_bulk(ep_desc)) {
1502 ep_type_name = "BULK";
1503 usb_fill_bulk_urb(urb, serial->dev,
1504 usb_sndbulkpipe(serial->dev, endpoint) | dir,
1505 buf, len, callback, ctx);
1506 } else {
1507 dev_warn(&serial->interface->dev,
1508 "unsupported endpoint type %x\n",
1509 ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
1510 usb_free_urb(urb);
1511 return NULL;
1512 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001514 dbg("%s - using urb %p for %s endpoint %x",
1515 __func__, urb, ep_type_name, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 return urb;
1517}
1518
1519static struct callbacks {
David Howells7d12e782006-10-05 14:55:46 +01001520 void (*instat_callback)(struct urb *);
1521 void (*glocont_callback)(struct urb *);
1522 void (*indat_callback)(struct urb *);
1523 void (*outdat_callback)(struct urb *);
1524 void (*inack_callback)(struct urb *);
1525 void (*outcont_callback)(struct urb *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526} keyspan_callbacks[] = {
1527 {
1528 /* msg_usa26 callbacks */
1529 .instat_callback = usa26_instat_callback,
1530 .glocont_callback = usa26_glocont_callback,
1531 .indat_callback = usa26_indat_callback,
1532 .outdat_callback = usa2x_outdat_callback,
1533 .inack_callback = usa26_inack_callback,
1534 .outcont_callback = usa26_outcont_callback,
1535 }, {
1536 /* msg_usa28 callbacks */
1537 .instat_callback = usa28_instat_callback,
1538 .glocont_callback = usa28_glocont_callback,
1539 .indat_callback = usa28_indat_callback,
1540 .outdat_callback = usa2x_outdat_callback,
1541 .inack_callback = usa28_inack_callback,
1542 .outcont_callback = usa28_outcont_callback,
1543 }, {
1544 /* msg_usa49 callbacks */
1545 .instat_callback = usa49_instat_callback,
1546 .glocont_callback = usa49_glocont_callback,
1547 .indat_callback = usa49_indat_callback,
1548 .outdat_callback = usa2x_outdat_callback,
1549 .inack_callback = usa49_inack_callback,
1550 .outcont_callback = usa49_outcont_callback,
1551 }, {
1552 /* msg_usa90 callbacks */
1553 .instat_callback = usa90_instat_callback,
Alan Coxdeb91682008-07-22 11:13:08 +01001554 .glocont_callback = usa28_glocont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555 .indat_callback = usa90_indat_callback,
1556 .outdat_callback = usa2x_outdat_callback,
1557 .inack_callback = usa28_inack_callback,
1558 .outcont_callback = usa90_outcont_callback,
Lucy McCoy0ca12682007-05-18 12:10:41 -07001559 }, {
1560 /* msg_usa67 callbacks */
1561 .instat_callback = usa67_instat_callback,
1562 .glocont_callback = usa67_glocont_callback,
1563 .indat_callback = usa26_indat_callback,
1564 .outdat_callback = usa2x_outdat_callback,
1565 .inack_callback = usa26_inack_callback,
1566 .outcont_callback = usa26_outcont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567 }
1568};
1569
1570 /* Generic setup urbs function that uses
1571 data in device_details */
1572static void keyspan_setup_urbs(struct usb_serial *serial)
1573{
1574 int i, j;
1575 struct keyspan_serial_private *s_priv;
1576 const struct keyspan_device_details *d_details;
1577 struct usb_serial_port *port;
1578 struct keyspan_port_private *p_priv;
1579 struct callbacks *cback;
1580 int endp;
1581
Alan Coxdeb91682008-07-22 11:13:08 +01001582 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583
1584 s_priv = usb_get_serial_data(serial);
1585 d_details = s_priv->device_details;
1586
Alan Coxdeb91682008-07-22 11:13:08 +01001587 /* Setup values for the various callback routines */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 cback = &keyspan_callbacks[d_details->msg_format];
1589
Alan Coxdeb91682008-07-22 11:13:08 +01001590 /* Allocate and set up urbs for each one that is in use,
1591 starting with instat endpoints */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 s_priv->instat_urb = keyspan_setup_urb
1593 (serial, d_details->instat_endpoint, USB_DIR_IN,
1594 serial, s_priv->instat_buf, INSTAT_BUFLEN,
1595 cback->instat_callback);
1596
Lucy McCoy0ca12682007-05-18 12:10:41 -07001597 s_priv->indat_urb = keyspan_setup_urb
1598 (serial, d_details->indat_endpoint, USB_DIR_IN,
1599 serial, s_priv->indat_buf, INDAT49W_BUFLEN,
1600 usa49wg_indat_callback);
1601
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602 s_priv->glocont_urb = keyspan_setup_urb
1603 (serial, d_details->glocont_endpoint, USB_DIR_OUT,
1604 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
1605 cback->glocont_callback);
1606
Alan Coxdeb91682008-07-22 11:13:08 +01001607 /* Setup endpoints for each port specific thing */
1608 for (i = 0; i < d_details->num_ports; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609 port = serial->port[i];
1610 p_priv = usb_get_serial_port_data(port);
1611
1612 /* Do indat endpoints first, once for each flip */
1613 endp = d_details->indat_endpoints[i];
1614 for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) {
1615 p_priv->in_urbs[j] = keyspan_setup_urb
1616 (serial, endp, USB_DIR_IN, port,
1617 p_priv->in_buffer[j], 64,
1618 cback->indat_callback);
1619 }
1620 for (; j < 2; ++j)
1621 p_priv->in_urbs[j] = NULL;
1622
1623 /* outdat endpoints also have flip */
1624 endp = d_details->outdat_endpoints[i];
1625 for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) {
1626 p_priv->out_urbs[j] = keyspan_setup_urb
1627 (serial, endp, USB_DIR_OUT, port,
1628 p_priv->out_buffer[j], 64,
1629 cback->outdat_callback);
1630 }
1631 for (; j < 2; ++j)
1632 p_priv->out_urbs[j] = NULL;
1633
1634 /* inack endpoint */
1635 p_priv->inack_urb = keyspan_setup_urb
1636 (serial, d_details->inack_endpoints[i], USB_DIR_IN,
1637 port, p_priv->inack_buffer, 1, cback->inack_callback);
1638
1639 /* outcont endpoint */
1640 p_priv->outcont_urb = keyspan_setup_urb
1641 (serial, d_details->outcont_endpoints[i], USB_DIR_OUT,
1642 port, p_priv->outcont_buffer, 64,
1643 cback->outcont_callback);
Alan Coxdeb91682008-07-22 11:13:08 +01001644 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645}
1646
1647/* usa19 function doesn't require prescaler */
1648static int keyspan_usa19_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
1649 u8 *rate_low, u8 *prescaler, int portnum)
1650{
1651 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001652 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653 cnt; /* inverse of divisor (programmed into 8051) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654
Alan Coxdeb91682008-07-22 11:13:08 +01001655 dbg("%s - %d.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656
Alan Coxdeb91682008-07-22 11:13:08 +01001657 /* prevent divide by zero... */
1658 b16 = baud_rate * 16L;
1659 if (b16 == 0)
1660 return KEYSPAN_INVALID_BAUD_RATE;
1661 /* Any "standard" rate over 57k6 is marginal on the USA-19
1662 as we run out of divisor resolution. */
1663 if (baud_rate > 57600)
1664 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665
Alan Coxdeb91682008-07-22 11:13:08 +01001666 /* calculate the divisor and the counter (its inverse) */
1667 div = baudclk / b16;
1668 if (div == 0)
1669 return KEYSPAN_INVALID_BAUD_RATE;
1670 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672
Alan Coxdeb91682008-07-22 11:13:08 +01001673 if (div > 0xffff)
1674 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675
Alan Coxdeb91682008-07-22 11:13:08 +01001676 /* return the counter values if non-null */
1677 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001679 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001681 if (rate_low && rate_hi)
1682 dbg("%s - %d %02x %02x.",
1683 __func__, baud_rate, *rate_hi, *rate_low);
1684 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685}
1686
1687/* usa19hs function doesn't require prescaler */
1688static int keyspan_usa19hs_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
1689 u8 *rate_low, u8 *prescaler, int portnum)
1690{
1691 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001692 div; /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693
Alan Coxdeb91682008-07-22 11:13:08 +01001694 dbg("%s - %d.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695
Alan Coxdeb91682008-07-22 11:13:08 +01001696 /* prevent divide by zero... */
1697 b16 = baud_rate * 16L;
1698 if (b16 == 0)
1699 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700
Alan Coxdeb91682008-07-22 11:13:08 +01001701 /* calculate the divisor */
1702 div = baudclk / b16;
1703 if (div == 0)
1704 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705
Alan Coxdeb91682008-07-22 11:13:08 +01001706 if (div > 0xffff)
1707 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708
Alan Coxdeb91682008-07-22 11:13:08 +01001709 /* return the counter values if non-null */
1710 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001712
1713 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714 *rate_hi = (u8) ((div >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001715
1716 if (rate_low && rate_hi)
1717 dbg("%s - %d %02x %02x.",
1718 __func__, baud_rate, *rate_hi, *rate_low);
1719
1720 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721}
1722
1723static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
1724 u8 *rate_low, u8 *prescaler, int portnum)
1725{
1726 u32 b16, /* baud rate times 16 (actual rate used internally) */
1727 clk, /* clock with 13/8 prescaler */
Alan Coxdeb91682008-07-22 11:13:08 +01001728 div, /* divisor using 13/8 prescaler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 res, /* resulting baud rate using 13/8 prescaler */
1730 diff, /* error using 13/8 prescaler */
1731 smallest_diff;
1732 u8 best_prescaler;
1733 int i;
1734
Alan Coxdeb91682008-07-22 11:13:08 +01001735 dbg("%s - %d.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736
Alan Coxdeb91682008-07-22 11:13:08 +01001737 /* prevent divide by zero */
1738 b16 = baud_rate * 16L;
1739 if (b16 == 0)
1740 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741
Alan Coxdeb91682008-07-22 11:13:08 +01001742 /* Calculate prescaler by trying them all and looking
1743 for best fit */
1744
1745 /* start with largest possible difference */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746 smallest_diff = 0xffffffff;
1747
1748 /* 0 is an invalid prescaler, used as a flag */
1749 best_prescaler = 0;
1750
Alan Coxdeb91682008-07-22 11:13:08 +01001751 for (i = 8; i <= 0xff; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752 clk = (baudclk * 8) / (u32) i;
Alan Coxdeb91682008-07-22 11:13:08 +01001753
1754 div = clk / b16;
1755 if (div == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757
1758 res = clk / div;
Alan Coxdeb91682008-07-22 11:13:08 +01001759 diff = (res > b16) ? (res-b16) : (b16-res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760
Alan Coxdeb91682008-07-22 11:13:08 +01001761 if (diff < smallest_diff) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 best_prescaler = i;
1763 smallest_diff = diff;
1764 }
1765 }
1766
Alan Coxdeb91682008-07-22 11:13:08 +01001767 if (best_prescaler == 0)
1768 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769
1770 clk = (baudclk * 8) / (u32) best_prescaler;
1771 div = clk / b16;
1772
Alan Coxdeb91682008-07-22 11:13:08 +01001773 /* return the divisor and prescaler if non-null */
1774 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001776 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777 *rate_hi = (u8) ((div >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 if (prescaler) {
1779 *prescaler = best_prescaler;
Harvey Harrison441b62c2008-03-03 16:08:34 -08001780 /* dbg("%s - %d %d", __func__, *prescaler, div); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781 }
Alan Coxdeb91682008-07-22 11:13:08 +01001782 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783}
1784
1785 /* USA-28 supports different maximum baud rates on each port */
1786static int keyspan_usa28_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
1787 u8 *rate_low, u8 *prescaler, int portnum)
1788{
1789 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001790 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791 cnt; /* inverse of divisor (programmed into 8051) */
1792
Alan Coxdeb91682008-07-22 11:13:08 +01001793 dbg("%s - %d.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794
1795 /* prevent divide by zero */
Alan Coxdeb91682008-07-22 11:13:08 +01001796 b16 = baud_rate * 16L;
1797 if (b16 == 0)
1798 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799
Alan Coxdeb91682008-07-22 11:13:08 +01001800 /* calculate the divisor and the counter (its inverse) */
1801 div = KEYSPAN_USA28_BAUDCLK / b16;
1802 if (div == 0)
1803 return KEYSPAN_INVALID_BAUD_RATE;
1804 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806
Alan Coxdeb91682008-07-22 11:13:08 +01001807 /* check for out of range, based on portnum,
1808 and return result */
1809 if (portnum == 0) {
1810 if (div > 0xffff)
1811 return KEYSPAN_INVALID_BAUD_RATE;
1812 } else {
1813 if (portnum == 1) {
1814 if (div > 0xff)
1815 return KEYSPAN_INVALID_BAUD_RATE;
1816 } else
1817 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818 }
1819
1820 /* return the counter values if not NULL
1821 (port 1 will ignore retHi) */
Alan Coxdeb91682008-07-22 11:13:08 +01001822 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001824 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001826 dbg("%s - %d OK.", __func__, baud_rate);
1827 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828}
1829
1830static int keyspan_usa26_send_setup(struct usb_serial *serial,
1831 struct usb_serial_port *port,
1832 int reset_port)
1833{
Alan Coxdeb91682008-07-22 11:13:08 +01001834 struct keyspan_usa26_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835 struct keyspan_serial_private *s_priv;
1836 struct keyspan_port_private *p_priv;
1837 const struct keyspan_device_details *d_details;
1838 int outcont_urb;
1839 struct urb *this_urb;
1840 int device_port, err;
1841
Alan Coxdeb91682008-07-22 11:13:08 +01001842 dbg("%s reset=%d", __func__, reset_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843
1844 s_priv = usb_get_serial_data(serial);
1845 p_priv = usb_get_serial_port_data(port);
1846 d_details = s_priv->device_details;
1847 device_port = port->number - port->serial->minor;
1848
1849 outcont_urb = d_details->outcont_endpoints[port->number];
1850 this_urb = p_priv->outcont_urb;
1851
Harvey Harrison441b62c2008-03-03 16:08:34 -08001852 dbg("%s - endpoint %d", __func__, usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853
1854 /* Make sure we have an urb then send the message */
1855 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001856 dbg("%s - oops no urb.", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857 return -1;
1858 }
1859
1860 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001861 Don't overwrite resend for open/close condition. */
1862 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863 p_priv->resend_cont = reset_port + 1;
1864 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +01001865 /* dbg("%s - already writing", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001867 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868 }
1869
Alan Coxdeb91682008-07-22 11:13:08 +01001870 memset(&msg, 0, sizeof(struct keyspan_usa26_portControlMessage));
1871
1872 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873 if (p_priv->old_baud != p_priv->baud) {
1874 p_priv->old_baud = p_priv->baud;
1875 msg.setClocking = 0xff;
1876 if (d_details->calculate_baud_rate
1877 (p_priv->baud, d_details->baudclk, &msg.baudHi,
Alan Coxdeb91682008-07-22 11:13:08 +01001878 &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1879 dbg("%s - Invalid baud rate %d requested, using 9600.",
1880 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881 msg.baudLo = 0;
1882 msg.baudHi = 125; /* Values for 9600 baud */
1883 msg.prescaler = 10;
1884 }
1885 msg.setPrescaler = 0xff;
1886 }
1887
1888 msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
1889 switch (p_priv->cflag & CSIZE) {
1890 case CS5:
1891 msg.lcr |= USA_DATABITS_5;
1892 break;
1893 case CS6:
1894 msg.lcr |= USA_DATABITS_6;
1895 break;
1896 case CS7:
1897 msg.lcr |= USA_DATABITS_7;
1898 break;
1899 case CS8:
1900 msg.lcr |= USA_DATABITS_8;
1901 break;
1902 }
1903 if (p_priv->cflag & PARENB) {
1904 /* note USA_PARITY_NONE == 0 */
1905 msg.lcr |= (p_priv->cflag & PARODD)?
Alan Coxdeb91682008-07-22 11:13:08 +01001906 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907 }
1908 msg.setLcr = 0xff;
1909
1910 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1911 msg.xonFlowControl = 0;
1912 msg.setFlowControl = 0xff;
1913 msg.forwardingLength = 16;
1914 msg.xonChar = 17;
1915 msg.xoffChar = 19;
1916
1917 /* Opening port */
1918 if (reset_port == 1) {
1919 msg._txOn = 1;
1920 msg._txOff = 0;
1921 msg.txFlush = 0;
1922 msg.txBreak = 0;
1923 msg.rxOn = 1;
1924 msg.rxOff = 0;
1925 msg.rxFlush = 1;
1926 msg.rxForward = 0;
1927 msg.returnStatus = 0;
1928 msg.resetDataToggle = 0xff;
1929 }
1930
1931 /* Closing port */
1932 else if (reset_port == 2) {
1933 msg._txOn = 0;
1934 msg._txOff = 1;
1935 msg.txFlush = 0;
1936 msg.txBreak = 0;
1937 msg.rxOn = 0;
1938 msg.rxOff = 1;
1939 msg.rxFlush = 1;
1940 msg.rxForward = 0;
1941 msg.returnStatus = 0;
1942 msg.resetDataToggle = 0;
1943 }
1944
1945 /* Sending intermediate configs */
1946 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001947 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948 msg._txOff = 0;
1949 msg.txFlush = 0;
1950 msg.txBreak = (p_priv->break_on);
1951 msg.rxOn = 0;
1952 msg.rxOff = 0;
1953 msg.rxFlush = 0;
1954 msg.rxForward = 0;
1955 msg.returnStatus = 0;
1956 msg.resetDataToggle = 0x0;
1957 }
1958
Alan Coxdeb91682008-07-22 11:13:08 +01001959 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960 msg.setTxTriState_setRts = 0xff;
1961 msg.txTriState_rts = p_priv->rts_state;
1962
1963 msg.setHskoa_setDtr = 0xff;
1964 msg.hskoa_dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01001965
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001967 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
1968
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 /* send the data out the device on control endpoint */
1970 this_urb->transfer_buffer_length = sizeof(msg);
1971
1972 this_urb->dev = serial->dev;
Alan Coxdeb91682008-07-22 11:13:08 +01001973 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1974 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08001975 dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976#if 0
1977 else {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001978 dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979 outcont_urb, this_urb->transfer_buffer_length,
1980 usb_pipeendpoint(this_urb->pipe));
1981 }
1982#endif
1983
Alan Coxa5b6f602008-04-08 17:16:06 +01001984 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985}
1986
1987static int keyspan_usa28_send_setup(struct usb_serial *serial,
1988 struct usb_serial_port *port,
1989 int reset_port)
1990{
Alan Coxdeb91682008-07-22 11:13:08 +01001991 struct keyspan_usa28_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 struct keyspan_serial_private *s_priv;
1993 struct keyspan_port_private *p_priv;
1994 const struct keyspan_device_details *d_details;
1995 struct urb *this_urb;
1996 int device_port, err;
1997
Alan Coxdeb91682008-07-22 11:13:08 +01001998 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999
2000 s_priv = usb_get_serial_data(serial);
2001 p_priv = usb_get_serial_port_data(port);
2002 d_details = s_priv->device_details;
2003 device_port = port->number - port->serial->minor;
2004
2005 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01002006 this_urb = p_priv->outcont_urb;
2007 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002008 dbg("%s - oops no urb.", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 return -1;
2010 }
2011
2012 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07002013 Don't overwrite resend for open/close condition. */
2014 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015 p_priv->resend_cont = reset_port + 1;
2016 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +01002017 dbg("%s already writing", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002019 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 }
2021
Alan Coxdeb91682008-07-22 11:13:08 +01002022 memset(&msg, 0, sizeof(struct keyspan_usa28_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023
2024 msg.setBaudRate = 1;
2025 if (d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk,
Alan Coxdeb91682008-07-22 11:13:08 +01002026 &msg.baudHi, &msg.baudLo, NULL, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2027 dbg("%s - Invalid baud rate requested %d.",
2028 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029 msg.baudLo = 0xff;
2030 msg.baudHi = 0xb2; /* Values for 9600 baud */
2031 }
2032
2033 /* If parity is enabled, we must calculate it ourselves. */
2034 msg.parity = 0; /* XXX for now */
2035
2036 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2037 msg.xonFlowControl = 0;
2038
Alan Coxdeb91682008-07-22 11:13:08 +01002039 /* Do handshaking outputs, DTR is inverted relative to RTS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 msg.rts = p_priv->rts_state;
2041 msg.dtr = p_priv->dtr_state;
2042
2043 msg.forwardingLength = 16;
2044 msg.forwardMs = 10;
2045 msg.breakThreshold = 45;
2046 msg.xonChar = 17;
2047 msg.xoffChar = 19;
2048
2049 /*msg.returnStatus = 1;
2050 msg.resetDataToggle = 0xff;*/
2051 /* Opening port */
2052 if (reset_port == 1) {
2053 msg._txOn = 1;
2054 msg._txOff = 0;
2055 msg.txFlush = 0;
2056 msg.txForceXoff = 0;
2057 msg.txBreak = 0;
2058 msg.rxOn = 1;
2059 msg.rxOff = 0;
2060 msg.rxFlush = 1;
2061 msg.rxForward = 0;
2062 msg.returnStatus = 0;
2063 msg.resetDataToggle = 0xff;
2064 }
2065 /* Closing port */
2066 else if (reset_port == 2) {
2067 msg._txOn = 0;
2068 msg._txOff = 1;
2069 msg.txFlush = 0;
2070 msg.txForceXoff = 0;
2071 msg.txBreak = 0;
2072 msg.rxOn = 0;
2073 msg.rxOff = 1;
2074 msg.rxFlush = 1;
2075 msg.rxForward = 0;
2076 msg.returnStatus = 0;
2077 msg.resetDataToggle = 0;
2078 }
2079 /* Sending intermediate configs */
2080 else {
Alan Coxdeb91682008-07-22 11:13:08 +01002081 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082 msg._txOff = 0;
2083 msg.txFlush = 0;
2084 msg.txForceXoff = 0;
2085 msg.txBreak = (p_priv->break_on);
2086 msg.rxOn = 0;
2087 msg.rxOff = 0;
2088 msg.rxFlush = 0;
2089 msg.rxForward = 0;
2090 msg.returnStatus = 0;
2091 msg.resetDataToggle = 0x0;
2092 }
2093
2094 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01002095 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096
2097 /* send the data out the device on control endpoint */
2098 this_urb->transfer_buffer_length = sizeof(msg);
2099
2100 this_urb->dev = serial->dev;
Alan Coxdeb91682008-07-22 11:13:08 +01002101 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2102 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002103 dbg("%s - usb_submit_urb(setup) failed", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104#if 0
2105 else {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002106 dbg("%s - usb_submit_urb(setup) OK %d bytes", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 this_urb->transfer_buffer_length);
2108 }
2109#endif
2110
Alan Coxa5b6f602008-04-08 17:16:06 +01002111 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112}
2113
2114static int keyspan_usa49_send_setup(struct usb_serial *serial,
2115 struct usb_serial_port *port,
2116 int reset_port)
2117{
Lucy McCoy0ca12682007-05-18 12:10:41 -07002118 struct keyspan_usa49_portControlMessage msg;
2119 struct usb_ctrlrequest *dr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120 struct keyspan_serial_private *s_priv;
2121 struct keyspan_port_private *p_priv;
2122 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123 struct urb *this_urb;
2124 int err, device_port;
2125
Alan Coxdeb91682008-07-22 11:13:08 +01002126 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127
2128 s_priv = usb_get_serial_data(serial);
2129 p_priv = usb_get_serial_port_data(port);
2130 d_details = s_priv->device_details;
2131
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132 this_urb = s_priv->glocont_urb;
2133
Lucy McCoy0ca12682007-05-18 12:10:41 -07002134 /* Work out which port within the device is being setup */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135 device_port = port->number - port->serial->minor;
2136
Alan Coxdeb91682008-07-22 11:13:08 +01002137 dbg("%s - endpoint %d port %d (%d)",
2138 __func__, usb_pipeendpoint(this_urb->pipe),
2139 port->number, device_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140
2141 /* Make sure we have an urb then send the message */
2142 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002143 dbg("%s - oops no urb for port %d.", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 return -1;
2145 }
2146
2147 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07002148 Don't overwrite resend for open/close condition. */
2149 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150 p_priv->resend_cont = reset_port + 1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002151
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +01002153 /* dbg("%s - already writing", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002155 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156 }
2157
Alan Coxdeb91682008-07-22 11:13:08 +01002158 memset(&msg, 0, sizeof(struct keyspan_usa49_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159
2160 /*msg.portNumber = port->number;*/
2161 msg.portNumber = device_port;
Alan Coxdeb91682008-07-22 11:13:08 +01002162
2163 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 if (p_priv->old_baud != p_priv->baud) {
2165 p_priv->old_baud = p_priv->baud;
2166 msg.setClocking = 0xff;
2167 if (d_details->calculate_baud_rate
2168 (p_priv->baud, d_details->baudclk, &msg.baudHi,
Alan Coxdeb91682008-07-22 11:13:08 +01002169 &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2170 dbg("%s - Invalid baud rate %d requested, using 9600.",
2171 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172 msg.baudLo = 0;
2173 msg.baudHi = 125; /* Values for 9600 baud */
2174 msg.prescaler = 10;
2175 }
Alan Coxdeb91682008-07-22 11:13:08 +01002176 /* msg.setPrescaler = 0xff; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177 }
2178
2179 msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
2180 switch (p_priv->cflag & CSIZE) {
2181 case CS5:
2182 msg.lcr |= USA_DATABITS_5;
2183 break;
2184 case CS6:
2185 msg.lcr |= USA_DATABITS_6;
2186 break;
2187 case CS7:
2188 msg.lcr |= USA_DATABITS_7;
2189 break;
2190 case CS8:
2191 msg.lcr |= USA_DATABITS_8;
2192 break;
2193 }
2194 if (p_priv->cflag & PARENB) {
2195 /* note USA_PARITY_NONE == 0 */
2196 msg.lcr |= (p_priv->cflag & PARODD)?
Alan Coxdeb91682008-07-22 11:13:08 +01002197 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 }
2199 msg.setLcr = 0xff;
2200
2201 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2202 msg.xonFlowControl = 0;
2203 msg.setFlowControl = 0xff;
Alan Coxdeb91682008-07-22 11:13:08 +01002204
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205 msg.forwardingLength = 16;
2206 msg.xonChar = 17;
2207 msg.xoffChar = 19;
2208
Alan Coxdeb91682008-07-22 11:13:08 +01002209 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210 if (reset_port == 1) {
2211 msg._txOn = 1;
2212 msg._txOff = 0;
2213 msg.txFlush = 0;
2214 msg.txBreak = 0;
2215 msg.rxOn = 1;
2216 msg.rxOff = 0;
2217 msg.rxFlush = 1;
2218 msg.rxForward = 0;
2219 msg.returnStatus = 0;
2220 msg.resetDataToggle = 0xff;
2221 msg.enablePort = 1;
2222 msg.disablePort = 0;
2223 }
2224 /* Closing port */
2225 else if (reset_port == 2) {
2226 msg._txOn = 0;
2227 msg._txOff = 1;
2228 msg.txFlush = 0;
2229 msg.txBreak = 0;
2230 msg.rxOn = 0;
2231 msg.rxOff = 1;
2232 msg.rxFlush = 1;
2233 msg.rxForward = 0;
2234 msg.returnStatus = 0;
2235 msg.resetDataToggle = 0;
2236 msg.enablePort = 0;
2237 msg.disablePort = 1;
2238 }
2239 /* Sending intermediate configs */
2240 else {
Alan Coxdeb91682008-07-22 11:13:08 +01002241 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242 msg._txOff = 0;
2243 msg.txFlush = 0;
2244 msg.txBreak = (p_priv->break_on);
2245 msg.rxOn = 0;
2246 msg.rxOff = 0;
2247 msg.rxFlush = 0;
2248 msg.rxForward = 0;
2249 msg.returnStatus = 0;
2250 msg.resetDataToggle = 0x0;
2251 msg.enablePort = 0;
2252 msg.disablePort = 0;
2253 }
2254
Alan Coxdeb91682008-07-22 11:13:08 +01002255 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256 msg.setRts = 0xff;
2257 msg.rts = p_priv->rts_state;
2258
2259 msg.setDtr = 0xff;
2260 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002261
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262 p_priv->resend_cont = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263
Alan Coxdeb91682008-07-22 11:13:08 +01002264 /* if the device is a 49wg, we send control message on usb
2265 control EP 0 */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002266
2267 if (d_details->product_id == keyspan_usa49wg_product_id) {
2268 dr = (void *)(s_priv->ctrl_buf);
2269 dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT;
2270 dr->bRequest = 0xB0; /* 49wg control message */;
2271 dr->wValue = 0;
2272 dr->wIndex = 0;
2273 dr->wLength = cpu_to_le16(sizeof(msg));
2274
Alan Coxdeb91682008-07-22 11:13:08 +01002275 memcpy(s_priv->glocont_buf, &msg, sizeof(msg));
Lucy McCoy0ca12682007-05-18 12:10:41 -07002276
Alan Coxdeb91682008-07-22 11:13:08 +01002277 usb_fill_control_urb(this_urb, serial->dev,
2278 usb_sndctrlpipe(serial->dev, 0),
2279 (unsigned char *)dr, s_priv->glocont_buf,
2280 sizeof(msg), usa49_glocont_callback, serial);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002281
2282 } else {
2283 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Alan Coxdeb91682008-07-22 11:13:08 +01002284
Lucy McCoy0ca12682007-05-18 12:10:41 -07002285 /* send the data out the device on control endpoint */
2286 this_urb->transfer_buffer_length = sizeof(msg);
2287
2288 this_urb->dev = serial->dev;
2289 }
Alan Coxdeb91682008-07-22 11:13:08 +01002290 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2291 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002292 dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293#if 0
2294 else {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002295 dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002296 outcont_urb, this_urb->transfer_buffer_length,
2297 usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298 }
2299#endif
2300
Alan Coxa5b6f602008-04-08 17:16:06 +01002301 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302}
2303
2304static int keyspan_usa90_send_setup(struct usb_serial *serial,
2305 struct usb_serial_port *port,
2306 int reset_port)
2307{
Alan Coxdeb91682008-07-22 11:13:08 +01002308 struct keyspan_usa90_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309 struct keyspan_serial_private *s_priv;
2310 struct keyspan_port_private *p_priv;
2311 const struct keyspan_device_details *d_details;
2312 struct urb *this_urb;
2313 int err;
2314 u8 prescaler;
2315
Alan Coxdeb91682008-07-22 11:13:08 +01002316 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317
2318 s_priv = usb_get_serial_data(serial);
2319 p_priv = usb_get_serial_port_data(port);
2320 d_details = s_priv->device_details;
2321
2322 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01002323 this_urb = p_priv->outcont_urb;
2324 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002325 dbg("%s - oops no urb.", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326 return -1;
2327 }
2328
2329 /* Save reset port val for resend.
2330 Don't overwrite resend for open/close condition. */
2331 if ((reset_port + 1) > p_priv->resend_cont)
2332 p_priv->resend_cont = reset_port + 1;
2333 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +01002334 dbg("%s already writing", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002336 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 }
2338
Alan Coxdeb91682008-07-22 11:13:08 +01002339 memset(&msg, 0, sizeof(struct keyspan_usa90_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340
Alan Coxdeb91682008-07-22 11:13:08 +01002341 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342 if (p_priv->old_baud != p_priv->baud) {
2343 p_priv->old_baud = p_priv->baud;
2344 msg.setClocking = 0x01;
2345 if (d_details->calculate_baud_rate
2346 (p_priv->baud, d_details->baudclk, &msg.baudHi,
Alan Coxdeb91682008-07-22 11:13:08 +01002347 &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) {
2348 dbg("%s - Invalid baud rate %d requested, using 9600.",
2349 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 p_priv->baud = 9600;
Alan Coxdeb91682008-07-22 11:13:08 +01002351 d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 &msg.baudHi, &msg.baudLo, &prescaler, 0);
2353 }
2354 msg.setRxMode = 1;
2355 msg.setTxMode = 1;
2356 }
2357
2358 /* modes must always be correctly specified */
Alan Coxdeb91682008-07-22 11:13:08 +01002359 if (p_priv->baud > 57600) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 msg.rxMode = RXMODE_DMA;
2361 msg.txMode = TXMODE_DMA;
Alan Coxdeb91682008-07-22 11:13:08 +01002362 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 msg.rxMode = RXMODE_BYHAND;
2364 msg.txMode = TXMODE_BYHAND;
2365 }
2366
2367 msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
2368 switch (p_priv->cflag & CSIZE) {
2369 case CS5:
2370 msg.lcr |= USA_DATABITS_5;
2371 break;
2372 case CS6:
2373 msg.lcr |= USA_DATABITS_6;
2374 break;
2375 case CS7:
2376 msg.lcr |= USA_DATABITS_7;
2377 break;
2378 case CS8:
2379 msg.lcr |= USA_DATABITS_8;
2380 break;
2381 }
2382 if (p_priv->cflag & PARENB) {
2383 /* note USA_PARITY_NONE == 0 */
2384 msg.lcr |= (p_priv->cflag & PARODD)?
Alan Coxdeb91682008-07-22 11:13:08 +01002385 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386 }
2387 if (p_priv->old_cflag != p_priv->cflag) {
2388 p_priv->old_cflag = p_priv->cflag;
2389 msg.setLcr = 0x01;
2390 }
2391
2392 if (p_priv->flow_control == flow_cts)
2393 msg.txFlowControl = TXFLOW_CTS;
2394 msg.setTxFlowControl = 0x01;
2395 msg.setRxFlowControl = 0x01;
Alan Coxdeb91682008-07-22 11:13:08 +01002396
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397 msg.rxForwardingLength = 16;
Alan Coxdeb91682008-07-22 11:13:08 +01002398 msg.rxForwardingTimeout = 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 msg.txAckSetting = 0;
2400 msg.xonChar = 17;
2401 msg.xoffChar = 19;
2402
Alan Coxdeb91682008-07-22 11:13:08 +01002403 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 if (reset_port == 1) {
2405 msg.portEnabled = 1;
2406 msg.rxFlush = 1;
2407 msg.txBreak = (p_priv->break_on);
2408 }
2409 /* Closing port */
Alan Coxdeb91682008-07-22 11:13:08 +01002410 else if (reset_port == 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411 msg.portEnabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412 /* Sending intermediate configs */
2413 else {
Alan Cox95da3102008-07-22 11:09:07 +01002414 if (port->port.count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415 msg.portEnabled = 1;
2416 msg.txBreak = (p_priv->break_on);
2417 }
2418
Alan Coxdeb91682008-07-22 11:13:08 +01002419 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420 msg.setRts = 0x01;
2421 msg.rts = p_priv->rts_state;
2422
2423 msg.setDtr = 0x01;
2424 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002425
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01002427 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2428
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429 /* send the data out the device on control endpoint */
2430 this_urb->transfer_buffer_length = sizeof(msg);
2431
2432 this_urb->dev = serial->dev;
Alan Coxdeb91682008-07-22 11:13:08 +01002433 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2434 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002435 dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002436 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437}
2438
Lucy McCoy0ca12682007-05-18 12:10:41 -07002439static int keyspan_usa67_send_setup(struct usb_serial *serial,
2440 struct usb_serial_port *port,
2441 int reset_port)
2442{
2443 struct keyspan_usa67_portControlMessage msg;
2444 struct keyspan_serial_private *s_priv;
2445 struct keyspan_port_private *p_priv;
2446 const struct keyspan_device_details *d_details;
2447 struct urb *this_urb;
2448 int err, device_port;
2449
Alan Coxdeb91682008-07-22 11:13:08 +01002450 dbg("%s", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002451
2452 s_priv = usb_get_serial_data(serial);
2453 p_priv = usb_get_serial_port_data(port);
2454 d_details = s_priv->device_details;
2455
2456 this_urb = s_priv->glocont_urb;
2457
2458 /* Work out which port within the device is being setup */
2459 device_port = port->number - port->serial->minor;
2460
2461 /* Make sure we have an urb then send the message */
2462 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002463 dbg("%s - oops no urb for port %d.", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002464 port->number);
2465 return -1;
2466 }
2467
2468 /* Save reset port val for resend.
2469 Don't overwrite resend for open/close condition. */
2470 if ((reset_port + 1) > p_priv->resend_cont)
2471 p_priv->resend_cont = reset_port + 1;
2472 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +01002473 /* dbg("%s - already writing", __func__); */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002474 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002475 return -1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002476 }
2477
2478 memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
2479
2480 msg.port = device_port;
2481
2482 /* Only set baud rate if it's changed */
2483 if (p_priv->old_baud != p_priv->baud) {
2484 p_priv->old_baud = p_priv->baud;
2485 msg.setClocking = 0xff;
2486 if (d_details->calculate_baud_rate
2487 (p_priv->baud, d_details->baudclk, &msg.baudHi,
Alan Coxdeb91682008-07-22 11:13:08 +01002488 &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2489 dbg("%s - Invalid baud rate %d requested, using 9600.",
2490 __func__, p_priv->baud);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002491 msg.baudLo = 0;
2492 msg.baudHi = 125; /* Values for 9600 baud */
2493 msg.prescaler = 10;
2494 }
2495 msg.setPrescaler = 0xff;
2496 }
2497
2498 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
2499 switch (p_priv->cflag & CSIZE) {
2500 case CS5:
2501 msg.lcr |= USA_DATABITS_5;
2502 break;
2503 case CS6:
2504 msg.lcr |= USA_DATABITS_6;
2505 break;
2506 case CS7:
2507 msg.lcr |= USA_DATABITS_7;
2508 break;
2509 case CS8:
2510 msg.lcr |= USA_DATABITS_8;
2511 break;
2512 }
2513 if (p_priv->cflag & PARENB) {
2514 /* note USA_PARITY_NONE == 0 */
2515 msg.lcr |= (p_priv->cflag & PARODD)?
Alan Coxdeb91682008-07-22 11:13:08 +01002516 USA_PARITY_ODD : USA_PARITY_EVEN;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002517 }
2518 msg.setLcr = 0xff;
2519
2520 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2521 msg.xonFlowControl = 0;
2522 msg.setFlowControl = 0xff;
2523 msg.forwardingLength = 16;
2524 msg.xonChar = 17;
2525 msg.xoffChar = 19;
2526
2527 if (reset_port == 1) {
2528 /* Opening port */
2529 msg._txOn = 1;
2530 msg._txOff = 0;
2531 msg.txFlush = 0;
2532 msg.txBreak = 0;
2533 msg.rxOn = 1;
2534 msg.rxOff = 0;
2535 msg.rxFlush = 1;
2536 msg.rxForward = 0;
2537 msg.returnStatus = 0;
2538 msg.resetDataToggle = 0xff;
2539 } else if (reset_port == 2) {
2540 /* Closing port */
2541 msg._txOn = 0;
2542 msg._txOff = 1;
2543 msg.txFlush = 0;
2544 msg.txBreak = 0;
2545 msg.rxOn = 0;
2546 msg.rxOff = 1;
2547 msg.rxFlush = 1;
2548 msg.rxForward = 0;
2549 msg.returnStatus = 0;
2550 msg.resetDataToggle = 0;
2551 } else {
2552 /* Sending intermediate configs */
Alan Coxdeb91682008-07-22 11:13:08 +01002553 msg._txOn = (!p_priv->break_on);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002554 msg._txOff = 0;
2555 msg.txFlush = 0;
2556 msg.txBreak = (p_priv->break_on);
2557 msg.rxOn = 0;
2558 msg.rxOff = 0;
2559 msg.rxFlush = 0;
2560 msg.rxForward = 0;
2561 msg.returnStatus = 0;
2562 msg.resetDataToggle = 0x0;
2563 }
2564
2565 /* Do handshaking outputs */
2566 msg.setTxTriState_setRts = 0xff;
2567 msg.txTriState_rts = p_priv->rts_state;
2568
2569 msg.setHskoa_setDtr = 0xff;
2570 msg.hskoa_dtr = p_priv->dtr_state;
2571
2572 p_priv->resend_cont = 0;
2573
2574 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2575
2576 /* send the data out the device on control endpoint */
2577 this_urb->transfer_buffer_length = sizeof(msg);
2578 this_urb->dev = serial->dev;
2579
2580 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2581 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002582 dbg("%s - usb_submit_urb(setup) failed (%d)", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002583 err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002584 return 0;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002585}
2586
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
2588{
2589 struct usb_serial *serial = port->serial;
2590 struct keyspan_serial_private *s_priv;
2591 const struct keyspan_device_details *d_details;
2592
Alan Coxdeb91682008-07-22 11:13:08 +01002593 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594
2595 s_priv = usb_get_serial_data(serial);
2596 d_details = s_priv->device_details;
2597
2598 switch (d_details->msg_format) {
2599 case msg_usa26:
2600 keyspan_usa26_send_setup(serial, port, reset_port);
2601 break;
2602 case msg_usa28:
2603 keyspan_usa28_send_setup(serial, port, reset_port);
2604 break;
2605 case msg_usa49:
2606 keyspan_usa49_send_setup(serial, port, reset_port);
2607 break;
2608 case msg_usa90:
2609 keyspan_usa90_send_setup(serial, port, reset_port);
2610 break;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002611 case msg_usa67:
2612 keyspan_usa67_send_setup(serial, port, reset_port);
2613 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614 }
2615}
2616
2617
2618/* Gets called by the "real" driver (ie once firmware is loaded
2619 and renumeration has taken place. */
Alan Coxdeb91682008-07-22 11:13:08 +01002620static int keyspan_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621{
2622 int i, err;
2623 struct usb_serial_port *port;
2624 struct keyspan_serial_private *s_priv;
2625 struct keyspan_port_private *p_priv;
2626 const struct keyspan_device_details *d_details;
2627
Harvey Harrison441b62c2008-03-03 16:08:34 -08002628 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629
2630 for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
Alan Coxdeb91682008-07-22 11:13:08 +01002631 if (d_details->product_id ==
2632 le16_to_cpu(serial->dev->descriptor.idProduct))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633 break;
2634 if (d_details == NULL) {
Alan Coxdeb91682008-07-22 11:13:08 +01002635 dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
2636 __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637 return 1;
2638 }
2639
2640 /* Setup private data for serial driver */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01002641 s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642 if (!s_priv) {
Alan Coxdeb91682008-07-22 11:13:08 +01002643 dbg("%s - kmalloc for keyspan_serial_private failed.",
2644 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645 return -ENOMEM;
2646 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647
2648 s_priv->device_details = d_details;
2649 usb_set_serial_data(serial, s_priv);
2650
2651 /* Now setup per port private data */
2652 for (i = 0; i < serial->num_ports; i++) {
2653 port = serial->port[i];
Alan Coxdeb91682008-07-22 11:13:08 +01002654 p_priv = kzalloc(sizeof(struct keyspan_port_private),
2655 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656 if (!p_priv) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002657 dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __func__, i);
Alan Coxdeb91682008-07-22 11:13:08 +01002658 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660 p_priv->device_details = d_details;
2661 usb_set_serial_port_data(port, p_priv);
2662 }
2663
2664 keyspan_setup_urbs(serial);
2665
Lucy McCoy0ca12682007-05-18 12:10:41 -07002666 if (s_priv->instat_urb != NULL) {
2667 s_priv->instat_urb->dev = serial->dev;
2668 err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
2669 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002670 dbg("%s - submit instat urb failed %d", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002671 err);
2672 }
2673 if (s_priv->indat_urb != NULL) {
2674 s_priv->indat_urb->dev = serial->dev;
2675 err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
2676 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002677 dbg("%s - submit indat urb failed %d", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002678 err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679 }
Alan Coxdeb91682008-07-22 11:13:08 +01002680
Alan Coxa5b6f602008-04-08 17:16:06 +01002681 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682}
2683
Alan Coxdeb91682008-07-22 11:13:08 +01002684static void keyspan_shutdown(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685{
2686 int i, j;
2687 struct usb_serial_port *port;
2688 struct keyspan_serial_private *s_priv;
2689 struct keyspan_port_private *p_priv;
2690
Harvey Harrison441b62c2008-03-03 16:08:34 -08002691 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002692
2693 s_priv = usb_get_serial_data(serial);
2694
2695 /* Stop reading/writing urbs */
2696 stop_urb(s_priv->instat_urb);
2697 stop_urb(s_priv->glocont_urb);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002698 stop_urb(s_priv->indat_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699 for (i = 0; i < serial->num_ports; ++i) {
2700 port = serial->port[i];
2701 p_priv = usb_get_serial_port_data(port);
2702 stop_urb(p_priv->inack_urb);
2703 stop_urb(p_priv->outcont_urb);
2704 for (j = 0; j < 2; j++) {
2705 stop_urb(p_priv->in_urbs[j]);
2706 stop_urb(p_priv->out_urbs[j]);
2707 }
2708 }
2709
2710 /* Now free them */
Mariusz Kozlowski1cadc132006-11-08 15:36:34 +01002711 usb_free_urb(s_priv->instat_urb);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002712 usb_free_urb(s_priv->indat_urb);
Mariusz Kozlowski1cadc132006-11-08 15:36:34 +01002713 usb_free_urb(s_priv->glocont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714 for (i = 0; i < serial->num_ports; ++i) {
2715 port = serial->port[i];
2716 p_priv = usb_get_serial_port_data(port);
Mariusz Kozlowski1cadc132006-11-08 15:36:34 +01002717 usb_free_urb(p_priv->inack_urb);
2718 usb_free_urb(p_priv->outcont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719 for (j = 0; j < 2; j++) {
Mariusz Kozlowski1cadc132006-11-08 15:36:34 +01002720 usb_free_urb(p_priv->in_urbs[j]);
2721 usb_free_urb(p_priv->out_urbs[j]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722 }
2723 }
2724
2725 /* dbg("Freeing serial->private."); */
2726 kfree(s_priv);
2727
2728 /* dbg("Freeing port->private."); */
2729 /* Now free per port private data */
2730 for (i = 0; i < serial->num_ports; i++) {
2731 port = serial->port[i];
2732 kfree(usb_get_serial_port_data(port));
2733 }
2734}
2735
Alan Coxdeb91682008-07-22 11:13:08 +01002736MODULE_AUTHOR(DRIVER_AUTHOR);
2737MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738MODULE_LICENSE("GPL");
2739
David Woodhouse2971c572008-05-30 14:04:03 +03002740MODULE_FIRMWARE("keyspan/usa28.fw");
2741MODULE_FIRMWARE("keyspan/usa28x.fw");
2742MODULE_FIRMWARE("keyspan/usa28xa.fw");
2743MODULE_FIRMWARE("keyspan/usa28xb.fw");
2744MODULE_FIRMWARE("keyspan/usa19.fw");
2745MODULE_FIRMWARE("keyspan/usa19qi.fw");
2746MODULE_FIRMWARE("keyspan/mpr.fw");
2747MODULE_FIRMWARE("keyspan/usa19qw.fw");
2748MODULE_FIRMWARE("keyspan/usa18x.fw");
2749MODULE_FIRMWARE("keyspan/usa19w.fw");
2750MODULE_FIRMWARE("keyspan/usa49w.fw");
2751MODULE_FIRMWARE("keyspan/usa49wlc.fw");
2752
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753module_param(debug, bool, S_IRUGO | S_IWUSR);
2754MODULE_PARM_DESC(debug, "Debug enabled or not");
2755