blob: 4cc36c76180126f80a9d81e23759318971873599 [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
Justin P. Mattock631dd1a2010-10-18 11:03:14 +020012 See http://blemings.org/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.
Linus Torvalds1da177e2005-04-16 15:20:36 -070028*/
29
30
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/kernel.h>
32#include <linux/jiffies.h>
33#include <linux/errno.h>
34#include <linux/init.h>
35#include <linux/slab.h>
36#include <linux/tty.h>
37#include <linux/tty_driver.h>
38#include <linux/tty_flip.h>
39#include <linux/module.h>
40#include <linux/spinlock.h>
David Woodhouse2971c572008-05-30 14:04:03 +030041#include <linux/firmware.h>
42#include <linux/ihex.h>
Alan Coxdeb91682008-07-22 11:13:08 +010043#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <linux/usb.h>
Greg Kroah-Hartmana9698882006-07-11 21:22:58 -070045#include <linux/usb/serial.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070046#include "keyspan.h"
47
Rusty Russell90ab5ee2012-01-13 09:32:20 +103048static bool debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
50/*
51 * Version Information
52 */
Lucy McCoy0ca12682007-05-18 12:10:41 -070053#define DRIVER_VERSION "v1.1.5"
Linus Torvalds1da177e2005-04-16 15:20:36 -070054#define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu"
55#define DRIVER_DESC "Keyspan USB to Serial Converter Driver"
56
57#define INSTAT_BUFLEN 32
58#define GLOCONT_BUFLEN 64
Lucy McCoy0ca12682007-05-18 12:10:41 -070059#define INDAT49W_BUFLEN 512
Linus Torvalds1da177e2005-04-16 15:20:36 -070060
61 /* Per device and per port private data */
62struct keyspan_serial_private {
63 const struct keyspan_device_details *device_details;
64
65 struct urb *instat_urb;
66 char instat_buf[INSTAT_BUFLEN];
67
Alan Coxdeb91682008-07-22 11:13:08 +010068 /* added to support 49wg, where data from all 4 ports comes in
69 on 1 EP and high-speed supported */
Lucy McCoy0ca12682007-05-18 12:10:41 -070070 struct urb *indat_urb;
71 char indat_buf[INDAT49W_BUFLEN];
72
Linus Torvalds1da177e2005-04-16 15:20:36 -070073 /* XXX this one probably will need a lock */
74 struct urb *glocont_urb;
75 char glocont_buf[GLOCONT_BUFLEN];
Alan Coxdeb91682008-07-22 11:13:08 +010076 char ctrl_buf[8]; /* for EP0 control message */
Linus Torvalds1da177e2005-04-16 15:20:36 -070077};
78
79struct keyspan_port_private {
80 /* Keep track of which input & output endpoints to use */
81 int in_flip;
82 int out_flip;
83
84 /* Keep duplicate of device details in each port
85 structure as well - simplifies some of the
86 callback functions etc. */
87 const struct keyspan_device_details *device_details;
88
89 /* Input endpoints and buffer for this port */
90 struct urb *in_urbs[2];
91 char in_buffer[2][64];
92 /* Output endpoints and buffer for this port */
93 struct urb *out_urbs[2];
94 char out_buffer[2][64];
95
96 /* Input ack endpoint */
97 struct urb *inack_urb;
98 char inack_buffer[1];
99
100 /* Output control endpoint */
101 struct urb *outcont_urb;
102 char outcont_buffer[64];
103
104 /* Settings for the port */
105 int baud;
106 int old_baud;
107 unsigned int cflag;
108 unsigned int old_cflag;
109 enum {flow_none, flow_cts, flow_xon} flow_control;
110 int rts_state; /* Handshaking pins (outputs) */
111 int dtr_state;
112 int cts_state; /* Handshaking pins (inputs) */
113 int dsr_state;
114 int dcd_state;
115 int ri_state;
116 int break_on;
117
118 unsigned long tx_start_time[2];
119 int resend_cont; /* need to resend control packet */
120};
121
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122/* Include Keyspan message headers. All current Keyspan Adapters
Lucy McCoy0ca12682007-05-18 12:10:41 -0700123 make use of one of five message formats which are referred
Alan Coxdeb91682008-07-22 11:13:08 +0100124 to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and
125 within this driver. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126#include "keyspan_usa26msg.h"
127#include "keyspan_usa28msg.h"
128#include "keyspan_usa49msg.h"
129#include "keyspan_usa90msg.h"
Lucy McCoy0ca12682007-05-18 12:10:41 -0700130#include "keyspan_usa67msg.h"
Alan Coxdeb91682008-07-22 11:13:08 +0100131
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
133/* Functions used by new usb-serial code. */
Alan Coxdeb91682008-07-22 11:13:08 +0100134static int __init keyspan_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135{
136 int retval;
137 retval = usb_serial_register(&keyspan_pre_device);
138 if (retval)
139 goto failed_pre_device_register;
140 retval = usb_serial_register(&keyspan_1port_device);
141 if (retval)
142 goto failed_1port_device_register;
143 retval = usb_serial_register(&keyspan_2port_device);
144 if (retval)
145 goto failed_2port_device_register;
146 retval = usb_serial_register(&keyspan_4port_device);
147 if (retval)
148 goto failed_4port_device_register;
149 retval = usb_register(&keyspan_driver);
Alan Coxdeb91682008-07-22 11:13:08 +0100150 if (retval)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 goto failed_usb_register;
152
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -0700153 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
154 DRIVER_DESC "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155
156 return 0;
157failed_usb_register:
158 usb_serial_deregister(&keyspan_4port_device);
159failed_4port_device_register:
160 usb_serial_deregister(&keyspan_2port_device);
161failed_2port_device_register:
162 usb_serial_deregister(&keyspan_1port_device);
163failed_1port_device_register:
164 usb_serial_deregister(&keyspan_pre_device);
165failed_pre_device_register:
166 return retval;
167}
168
Alan Coxdeb91682008-07-22 11:13:08 +0100169static void __exit keyspan_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170{
Alan Coxdeb91682008-07-22 11:13:08 +0100171 usb_deregister(&keyspan_driver);
172 usb_serial_deregister(&keyspan_pre_device);
173 usb_serial_deregister(&keyspan_1port_device);
174 usb_serial_deregister(&keyspan_2port_device);
175 usb_serial_deregister(&keyspan_4port_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176}
177
178module_init(keyspan_init);
179module_exit(keyspan_exit);
180
Alan Cox95da3102008-07-22 11:09:07 +0100181static void keyspan_break_ctl(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182{
Alan Cox95da3102008-07-22 11:09:07 +0100183 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 struct keyspan_port_private *p_priv;
185
Alan Coxdeb91682008-07-22 11:13:08 +0100186 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187
188 p_priv = usb_get_serial_port_data(port);
189
190 if (break_state == -1)
191 p_priv->break_on = 1;
192 else
193 p_priv->break_on = 0;
194
195 keyspan_send_setup(port, 0);
196}
197
198
Alan Coxdeb91682008-07-22 11:13:08 +0100199static void keyspan_set_termios(struct tty_struct *tty,
Alan Cox95da3102008-07-22 11:09:07 +0100200 struct usb_serial_port *port, struct ktermios *old_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201{
202 int baud_rate, device_port;
203 struct keyspan_port_private *p_priv;
204 const struct keyspan_device_details *d_details;
205 unsigned int cflag;
206
Harvey Harrison441b62c2008-03-03 16:08:34 -0800207 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208
209 p_priv = usb_get_serial_port_data(port);
210 d_details = p_priv->device_details;
Alan Cox74240b02007-10-18 01:24:20 -0700211 cflag = tty->termios->c_cflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 device_port = port->number - port->serial->minor;
213
214 /* Baud rate calculation takes baud rate as an integer
215 so other rates can be generated if desired. */
Alan Cox74240b02007-10-18 01:24:20 -0700216 baud_rate = tty_get_baud_rate(tty);
Alan Coxdeb91682008-07-22 11:13:08 +0100217 /* If no match or invalid, don't change */
Alan Cox74240b02007-10-18 01:24:20 -0700218 if (d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
220 /* FIXME - more to do here to ensure rate changes cleanly */
Alan Cox74240b02007-10-18 01:24:20 -0700221 /* FIXME - calcuate exact rate from divisor ? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 p_priv->baud = baud_rate;
Alan Cox74240b02007-10-18 01:24:20 -0700223 } else
224 baud_rate = tty_termios_baud_rate(old_termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225
Alan Cox74240b02007-10-18 01:24:20 -0700226 tty_encode_baud_rate(tty, baud_rate, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 /* set CTS/RTS handshake etc. */
228 p_priv->cflag = cflag;
229 p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none;
230
Alan Cox74240b02007-10-18 01:24:20 -0700231 /* Mark/Space not supported */
232 tty->termios->c_cflag &= ~CMSPAR;
233
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 keyspan_send_setup(port, 0);
235}
236
Alan Cox60b33c12011-02-14 16:26:14 +0000237static int keyspan_tiocmget(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238{
Alan Cox95da3102008-07-22 11:09:07 +0100239 struct usb_serial_port *port = tty->driver_data;
240 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 unsigned int value;
Alan Coxdeb91682008-07-22 11:13:08 +0100242
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 value = ((p_priv->rts_state) ? TIOCM_RTS : 0) |
244 ((p_priv->dtr_state) ? TIOCM_DTR : 0) |
245 ((p_priv->cts_state) ? TIOCM_CTS : 0) |
246 ((p_priv->dsr_state) ? TIOCM_DSR : 0) |
247 ((p_priv->dcd_state) ? TIOCM_CAR : 0) |
Alan Coxdeb91682008-07-22 11:13:08 +0100248 ((p_priv->ri_state) ? TIOCM_RNG : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249
250 return value;
251}
252
Alan Cox20b9d172011-02-14 16:26:50 +0000253static int keyspan_tiocmset(struct tty_struct *tty,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 unsigned int set, unsigned int clear)
255{
Alan Cox95da3102008-07-22 11:09:07 +0100256 struct usb_serial_port *port = tty->driver_data;
257 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100258
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 if (set & TIOCM_RTS)
260 p_priv->rts_state = 1;
261 if (set & TIOCM_DTR)
262 p_priv->dtr_state = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 if (clear & TIOCM_RTS)
264 p_priv->rts_state = 0;
265 if (clear & TIOCM_DTR)
266 p_priv->dtr_state = 0;
267 keyspan_send_setup(port, 0);
268 return 0;
269}
270
Alan Cox95da3102008-07-22 11:09:07 +0100271/* Write function is similar for the four protocols used
272 with only a minor change for usa90 (usa19hs) required */
273static int keyspan_write(struct tty_struct *tty,
274 struct usb_serial_port *port, const unsigned char *buf, int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275{
276 struct keyspan_port_private *p_priv;
277 const struct keyspan_device_details *d_details;
278 int flip;
279 int left, todo;
280 struct urb *this_urb;
Alan Coxdeb91682008-07-22 11:13:08 +0100281 int err, maxDataLen, dataOffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282
283 p_priv = usb_get_serial_port_data(port);
284 d_details = p_priv->device_details;
285
286 if (d_details->msg_format == msg_usa90) {
Alan Coxdeb91682008-07-22 11:13:08 +0100287 maxDataLen = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 dataOffset = 0;
289 } else {
290 maxDataLen = 63;
291 dataOffset = 1;
292 }
Alan Coxdeb91682008-07-22 11:13:08 +0100293
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 dbg("%s - for port %d (%d chars), flip=%d",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800295 __func__, port->number, count, p_priv->out_flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296
297 for (left = count; left > 0; left -= todo) {
298 todo = left;
299 if (todo > maxDataLen)
300 todo = maxDataLen;
301
302 flip = p_priv->out_flip;
Alan Coxdeb91682008-07-22 11:13:08 +0100303
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 /* Check we have a valid urb/endpoint before we use it... */
Alan Coxdeb91682008-07-22 11:13:08 +0100305 this_urb = p_priv->out_urbs[flip];
306 if (this_urb == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 /* no bulk out, so return 0 bytes written */
Harvey Harrison441b62c2008-03-03 16:08:34 -0800308 dbg("%s - no output urb :(", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 return count;
310 }
311
Alan Coxdeb91682008-07-22 11:13:08 +0100312 dbg("%s - endpoint %d flip %d",
313 __func__, usb_pipeendpoint(this_urb->pipe), flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314
315 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +0100316 if (time_before(jiffies,
317 p_priv->tx_start_time[flip] + 10 * HZ))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 usb_unlink_urb(this_urb);
320 break;
321 }
322
Alan Coxdeb91682008-07-22 11:13:08 +0100323 /* First byte in buffer is "last flag" (except for usa19hx)
324 - unused so for now so set to zero */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 ((char *)this_urb->transfer_buffer)[0] = 0;
326
Alan Coxdeb91682008-07-22 11:13:08 +0100327 memcpy(this_urb->transfer_buffer + dataOffset, buf, todo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 buf += todo;
329
330 /* send the data out the bulk port */
331 this_urb->transfer_buffer_length = todo + dataOffset;
332
Alan Coxdeb91682008-07-22 11:13:08 +0100333 err = usb_submit_urb(this_urb, GFP_ATOMIC);
334 if (err != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 dbg("usb_submit_urb(write bulk) failed (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 p_priv->tx_start_time[flip] = jiffies;
337
338 /* Flip for next time if usa26 or usa28 interface
339 (not used on usa49) */
340 p_priv->out_flip = (flip + 1) & d_details->outdat_endp_flip;
341 }
342
343 return count - left;
344}
345
David Howells7d12e782006-10-05 14:55:46 +0100346static void usa26_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347{
348 int i, err;
349 int endpoint;
350 struct usb_serial_port *port;
351 struct tty_struct *tty;
352 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700353 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354
Alan Coxdeb91682008-07-22 11:13:08 +0100355 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356
357 endpoint = usb_pipeendpoint(urb->pipe);
358
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700359 if (status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 dbg("%s - nonzero status: %x on endpoint %d.",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800361 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 return;
363 }
364
Ming Leicdc97792008-02-24 18:41:47 +0800365 port = urb->context;
Alan Cox4a90f092008-10-13 10:39:46 +0100366 tty = tty_port_tty_get(&port->port);
Alan Coxa5569a52008-01-21 17:18:24 -0800367 if (tty && urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 /* 0x80 bit is error flag */
369 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100370 /* no errors on individual bytes, only
371 possible overrun err */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 if (data[0] & RXERROR_OVERRUN)
Alan Coxdeb91682008-07-22 11:13:08 +0100373 err = TTY_OVERRUN;
374 else
375 err = 0;
376 for (i = 1; i < urb->actual_length ; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 tty_insert_flip_char(tty, data[i], err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 } else {
379 /* some bytes had errors, every byte has status */
Harvey Harrison441b62c2008-03-03 16:08:34 -0800380 dbg("%s - RX error!!!!", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 for (i = 0; i + 1 < urb->actual_length; i += 2) {
382 int stat = data[i], flag = 0;
383 if (stat & RXERROR_OVERRUN)
384 flag |= TTY_OVERRUN;
385 if (stat & RXERROR_FRAMING)
386 flag |= TTY_FRAME;
387 if (stat & RXERROR_PARITY)
388 flag |= TTY_PARITY;
389 /* XXX should handle break (0x10) */
390 tty_insert_flip_char(tty, data[i+1], flag);
391 }
392 }
393 tty_flip_buffer_push(tty);
394 }
Alan Cox4a90f092008-10-13 10:39:46 +0100395 tty_kref_put(tty);
Alan Coxdeb91682008-07-22 11:13:08 +0100396
397 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500398 err = usb_submit_urb(urb, GFP_ATOMIC);
399 if (err != 0)
400 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401}
402
Alan Coxdeb91682008-07-22 11:13:08 +0100403/* Outdat handling is common for all devices */
David Howells7d12e782006-10-05 14:55:46 +0100404static void usa2x_outdat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405{
406 struct usb_serial_port *port;
407 struct keyspan_port_private *p_priv;
408
Ming Leicdc97792008-02-24 18:41:47 +0800409 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100411 dbg("%s - urb %d", __func__, urb == p_priv->out_urbs[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412
Alan Stern1f871582010-02-17 10:05:47 -0500413 usb_serial_port_softint(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414}
415
David Howells7d12e782006-10-05 14:55:46 +0100416static void usa26_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417{
Alan Coxdeb91682008-07-22 11:13:08 +0100418 dbg("%s", __func__);
419
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420}
421
David Howells7d12e782006-10-05 14:55:46 +0100422static void usa26_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423{
424 struct usb_serial_port *port;
425 struct keyspan_port_private *p_priv;
426
Ming Leicdc97792008-02-24 18:41:47 +0800427 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 p_priv = usb_get_serial_port_data(port);
429
430 if (p_priv->resend_cont) {
Alan Coxdeb91682008-07-22 11:13:08 +0100431 dbg("%s - sending setup", __func__);
432 keyspan_usa26_send_setup(port->serial, port,
433 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 }
435}
436
David Howells7d12e782006-10-05 14:55:46 +0100437static void usa26_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438{
439 unsigned char *data = urb->transfer_buffer;
440 struct keyspan_usa26_portStatusMessage *msg;
441 struct usb_serial *serial;
442 struct usb_serial_port *port;
443 struct keyspan_port_private *p_priv;
Alan Cox4a90f092008-10-13 10:39:46 +0100444 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700446 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447
Ming Leicdc97792008-02-24 18:41:47 +0800448 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700450 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800451 dbg("%s - nonzero status: %x", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 return;
453 }
454 if (urb->actual_length != 9) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800455 dbg("%s - %d byte report??", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 goto exit;
457 }
458
459 msg = (struct keyspan_usa26_portStatusMessage *)data;
460
461#if 0
462 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 -0800463 __func__, msg->port, msg->hskia_cts, msg->gpia_dcd, msg->dsr, msg->ri, msg->_txOff,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 msg->_txXoff, msg->rxEnabled, msg->controlResponse);
465#endif
466
467 /* Now do something useful with the data */
468
469
Alan Coxdeb91682008-07-22 11:13:08 +0100470 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 if (msg->port >= serial->num_ports) {
Alan Coxdeb91682008-07-22 11:13:08 +0100472 dbg("%s - Unexpected port number %d", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 goto exit;
474 }
475 port = serial->port[msg->port];
476 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100477
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 /* Update handshaking pin state information */
479 old_dcd_state = p_priv->dcd_state;
480 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
481 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
482 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
483 p_priv->ri_state = ((msg->ri) ? 1 : 0);
484
Alan Cox4a90f092008-10-13 10:39:46 +0100485 if (old_dcd_state != p_priv->dcd_state) {
486 tty = tty_port_tty_get(&port->port);
487 if (tty && !C_CLOCAL(tty))
488 tty_hangup(tty);
489 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 }
Alan Coxdeb91682008-07-22 11:13:08 +0100491
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100493 err = usb_submit_urb(urb, GFP_ATOMIC);
494 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800495 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496exit: ;
497}
498
David Howells7d12e782006-10-05 14:55:46 +0100499static void usa26_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500{
Alan Coxdeb91682008-07-22 11:13:08 +0100501 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502}
503
504
David Howells7d12e782006-10-05 14:55:46 +0100505static void usa28_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506{
Alan Coxf035a8a2008-07-22 11:13:32 +0100507 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 struct usb_serial_port *port;
509 struct tty_struct *tty;
510 unsigned char *data;
511 struct keyspan_port_private *p_priv;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700512 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513
Alan Coxdeb91682008-07-22 11:13:08 +0100514 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515
Ming Leicdc97792008-02-24 18:41:47 +0800516 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 p_priv = usb_get_serial_port_data(port);
518 data = urb->transfer_buffer;
519
520 if (urb != p_priv->in_urbs[p_priv->in_flip])
521 return;
522
523 do {
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700524 if (status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 dbg("%s - nonzero status: %x on endpoint %d.",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800526 __func__, status, usb_pipeendpoint(urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 return;
528 }
529
Ming Leicdc97792008-02-24 18:41:47 +0800530 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 p_priv = usb_get_serial_port_data(port);
532 data = urb->transfer_buffer;
533
Alan Cox4a90f092008-10-13 10:39:46 +0100534 tty =tty_port_tty_get(&port->port);
535 if (tty && urb->actual_length) {
Alan Coxf035a8a2008-07-22 11:13:32 +0100536 tty_insert_flip_string(tty, data, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 tty_flip_buffer_push(tty);
538 }
Alan Cox4a90f092008-10-13 10:39:46 +0100539 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540
541 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500542 err = usb_submit_urb(urb, GFP_ATOMIC);
543 if (err != 0)
544 dbg("%s - resubmit read urb failed. (%d)",
545 __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 p_priv->in_flip ^= 1;
547
548 urb = p_priv->in_urbs[p_priv->in_flip];
549 } while (urb->status != -EINPROGRESS);
550}
551
David Howells7d12e782006-10-05 14:55:46 +0100552static void usa28_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553{
Alan Coxdeb91682008-07-22 11:13:08 +0100554 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555}
556
David Howells7d12e782006-10-05 14:55:46 +0100557static void usa28_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558{
559 struct usb_serial_port *port;
560 struct keyspan_port_private *p_priv;
561
Ming Leicdc97792008-02-24 18:41:47 +0800562 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 p_priv = usb_get_serial_port_data(port);
564
565 if (p_priv->resend_cont) {
Alan Coxdeb91682008-07-22 11:13:08 +0100566 dbg("%s - sending setup", __func__);
567 keyspan_usa28_send_setup(port->serial, port,
568 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 }
570}
571
David Howells7d12e782006-10-05 14:55:46 +0100572static void usa28_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573{
574 int err;
575 unsigned char *data = urb->transfer_buffer;
576 struct keyspan_usa28_portStatusMessage *msg;
577 struct usb_serial *serial;
578 struct usb_serial_port *port;
579 struct keyspan_port_private *p_priv;
Alan Cox4a90f092008-10-13 10:39:46 +0100580 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700582 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583
Ming Leicdc97792008-02-24 18:41:47 +0800584 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700586 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800587 dbg("%s - nonzero status: %x", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 return;
589 }
590
591 if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800592 dbg("%s - bad length %d", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593 goto exit;
594 }
595
Harvey Harrison441b62c2008-03-03 16:08:34 -0800596 /*dbg("%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 data[0], data[1], data[2], data[3], data[4], data[5],
598 data[6], data[7], data[8], data[9], data[10], data[11]);*/
Alan Coxdeb91682008-07-22 11:13:08 +0100599
600 /* Now do something useful with the data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 msg = (struct keyspan_usa28_portStatusMessage *)data;
602
Alan Coxdeb91682008-07-22 11:13:08 +0100603 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 if (msg->port >= serial->num_ports) {
Alan Coxdeb91682008-07-22 11:13:08 +0100605 dbg("%s - Unexpected port number %d", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 goto exit;
607 }
608 port = serial->port[msg->port];
609 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100610
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 /* Update handshaking pin state information */
612 old_dcd_state = p_priv->dcd_state;
613 p_priv->cts_state = ((msg->cts) ? 1 : 0);
614 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
615 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
616 p_priv->ri_state = ((msg->ri) ? 1 : 0);
617
Alan Cox4a90f092008-10-13 10:39:46 +0100618 if( old_dcd_state != p_priv->dcd_state && old_dcd_state) {
619 tty = tty_port_tty_get(&port->port);
620 if (tty && !C_CLOCAL(tty))
621 tty_hangup(tty);
622 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 }
624
625 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100626 err = usb_submit_urb(urb, GFP_ATOMIC);
627 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800628 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629exit: ;
630}
631
David Howells7d12e782006-10-05 14:55:46 +0100632static void usa28_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633{
Alan Coxdeb91682008-07-22 11:13:08 +0100634 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635}
636
637
David Howells7d12e782006-10-05 14:55:46 +0100638static void usa49_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639{
640 struct usb_serial *serial;
641 struct usb_serial_port *port;
642 struct keyspan_port_private *p_priv;
643 int i;
644
Alan Coxdeb91682008-07-22 11:13:08 +0100645 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646
Ming Leicdc97792008-02-24 18:41:47 +0800647 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 for (i = 0; i < serial->num_ports; ++i) {
649 port = serial->port[i];
650 p_priv = usb_get_serial_port_data(port);
651
652 if (p_priv->resend_cont) {
Alan Coxdeb91682008-07-22 11:13:08 +0100653 dbg("%s - sending setup", __func__);
654 keyspan_usa49_send_setup(serial, port,
655 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 break;
657 }
658 }
659}
660
661 /* This is actually called glostat in the Keyspan
662 doco */
David Howells7d12e782006-10-05 14:55:46 +0100663static void usa49_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664{
665 int err;
666 unsigned char *data = urb->transfer_buffer;
667 struct keyspan_usa49_portStatusMessage *msg;
668 struct usb_serial *serial;
669 struct usb_serial_port *port;
670 struct keyspan_port_private *p_priv;
671 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700672 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673
Alan Coxdeb91682008-07-22 11:13:08 +0100674 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675
Ming Leicdc97792008-02-24 18:41:47 +0800676 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700678 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800679 dbg("%s - nonzero status: %x", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 return;
681 }
682
Alan Coxdeb91682008-07-22 11:13:08 +0100683 if (urb->actual_length !=
684 sizeof(struct keyspan_usa49_portStatusMessage)) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800685 dbg("%s - bad length %d", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 goto exit;
687 }
688
Harvey Harrison441b62c2008-03-03 16:08:34 -0800689 /*dbg(" %x %x %x %x %x %x %x %x %x %x %x", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 data[0], data[1], data[2], data[3], data[4], data[5],
691 data[6], data[7], data[8], data[9], data[10]);*/
Alan Coxdeb91682008-07-22 11:13:08 +0100692
693 /* Now do something useful with the data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 msg = (struct keyspan_usa49_portStatusMessage *)data;
695
Alan Coxdeb91682008-07-22 11:13:08 +0100696 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 if (msg->portNumber >= serial->num_ports) {
Alan Coxdeb91682008-07-22 11:13:08 +0100698 dbg("%s - Unexpected port number %d",
699 __func__, msg->portNumber);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 goto exit;
701 }
702 port = serial->port[msg->portNumber];
703 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100704
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 /* Update handshaking pin state information */
706 old_dcd_state = p_priv->dcd_state;
707 p_priv->cts_state = ((msg->cts) ? 1 : 0);
708 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
709 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
710 p_priv->ri_state = ((msg->ri) ? 1 : 0);
711
Alan Cox4a90f092008-10-13 10:39:46 +0100712 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
713 struct tty_struct *tty = tty_port_tty_get(&port->port);
714 if (tty && !C_CLOCAL(tty))
715 tty_hangup(tty);
716 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 }
718
Alan Coxdeb91682008-07-22 11:13:08 +0100719 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100720 err = usb_submit_urb(urb, GFP_ATOMIC);
721 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800722 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723exit: ;
724}
725
David Howells7d12e782006-10-05 14:55:46 +0100726static void usa49_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727{
Alan Coxdeb91682008-07-22 11:13:08 +0100728 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729}
730
David Howells7d12e782006-10-05 14:55:46 +0100731static void usa49_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732{
733 int i, err;
734 int endpoint;
735 struct usb_serial_port *port;
736 struct tty_struct *tty;
737 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700738 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739
Alan Coxdeb91682008-07-22 11:13:08 +0100740 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741
742 endpoint = usb_pipeendpoint(urb->pipe);
743
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700744 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800745 dbg("%s - nonzero status: %x on endpoint %d.", __func__,
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700746 status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747 return;
748 }
749
Ming Leicdc97792008-02-24 18:41:47 +0800750 port = urb->context;
Alan Cox4a90f092008-10-13 10:39:46 +0100751 tty = tty_port_tty_get(&port->port);
Alan Cox3004e532008-01-03 16:59:04 +0000752 if (tty && urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 /* 0x80 bit is error flag */
754 if ((data[0] & 0x80) == 0) {
755 /* no error on any byte */
Alan Coxf035a8a2008-07-22 11:13:32 +0100756 tty_insert_flip_string(tty, data + 1,
757 urb->actual_length - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 } else {
759 /* some bytes had errors, every byte has status */
760 for (i = 0; i + 1 < urb->actual_length; i += 2) {
761 int stat = data[i], flag = 0;
762 if (stat & RXERROR_OVERRUN)
763 flag |= TTY_OVERRUN;
764 if (stat & RXERROR_FRAMING)
765 flag |= TTY_FRAME;
766 if (stat & RXERROR_PARITY)
767 flag |= TTY_PARITY;
768 /* XXX should handle break (0x10) */
769 tty_insert_flip_char(tty, data[i+1], flag);
770 }
771 }
772 tty_flip_buffer_push(tty);
773 }
Alan Cox4a90f092008-10-13 10:39:46 +0100774 tty_kref_put(tty);
Alan Coxdeb91682008-07-22 11:13:08 +0100775
776 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500777 err = usb_submit_urb(urb, GFP_ATOMIC);
778 if (err != 0)
779 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780}
781
Lucy McCoy0ca12682007-05-18 12:10:41 -0700782static void usa49wg_indat_callback(struct urb *urb)
783{
784 int i, len, x, err;
785 struct usb_serial *serial;
786 struct usb_serial_port *port;
787 struct tty_struct *tty;
788 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700789 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700790
Alan Coxdeb91682008-07-22 11:13:08 +0100791 dbg("%s", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700792
793 serial = urb->context;
794
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700795 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800796 dbg("%s - nonzero status: %x", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700797 return;
798 }
799
800 /* inbound data is in the form P#, len, status, data */
801 i = 0;
802 len = 0;
803
804 if (urb->actual_length) {
805 while (i < urb->actual_length) {
806
807 /* Check port number from message*/
808 if (data[i] >= serial->num_ports) {
Alan Coxdeb91682008-07-22 11:13:08 +0100809 dbg("%s - Unexpected port number %d",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800810 __func__, data[i]);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700811 return;
812 }
813 port = serial->port[data[i++]];
Alan Cox4a90f092008-10-13 10:39:46 +0100814 tty = tty_port_tty_get(&port->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700815 len = data[i++];
816
817 /* 0x80 bit is error flag */
818 if ((data[i] & 0x80) == 0) {
819 /* no error on any byte */
820 i++;
821 for (x = 1; x < len ; ++x)
Alan Stern1f871582010-02-17 10:05:47 -0500822 tty_insert_flip_char(tty, data[i++], 0);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700823 } else {
824 /*
825 * some bytes had errors, every byte has status
826 */
827 for (x = 0; x + 1 < len; x += 2) {
828 int stat = data[i], flag = 0;
829 if (stat & RXERROR_OVERRUN)
830 flag |= TTY_OVERRUN;
831 if (stat & RXERROR_FRAMING)
832 flag |= TTY_FRAME;
833 if (stat & RXERROR_PARITY)
834 flag |= TTY_PARITY;
835 /* XXX should handle break (0x10) */
Alan Stern1f871582010-02-17 10:05:47 -0500836 tty_insert_flip_char(tty,
Lucy McCoy0ca12682007-05-18 12:10:41 -0700837 data[i+1], flag);
838 i += 2;
839 }
840 }
Alan Stern1f871582010-02-17 10:05:47 -0500841 tty_flip_buffer_push(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100842 tty_kref_put(tty);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700843 }
844 }
845
846 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700847 err = usb_submit_urb(urb, GFP_ATOMIC);
848 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800849 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700850}
851
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852/* not used, usa-49 doesn't have per-port control endpoints */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700853static void usa49_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854{
Alan Coxdeb91682008-07-22 11:13:08 +0100855 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856}
857
Lucy McCoy0ca12682007-05-18 12:10:41 -0700858static void usa90_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859{
860 int i, err;
861 int endpoint;
862 struct usb_serial_port *port;
863 struct keyspan_port_private *p_priv;
864 struct tty_struct *tty;
865 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700866 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867
Alan Coxdeb91682008-07-22 11:13:08 +0100868 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869
870 endpoint = usb_pipeendpoint(urb->pipe);
871
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700872 if (status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 dbg("%s - nonzero status: %x on endpoint %d.",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800874 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 return;
876 }
877
Ming Leicdc97792008-02-24 18:41:47 +0800878 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 p_priv = usb_get_serial_port_data(port);
880
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 if (urb->actual_length) {
Alan Cox4a90f092008-10-13 10:39:46 +0100882 tty = tty_port_tty_get(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 /* if current mode is DMA, looks like usa28 format
Alan Coxdeb91682008-07-22 11:13:08 +0100884 otherwise looks like usa26 data format */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885
Alan Coxf035a8a2008-07-22 11:13:32 +0100886 if (p_priv->baud > 57600)
887 tty_insert_flip_string(tty, data, urb->actual_length);
888 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 /* 0x80 bit is error flag */
890 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100891 /* no errors on individual bytes, only
892 possible overrun err*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 if (data[0] & RXERROR_OVERRUN)
Alan Coxdeb91682008-07-22 11:13:08 +0100894 err = TTY_OVERRUN;
895 else
896 err = 0;
897 for (i = 1; i < urb->actual_length ; ++i)
898 tty_insert_flip_char(tty, data[i],
899 err);
900 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 /* some bytes had errors, every byte has status */
Harvey Harrison441b62c2008-03-03 16:08:34 -0800902 dbg("%s - RX error!!!!", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 for (i = 0; i + 1 < urb->actual_length; i += 2) {
904 int stat = data[i], flag = 0;
905 if (stat & RXERROR_OVERRUN)
906 flag |= TTY_OVERRUN;
907 if (stat & RXERROR_FRAMING)
908 flag |= TTY_FRAME;
909 if (stat & RXERROR_PARITY)
910 flag |= TTY_PARITY;
911 /* XXX should handle break (0x10) */
Alan Coxdeb91682008-07-22 11:13:08 +0100912 tty_insert_flip_char(tty, data[i+1],
913 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 }
915 }
916 }
917 tty_flip_buffer_push(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100918 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 }
Alan Coxdeb91682008-07-22 11:13:08 +0100920
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500922 err = usb_submit_urb(urb, GFP_ATOMIC);
923 if (err != 0)
924 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925}
926
927
David Howells7d12e782006-10-05 14:55:46 +0100928static void usa90_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929{
930 unsigned char *data = urb->transfer_buffer;
931 struct keyspan_usa90_portStatusMessage *msg;
932 struct usb_serial *serial;
933 struct usb_serial_port *port;
934 struct keyspan_port_private *p_priv;
Alan Cox4a90f092008-10-13 10:39:46 +0100935 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700937 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938
Ming Leicdc97792008-02-24 18:41:47 +0800939 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700941 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800942 dbg("%s - nonzero status: %x", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 return;
944 }
945 if (urb->actual_length < 14) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800946 dbg("%s - %d byte report??", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 goto exit;
948 }
949
950 msg = (struct keyspan_usa90_portStatusMessage *)data;
951
952 /* Now do something useful with the data */
953
954 port = serial->port[0];
955 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100956
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 /* Update handshaking pin state information */
958 old_dcd_state = p_priv->dcd_state;
959 p_priv->cts_state = ((msg->cts) ? 1 : 0);
960 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
961 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
962 p_priv->ri_state = ((msg->ri) ? 1 : 0);
963
Alan Cox4a90f092008-10-13 10:39:46 +0100964 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
965 tty = tty_port_tty_get(&port->port);
966 if (tty && !C_CLOCAL(tty))
967 tty_hangup(tty);
968 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 }
Alan Coxdeb91682008-07-22 11:13:08 +0100970
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100972 err = usb_submit_urb(urb, GFP_ATOMIC);
973 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800974 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975exit:
976 ;
977}
978
David Howells7d12e782006-10-05 14:55:46 +0100979static void usa90_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980{
981 struct usb_serial_port *port;
982 struct keyspan_port_private *p_priv;
983
Ming Leicdc97792008-02-24 18:41:47 +0800984 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 p_priv = usb_get_serial_port_data(port);
986
987 if (p_priv->resend_cont) {
Alan Coxdeb91682008-07-22 11:13:08 +0100988 dbg("%s - sending setup", __func__);
989 keyspan_usa90_send_setup(port->serial, port,
990 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 }
992}
993
Lucy McCoy0ca12682007-05-18 12:10:41 -0700994/* Status messages from the 28xg */
995static void usa67_instat_callback(struct urb *urb)
996{
997 int err;
998 unsigned char *data = urb->transfer_buffer;
999 struct keyspan_usa67_portStatusMessage *msg;
1000 struct usb_serial *serial;
1001 struct usb_serial_port *port;
1002 struct keyspan_port_private *p_priv;
1003 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001004 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001005
Alan Coxdeb91682008-07-22 11:13:08 +01001006 dbg("%s", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001007
1008 serial = urb->context;
1009
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001010 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001011 dbg("%s - nonzero status: %x", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001012 return;
1013 }
1014
Alan Coxdeb91682008-07-22 11:13:08 +01001015 if (urb->actual_length !=
1016 sizeof(struct keyspan_usa67_portStatusMessage)) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001017 dbg("%s - bad length %d", __func__, urb->actual_length);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001018 return;
1019 }
1020
1021
1022 /* Now do something useful with the data */
1023 msg = (struct keyspan_usa67_portStatusMessage *)data;
1024
1025 /* Check port number from message and retrieve private data */
1026 if (msg->port >= serial->num_ports) {
Alan Coxdeb91682008-07-22 11:13:08 +01001027 dbg("%s - Unexpected port number %d", __func__, msg->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001028 return;
1029 }
1030
1031 port = serial->port[msg->port];
1032 p_priv = usb_get_serial_port_data(port);
1033
1034 /* Update handshaking pin state information */
1035 old_dcd_state = p_priv->dcd_state;
1036 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
1037 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
1038
Alan Cox4a90f092008-10-13 10:39:46 +01001039 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
1040 struct tty_struct *tty = tty_port_tty_get(&port->port);
1041 if (tty && !C_CLOCAL(tty))
1042 tty_hangup(tty);
1043 tty_kref_put(tty);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001044 }
1045
1046 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -07001047 err = usb_submit_urb(urb, GFP_ATOMIC);
1048 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08001049 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001050}
1051
1052static void usa67_glocont_callback(struct urb *urb)
1053{
1054 struct usb_serial *serial;
1055 struct usb_serial_port *port;
1056 struct keyspan_port_private *p_priv;
1057 int i;
1058
Alan Coxdeb91682008-07-22 11:13:08 +01001059 dbg("%s", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001060
1061 serial = urb->context;
1062 for (i = 0; i < serial->num_ports; ++i) {
1063 port = serial->port[i];
1064 p_priv = usb_get_serial_port_data(port);
1065
1066 if (p_priv->resend_cont) {
Alan Coxdeb91682008-07-22 11:13:08 +01001067 dbg("%s - sending setup", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001068 keyspan_usa67_send_setup(serial, port,
1069 p_priv->resend_cont - 1);
1070 break;
1071 }
1072 }
1073}
1074
Alan Cox95da3102008-07-22 11:09:07 +01001075static int keyspan_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076{
Alan Cox95da3102008-07-22 11:09:07 +01001077 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 struct keyspan_port_private *p_priv;
1079 const struct keyspan_device_details *d_details;
1080 int flip;
1081 int data_len;
1082 struct urb *this_urb;
1083
Harvey Harrison441b62c2008-03-03 16:08:34 -08001084 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 p_priv = usb_get_serial_port_data(port);
1086 d_details = p_priv->device_details;
1087
Alan Coxa5b6f602008-04-08 17:16:06 +01001088 /* FIXME: locking */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 if (d_details->msg_format == msg_usa90)
Alan Coxdeb91682008-07-22 11:13:08 +01001090 data_len = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 else
1092 data_len = 63;
1093
1094 flip = p_priv->out_flip;
1095
1096 /* Check both endpoints to see if any are available. */
Alan Coxdeb91682008-07-22 11:13:08 +01001097 this_urb = p_priv->out_urbs[flip];
1098 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001100 return data_len;
1101 flip = (flip + 1) & d_details->outdat_endp_flip;
1102 this_urb = p_priv->out_urbs[flip];
1103 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001105 return data_len;
1106 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 }
Alan Coxa5b6f602008-04-08 17:16:06 +01001108 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109}
1110
1111
Alan Coxa509a7e2009-09-19 13:13:26 -07001112static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113{
Andrew Mortonf78ba152007-11-28 16:21:54 -08001114 struct keyspan_port_private *p_priv;
1115 struct keyspan_serial_private *s_priv;
1116 struct usb_serial *serial = port->serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 const struct keyspan_device_details *d_details;
1118 int i, err;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001119 int baud_rate, device_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 struct urb *urb;
Alan Cox95da3102008-07-22 11:09:07 +01001121 unsigned int cflag = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122
1123 s_priv = usb_get_serial_data(serial);
1124 p_priv = usb_get_serial_port_data(port);
1125 d_details = p_priv->device_details;
Borislav Petkov7eea4362007-11-14 17:00:39 -08001126
Harvey Harrison441b62c2008-03-03 16:08:34 -08001127 dbg("%s - port%d.", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128
1129 /* Set some sane defaults */
1130 p_priv->rts_state = 1;
1131 p_priv->dtr_state = 1;
1132 p_priv->baud = 9600;
1133
1134 /* force baud and lcr to be set on open */
1135 p_priv->old_baud = 0;
1136 p_priv->old_cflag = 0;
1137
1138 p_priv->out_flip = 0;
1139 p_priv->in_flip = 0;
1140
1141 /* Reset low level data toggle and start reading from endpoints */
1142 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001143 urb = p_priv->in_urbs[i];
1144 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146
Alan Coxdeb91682008-07-22 11:13:08 +01001147 /* make sure endpoint data toggle is synchronized
1148 with the device */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 usb_clear_halt(urb->dev, urb->pipe);
Alan Coxdeb91682008-07-22 11:13:08 +01001150 err = usb_submit_urb(urb, GFP_KERNEL);
1151 if (err != 0)
1152 dbg("%s - submit urb %d failed (%d)",
1153 __func__, i, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 }
1155
1156 /* Reset low level data toggle on out endpoints */
1157 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001158 urb = p_priv->out_urbs[i];
1159 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 continue;
Alan Coxdeb91682008-07-22 11:13:08 +01001161 /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
1162 usb_pipeout(urb->pipe), 0); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 }
1164
Andrew Mortonf78ba152007-11-28 16:21:54 -08001165 /* get the terminal config for the setup message now so we don't
1166 * need to send 2 of them */
1167
Andrew Mortonf78ba152007-11-28 16:21:54 -08001168 device_port = port->number - port->serial->minor;
Alan Cox95da3102008-07-22 11:09:07 +01001169 if (tty) {
1170 cflag = tty->termios->c_cflag;
1171 /* Baud rate calculation takes baud rate as an integer
1172 so other rates can be generated if desired. */
1173 baud_rate = tty_get_baud_rate(tty);
1174 /* If no match or invalid, leave as default */
1175 if (baud_rate >= 0
1176 && d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
1177 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
1178 p_priv->baud = baud_rate;
1179 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001180 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001181 /* set CTS/RTS handshake etc. */
1182 p_priv->cflag = cflag;
1183 p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none;
1184
1185 keyspan_send_setup(port, 1);
Alan Coxdeb91682008-07-22 11:13:08 +01001186 /* mdelay(100); */
1187 /* keyspan_set_termios(port, NULL); */
Andrew Mortonf78ba152007-11-28 16:21:54 -08001188
Alan Coxa5b6f602008-04-08 17:16:06 +01001189 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190}
1191
1192static inline void stop_urb(struct urb *urb)
1193{
Greg Kroah-Hartman242cf672005-07-29 16:11:07 -04001194 if (urb && urb->status == -EINPROGRESS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 usb_kill_urb(urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196}
1197
Alan Cox335f8512009-06-11 12:26:29 +01001198static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
1199{
1200 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
1201
1202 p_priv->rts_state = on;
1203 p_priv->dtr_state = on;
1204 keyspan_send_setup(port, 0);
1205}
1206
1207static void keyspan_close(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208{
1209 int i;
1210 struct usb_serial *serial = port->serial;
1211 struct keyspan_serial_private *s_priv;
1212 struct keyspan_port_private *p_priv;
1213
Harvey Harrison441b62c2008-03-03 16:08:34 -08001214 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 s_priv = usb_get_serial_data(serial);
1216 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +01001217
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 p_priv->rts_state = 0;
1219 p_priv->dtr_state = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001220
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 if (serial->dev) {
1222 keyspan_send_setup(port, 2);
1223 /* pilot-xfer seems to work best with this delay */
1224 mdelay(100);
Alan Coxdeb91682008-07-22 11:13:08 +01001225 /* keyspan_set_termios(port, NULL); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 }
1227
1228 /*while (p_priv->outcont_urb->status == -EINPROGRESS) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001229 dbg("%s - urb in progress", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 }*/
1231
1232 p_priv->out_flip = 0;
1233 p_priv->in_flip = 0;
1234
1235 if (serial->dev) {
1236 /* Stop reading/writing urbs */
1237 stop_urb(p_priv->inack_urb);
1238 /* stop_urb(p_priv->outcont_urb); */
1239 for (i = 0; i < 2; i++) {
1240 stop_urb(p_priv->in_urbs[i]);
1241 stop_urb(p_priv->out_urbs[i]);
1242 }
1243 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244}
1245
Alan Coxdeb91682008-07-22 11:13:08 +01001246/* download the firmware to a pre-renumeration device */
1247static int keyspan_fake_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248{
1249 int response;
David Woodhouse2971c572008-05-30 14:04:03 +03001250 const struct ihex_binrec *record;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 char *fw_name;
David Woodhouse2971c572008-05-30 14:04:03 +03001252 const struct firmware *fw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253
1254 dbg("Keyspan startup version %04x product %04x",
1255 le16_to_cpu(serial->dev->descriptor.bcdDevice),
1256 le16_to_cpu(serial->dev->descriptor.idProduct));
Alan Coxdeb91682008-07-22 11:13:08 +01001257
1258 if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000)
1259 != 0x8000) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 dbg("Firmware already loaded. Quitting.");
Alan Coxdeb91682008-07-22 11:13:08 +01001261 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 }
1263
1264 /* Select firmware image on the basis of idProduct */
1265 switch (le16_to_cpu(serial->dev->descriptor.idProduct)) {
1266 case keyspan_usa28_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001267 fw_name = "keyspan/usa28.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 break;
1269
1270 case keyspan_usa28x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001271 fw_name = "keyspan/usa28x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272 break;
1273
1274 case keyspan_usa28xa_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001275 fw_name = "keyspan/usa28xa.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 break;
1277
1278 case keyspan_usa28xb_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001279 fw_name = "keyspan/usa28xb.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 break;
1281
1282 case keyspan_usa19_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001283 fw_name = "keyspan/usa19.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001285
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 case keyspan_usa19qi_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001287 fw_name = "keyspan/usa19qi.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001289
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 case keyspan_mpr_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001291 fw_name = "keyspan/mpr.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 break;
1293
1294 case keyspan_usa19qw_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001295 fw_name = "keyspan/usa19qw.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001297
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 case keyspan_usa18x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001299 fw_name = "keyspan/usa18x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001301
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 case keyspan_usa19w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001303 fw_name = "keyspan/usa19w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001305
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 case keyspan_usa49w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001307 fw_name = "keyspan/usa49w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 break;
1309
1310 case keyspan_usa49wlc_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001311 fw_name = "keyspan/usa49wlc.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 break;
1313
1314 default:
David Woodhouse2971c572008-05-30 14:04:03 +03001315 dev_err(&serial->dev->dev, "Unknown product ID (%04x)\n",
1316 le16_to_cpu(serial->dev->descriptor.idProduct));
1317 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 }
1319
David Woodhouse2971c572008-05-30 14:04:03 +03001320 if (request_ihex_firmware(&fw, fw_name, &serial->dev->dev)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 dev_err(&serial->dev->dev, "Required keyspan firmware image (%s) unavailable.\n", fw_name);
1322 return(1);
1323 }
1324
1325 dbg("Uploading Keyspan %s firmware.", fw_name);
1326
1327 /* download the firmware image */
1328 response = ezusb_set_reset(serial, 1);
1329
David Woodhouse2971c572008-05-30 14:04:03 +03001330 record = (const struct ihex_binrec *)fw->data;
1331
1332 while (record) {
1333 response = ezusb_writememory(serial, be32_to_cpu(record->addr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 (unsigned char *)record->data,
David Woodhouse2971c572008-05-30 14:04:03 +03001335 be16_to_cpu(record->len), 0xa0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 if (response < 0) {
Alan Coxdeb91682008-07-22 11:13:08 +01001337 dev_err(&serial->dev->dev, "ezusb_writememory failed for Keyspan firmware (%d %04X %p %d)\n",
David Woodhouse2971c572008-05-30 14:04:03 +03001338 response, be32_to_cpu(record->addr),
1339 record->data, be16_to_cpu(record->len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 break;
1341 }
David Woodhouse2971c572008-05-30 14:04:03 +03001342 record = ihex_next_binrec(record);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 }
David Woodhouse2971c572008-05-30 14:04:03 +03001344 release_firmware(fw);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 /* bring device out of reset. Renumeration will occur in a
1346 moment and the new device will bind to the real driver */
1347 response = ezusb_set_reset(serial, 0);
1348
1349 /* we don't want this device to have a driver assigned to it. */
Alan Coxdeb91682008-07-22 11:13:08 +01001350 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351}
1352
1353/* Helper functions used by keyspan_setup_urbs */
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001354static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *serial,
1355 int endpoint)
1356{
1357 struct usb_host_interface *iface_desc;
1358 struct usb_endpoint_descriptor *ep;
1359 int i;
1360
1361 iface_desc = serial->interface->cur_altsetting;
1362 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1363 ep = &iface_desc->endpoint[i].desc;
1364 if (ep->bEndpointAddress == endpoint)
1365 return ep;
1366 }
1367 dev_warn(&serial->interface->dev, "found no endpoint descriptor for "
1368 "endpoint %x\n", endpoint);
1369 return NULL;
1370}
1371
Alan Coxdeb91682008-07-22 11:13:08 +01001372static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 int dir, void *ctx, char *buf, int len,
David Howells7d12e782006-10-05 14:55:46 +01001374 void (*callback)(struct urb *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375{
1376 struct urb *urb;
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001377 struct usb_endpoint_descriptor const *ep_desc;
1378 char const *ep_type_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379
1380 if (endpoint == -1)
1381 return NULL; /* endpoint not needed */
1382
Alan Coxdeb91682008-07-22 11:13:08 +01001383 dbg("%s - alloc for endpoint %d.", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
1385 if (urb == NULL) {
Alan Coxdeb91682008-07-22 11:13:08 +01001386 dbg("%s - alloc for endpoint %d failed.", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 return NULL;
1388 }
1389
Lucy McCoy0ca12682007-05-18 12:10:41 -07001390 if (endpoint == 0) {
1391 /* control EP filled in when used */
1392 return urb;
1393 }
1394
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001395 ep_desc = find_ep(serial, endpoint);
1396 if (!ep_desc) {
1397 /* leak the urb, something's wrong and the callers don't care */
1398 return urb;
1399 }
1400 if (usb_endpoint_xfer_int(ep_desc)) {
1401 ep_type_name = "INT";
1402 usb_fill_int_urb(urb, serial->dev,
1403 usb_sndintpipe(serial->dev, endpoint) | dir,
1404 buf, len, callback, ctx,
1405 ep_desc->bInterval);
1406 } else if (usb_endpoint_xfer_bulk(ep_desc)) {
1407 ep_type_name = "BULK";
1408 usb_fill_bulk_urb(urb, serial->dev,
1409 usb_sndbulkpipe(serial->dev, endpoint) | dir,
1410 buf, len, callback, ctx);
1411 } else {
1412 dev_warn(&serial->interface->dev,
1413 "unsupported endpoint type %x\n",
Julia Lawall2e0fe702008-12-29 11:22:14 +01001414 usb_endpoint_type(ep_desc));
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001415 usb_free_urb(urb);
1416 return NULL;
1417 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001419 dbg("%s - using urb %p for %s endpoint %x",
1420 __func__, urb, ep_type_name, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 return urb;
1422}
1423
1424static struct callbacks {
David Howells7d12e782006-10-05 14:55:46 +01001425 void (*instat_callback)(struct urb *);
1426 void (*glocont_callback)(struct urb *);
1427 void (*indat_callback)(struct urb *);
1428 void (*outdat_callback)(struct urb *);
1429 void (*inack_callback)(struct urb *);
1430 void (*outcont_callback)(struct urb *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431} keyspan_callbacks[] = {
1432 {
1433 /* msg_usa26 callbacks */
1434 .instat_callback = usa26_instat_callback,
1435 .glocont_callback = usa26_glocont_callback,
1436 .indat_callback = usa26_indat_callback,
1437 .outdat_callback = usa2x_outdat_callback,
1438 .inack_callback = usa26_inack_callback,
1439 .outcont_callback = usa26_outcont_callback,
1440 }, {
1441 /* msg_usa28 callbacks */
1442 .instat_callback = usa28_instat_callback,
1443 .glocont_callback = usa28_glocont_callback,
1444 .indat_callback = usa28_indat_callback,
1445 .outdat_callback = usa2x_outdat_callback,
1446 .inack_callback = usa28_inack_callback,
1447 .outcont_callback = usa28_outcont_callback,
1448 }, {
1449 /* msg_usa49 callbacks */
1450 .instat_callback = usa49_instat_callback,
1451 .glocont_callback = usa49_glocont_callback,
1452 .indat_callback = usa49_indat_callback,
1453 .outdat_callback = usa2x_outdat_callback,
1454 .inack_callback = usa49_inack_callback,
1455 .outcont_callback = usa49_outcont_callback,
1456 }, {
1457 /* msg_usa90 callbacks */
1458 .instat_callback = usa90_instat_callback,
Alan Coxdeb91682008-07-22 11:13:08 +01001459 .glocont_callback = usa28_glocont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460 .indat_callback = usa90_indat_callback,
1461 .outdat_callback = usa2x_outdat_callback,
1462 .inack_callback = usa28_inack_callback,
1463 .outcont_callback = usa90_outcont_callback,
Lucy McCoy0ca12682007-05-18 12:10:41 -07001464 }, {
1465 /* msg_usa67 callbacks */
1466 .instat_callback = usa67_instat_callback,
1467 .glocont_callback = usa67_glocont_callback,
1468 .indat_callback = usa26_indat_callback,
1469 .outdat_callback = usa2x_outdat_callback,
1470 .inack_callback = usa26_inack_callback,
1471 .outcont_callback = usa26_outcont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 }
1473};
1474
1475 /* Generic setup urbs function that uses
1476 data in device_details */
1477static void keyspan_setup_urbs(struct usb_serial *serial)
1478{
1479 int i, j;
1480 struct keyspan_serial_private *s_priv;
1481 const struct keyspan_device_details *d_details;
1482 struct usb_serial_port *port;
1483 struct keyspan_port_private *p_priv;
1484 struct callbacks *cback;
1485 int endp;
1486
Alan Coxdeb91682008-07-22 11:13:08 +01001487 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488
1489 s_priv = usb_get_serial_data(serial);
1490 d_details = s_priv->device_details;
1491
Alan Coxdeb91682008-07-22 11:13:08 +01001492 /* Setup values for the various callback routines */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 cback = &keyspan_callbacks[d_details->msg_format];
1494
Alan Coxdeb91682008-07-22 11:13:08 +01001495 /* Allocate and set up urbs for each one that is in use,
1496 starting with instat endpoints */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 s_priv->instat_urb = keyspan_setup_urb
1498 (serial, d_details->instat_endpoint, USB_DIR_IN,
1499 serial, s_priv->instat_buf, INSTAT_BUFLEN,
1500 cback->instat_callback);
1501
Lucy McCoy0ca12682007-05-18 12:10:41 -07001502 s_priv->indat_urb = keyspan_setup_urb
1503 (serial, d_details->indat_endpoint, USB_DIR_IN,
1504 serial, s_priv->indat_buf, INDAT49W_BUFLEN,
1505 usa49wg_indat_callback);
1506
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 s_priv->glocont_urb = keyspan_setup_urb
1508 (serial, d_details->glocont_endpoint, USB_DIR_OUT,
1509 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
1510 cback->glocont_callback);
1511
Alan Coxdeb91682008-07-22 11:13:08 +01001512 /* Setup endpoints for each port specific thing */
1513 for (i = 0; i < d_details->num_ports; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 port = serial->port[i];
1515 p_priv = usb_get_serial_port_data(port);
1516
1517 /* Do indat endpoints first, once for each flip */
1518 endp = d_details->indat_endpoints[i];
1519 for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) {
1520 p_priv->in_urbs[j] = keyspan_setup_urb
1521 (serial, endp, USB_DIR_IN, port,
1522 p_priv->in_buffer[j], 64,
1523 cback->indat_callback);
1524 }
1525 for (; j < 2; ++j)
1526 p_priv->in_urbs[j] = NULL;
1527
1528 /* outdat endpoints also have flip */
1529 endp = d_details->outdat_endpoints[i];
1530 for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) {
1531 p_priv->out_urbs[j] = keyspan_setup_urb
1532 (serial, endp, USB_DIR_OUT, port,
1533 p_priv->out_buffer[j], 64,
1534 cback->outdat_callback);
1535 }
1536 for (; j < 2; ++j)
1537 p_priv->out_urbs[j] = NULL;
1538
1539 /* inack endpoint */
1540 p_priv->inack_urb = keyspan_setup_urb
1541 (serial, d_details->inack_endpoints[i], USB_DIR_IN,
1542 port, p_priv->inack_buffer, 1, cback->inack_callback);
1543
1544 /* outcont endpoint */
1545 p_priv->outcont_urb = keyspan_setup_urb
1546 (serial, d_details->outcont_endpoints[i], USB_DIR_OUT,
1547 port, p_priv->outcont_buffer, 64,
1548 cback->outcont_callback);
Alan Coxdeb91682008-07-22 11:13:08 +01001549 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550}
1551
1552/* usa19 function doesn't require prescaler */
1553static int keyspan_usa19_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
1554 u8 *rate_low, u8 *prescaler, int portnum)
1555{
1556 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001557 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 cnt; /* inverse of divisor (programmed into 8051) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559
Alan Coxdeb91682008-07-22 11:13:08 +01001560 dbg("%s - %d.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561
Alan Coxdeb91682008-07-22 11:13:08 +01001562 /* prevent divide by zero... */
1563 b16 = baud_rate * 16L;
1564 if (b16 == 0)
1565 return KEYSPAN_INVALID_BAUD_RATE;
1566 /* Any "standard" rate over 57k6 is marginal on the USA-19
1567 as we run out of divisor resolution. */
1568 if (baud_rate > 57600)
1569 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570
Alan Coxdeb91682008-07-22 11:13:08 +01001571 /* calculate the divisor and the counter (its inverse) */
1572 div = baudclk / b16;
1573 if (div == 0)
1574 return KEYSPAN_INVALID_BAUD_RATE;
1575 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577
Alan Coxdeb91682008-07-22 11:13:08 +01001578 if (div > 0xffff)
1579 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580
Alan Coxdeb91682008-07-22 11:13:08 +01001581 /* return the counter values if non-null */
1582 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001584 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001586 if (rate_low && rate_hi)
1587 dbg("%s - %d %02x %02x.",
1588 __func__, baud_rate, *rate_hi, *rate_low);
1589 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590}
1591
1592/* usa19hs function doesn't require prescaler */
1593static int keyspan_usa19hs_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
1594 u8 *rate_low, u8 *prescaler, int portnum)
1595{
1596 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001597 div; /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598
Alan Coxdeb91682008-07-22 11:13:08 +01001599 dbg("%s - %d.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600
Alan Coxdeb91682008-07-22 11:13:08 +01001601 /* prevent divide by zero... */
1602 b16 = baud_rate * 16L;
1603 if (b16 == 0)
1604 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605
Alan Coxdeb91682008-07-22 11:13:08 +01001606 /* calculate the divisor */
1607 div = baudclk / b16;
1608 if (div == 0)
1609 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610
Alan Coxdeb91682008-07-22 11:13:08 +01001611 if (div > 0xffff)
1612 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613
Alan Coxdeb91682008-07-22 11:13:08 +01001614 /* return the counter values if non-null */
1615 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001617
1618 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619 *rate_hi = (u8) ((div >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001620
1621 if (rate_low && rate_hi)
1622 dbg("%s - %d %02x %02x.",
1623 __func__, baud_rate, *rate_hi, *rate_low);
1624
1625 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626}
1627
1628static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
1629 u8 *rate_low, u8 *prescaler, int portnum)
1630{
1631 u32 b16, /* baud rate times 16 (actual rate used internally) */
1632 clk, /* clock with 13/8 prescaler */
Alan Coxdeb91682008-07-22 11:13:08 +01001633 div, /* divisor using 13/8 prescaler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 res, /* resulting baud rate using 13/8 prescaler */
1635 diff, /* error using 13/8 prescaler */
1636 smallest_diff;
1637 u8 best_prescaler;
1638 int i;
1639
Alan Coxdeb91682008-07-22 11:13:08 +01001640 dbg("%s - %d.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641
Alan Coxdeb91682008-07-22 11:13:08 +01001642 /* prevent divide by zero */
1643 b16 = baud_rate * 16L;
1644 if (b16 == 0)
1645 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646
Alan Coxdeb91682008-07-22 11:13:08 +01001647 /* Calculate prescaler by trying them all and looking
1648 for best fit */
1649
1650 /* start with largest possible difference */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651 smallest_diff = 0xffffffff;
1652
1653 /* 0 is an invalid prescaler, used as a flag */
1654 best_prescaler = 0;
1655
Alan Coxdeb91682008-07-22 11:13:08 +01001656 for (i = 8; i <= 0xff; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 clk = (baudclk * 8) / (u32) i;
Alan Coxdeb91682008-07-22 11:13:08 +01001658
1659 div = clk / b16;
1660 if (div == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662
1663 res = clk / div;
Alan Coxdeb91682008-07-22 11:13:08 +01001664 diff = (res > b16) ? (res-b16) : (b16-res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665
Alan Coxdeb91682008-07-22 11:13:08 +01001666 if (diff < smallest_diff) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667 best_prescaler = i;
1668 smallest_diff = diff;
1669 }
1670 }
1671
Alan Coxdeb91682008-07-22 11:13:08 +01001672 if (best_prescaler == 0)
1673 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674
1675 clk = (baudclk * 8) / (u32) best_prescaler;
1676 div = clk / b16;
1677
Alan Coxdeb91682008-07-22 11:13:08 +01001678 /* return the divisor and prescaler if non-null */
1679 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001681 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 *rate_hi = (u8) ((div >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683 if (prescaler) {
1684 *prescaler = best_prescaler;
Harvey Harrison441b62c2008-03-03 16:08:34 -08001685 /* dbg("%s - %d %d", __func__, *prescaler, div); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686 }
Alan Coxdeb91682008-07-22 11:13:08 +01001687 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688}
1689
1690 /* USA-28 supports different maximum baud rates on each port */
1691static int keyspan_usa28_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
1692 u8 *rate_low, u8 *prescaler, int portnum)
1693{
1694 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001695 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 cnt; /* inverse of divisor (programmed into 8051) */
1697
Alan Coxdeb91682008-07-22 11:13:08 +01001698 dbg("%s - %d.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699
1700 /* prevent divide by zero */
Alan Coxdeb91682008-07-22 11:13:08 +01001701 b16 = baud_rate * 16L;
1702 if (b16 == 0)
1703 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704
Alan Coxdeb91682008-07-22 11:13:08 +01001705 /* calculate the divisor and the counter (its inverse) */
1706 div = KEYSPAN_USA28_BAUDCLK / b16;
1707 if (div == 0)
1708 return KEYSPAN_INVALID_BAUD_RATE;
1709 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711
Alan Coxdeb91682008-07-22 11:13:08 +01001712 /* check for out of range, based on portnum,
1713 and return result */
1714 if (portnum == 0) {
1715 if (div > 0xffff)
1716 return KEYSPAN_INVALID_BAUD_RATE;
1717 } else {
1718 if (portnum == 1) {
1719 if (div > 0xff)
1720 return KEYSPAN_INVALID_BAUD_RATE;
1721 } else
1722 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723 }
1724
1725 /* return the counter values if not NULL
1726 (port 1 will ignore retHi) */
Alan Coxdeb91682008-07-22 11:13:08 +01001727 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001729 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001731 dbg("%s - %d OK.", __func__, baud_rate);
1732 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733}
1734
1735static int keyspan_usa26_send_setup(struct usb_serial *serial,
1736 struct usb_serial_port *port,
1737 int reset_port)
1738{
Alan Coxdeb91682008-07-22 11:13:08 +01001739 struct keyspan_usa26_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 struct keyspan_serial_private *s_priv;
1741 struct keyspan_port_private *p_priv;
1742 const struct keyspan_device_details *d_details;
1743 int outcont_urb;
1744 struct urb *this_urb;
1745 int device_port, err;
1746
Alan Coxdeb91682008-07-22 11:13:08 +01001747 dbg("%s reset=%d", __func__, reset_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748
1749 s_priv = usb_get_serial_data(serial);
1750 p_priv = usb_get_serial_port_data(port);
1751 d_details = s_priv->device_details;
1752 device_port = port->number - port->serial->minor;
1753
1754 outcont_urb = d_details->outcont_endpoints[port->number];
1755 this_urb = p_priv->outcont_urb;
1756
Harvey Harrison441b62c2008-03-03 16:08:34 -08001757 dbg("%s - endpoint %d", __func__, usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758
1759 /* Make sure we have an urb then send the message */
1760 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001761 dbg("%s - oops no urb.", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 return -1;
1763 }
1764
1765 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001766 Don't overwrite resend for open/close condition. */
1767 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768 p_priv->resend_cont = reset_port + 1;
1769 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +01001770 /* dbg("%s - already writing", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001772 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773 }
1774
Alan Coxdeb91682008-07-22 11:13:08 +01001775 memset(&msg, 0, sizeof(struct keyspan_usa26_portControlMessage));
1776
1777 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 if (p_priv->old_baud != p_priv->baud) {
1779 p_priv->old_baud = p_priv->baud;
1780 msg.setClocking = 0xff;
1781 if (d_details->calculate_baud_rate
1782 (p_priv->baud, d_details->baudclk, &msg.baudHi,
Alan Coxdeb91682008-07-22 11:13:08 +01001783 &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1784 dbg("%s - Invalid baud rate %d requested, using 9600.",
1785 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786 msg.baudLo = 0;
1787 msg.baudHi = 125; /* Values for 9600 baud */
1788 msg.prescaler = 10;
1789 }
1790 msg.setPrescaler = 0xff;
1791 }
1792
1793 msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
1794 switch (p_priv->cflag & CSIZE) {
1795 case CS5:
1796 msg.lcr |= USA_DATABITS_5;
1797 break;
1798 case CS6:
1799 msg.lcr |= USA_DATABITS_6;
1800 break;
1801 case CS7:
1802 msg.lcr |= USA_DATABITS_7;
1803 break;
1804 case CS8:
1805 msg.lcr |= USA_DATABITS_8;
1806 break;
1807 }
1808 if (p_priv->cflag & PARENB) {
1809 /* note USA_PARITY_NONE == 0 */
1810 msg.lcr |= (p_priv->cflag & PARODD)?
Alan Coxdeb91682008-07-22 11:13:08 +01001811 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 }
1813 msg.setLcr = 0xff;
1814
1815 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1816 msg.xonFlowControl = 0;
1817 msg.setFlowControl = 0xff;
1818 msg.forwardingLength = 16;
1819 msg.xonChar = 17;
1820 msg.xoffChar = 19;
1821
1822 /* Opening port */
1823 if (reset_port == 1) {
1824 msg._txOn = 1;
1825 msg._txOff = 0;
1826 msg.txFlush = 0;
1827 msg.txBreak = 0;
1828 msg.rxOn = 1;
1829 msg.rxOff = 0;
1830 msg.rxFlush = 1;
1831 msg.rxForward = 0;
1832 msg.returnStatus = 0;
1833 msg.resetDataToggle = 0xff;
1834 }
1835
1836 /* Closing port */
1837 else if (reset_port == 2) {
1838 msg._txOn = 0;
1839 msg._txOff = 1;
1840 msg.txFlush = 0;
1841 msg.txBreak = 0;
1842 msg.rxOn = 0;
1843 msg.rxOff = 1;
1844 msg.rxFlush = 1;
1845 msg.rxForward = 0;
1846 msg.returnStatus = 0;
1847 msg.resetDataToggle = 0;
1848 }
1849
1850 /* Sending intermediate configs */
1851 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001852 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853 msg._txOff = 0;
1854 msg.txFlush = 0;
1855 msg.txBreak = (p_priv->break_on);
1856 msg.rxOn = 0;
1857 msg.rxOff = 0;
1858 msg.rxFlush = 0;
1859 msg.rxForward = 0;
1860 msg.returnStatus = 0;
1861 msg.resetDataToggle = 0x0;
1862 }
1863
Alan Coxdeb91682008-07-22 11:13:08 +01001864 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865 msg.setTxTriState_setRts = 0xff;
1866 msg.txTriState_rts = p_priv->rts_state;
1867
1868 msg.setHskoa_setDtr = 0xff;
1869 msg.hskoa_dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01001870
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001872 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
1873
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874 /* send the data out the device on control endpoint */
1875 this_urb->transfer_buffer_length = sizeof(msg);
1876
Alan Coxdeb91682008-07-22 11:13:08 +01001877 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1878 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08001879 dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880#if 0
1881 else {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001882 dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883 outcont_urb, this_urb->transfer_buffer_length,
1884 usb_pipeendpoint(this_urb->pipe));
1885 }
1886#endif
1887
Alan Coxa5b6f602008-04-08 17:16:06 +01001888 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889}
1890
1891static int keyspan_usa28_send_setup(struct usb_serial *serial,
1892 struct usb_serial_port *port,
1893 int reset_port)
1894{
Alan Coxdeb91682008-07-22 11:13:08 +01001895 struct keyspan_usa28_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 struct keyspan_serial_private *s_priv;
1897 struct keyspan_port_private *p_priv;
1898 const struct keyspan_device_details *d_details;
1899 struct urb *this_urb;
1900 int device_port, err;
1901
Alan Coxdeb91682008-07-22 11:13:08 +01001902 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903
1904 s_priv = usb_get_serial_data(serial);
1905 p_priv = usb_get_serial_port_data(port);
1906 d_details = s_priv->device_details;
1907 device_port = port->number - port->serial->minor;
1908
1909 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01001910 this_urb = p_priv->outcont_urb;
1911 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001912 dbg("%s - oops no urb.", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 return -1;
1914 }
1915
1916 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001917 Don't overwrite resend for open/close condition. */
1918 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919 p_priv->resend_cont = reset_port + 1;
1920 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +01001921 dbg("%s already writing", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001923 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924 }
1925
Alan Coxdeb91682008-07-22 11:13:08 +01001926 memset(&msg, 0, sizeof(struct keyspan_usa28_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927
1928 msg.setBaudRate = 1;
1929 if (d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk,
Alan Coxdeb91682008-07-22 11:13:08 +01001930 &msg.baudHi, &msg.baudLo, NULL, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1931 dbg("%s - Invalid baud rate requested %d.",
1932 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 msg.baudLo = 0xff;
1934 msg.baudHi = 0xb2; /* Values for 9600 baud */
1935 }
1936
1937 /* If parity is enabled, we must calculate it ourselves. */
1938 msg.parity = 0; /* XXX for now */
1939
1940 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1941 msg.xonFlowControl = 0;
1942
Alan Coxdeb91682008-07-22 11:13:08 +01001943 /* Do handshaking outputs, DTR is inverted relative to RTS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944 msg.rts = p_priv->rts_state;
1945 msg.dtr = p_priv->dtr_state;
1946
1947 msg.forwardingLength = 16;
1948 msg.forwardMs = 10;
1949 msg.breakThreshold = 45;
1950 msg.xonChar = 17;
1951 msg.xoffChar = 19;
1952
1953 /*msg.returnStatus = 1;
1954 msg.resetDataToggle = 0xff;*/
1955 /* Opening port */
1956 if (reset_port == 1) {
1957 msg._txOn = 1;
1958 msg._txOff = 0;
1959 msg.txFlush = 0;
1960 msg.txForceXoff = 0;
1961 msg.txBreak = 0;
1962 msg.rxOn = 1;
1963 msg.rxOff = 0;
1964 msg.rxFlush = 1;
1965 msg.rxForward = 0;
1966 msg.returnStatus = 0;
1967 msg.resetDataToggle = 0xff;
1968 }
1969 /* Closing port */
1970 else if (reset_port == 2) {
1971 msg._txOn = 0;
1972 msg._txOff = 1;
1973 msg.txFlush = 0;
1974 msg.txForceXoff = 0;
1975 msg.txBreak = 0;
1976 msg.rxOn = 0;
1977 msg.rxOff = 1;
1978 msg.rxFlush = 1;
1979 msg.rxForward = 0;
1980 msg.returnStatus = 0;
1981 msg.resetDataToggle = 0;
1982 }
1983 /* Sending intermediate configs */
1984 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001985 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986 msg._txOff = 0;
1987 msg.txFlush = 0;
1988 msg.txForceXoff = 0;
1989 msg.txBreak = (p_priv->break_on);
1990 msg.rxOn = 0;
1991 msg.rxOff = 0;
1992 msg.rxFlush = 0;
1993 msg.rxForward = 0;
1994 msg.returnStatus = 0;
1995 msg.resetDataToggle = 0x0;
1996 }
1997
1998 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001999 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000
2001 /* send the data out the device on control endpoint */
2002 this_urb->transfer_buffer_length = sizeof(msg);
2003
Alan Coxdeb91682008-07-22 11:13:08 +01002004 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2005 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002006 dbg("%s - usb_submit_urb(setup) failed", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007#if 0
2008 else {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002009 dbg("%s - usb_submit_urb(setup) OK %d bytes", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010 this_urb->transfer_buffer_length);
2011 }
2012#endif
2013
Alan Coxa5b6f602008-04-08 17:16:06 +01002014 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015}
2016
2017static int keyspan_usa49_send_setup(struct usb_serial *serial,
2018 struct usb_serial_port *port,
2019 int reset_port)
2020{
Lucy McCoy0ca12682007-05-18 12:10:41 -07002021 struct keyspan_usa49_portControlMessage msg;
2022 struct usb_ctrlrequest *dr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023 struct keyspan_serial_private *s_priv;
2024 struct keyspan_port_private *p_priv;
2025 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026 struct urb *this_urb;
2027 int err, device_port;
2028
Alan Coxdeb91682008-07-22 11:13:08 +01002029 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030
2031 s_priv = usb_get_serial_data(serial);
2032 p_priv = usb_get_serial_port_data(port);
2033 d_details = s_priv->device_details;
2034
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035 this_urb = s_priv->glocont_urb;
2036
Lucy McCoy0ca12682007-05-18 12:10:41 -07002037 /* Work out which port within the device is being setup */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038 device_port = port->number - port->serial->minor;
2039
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05302040 /* Make sure we have an urb then send the message */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002042 dbg("%s - oops no urb for port %d.", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043 return -1;
2044 }
2045
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05302046 dbg("%s - endpoint %d port %d (%d)",
2047 __func__, usb_pipeendpoint(this_urb->pipe),
2048 port->number, device_port);
2049
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07002051 Don't overwrite resend for open/close condition. */
2052 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 p_priv->resend_cont = reset_port + 1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002054
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +01002056 /* dbg("%s - already writing", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002058 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 }
2060
Alan Coxdeb91682008-07-22 11:13:08 +01002061 memset(&msg, 0, sizeof(struct keyspan_usa49_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062
2063 /*msg.portNumber = port->number;*/
2064 msg.portNumber = device_port;
Alan Coxdeb91682008-07-22 11:13:08 +01002065
2066 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067 if (p_priv->old_baud != p_priv->baud) {
2068 p_priv->old_baud = p_priv->baud;
2069 msg.setClocking = 0xff;
2070 if (d_details->calculate_baud_rate
2071 (p_priv->baud, d_details->baudclk, &msg.baudHi,
Alan Coxdeb91682008-07-22 11:13:08 +01002072 &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2073 dbg("%s - Invalid baud rate %d requested, using 9600.",
2074 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075 msg.baudLo = 0;
2076 msg.baudHi = 125; /* Values for 9600 baud */
2077 msg.prescaler = 10;
2078 }
Alan Coxdeb91682008-07-22 11:13:08 +01002079 /* msg.setPrescaler = 0xff; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 }
2081
2082 msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
2083 switch (p_priv->cflag & CSIZE) {
2084 case CS5:
2085 msg.lcr |= USA_DATABITS_5;
2086 break;
2087 case CS6:
2088 msg.lcr |= USA_DATABITS_6;
2089 break;
2090 case CS7:
2091 msg.lcr |= USA_DATABITS_7;
2092 break;
2093 case CS8:
2094 msg.lcr |= USA_DATABITS_8;
2095 break;
2096 }
2097 if (p_priv->cflag & PARENB) {
2098 /* note USA_PARITY_NONE == 0 */
2099 msg.lcr |= (p_priv->cflag & PARODD)?
Alan Coxdeb91682008-07-22 11:13:08 +01002100 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101 }
2102 msg.setLcr = 0xff;
2103
2104 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2105 msg.xonFlowControl = 0;
2106 msg.setFlowControl = 0xff;
Alan Coxdeb91682008-07-22 11:13:08 +01002107
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108 msg.forwardingLength = 16;
2109 msg.xonChar = 17;
2110 msg.xoffChar = 19;
2111
Alan Coxdeb91682008-07-22 11:13:08 +01002112 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113 if (reset_port == 1) {
2114 msg._txOn = 1;
2115 msg._txOff = 0;
2116 msg.txFlush = 0;
2117 msg.txBreak = 0;
2118 msg.rxOn = 1;
2119 msg.rxOff = 0;
2120 msg.rxFlush = 1;
2121 msg.rxForward = 0;
2122 msg.returnStatus = 0;
2123 msg.resetDataToggle = 0xff;
2124 msg.enablePort = 1;
2125 msg.disablePort = 0;
2126 }
2127 /* Closing port */
2128 else if (reset_port == 2) {
2129 msg._txOn = 0;
2130 msg._txOff = 1;
2131 msg.txFlush = 0;
2132 msg.txBreak = 0;
2133 msg.rxOn = 0;
2134 msg.rxOff = 1;
2135 msg.rxFlush = 1;
2136 msg.rxForward = 0;
2137 msg.returnStatus = 0;
2138 msg.resetDataToggle = 0;
2139 msg.enablePort = 0;
2140 msg.disablePort = 1;
2141 }
2142 /* Sending intermediate configs */
2143 else {
Alan Coxdeb91682008-07-22 11:13:08 +01002144 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145 msg._txOff = 0;
2146 msg.txFlush = 0;
2147 msg.txBreak = (p_priv->break_on);
2148 msg.rxOn = 0;
2149 msg.rxOff = 0;
2150 msg.rxFlush = 0;
2151 msg.rxForward = 0;
2152 msg.returnStatus = 0;
2153 msg.resetDataToggle = 0x0;
2154 msg.enablePort = 0;
2155 msg.disablePort = 0;
2156 }
2157
Alan Coxdeb91682008-07-22 11:13:08 +01002158 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159 msg.setRts = 0xff;
2160 msg.rts = p_priv->rts_state;
2161
2162 msg.setDtr = 0xff;
2163 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002164
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165 p_priv->resend_cont = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166
Alan Coxdeb91682008-07-22 11:13:08 +01002167 /* if the device is a 49wg, we send control message on usb
2168 control EP 0 */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002169
2170 if (d_details->product_id == keyspan_usa49wg_product_id) {
2171 dr = (void *)(s_priv->ctrl_buf);
2172 dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT;
2173 dr->bRequest = 0xB0; /* 49wg control message */;
2174 dr->wValue = 0;
2175 dr->wIndex = 0;
2176 dr->wLength = cpu_to_le16(sizeof(msg));
2177
Alan Coxdeb91682008-07-22 11:13:08 +01002178 memcpy(s_priv->glocont_buf, &msg, sizeof(msg));
Lucy McCoy0ca12682007-05-18 12:10:41 -07002179
Alan Coxdeb91682008-07-22 11:13:08 +01002180 usb_fill_control_urb(this_urb, serial->dev,
2181 usb_sndctrlpipe(serial->dev, 0),
2182 (unsigned char *)dr, s_priv->glocont_buf,
2183 sizeof(msg), usa49_glocont_callback, serial);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002184
2185 } else {
2186 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Alan Coxdeb91682008-07-22 11:13:08 +01002187
Lucy McCoy0ca12682007-05-18 12:10:41 -07002188 /* send the data out the device on control endpoint */
2189 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002190 }
Alan Coxdeb91682008-07-22 11:13:08 +01002191 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2192 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002193 dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194#if 0
2195 else {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002196 dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002197 outcont_urb, this_urb->transfer_buffer_length,
2198 usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199 }
2200#endif
2201
Alan Coxa5b6f602008-04-08 17:16:06 +01002202 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203}
2204
2205static int keyspan_usa90_send_setup(struct usb_serial *serial,
2206 struct usb_serial_port *port,
2207 int reset_port)
2208{
Alan Coxdeb91682008-07-22 11:13:08 +01002209 struct keyspan_usa90_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210 struct keyspan_serial_private *s_priv;
2211 struct keyspan_port_private *p_priv;
2212 const struct keyspan_device_details *d_details;
2213 struct urb *this_urb;
2214 int err;
2215 u8 prescaler;
2216
Alan Coxdeb91682008-07-22 11:13:08 +01002217 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218
2219 s_priv = usb_get_serial_data(serial);
2220 p_priv = usb_get_serial_port_data(port);
2221 d_details = s_priv->device_details;
2222
2223 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01002224 this_urb = p_priv->outcont_urb;
2225 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002226 dbg("%s - oops no urb.", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227 return -1;
2228 }
2229
2230 /* Save reset port val for resend.
2231 Don't overwrite resend for open/close condition. */
2232 if ((reset_port + 1) > p_priv->resend_cont)
2233 p_priv->resend_cont = reset_port + 1;
2234 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +01002235 dbg("%s already writing", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002237 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238 }
2239
Alan Coxdeb91682008-07-22 11:13:08 +01002240 memset(&msg, 0, sizeof(struct keyspan_usa90_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241
Alan Coxdeb91682008-07-22 11:13:08 +01002242 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 if (p_priv->old_baud != p_priv->baud) {
2244 p_priv->old_baud = p_priv->baud;
2245 msg.setClocking = 0x01;
2246 if (d_details->calculate_baud_rate
2247 (p_priv->baud, d_details->baudclk, &msg.baudHi,
Alan Coxdeb91682008-07-22 11:13:08 +01002248 &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) {
2249 dbg("%s - Invalid baud rate %d requested, using 9600.",
2250 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251 p_priv->baud = 9600;
Alan Coxdeb91682008-07-22 11:13:08 +01002252 d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253 &msg.baudHi, &msg.baudLo, &prescaler, 0);
2254 }
2255 msg.setRxMode = 1;
2256 msg.setTxMode = 1;
2257 }
2258
2259 /* modes must always be correctly specified */
Alan Coxdeb91682008-07-22 11:13:08 +01002260 if (p_priv->baud > 57600) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261 msg.rxMode = RXMODE_DMA;
2262 msg.txMode = TXMODE_DMA;
Alan Coxdeb91682008-07-22 11:13:08 +01002263 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264 msg.rxMode = RXMODE_BYHAND;
2265 msg.txMode = TXMODE_BYHAND;
2266 }
2267
2268 msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
2269 switch (p_priv->cflag & CSIZE) {
2270 case CS5:
2271 msg.lcr |= USA_DATABITS_5;
2272 break;
2273 case CS6:
2274 msg.lcr |= USA_DATABITS_6;
2275 break;
2276 case CS7:
2277 msg.lcr |= USA_DATABITS_7;
2278 break;
2279 case CS8:
2280 msg.lcr |= USA_DATABITS_8;
2281 break;
2282 }
2283 if (p_priv->cflag & PARENB) {
2284 /* note USA_PARITY_NONE == 0 */
2285 msg.lcr |= (p_priv->cflag & PARODD)?
Alan Coxdeb91682008-07-22 11:13:08 +01002286 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 }
2288 if (p_priv->old_cflag != p_priv->cflag) {
2289 p_priv->old_cflag = p_priv->cflag;
2290 msg.setLcr = 0x01;
2291 }
2292
2293 if (p_priv->flow_control == flow_cts)
2294 msg.txFlowControl = TXFLOW_CTS;
2295 msg.setTxFlowControl = 0x01;
2296 msg.setRxFlowControl = 0x01;
Alan Coxdeb91682008-07-22 11:13:08 +01002297
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298 msg.rxForwardingLength = 16;
Alan Coxdeb91682008-07-22 11:13:08 +01002299 msg.rxForwardingTimeout = 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300 msg.txAckSetting = 0;
2301 msg.xonChar = 17;
2302 msg.xoffChar = 19;
2303
Alan Coxdeb91682008-07-22 11:13:08 +01002304 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305 if (reset_port == 1) {
2306 msg.portEnabled = 1;
2307 msg.rxFlush = 1;
2308 msg.txBreak = (p_priv->break_on);
2309 }
2310 /* Closing port */
Alan Coxdeb91682008-07-22 11:13:08 +01002311 else if (reset_port == 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 msg.portEnabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313 /* Sending intermediate configs */
2314 else {
Alan Stern1f871582010-02-17 10:05:47 -05002315 msg.portEnabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316 msg.txBreak = (p_priv->break_on);
2317 }
2318
Alan Coxdeb91682008-07-22 11:13:08 +01002319 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 msg.setRts = 0x01;
2321 msg.rts = p_priv->rts_state;
2322
2323 msg.setDtr = 0x01;
2324 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002325
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01002327 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2328
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329 /* send the data out the device on control endpoint */
2330 this_urb->transfer_buffer_length = sizeof(msg);
2331
Alan Coxdeb91682008-07-22 11:13:08 +01002332 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2333 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002334 dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002335 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336}
2337
Lucy McCoy0ca12682007-05-18 12:10:41 -07002338static int keyspan_usa67_send_setup(struct usb_serial *serial,
2339 struct usb_serial_port *port,
2340 int reset_port)
2341{
2342 struct keyspan_usa67_portControlMessage msg;
2343 struct keyspan_serial_private *s_priv;
2344 struct keyspan_port_private *p_priv;
2345 const struct keyspan_device_details *d_details;
2346 struct urb *this_urb;
2347 int err, device_port;
2348
Alan Coxdeb91682008-07-22 11:13:08 +01002349 dbg("%s", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002350
2351 s_priv = usb_get_serial_data(serial);
2352 p_priv = usb_get_serial_port_data(port);
2353 d_details = s_priv->device_details;
2354
2355 this_urb = s_priv->glocont_urb;
2356
2357 /* Work out which port within the device is being setup */
2358 device_port = port->number - port->serial->minor;
2359
2360 /* Make sure we have an urb then send the message */
2361 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002362 dbg("%s - oops no urb for port %d.", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002363 port->number);
2364 return -1;
2365 }
2366
2367 /* Save reset port val for resend.
2368 Don't overwrite resend for open/close condition. */
2369 if ((reset_port + 1) > p_priv->resend_cont)
2370 p_priv->resend_cont = reset_port + 1;
2371 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +01002372 /* dbg("%s - already writing", __func__); */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002373 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002374 return -1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002375 }
2376
2377 memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
2378
2379 msg.port = device_port;
2380
2381 /* Only set baud rate if it's changed */
2382 if (p_priv->old_baud != p_priv->baud) {
2383 p_priv->old_baud = p_priv->baud;
2384 msg.setClocking = 0xff;
2385 if (d_details->calculate_baud_rate
2386 (p_priv->baud, d_details->baudclk, &msg.baudHi,
Alan Coxdeb91682008-07-22 11:13:08 +01002387 &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2388 dbg("%s - Invalid baud rate %d requested, using 9600.",
2389 __func__, p_priv->baud);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002390 msg.baudLo = 0;
2391 msg.baudHi = 125; /* Values for 9600 baud */
2392 msg.prescaler = 10;
2393 }
2394 msg.setPrescaler = 0xff;
2395 }
2396
2397 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
2398 switch (p_priv->cflag & CSIZE) {
2399 case CS5:
2400 msg.lcr |= USA_DATABITS_5;
2401 break;
2402 case CS6:
2403 msg.lcr |= USA_DATABITS_6;
2404 break;
2405 case CS7:
2406 msg.lcr |= USA_DATABITS_7;
2407 break;
2408 case CS8:
2409 msg.lcr |= USA_DATABITS_8;
2410 break;
2411 }
2412 if (p_priv->cflag & PARENB) {
2413 /* note USA_PARITY_NONE == 0 */
2414 msg.lcr |= (p_priv->cflag & PARODD)?
Alan Coxdeb91682008-07-22 11:13:08 +01002415 USA_PARITY_ODD : USA_PARITY_EVEN;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002416 }
2417 msg.setLcr = 0xff;
2418
2419 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2420 msg.xonFlowControl = 0;
2421 msg.setFlowControl = 0xff;
2422 msg.forwardingLength = 16;
2423 msg.xonChar = 17;
2424 msg.xoffChar = 19;
2425
2426 if (reset_port == 1) {
2427 /* Opening port */
2428 msg._txOn = 1;
2429 msg._txOff = 0;
2430 msg.txFlush = 0;
2431 msg.txBreak = 0;
2432 msg.rxOn = 1;
2433 msg.rxOff = 0;
2434 msg.rxFlush = 1;
2435 msg.rxForward = 0;
2436 msg.returnStatus = 0;
2437 msg.resetDataToggle = 0xff;
2438 } else if (reset_port == 2) {
2439 /* Closing port */
2440 msg._txOn = 0;
2441 msg._txOff = 1;
2442 msg.txFlush = 0;
2443 msg.txBreak = 0;
2444 msg.rxOn = 0;
2445 msg.rxOff = 1;
2446 msg.rxFlush = 1;
2447 msg.rxForward = 0;
2448 msg.returnStatus = 0;
2449 msg.resetDataToggle = 0;
2450 } else {
2451 /* Sending intermediate configs */
Alan Coxdeb91682008-07-22 11:13:08 +01002452 msg._txOn = (!p_priv->break_on);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002453 msg._txOff = 0;
2454 msg.txFlush = 0;
2455 msg.txBreak = (p_priv->break_on);
2456 msg.rxOn = 0;
2457 msg.rxOff = 0;
2458 msg.rxFlush = 0;
2459 msg.rxForward = 0;
2460 msg.returnStatus = 0;
2461 msg.resetDataToggle = 0x0;
2462 }
2463
2464 /* Do handshaking outputs */
2465 msg.setTxTriState_setRts = 0xff;
2466 msg.txTriState_rts = p_priv->rts_state;
2467
2468 msg.setHskoa_setDtr = 0xff;
2469 msg.hskoa_dtr = p_priv->dtr_state;
2470
2471 p_priv->resend_cont = 0;
2472
2473 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2474
2475 /* send the data out the device on control endpoint */
2476 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002477
2478 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2479 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002480 dbg("%s - usb_submit_urb(setup) failed (%d)", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002481 err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002482 return 0;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002483}
2484
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
2486{
2487 struct usb_serial *serial = port->serial;
2488 struct keyspan_serial_private *s_priv;
2489 const struct keyspan_device_details *d_details;
2490
Alan Coxdeb91682008-07-22 11:13:08 +01002491 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492
2493 s_priv = usb_get_serial_data(serial);
2494 d_details = s_priv->device_details;
2495
2496 switch (d_details->msg_format) {
2497 case msg_usa26:
2498 keyspan_usa26_send_setup(serial, port, reset_port);
2499 break;
2500 case msg_usa28:
2501 keyspan_usa28_send_setup(serial, port, reset_port);
2502 break;
2503 case msg_usa49:
2504 keyspan_usa49_send_setup(serial, port, reset_port);
2505 break;
2506 case msg_usa90:
2507 keyspan_usa90_send_setup(serial, port, reset_port);
2508 break;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002509 case msg_usa67:
2510 keyspan_usa67_send_setup(serial, port, reset_port);
2511 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512 }
2513}
2514
2515
2516/* Gets called by the "real" driver (ie once firmware is loaded
2517 and renumeration has taken place. */
Alan Coxdeb91682008-07-22 11:13:08 +01002518static int keyspan_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519{
2520 int i, err;
2521 struct usb_serial_port *port;
2522 struct keyspan_serial_private *s_priv;
2523 struct keyspan_port_private *p_priv;
2524 const struct keyspan_device_details *d_details;
2525
Harvey Harrison441b62c2008-03-03 16:08:34 -08002526 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527
2528 for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
Alan Coxdeb91682008-07-22 11:13:08 +01002529 if (d_details->product_id ==
2530 le16_to_cpu(serial->dev->descriptor.idProduct))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531 break;
2532 if (d_details == NULL) {
Alan Coxdeb91682008-07-22 11:13:08 +01002533 dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
2534 __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002535 return 1;
2536 }
2537
2538 /* Setup private data for serial driver */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01002539 s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540 if (!s_priv) {
Alan Coxdeb91682008-07-22 11:13:08 +01002541 dbg("%s - kmalloc for keyspan_serial_private failed.",
2542 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543 return -ENOMEM;
2544 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545
2546 s_priv->device_details = d_details;
2547 usb_set_serial_data(serial, s_priv);
2548
2549 /* Now setup per port private data */
2550 for (i = 0; i < serial->num_ports; i++) {
2551 port = serial->port[i];
Alan Coxdeb91682008-07-22 11:13:08 +01002552 p_priv = kzalloc(sizeof(struct keyspan_port_private),
2553 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554 if (!p_priv) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002555 dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __func__, i);
Alan Coxdeb91682008-07-22 11:13:08 +01002556 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558 p_priv->device_details = d_details;
2559 usb_set_serial_port_data(port, p_priv);
2560 }
2561
2562 keyspan_setup_urbs(serial);
2563
Lucy McCoy0ca12682007-05-18 12:10:41 -07002564 if (s_priv->instat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002565 err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
2566 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002567 dbg("%s - submit instat urb failed %d", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002568 err);
2569 }
2570 if (s_priv->indat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002571 err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
2572 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002573 dbg("%s - submit indat urb failed %d", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002574 err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002575 }
Alan Coxdeb91682008-07-22 11:13:08 +01002576
Alan Coxa5b6f602008-04-08 17:16:06 +01002577 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578}
2579
Alan Sternf9c99bb2009-06-02 11:53:55 -04002580static void keyspan_disconnect(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581{
2582 int i, j;
2583 struct usb_serial_port *port;
2584 struct keyspan_serial_private *s_priv;
2585 struct keyspan_port_private *p_priv;
2586
Harvey Harrison441b62c2008-03-03 16:08:34 -08002587 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588
2589 s_priv = usb_get_serial_data(serial);
2590
2591 /* Stop reading/writing urbs */
2592 stop_urb(s_priv->instat_urb);
2593 stop_urb(s_priv->glocont_urb);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002594 stop_urb(s_priv->indat_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595 for (i = 0; i < serial->num_ports; ++i) {
2596 port = serial->port[i];
2597 p_priv = usb_get_serial_port_data(port);
2598 stop_urb(p_priv->inack_urb);
2599 stop_urb(p_priv->outcont_urb);
2600 for (j = 0; j < 2; j++) {
2601 stop_urb(p_priv->in_urbs[j]);
2602 stop_urb(p_priv->out_urbs[j]);
2603 }
2604 }
2605
2606 /* Now free them */
Mariusz Kozlowski1cadc132006-11-08 15:36:34 +01002607 usb_free_urb(s_priv->instat_urb);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002608 usb_free_urb(s_priv->indat_urb);
Mariusz Kozlowski1cadc132006-11-08 15:36:34 +01002609 usb_free_urb(s_priv->glocont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610 for (i = 0; i < serial->num_ports; ++i) {
2611 port = serial->port[i];
2612 p_priv = usb_get_serial_port_data(port);
Mariusz Kozlowski1cadc132006-11-08 15:36:34 +01002613 usb_free_urb(p_priv->inack_urb);
2614 usb_free_urb(p_priv->outcont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615 for (j = 0; j < 2; j++) {
Mariusz Kozlowski1cadc132006-11-08 15:36:34 +01002616 usb_free_urb(p_priv->in_urbs[j]);
2617 usb_free_urb(p_priv->out_urbs[j]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618 }
2619 }
Alan Sternf9c99bb2009-06-02 11:53:55 -04002620}
2621
2622static void keyspan_release(struct usb_serial *serial)
2623{
2624 int i;
2625 struct usb_serial_port *port;
2626 struct keyspan_serial_private *s_priv;
2627
2628 dbg("%s", __func__);
2629
2630 s_priv = usb_get_serial_data(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631
2632 /* dbg("Freeing serial->private."); */
2633 kfree(s_priv);
2634
2635 /* dbg("Freeing port->private."); */
2636 /* Now free per port private data */
2637 for (i = 0; i < serial->num_ports; i++) {
2638 port = serial->port[i];
2639 kfree(usb_get_serial_port_data(port));
2640 }
2641}
2642
Alan Coxdeb91682008-07-22 11:13:08 +01002643MODULE_AUTHOR(DRIVER_AUTHOR);
2644MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645MODULE_LICENSE("GPL");
2646
David Woodhouse2971c572008-05-30 14:04:03 +03002647MODULE_FIRMWARE("keyspan/usa28.fw");
2648MODULE_FIRMWARE("keyspan/usa28x.fw");
2649MODULE_FIRMWARE("keyspan/usa28xa.fw");
2650MODULE_FIRMWARE("keyspan/usa28xb.fw");
2651MODULE_FIRMWARE("keyspan/usa19.fw");
2652MODULE_FIRMWARE("keyspan/usa19qi.fw");
2653MODULE_FIRMWARE("keyspan/mpr.fw");
2654MODULE_FIRMWARE("keyspan/usa19qw.fw");
2655MODULE_FIRMWARE("keyspan/usa18x.fw");
2656MODULE_FIRMWARE("keyspan/usa19w.fw");
2657MODULE_FIRMWARE("keyspan/usa49w.fw");
2658MODULE_FIRMWARE("keyspan/usa49wlc.fw");
2659
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660module_param(debug, bool, S_IRUGO | S_IWUSR);
2661MODULE_PARM_DESC(debug, "Debug enabled or not");
2662