blob: af0b70eaf032f6617c36b596ce70776842a20d9f [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
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -0700133module_usb_serial_driver(serial_drivers, keyspan_ids_combined);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134
Alan Cox95da3102008-07-22 11:09:07 +0100135static void keyspan_break_ctl(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136{
Alan Cox95da3102008-07-22 11:09:07 +0100137 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 struct keyspan_port_private *p_priv;
139
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 p_priv = usb_get_serial_port_data(port);
141
142 if (break_state == -1)
143 p_priv->break_on = 1;
144 else
145 p_priv->break_on = 0;
146
147 keyspan_send_setup(port, 0);
148}
149
150
Alan Coxdeb91682008-07-22 11:13:08 +0100151static void keyspan_set_termios(struct tty_struct *tty,
Alan Cox95da3102008-07-22 11:09:07 +0100152 struct usb_serial_port *port, struct ktermios *old_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153{
154 int baud_rate, device_port;
155 struct keyspan_port_private *p_priv;
156 const struct keyspan_device_details *d_details;
157 unsigned int cflag;
158
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 p_priv = usb_get_serial_port_data(port);
160 d_details = p_priv->device_details;
Alan Cox74240b02007-10-18 01:24:20 -0700161 cflag = tty->termios->c_cflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 device_port = port->number - port->serial->minor;
163
164 /* Baud rate calculation takes baud rate as an integer
165 so other rates can be generated if desired. */
Alan Cox74240b02007-10-18 01:24:20 -0700166 baud_rate = tty_get_baud_rate(tty);
Alan Coxdeb91682008-07-22 11:13:08 +0100167 /* If no match or invalid, don't change */
Alan Cox74240b02007-10-18 01:24:20 -0700168 if (d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
170 /* FIXME - more to do here to ensure rate changes cleanly */
Alan Cox74240b02007-10-18 01:24:20 -0700171 /* FIXME - calcuate exact rate from divisor ? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172 p_priv->baud = baud_rate;
Alan Cox74240b02007-10-18 01:24:20 -0700173 } else
174 baud_rate = tty_termios_baud_rate(old_termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175
Alan Cox74240b02007-10-18 01:24:20 -0700176 tty_encode_baud_rate(tty, baud_rate, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 /* set CTS/RTS handshake etc. */
178 p_priv->cflag = cflag;
Ben Minerds2b982ab2012-07-12 00:10:16 +1000179 p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180
Alan Cox74240b02007-10-18 01:24:20 -0700181 /* Mark/Space not supported */
182 tty->termios->c_cflag &= ~CMSPAR;
183
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 keyspan_send_setup(port, 0);
185}
186
Alan Cox60b33c12011-02-14 16:26:14 +0000187static int keyspan_tiocmget(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188{
Alan Cox95da3102008-07-22 11:09:07 +0100189 struct usb_serial_port *port = tty->driver_data;
190 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 unsigned int value;
Alan Coxdeb91682008-07-22 11:13:08 +0100192
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193 value = ((p_priv->rts_state) ? TIOCM_RTS : 0) |
194 ((p_priv->dtr_state) ? TIOCM_DTR : 0) |
195 ((p_priv->cts_state) ? TIOCM_CTS : 0) |
196 ((p_priv->dsr_state) ? TIOCM_DSR : 0) |
197 ((p_priv->dcd_state) ? TIOCM_CAR : 0) |
Alan Coxdeb91682008-07-22 11:13:08 +0100198 ((p_priv->ri_state) ? TIOCM_RNG : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199
200 return value;
201}
202
Alan Cox20b9d172011-02-14 16:26:50 +0000203static int keyspan_tiocmset(struct tty_struct *tty,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 unsigned int set, unsigned int clear)
205{
Alan Cox95da3102008-07-22 11:09:07 +0100206 struct usb_serial_port *port = tty->driver_data;
207 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100208
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 if (set & TIOCM_RTS)
210 p_priv->rts_state = 1;
211 if (set & TIOCM_DTR)
212 p_priv->dtr_state = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 if (clear & TIOCM_RTS)
214 p_priv->rts_state = 0;
215 if (clear & TIOCM_DTR)
216 p_priv->dtr_state = 0;
217 keyspan_send_setup(port, 0);
218 return 0;
219}
220
Alan Cox95da3102008-07-22 11:09:07 +0100221/* Write function is similar for the four protocols used
222 with only a minor change for usa90 (usa19hs) required */
223static int keyspan_write(struct tty_struct *tty,
224 struct usb_serial_port *port, const unsigned char *buf, int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225{
226 struct keyspan_port_private *p_priv;
227 const struct keyspan_device_details *d_details;
228 int flip;
229 int left, todo;
230 struct urb *this_urb;
Alan Coxdeb91682008-07-22 11:13:08 +0100231 int err, maxDataLen, dataOffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232
233 p_priv = usb_get_serial_port_data(port);
234 d_details = p_priv->device_details;
235
236 if (d_details->msg_format == msg_usa90) {
Alan Coxdeb91682008-07-22 11:13:08 +0100237 maxDataLen = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 dataOffset = 0;
239 } else {
240 maxDataLen = 63;
241 dataOffset = 1;
242 }
Alan Coxdeb91682008-07-22 11:13:08 +0100243
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 dbg("%s - for port %d (%d chars), flip=%d",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800245 __func__, port->number, count, p_priv->out_flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246
247 for (left = count; left > 0; left -= todo) {
248 todo = left;
249 if (todo > maxDataLen)
250 todo = maxDataLen;
251
252 flip = p_priv->out_flip;
Alan Coxdeb91682008-07-22 11:13:08 +0100253
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 /* Check we have a valid urb/endpoint before we use it... */
Alan Coxdeb91682008-07-22 11:13:08 +0100255 this_urb = p_priv->out_urbs[flip];
256 if (this_urb == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 /* no bulk out, so return 0 bytes written */
Harvey Harrison441b62c2008-03-03 16:08:34 -0800258 dbg("%s - no output urb :(", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 return count;
260 }
261
Alan Coxdeb91682008-07-22 11:13:08 +0100262 dbg("%s - endpoint %d flip %d",
263 __func__, usb_pipeendpoint(this_urb->pipe), flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264
265 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +0100266 if (time_before(jiffies,
267 p_priv->tx_start_time[flip] + 10 * HZ))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 usb_unlink_urb(this_urb);
270 break;
271 }
272
Alan Coxdeb91682008-07-22 11:13:08 +0100273 /* First byte in buffer is "last flag" (except for usa19hx)
274 - unused so for now so set to zero */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 ((char *)this_urb->transfer_buffer)[0] = 0;
276
Alan Coxdeb91682008-07-22 11:13:08 +0100277 memcpy(this_urb->transfer_buffer + dataOffset, buf, todo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 buf += todo;
279
280 /* send the data out the bulk port */
281 this_urb->transfer_buffer_length = todo + dataOffset;
282
Alan Coxdeb91682008-07-22 11:13:08 +0100283 err = usb_submit_urb(this_urb, GFP_ATOMIC);
284 if (err != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 dbg("usb_submit_urb(write bulk) failed (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 p_priv->tx_start_time[flip] = jiffies;
287
288 /* Flip for next time if usa26 or usa28 interface
289 (not used on usa49) */
290 p_priv->out_flip = (flip + 1) & d_details->outdat_endp_flip;
291 }
292
293 return count - left;
294}
295
David Howells7d12e782006-10-05 14:55:46 +0100296static void usa26_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297{
298 int i, err;
299 int endpoint;
300 struct usb_serial_port *port;
301 struct tty_struct *tty;
302 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700303 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 endpoint = usb_pipeendpoint(urb->pipe);
306
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700307 if (status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 dbg("%s - nonzero status: %x on endpoint %d.",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800309 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 return;
311 }
312
Ming Leicdc97792008-02-24 18:41:47 +0800313 port = urb->context;
Alan Cox4a90f092008-10-13 10:39:46 +0100314 tty = tty_port_tty_get(&port->port);
Alan Coxa5569a52008-01-21 17:18:24 -0800315 if (tty && urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 /* 0x80 bit is error flag */
317 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100318 /* no errors on individual bytes, only
319 possible overrun err */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 if (data[0] & RXERROR_OVERRUN)
Alan Coxdeb91682008-07-22 11:13:08 +0100321 err = TTY_OVERRUN;
322 else
323 err = 0;
324 for (i = 1; i < urb->actual_length ; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 tty_insert_flip_char(tty, data[i], err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 } else {
327 /* some bytes had errors, every byte has status */
Harvey Harrison441b62c2008-03-03 16:08:34 -0800328 dbg("%s - RX error!!!!", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 for (i = 0; i + 1 < urb->actual_length; i += 2) {
330 int stat = data[i], flag = 0;
331 if (stat & RXERROR_OVERRUN)
332 flag |= TTY_OVERRUN;
333 if (stat & RXERROR_FRAMING)
334 flag |= TTY_FRAME;
335 if (stat & RXERROR_PARITY)
336 flag |= TTY_PARITY;
337 /* XXX should handle break (0x10) */
338 tty_insert_flip_char(tty, data[i+1], flag);
339 }
340 }
341 tty_flip_buffer_push(tty);
342 }
Alan Cox4a90f092008-10-13 10:39:46 +0100343 tty_kref_put(tty);
Alan Coxdeb91682008-07-22 11:13:08 +0100344
345 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500346 err = usb_submit_urb(urb, GFP_ATOMIC);
347 if (err != 0)
348 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349}
350
Alan Coxdeb91682008-07-22 11:13:08 +0100351/* Outdat handling is common for all devices */
David Howells7d12e782006-10-05 14:55:46 +0100352static void usa2x_outdat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353{
354 struct usb_serial_port *port;
355 struct keyspan_port_private *p_priv;
356
Ming Leicdc97792008-02-24 18:41:47 +0800357 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100359 dbg("%s - urb %d", __func__, urb == p_priv->out_urbs[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360
Alan Stern1f871582010-02-17 10:05:47 -0500361 usb_serial_port_softint(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362}
363
David Howells7d12e782006-10-05 14:55:46 +0100364static void usa26_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366}
367
David Howells7d12e782006-10-05 14:55:46 +0100368static void usa26_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369{
370 struct usb_serial_port *port;
371 struct keyspan_port_private *p_priv;
372
Ming Leicdc97792008-02-24 18:41:47 +0800373 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 p_priv = usb_get_serial_port_data(port);
375
376 if (p_priv->resend_cont) {
Alan Coxdeb91682008-07-22 11:13:08 +0100377 dbg("%s - sending setup", __func__);
378 keyspan_usa26_send_setup(port->serial, port,
379 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 }
381}
382
David Howells7d12e782006-10-05 14:55:46 +0100383static void usa26_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384{
385 unsigned char *data = urb->transfer_buffer;
386 struct keyspan_usa26_portStatusMessage *msg;
387 struct usb_serial *serial;
388 struct usb_serial_port *port;
389 struct keyspan_port_private *p_priv;
Alan Cox4a90f092008-10-13 10:39:46 +0100390 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700392 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393
Ming Leicdc97792008-02-24 18:41:47 +0800394 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700396 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800397 dbg("%s - nonzero status: %x", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 return;
399 }
400 if (urb->actual_length != 9) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800401 dbg("%s - %d byte report??", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 goto exit;
403 }
404
405 msg = (struct keyspan_usa26_portStatusMessage *)data;
406
407#if 0
408 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 -0800409 __func__, msg->port, msg->hskia_cts, msg->gpia_dcd, msg->dsr, msg->ri, msg->_txOff,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 msg->_txXoff, msg->rxEnabled, msg->controlResponse);
411#endif
412
413 /* Now do something useful with the data */
414
415
Alan Coxdeb91682008-07-22 11:13:08 +0100416 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 if (msg->port >= serial->num_ports) {
Alan Coxdeb91682008-07-22 11:13:08 +0100418 dbg("%s - Unexpected port number %d", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 goto exit;
420 }
421 port = serial->port[msg->port];
422 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100423
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 /* Update handshaking pin state information */
425 old_dcd_state = p_priv->dcd_state;
426 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
427 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
428 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
429 p_priv->ri_state = ((msg->ri) ? 1 : 0);
430
Alan Cox4a90f092008-10-13 10:39:46 +0100431 if (old_dcd_state != p_priv->dcd_state) {
432 tty = tty_port_tty_get(&port->port);
433 if (tty && !C_CLOCAL(tty))
434 tty_hangup(tty);
435 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 }
Alan Coxdeb91682008-07-22 11:13:08 +0100437
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100439 err = usb_submit_urb(urb, GFP_ATOMIC);
440 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800441 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442exit: ;
443}
444
David Howells7d12e782006-10-05 14:55:46 +0100445static void usa26_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447}
448
449
David Howells7d12e782006-10-05 14:55:46 +0100450static void usa28_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451{
Alan Coxf035a8a2008-07-22 11:13:32 +0100452 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 struct usb_serial_port *port;
454 struct tty_struct *tty;
455 unsigned char *data;
456 struct keyspan_port_private *p_priv;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700457 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458
Ming Leicdc97792008-02-24 18:41:47 +0800459 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 p_priv = usb_get_serial_port_data(port);
461 data = urb->transfer_buffer;
462
463 if (urb != p_priv->in_urbs[p_priv->in_flip])
464 return;
465
466 do {
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700467 if (status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 dbg("%s - nonzero status: %x on endpoint %d.",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800469 __func__, status, usb_pipeendpoint(urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 return;
471 }
472
Ming Leicdc97792008-02-24 18:41:47 +0800473 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 p_priv = usb_get_serial_port_data(port);
475 data = urb->transfer_buffer;
476
Ben Minerds40adac82012-07-12 00:10:17 +1000477 tty = tty_port_tty_get(&port->port);
Alan Cox4a90f092008-10-13 10:39:46 +0100478 if (tty && urb->actual_length) {
Alan Coxf035a8a2008-07-22 11:13:32 +0100479 tty_insert_flip_string(tty, data, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 tty_flip_buffer_push(tty);
481 }
Alan Cox4a90f092008-10-13 10:39:46 +0100482 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483
484 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500485 err = usb_submit_urb(urb, GFP_ATOMIC);
486 if (err != 0)
487 dbg("%s - resubmit read urb failed. (%d)",
488 __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 p_priv->in_flip ^= 1;
490
491 urb = p_priv->in_urbs[p_priv->in_flip];
492 } while (urb->status != -EINPROGRESS);
493}
494
David Howells7d12e782006-10-05 14:55:46 +0100495static void usa28_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497}
498
David Howells7d12e782006-10-05 14:55:46 +0100499static void usa28_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500{
501 struct usb_serial_port *port;
502 struct keyspan_port_private *p_priv;
503
Ming Leicdc97792008-02-24 18:41:47 +0800504 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 p_priv = usb_get_serial_port_data(port);
506
507 if (p_priv->resend_cont) {
Alan Coxdeb91682008-07-22 11:13:08 +0100508 dbg("%s - sending setup", __func__);
509 keyspan_usa28_send_setup(port->serial, port,
510 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 }
512}
513
David Howells7d12e782006-10-05 14:55:46 +0100514static void usa28_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515{
516 int err;
517 unsigned char *data = urb->transfer_buffer;
518 struct keyspan_usa28_portStatusMessage *msg;
519 struct usb_serial *serial;
520 struct usb_serial_port *port;
521 struct keyspan_port_private *p_priv;
Alan Cox4a90f092008-10-13 10:39:46 +0100522 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700524 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525
Ming Leicdc97792008-02-24 18:41:47 +0800526 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700528 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800529 dbg("%s - nonzero status: %x", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 return;
531 }
532
533 if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800534 dbg("%s - bad length %d", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 goto exit;
536 }
537
Harvey Harrison441b62c2008-03-03 16:08:34 -0800538 /*dbg("%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 data[0], data[1], data[2], data[3], data[4], data[5],
540 data[6], data[7], data[8], data[9], data[10], data[11]);*/
Alan Coxdeb91682008-07-22 11:13:08 +0100541
542 /* Now do something useful with the data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 msg = (struct keyspan_usa28_portStatusMessage *)data;
544
Alan Coxdeb91682008-07-22 11:13:08 +0100545 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 if (msg->port >= serial->num_ports) {
Alan Coxdeb91682008-07-22 11:13:08 +0100547 dbg("%s - Unexpected port number %d", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 goto exit;
549 }
550 port = serial->port[msg->port];
551 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100552
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 /* Update handshaking pin state information */
554 old_dcd_state = p_priv->dcd_state;
555 p_priv->cts_state = ((msg->cts) ? 1 : 0);
556 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
557 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
558 p_priv->ri_state = ((msg->ri) ? 1 : 0);
559
Ben Minerdsddc04ae2012-07-12 00:10:18 +1000560 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
Alan Cox4a90f092008-10-13 10:39:46 +0100561 tty = tty_port_tty_get(&port->port);
Ben Minerds878b5fd2012-07-12 00:10:19 +1000562 if (tty && !C_CLOCAL(tty))
Alan Cox4a90f092008-10-13 10:39:46 +0100563 tty_hangup(tty);
564 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 }
566
567 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100568 err = usb_submit_urb(urb, GFP_ATOMIC);
569 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800570 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571exit: ;
572}
573
David Howells7d12e782006-10-05 14:55:46 +0100574static void usa28_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576}
577
578
David Howells7d12e782006-10-05 14:55:46 +0100579static void usa49_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580{
581 struct usb_serial *serial;
582 struct usb_serial_port *port;
583 struct keyspan_port_private *p_priv;
584 int i;
585
Ming Leicdc97792008-02-24 18:41:47 +0800586 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 for (i = 0; i < serial->num_ports; ++i) {
588 port = serial->port[i];
589 p_priv = usb_get_serial_port_data(port);
590
591 if (p_priv->resend_cont) {
Alan Coxdeb91682008-07-22 11:13:08 +0100592 dbg("%s - sending setup", __func__);
593 keyspan_usa49_send_setup(serial, port,
594 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 break;
596 }
597 }
598}
599
600 /* This is actually called glostat in the Keyspan
601 doco */
David Howells7d12e782006-10-05 14:55:46 +0100602static void usa49_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603{
604 int err;
605 unsigned char *data = urb->transfer_buffer;
606 struct keyspan_usa49_portStatusMessage *msg;
607 struct usb_serial *serial;
608 struct usb_serial_port *port;
609 struct keyspan_port_private *p_priv;
610 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700611 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612
Ming Leicdc97792008-02-24 18:41:47 +0800613 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700615 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800616 dbg("%s - nonzero status: %x", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 return;
618 }
619
Alan Coxdeb91682008-07-22 11:13:08 +0100620 if (urb->actual_length !=
621 sizeof(struct keyspan_usa49_portStatusMessage)) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800622 dbg("%s - bad length %d", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 goto exit;
624 }
625
Harvey Harrison441b62c2008-03-03 16:08:34 -0800626 /*dbg(" %x %x %x %x %x %x %x %x %x %x %x", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 data[0], data[1], data[2], data[3], data[4], data[5],
628 data[6], data[7], data[8], data[9], data[10]);*/
Alan Coxdeb91682008-07-22 11:13:08 +0100629
630 /* Now do something useful with the data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 msg = (struct keyspan_usa49_portStatusMessage *)data;
632
Alan Coxdeb91682008-07-22 11:13:08 +0100633 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 if (msg->portNumber >= serial->num_ports) {
Alan Coxdeb91682008-07-22 11:13:08 +0100635 dbg("%s - Unexpected port number %d",
636 __func__, msg->portNumber);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 goto exit;
638 }
639 port = serial->port[msg->portNumber];
640 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100641
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 /* Update handshaking pin state information */
643 old_dcd_state = p_priv->dcd_state;
644 p_priv->cts_state = ((msg->cts) ? 1 : 0);
645 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
646 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
647 p_priv->ri_state = ((msg->ri) ? 1 : 0);
648
Alan Cox4a90f092008-10-13 10:39:46 +0100649 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
650 struct tty_struct *tty = tty_port_tty_get(&port->port);
651 if (tty && !C_CLOCAL(tty))
652 tty_hangup(tty);
653 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 }
655
Alan Coxdeb91682008-07-22 11:13:08 +0100656 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100657 err = usb_submit_urb(urb, GFP_ATOMIC);
658 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800659 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660exit: ;
661}
662
David Howells7d12e782006-10-05 14:55:46 +0100663static void usa49_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665}
666
David Howells7d12e782006-10-05 14:55:46 +0100667static void usa49_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668{
669 int i, err;
670 int endpoint;
671 struct usb_serial_port *port;
672 struct tty_struct *tty;
673 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700674 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 endpoint = usb_pipeendpoint(urb->pipe);
677
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700678 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800679 dbg("%s - nonzero status: %x on endpoint %d.", __func__,
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700680 status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681 return;
682 }
683
Ming Leicdc97792008-02-24 18:41:47 +0800684 port = urb->context;
Alan Cox4a90f092008-10-13 10:39:46 +0100685 tty = tty_port_tty_get(&port->port);
Alan Cox3004e532008-01-03 16:59:04 +0000686 if (tty && urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 /* 0x80 bit is error flag */
688 if ((data[0] & 0x80) == 0) {
689 /* no error on any byte */
Alan Coxf035a8a2008-07-22 11:13:32 +0100690 tty_insert_flip_string(tty, data + 1,
691 urb->actual_length - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 } else {
693 /* some bytes had errors, every byte has status */
694 for (i = 0; i + 1 < urb->actual_length; i += 2) {
695 int stat = data[i], flag = 0;
696 if (stat & RXERROR_OVERRUN)
697 flag |= TTY_OVERRUN;
698 if (stat & RXERROR_FRAMING)
699 flag |= TTY_FRAME;
700 if (stat & RXERROR_PARITY)
701 flag |= TTY_PARITY;
702 /* XXX should handle break (0x10) */
703 tty_insert_flip_char(tty, data[i+1], flag);
704 }
705 }
706 tty_flip_buffer_push(tty);
707 }
Alan Cox4a90f092008-10-13 10:39:46 +0100708 tty_kref_put(tty);
Alan Coxdeb91682008-07-22 11:13:08 +0100709
710 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500711 err = usb_submit_urb(urb, GFP_ATOMIC);
712 if (err != 0)
713 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714}
715
Lucy McCoy0ca12682007-05-18 12:10:41 -0700716static void usa49wg_indat_callback(struct urb *urb)
717{
718 int i, len, x, err;
719 struct usb_serial *serial;
720 struct usb_serial_port *port;
721 struct tty_struct *tty;
722 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700723 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700724
Lucy McCoy0ca12682007-05-18 12:10:41 -0700725 serial = urb->context;
726
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700727 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800728 dbg("%s - nonzero status: %x", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700729 return;
730 }
731
732 /* inbound data is in the form P#, len, status, data */
733 i = 0;
734 len = 0;
735
736 if (urb->actual_length) {
737 while (i < urb->actual_length) {
738
739 /* Check port number from message*/
740 if (data[i] >= serial->num_ports) {
Alan Coxdeb91682008-07-22 11:13:08 +0100741 dbg("%s - Unexpected port number %d",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800742 __func__, data[i]);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700743 return;
744 }
745 port = serial->port[data[i++]];
Alan Cox4a90f092008-10-13 10:39:46 +0100746 tty = tty_port_tty_get(&port->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700747 len = data[i++];
748
749 /* 0x80 bit is error flag */
750 if ((data[i] & 0x80) == 0) {
751 /* no error on any byte */
752 i++;
753 for (x = 1; x < len ; ++x)
Alan Stern1f871582010-02-17 10:05:47 -0500754 tty_insert_flip_char(tty, data[i++], 0);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700755 } else {
756 /*
757 * some bytes had errors, every byte has status
758 */
759 for (x = 0; x + 1 < len; x += 2) {
760 int stat = data[i], flag = 0;
761 if (stat & RXERROR_OVERRUN)
762 flag |= TTY_OVERRUN;
763 if (stat & RXERROR_FRAMING)
764 flag |= TTY_FRAME;
765 if (stat & RXERROR_PARITY)
766 flag |= TTY_PARITY;
767 /* XXX should handle break (0x10) */
Alan Stern1f871582010-02-17 10:05:47 -0500768 tty_insert_flip_char(tty,
Lucy McCoy0ca12682007-05-18 12:10:41 -0700769 data[i+1], flag);
770 i += 2;
771 }
772 }
Alan Stern1f871582010-02-17 10:05:47 -0500773 tty_flip_buffer_push(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100774 tty_kref_put(tty);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700775 }
776 }
777
778 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700779 err = usb_submit_urb(urb, GFP_ATOMIC);
780 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800781 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700782}
783
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784/* not used, usa-49 doesn't have per-port control endpoints */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700785static void usa49_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787}
788
Lucy McCoy0ca12682007-05-18 12:10:41 -0700789static void usa90_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790{
791 int i, err;
792 int endpoint;
793 struct usb_serial_port *port;
794 struct keyspan_port_private *p_priv;
795 struct tty_struct *tty;
796 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700797 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 endpoint = usb_pipeendpoint(urb->pipe);
800
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700801 if (status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 dbg("%s - nonzero status: %x on endpoint %d.",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800803 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 return;
805 }
806
Ming Leicdc97792008-02-24 18:41:47 +0800807 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 p_priv = usb_get_serial_port_data(port);
809
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 if (urb->actual_length) {
Alan Cox4a90f092008-10-13 10:39:46 +0100811 tty = tty_port_tty_get(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 /* if current mode is DMA, looks like usa28 format
Alan Coxdeb91682008-07-22 11:13:08 +0100813 otherwise looks like usa26 data format */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814
Alan Coxf035a8a2008-07-22 11:13:32 +0100815 if (p_priv->baud > 57600)
816 tty_insert_flip_string(tty, data, urb->actual_length);
817 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 /* 0x80 bit is error flag */
819 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100820 /* no errors on individual bytes, only
821 possible overrun err*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 if (data[0] & RXERROR_OVERRUN)
Alan Coxdeb91682008-07-22 11:13:08 +0100823 err = TTY_OVERRUN;
824 else
825 err = 0;
826 for (i = 1; i < urb->actual_length ; ++i)
827 tty_insert_flip_char(tty, data[i],
828 err);
829 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 /* some bytes had errors, every byte has status */
Harvey Harrison441b62c2008-03-03 16:08:34 -0800831 dbg("%s - RX error!!!!", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 for (i = 0; i + 1 < urb->actual_length; i += 2) {
833 int stat = data[i], flag = 0;
834 if (stat & RXERROR_OVERRUN)
835 flag |= TTY_OVERRUN;
836 if (stat & RXERROR_FRAMING)
837 flag |= TTY_FRAME;
838 if (stat & RXERROR_PARITY)
839 flag |= TTY_PARITY;
840 /* XXX should handle break (0x10) */
Alan Coxdeb91682008-07-22 11:13:08 +0100841 tty_insert_flip_char(tty, data[i+1],
842 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 }
844 }
845 }
846 tty_flip_buffer_push(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100847 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 }
Alan Coxdeb91682008-07-22 11:13:08 +0100849
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500851 err = usb_submit_urb(urb, GFP_ATOMIC);
852 if (err != 0)
853 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854}
855
856
David Howells7d12e782006-10-05 14:55:46 +0100857static void usa90_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858{
859 unsigned char *data = urb->transfer_buffer;
860 struct keyspan_usa90_portStatusMessage *msg;
861 struct usb_serial *serial;
862 struct usb_serial_port *port;
863 struct keyspan_port_private *p_priv;
Alan Cox4a90f092008-10-13 10:39:46 +0100864 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700866 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867
Ming Leicdc97792008-02-24 18:41:47 +0800868 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700870 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800871 dbg("%s - nonzero status: %x", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 return;
873 }
874 if (urb->actual_length < 14) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800875 dbg("%s - %d byte report??", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 goto exit;
877 }
878
879 msg = (struct keyspan_usa90_portStatusMessage *)data;
880
881 /* Now do something useful with the data */
882
883 port = serial->port[0];
884 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100885
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 /* Update handshaking pin state information */
887 old_dcd_state = p_priv->dcd_state;
888 p_priv->cts_state = ((msg->cts) ? 1 : 0);
889 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
890 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
891 p_priv->ri_state = ((msg->ri) ? 1 : 0);
892
Alan Cox4a90f092008-10-13 10:39:46 +0100893 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
894 tty = tty_port_tty_get(&port->port);
895 if (tty && !C_CLOCAL(tty))
896 tty_hangup(tty);
897 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 }
Alan Coxdeb91682008-07-22 11:13:08 +0100899
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100901 err = usb_submit_urb(urb, GFP_ATOMIC);
902 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800903 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904exit:
905 ;
906}
907
David Howells7d12e782006-10-05 14:55:46 +0100908static void usa90_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909{
910 struct usb_serial_port *port;
911 struct keyspan_port_private *p_priv;
912
Ming Leicdc97792008-02-24 18:41:47 +0800913 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 p_priv = usb_get_serial_port_data(port);
915
916 if (p_priv->resend_cont) {
Alan Coxdeb91682008-07-22 11:13:08 +0100917 dbg("%s - sending setup", __func__);
918 keyspan_usa90_send_setup(port->serial, port,
919 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 }
921}
922
Lucy McCoy0ca12682007-05-18 12:10:41 -0700923/* Status messages from the 28xg */
924static void usa67_instat_callback(struct urb *urb)
925{
926 int err;
927 unsigned char *data = urb->transfer_buffer;
928 struct keyspan_usa67_portStatusMessage *msg;
929 struct usb_serial *serial;
930 struct usb_serial_port *port;
931 struct keyspan_port_private *p_priv;
932 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700933 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700934
Lucy McCoy0ca12682007-05-18 12:10:41 -0700935 serial = urb->context;
936
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700937 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800938 dbg("%s - nonzero status: %x", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700939 return;
940 }
941
Alan Coxdeb91682008-07-22 11:13:08 +0100942 if (urb->actual_length !=
943 sizeof(struct keyspan_usa67_portStatusMessage)) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800944 dbg("%s - bad length %d", __func__, urb->actual_length);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700945 return;
946 }
947
948
949 /* Now do something useful with the data */
950 msg = (struct keyspan_usa67_portStatusMessage *)data;
951
952 /* Check port number from message and retrieve private data */
953 if (msg->port >= serial->num_ports) {
Alan Coxdeb91682008-07-22 11:13:08 +0100954 dbg("%s - Unexpected port number %d", __func__, msg->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700955 return;
956 }
957
958 port = serial->port[msg->port];
959 p_priv = usb_get_serial_port_data(port);
960
961 /* Update handshaking pin state information */
962 old_dcd_state = p_priv->dcd_state;
963 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
964 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
965
Alan Cox4a90f092008-10-13 10:39:46 +0100966 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
967 struct tty_struct *tty = tty_port_tty_get(&port->port);
968 if (tty && !C_CLOCAL(tty))
969 tty_hangup(tty);
970 tty_kref_put(tty);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700971 }
972
973 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700974 err = usb_submit_urb(urb, GFP_ATOMIC);
975 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800976 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700977}
978
979static void usa67_glocont_callback(struct urb *urb)
980{
981 struct usb_serial *serial;
982 struct usb_serial_port *port;
983 struct keyspan_port_private *p_priv;
984 int i;
985
Lucy McCoy0ca12682007-05-18 12:10:41 -0700986 serial = urb->context;
987 for (i = 0; i < serial->num_ports; ++i) {
988 port = serial->port[i];
989 p_priv = usb_get_serial_port_data(port);
990
991 if (p_priv->resend_cont) {
Alan Coxdeb91682008-07-22 11:13:08 +0100992 dbg("%s - sending setup", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700993 keyspan_usa67_send_setup(serial, port,
994 p_priv->resend_cont - 1);
995 break;
996 }
997 }
998}
999
Alan Cox95da3102008-07-22 11:09:07 +01001000static int keyspan_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001{
Alan Cox95da3102008-07-22 11:09:07 +01001002 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 struct keyspan_port_private *p_priv;
1004 const struct keyspan_device_details *d_details;
1005 int flip;
1006 int data_len;
1007 struct urb *this_urb;
1008
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 p_priv = usb_get_serial_port_data(port);
1010 d_details = p_priv->device_details;
1011
Alan Coxa5b6f602008-04-08 17:16:06 +01001012 /* FIXME: locking */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 if (d_details->msg_format == msg_usa90)
Alan Coxdeb91682008-07-22 11:13:08 +01001014 data_len = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 else
1016 data_len = 63;
1017
1018 flip = p_priv->out_flip;
1019
1020 /* Check both endpoints to see if any are available. */
Alan Coxdeb91682008-07-22 11:13:08 +01001021 this_urb = p_priv->out_urbs[flip];
1022 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001024 return data_len;
1025 flip = (flip + 1) & d_details->outdat_endp_flip;
1026 this_urb = p_priv->out_urbs[flip];
1027 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001029 return data_len;
1030 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 }
Alan Coxa5b6f602008-04-08 17:16:06 +01001032 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033}
1034
1035
Alan Coxa509a7e2009-09-19 13:13:26 -07001036static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037{
Andrew Mortonf78ba152007-11-28 16:21:54 -08001038 struct keyspan_port_private *p_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 const struct keyspan_device_details *d_details;
1040 int i, err;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001041 int baud_rate, device_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 struct urb *urb;
Alan Cox95da3102008-07-22 11:09:07 +01001043 unsigned int cflag = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 p_priv = usb_get_serial_port_data(port);
1046 d_details = p_priv->device_details;
Borislav Petkov7eea4362007-11-14 17:00:39 -08001047
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 /* Set some sane defaults */
1049 p_priv->rts_state = 1;
1050 p_priv->dtr_state = 1;
1051 p_priv->baud = 9600;
1052
1053 /* force baud and lcr to be set on open */
1054 p_priv->old_baud = 0;
1055 p_priv->old_cflag = 0;
1056
1057 p_priv->out_flip = 0;
1058 p_priv->in_flip = 0;
1059
1060 /* Reset low level data toggle and start reading from endpoints */
1061 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001062 urb = p_priv->in_urbs[i];
1063 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065
Alan Coxdeb91682008-07-22 11:13:08 +01001066 /* make sure endpoint data toggle is synchronized
1067 with the device */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 usb_clear_halt(urb->dev, urb->pipe);
Alan Coxdeb91682008-07-22 11:13:08 +01001069 err = usb_submit_urb(urb, GFP_KERNEL);
1070 if (err != 0)
1071 dbg("%s - submit urb %d failed (%d)",
1072 __func__, i, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 }
1074
1075 /* Reset low level data toggle on out endpoints */
1076 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001077 urb = p_priv->out_urbs[i];
1078 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 continue;
Alan Coxdeb91682008-07-22 11:13:08 +01001080 /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
1081 usb_pipeout(urb->pipe), 0); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 }
1083
Andrew Mortonf78ba152007-11-28 16:21:54 -08001084 /* get the terminal config for the setup message now so we don't
1085 * need to send 2 of them */
1086
Andrew Mortonf78ba152007-11-28 16:21:54 -08001087 device_port = port->number - port->serial->minor;
Alan Cox95da3102008-07-22 11:09:07 +01001088 if (tty) {
1089 cflag = tty->termios->c_cflag;
1090 /* Baud rate calculation takes baud rate as an integer
1091 so other rates can be generated if desired. */
1092 baud_rate = tty_get_baud_rate(tty);
1093 /* If no match or invalid, leave as default */
1094 if (baud_rate >= 0
1095 && d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
1096 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
1097 p_priv->baud = baud_rate;
1098 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001099 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001100 /* set CTS/RTS handshake etc. */
1101 p_priv->cflag = cflag;
Ben Minerds2b982ab2012-07-12 00:10:16 +10001102 p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001103
1104 keyspan_send_setup(port, 1);
Alan Coxdeb91682008-07-22 11:13:08 +01001105 /* mdelay(100); */
1106 /* keyspan_set_termios(port, NULL); */
Andrew Mortonf78ba152007-11-28 16:21:54 -08001107
Alan Coxa5b6f602008-04-08 17:16:06 +01001108 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109}
1110
1111static inline void stop_urb(struct urb *urb)
1112{
Greg Kroah-Hartman242cf672005-07-29 16:11:07 -04001113 if (urb && urb->status == -EINPROGRESS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 usb_kill_urb(urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115}
1116
Alan Cox335f8512009-06-11 12:26:29 +01001117static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
1118{
1119 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
1120
1121 p_priv->rts_state = on;
1122 p_priv->dtr_state = on;
1123 keyspan_send_setup(port, 0);
1124}
1125
1126static void keyspan_close(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127{
1128 int i;
1129 struct usb_serial *serial = port->serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 struct keyspan_port_private *p_priv;
1131
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +01001133
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 p_priv->rts_state = 0;
1135 p_priv->dtr_state = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001136
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 if (serial->dev) {
1138 keyspan_send_setup(port, 2);
1139 /* pilot-xfer seems to work best with this delay */
1140 mdelay(100);
Alan Coxdeb91682008-07-22 11:13:08 +01001141 /* keyspan_set_termios(port, NULL); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142 }
1143
1144 /*while (p_priv->outcont_urb->status == -EINPROGRESS) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001145 dbg("%s - urb in progress", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 }*/
1147
1148 p_priv->out_flip = 0;
1149 p_priv->in_flip = 0;
1150
1151 if (serial->dev) {
1152 /* Stop reading/writing urbs */
1153 stop_urb(p_priv->inack_urb);
1154 /* stop_urb(p_priv->outcont_urb); */
1155 for (i = 0; i < 2; i++) {
1156 stop_urb(p_priv->in_urbs[i]);
1157 stop_urb(p_priv->out_urbs[i]);
1158 }
1159 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160}
1161
Alan Coxdeb91682008-07-22 11:13:08 +01001162/* download the firmware to a pre-renumeration device */
1163static int keyspan_fake_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164{
1165 int response;
David Woodhouse2971c572008-05-30 14:04:03 +03001166 const struct ihex_binrec *record;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 char *fw_name;
David Woodhouse2971c572008-05-30 14:04:03 +03001168 const struct firmware *fw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169
1170 dbg("Keyspan startup version %04x product %04x",
1171 le16_to_cpu(serial->dev->descriptor.bcdDevice),
1172 le16_to_cpu(serial->dev->descriptor.idProduct));
Alan Coxdeb91682008-07-22 11:13:08 +01001173
1174 if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000)
1175 != 0x8000) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 dbg("Firmware already loaded. Quitting.");
Alan Coxdeb91682008-07-22 11:13:08 +01001177 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 }
1179
1180 /* Select firmware image on the basis of idProduct */
1181 switch (le16_to_cpu(serial->dev->descriptor.idProduct)) {
1182 case keyspan_usa28_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001183 fw_name = "keyspan/usa28.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 break;
1185
1186 case keyspan_usa28x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001187 fw_name = "keyspan/usa28x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 break;
1189
1190 case keyspan_usa28xa_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001191 fw_name = "keyspan/usa28xa.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 break;
1193
1194 case keyspan_usa28xb_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001195 fw_name = "keyspan/usa28xb.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 break;
1197
1198 case keyspan_usa19_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001199 fw_name = "keyspan/usa19.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001201
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 case keyspan_usa19qi_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001203 fw_name = "keyspan/usa19qi.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001205
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 case keyspan_mpr_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001207 fw_name = "keyspan/mpr.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 break;
1209
1210 case keyspan_usa19qw_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001211 fw_name = "keyspan/usa19qw.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001213
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 case keyspan_usa18x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001215 fw_name = "keyspan/usa18x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001217
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 case keyspan_usa19w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001219 fw_name = "keyspan/usa19w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001221
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 case keyspan_usa49w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001223 fw_name = "keyspan/usa49w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 break;
1225
1226 case keyspan_usa49wlc_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001227 fw_name = "keyspan/usa49wlc.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 break;
1229
1230 default:
David Woodhouse2971c572008-05-30 14:04:03 +03001231 dev_err(&serial->dev->dev, "Unknown product ID (%04x)\n",
1232 le16_to_cpu(serial->dev->descriptor.idProduct));
1233 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 }
1235
David Woodhouse2971c572008-05-30 14:04:03 +03001236 if (request_ihex_firmware(&fw, fw_name, &serial->dev->dev)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 dev_err(&serial->dev->dev, "Required keyspan firmware image (%s) unavailable.\n", fw_name);
Ben Minerdsf9943c22012-07-12 00:10:20 +10001238 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 }
1240
1241 dbg("Uploading Keyspan %s firmware.", fw_name);
1242
1243 /* download the firmware image */
1244 response = ezusb_set_reset(serial, 1);
1245
David Woodhouse2971c572008-05-30 14:04:03 +03001246 record = (const struct ihex_binrec *)fw->data;
1247
1248 while (record) {
1249 response = ezusb_writememory(serial, be32_to_cpu(record->addr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 (unsigned char *)record->data,
David Woodhouse2971c572008-05-30 14:04:03 +03001251 be16_to_cpu(record->len), 0xa0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 if (response < 0) {
Alan Coxdeb91682008-07-22 11:13:08 +01001253 dev_err(&serial->dev->dev, "ezusb_writememory failed for Keyspan firmware (%d %04X %p %d)\n",
David Woodhouse2971c572008-05-30 14:04:03 +03001254 response, be32_to_cpu(record->addr),
1255 record->data, be16_to_cpu(record->len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 break;
1257 }
David Woodhouse2971c572008-05-30 14:04:03 +03001258 record = ihex_next_binrec(record);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 }
David Woodhouse2971c572008-05-30 14:04:03 +03001260 release_firmware(fw);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 /* bring device out of reset. Renumeration will occur in a
1262 moment and the new device will bind to the real driver */
1263 response = ezusb_set_reset(serial, 0);
1264
1265 /* we don't want this device to have a driver assigned to it. */
Alan Coxdeb91682008-07-22 11:13:08 +01001266 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267}
1268
1269/* Helper functions used by keyspan_setup_urbs */
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001270static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *serial,
1271 int endpoint)
1272{
1273 struct usb_host_interface *iface_desc;
1274 struct usb_endpoint_descriptor *ep;
1275 int i;
1276
1277 iface_desc = serial->interface->cur_altsetting;
1278 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1279 ep = &iface_desc->endpoint[i].desc;
1280 if (ep->bEndpointAddress == endpoint)
1281 return ep;
1282 }
1283 dev_warn(&serial->interface->dev, "found no endpoint descriptor for "
1284 "endpoint %x\n", endpoint);
1285 return NULL;
1286}
1287
Alan Coxdeb91682008-07-22 11:13:08 +01001288static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 int dir, void *ctx, char *buf, int len,
David Howells7d12e782006-10-05 14:55:46 +01001290 void (*callback)(struct urb *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291{
1292 struct urb *urb;
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001293 struct usb_endpoint_descriptor const *ep_desc;
1294 char const *ep_type_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295
1296 if (endpoint == -1)
1297 return NULL; /* endpoint not needed */
1298
Alan Coxdeb91682008-07-22 11:13:08 +01001299 dbg("%s - alloc for endpoint %d.", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
1301 if (urb == NULL) {
Alan Coxdeb91682008-07-22 11:13:08 +01001302 dbg("%s - alloc for endpoint %d failed.", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 return NULL;
1304 }
1305
Lucy McCoy0ca12682007-05-18 12:10:41 -07001306 if (endpoint == 0) {
1307 /* control EP filled in when used */
1308 return urb;
1309 }
1310
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001311 ep_desc = find_ep(serial, endpoint);
1312 if (!ep_desc) {
1313 /* leak the urb, something's wrong and the callers don't care */
1314 return urb;
1315 }
1316 if (usb_endpoint_xfer_int(ep_desc)) {
1317 ep_type_name = "INT";
1318 usb_fill_int_urb(urb, serial->dev,
1319 usb_sndintpipe(serial->dev, endpoint) | dir,
1320 buf, len, callback, ctx,
1321 ep_desc->bInterval);
1322 } else if (usb_endpoint_xfer_bulk(ep_desc)) {
1323 ep_type_name = "BULK";
1324 usb_fill_bulk_urb(urb, serial->dev,
1325 usb_sndbulkpipe(serial->dev, endpoint) | dir,
1326 buf, len, callback, ctx);
1327 } else {
1328 dev_warn(&serial->interface->dev,
1329 "unsupported endpoint type %x\n",
Julia Lawall2e0fe702008-12-29 11:22:14 +01001330 usb_endpoint_type(ep_desc));
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001331 usb_free_urb(urb);
1332 return NULL;
1333 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001335 dbg("%s - using urb %p for %s endpoint %x",
1336 __func__, urb, ep_type_name, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 return urb;
1338}
1339
1340static struct callbacks {
David Howells7d12e782006-10-05 14:55:46 +01001341 void (*instat_callback)(struct urb *);
1342 void (*glocont_callback)(struct urb *);
1343 void (*indat_callback)(struct urb *);
1344 void (*outdat_callback)(struct urb *);
1345 void (*inack_callback)(struct urb *);
1346 void (*outcont_callback)(struct urb *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347} keyspan_callbacks[] = {
1348 {
1349 /* msg_usa26 callbacks */
1350 .instat_callback = usa26_instat_callback,
1351 .glocont_callback = usa26_glocont_callback,
1352 .indat_callback = usa26_indat_callback,
1353 .outdat_callback = usa2x_outdat_callback,
1354 .inack_callback = usa26_inack_callback,
1355 .outcont_callback = usa26_outcont_callback,
1356 }, {
1357 /* msg_usa28 callbacks */
1358 .instat_callback = usa28_instat_callback,
1359 .glocont_callback = usa28_glocont_callback,
1360 .indat_callback = usa28_indat_callback,
1361 .outdat_callback = usa2x_outdat_callback,
1362 .inack_callback = usa28_inack_callback,
1363 .outcont_callback = usa28_outcont_callback,
1364 }, {
1365 /* msg_usa49 callbacks */
1366 .instat_callback = usa49_instat_callback,
1367 .glocont_callback = usa49_glocont_callback,
1368 .indat_callback = usa49_indat_callback,
1369 .outdat_callback = usa2x_outdat_callback,
1370 .inack_callback = usa49_inack_callback,
1371 .outcont_callback = usa49_outcont_callback,
1372 }, {
1373 /* msg_usa90 callbacks */
1374 .instat_callback = usa90_instat_callback,
Alan Coxdeb91682008-07-22 11:13:08 +01001375 .glocont_callback = usa28_glocont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 .indat_callback = usa90_indat_callback,
1377 .outdat_callback = usa2x_outdat_callback,
1378 .inack_callback = usa28_inack_callback,
1379 .outcont_callback = usa90_outcont_callback,
Lucy McCoy0ca12682007-05-18 12:10:41 -07001380 }, {
1381 /* msg_usa67 callbacks */
1382 .instat_callback = usa67_instat_callback,
1383 .glocont_callback = usa67_glocont_callback,
1384 .indat_callback = usa26_indat_callback,
1385 .outdat_callback = usa2x_outdat_callback,
1386 .inack_callback = usa26_inack_callback,
1387 .outcont_callback = usa26_outcont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388 }
1389};
1390
1391 /* Generic setup urbs function that uses
1392 data in device_details */
1393static void keyspan_setup_urbs(struct usb_serial *serial)
1394{
1395 int i, j;
1396 struct keyspan_serial_private *s_priv;
1397 const struct keyspan_device_details *d_details;
1398 struct usb_serial_port *port;
1399 struct keyspan_port_private *p_priv;
1400 struct callbacks *cback;
1401 int endp;
1402
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 s_priv = usb_get_serial_data(serial);
1404 d_details = s_priv->device_details;
1405
Alan Coxdeb91682008-07-22 11:13:08 +01001406 /* Setup values for the various callback routines */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 cback = &keyspan_callbacks[d_details->msg_format];
1408
Alan Coxdeb91682008-07-22 11:13:08 +01001409 /* Allocate and set up urbs for each one that is in use,
1410 starting with instat endpoints */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 s_priv->instat_urb = keyspan_setup_urb
1412 (serial, d_details->instat_endpoint, USB_DIR_IN,
1413 serial, s_priv->instat_buf, INSTAT_BUFLEN,
1414 cback->instat_callback);
1415
Lucy McCoy0ca12682007-05-18 12:10:41 -07001416 s_priv->indat_urb = keyspan_setup_urb
1417 (serial, d_details->indat_endpoint, USB_DIR_IN,
1418 serial, s_priv->indat_buf, INDAT49W_BUFLEN,
1419 usa49wg_indat_callback);
1420
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 s_priv->glocont_urb = keyspan_setup_urb
1422 (serial, d_details->glocont_endpoint, USB_DIR_OUT,
1423 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
1424 cback->glocont_callback);
1425
Alan Coxdeb91682008-07-22 11:13:08 +01001426 /* Setup endpoints for each port specific thing */
1427 for (i = 0; i < d_details->num_ports; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 port = serial->port[i];
1429 p_priv = usb_get_serial_port_data(port);
1430
1431 /* Do indat endpoints first, once for each flip */
1432 endp = d_details->indat_endpoints[i];
1433 for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) {
1434 p_priv->in_urbs[j] = keyspan_setup_urb
1435 (serial, endp, USB_DIR_IN, port,
1436 p_priv->in_buffer[j], 64,
1437 cback->indat_callback);
1438 }
1439 for (; j < 2; ++j)
1440 p_priv->in_urbs[j] = NULL;
1441
1442 /* outdat endpoints also have flip */
1443 endp = d_details->outdat_endpoints[i];
1444 for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) {
1445 p_priv->out_urbs[j] = keyspan_setup_urb
1446 (serial, endp, USB_DIR_OUT, port,
1447 p_priv->out_buffer[j], 64,
1448 cback->outdat_callback);
1449 }
1450 for (; j < 2; ++j)
1451 p_priv->out_urbs[j] = NULL;
1452
1453 /* inack endpoint */
1454 p_priv->inack_urb = keyspan_setup_urb
1455 (serial, d_details->inack_endpoints[i], USB_DIR_IN,
1456 port, p_priv->inack_buffer, 1, cback->inack_callback);
1457
1458 /* outcont endpoint */
1459 p_priv->outcont_urb = keyspan_setup_urb
1460 (serial, d_details->outcont_endpoints[i], USB_DIR_OUT,
1461 port, p_priv->outcont_buffer, 64,
1462 cback->outcont_callback);
Alan Coxdeb91682008-07-22 11:13:08 +01001463 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464}
1465
1466/* usa19 function doesn't require prescaler */
1467static int keyspan_usa19_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
1468 u8 *rate_low, u8 *prescaler, int portnum)
1469{
1470 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001471 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 cnt; /* inverse of divisor (programmed into 8051) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473
Alan Coxdeb91682008-07-22 11:13:08 +01001474 dbg("%s - %d.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475
Alan Coxdeb91682008-07-22 11:13:08 +01001476 /* prevent divide by zero... */
1477 b16 = baud_rate * 16L;
1478 if (b16 == 0)
1479 return KEYSPAN_INVALID_BAUD_RATE;
1480 /* Any "standard" rate over 57k6 is marginal on the USA-19
1481 as we run out of divisor resolution. */
1482 if (baud_rate > 57600)
1483 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484
Alan Coxdeb91682008-07-22 11:13:08 +01001485 /* calculate the divisor and the counter (its inverse) */
1486 div = baudclk / b16;
1487 if (div == 0)
1488 return KEYSPAN_INVALID_BAUD_RATE;
1489 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491
Alan Coxdeb91682008-07-22 11:13:08 +01001492 if (div > 0xffff)
1493 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494
Alan Coxdeb91682008-07-22 11:13:08 +01001495 /* return the counter values if non-null */
1496 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001498 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001500 if (rate_low && rate_hi)
1501 dbg("%s - %d %02x %02x.",
1502 __func__, baud_rate, *rate_hi, *rate_low);
1503 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504}
1505
1506/* usa19hs function doesn't require prescaler */
1507static int keyspan_usa19hs_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
1508 u8 *rate_low, u8 *prescaler, int portnum)
1509{
1510 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001511 div; /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512
Alan Coxdeb91682008-07-22 11:13:08 +01001513 dbg("%s - %d.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514
Alan Coxdeb91682008-07-22 11:13:08 +01001515 /* prevent divide by zero... */
1516 b16 = baud_rate * 16L;
1517 if (b16 == 0)
1518 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519
Alan Coxdeb91682008-07-22 11:13:08 +01001520 /* calculate the divisor */
1521 div = baudclk / b16;
1522 if (div == 0)
1523 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524
Alan Coxdeb91682008-07-22 11:13:08 +01001525 if (div > 0xffff)
1526 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527
Alan Coxdeb91682008-07-22 11:13:08 +01001528 /* return the counter values if non-null */
1529 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001531
1532 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533 *rate_hi = (u8) ((div >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001534
1535 if (rate_low && rate_hi)
1536 dbg("%s - %d %02x %02x.",
1537 __func__, baud_rate, *rate_hi, *rate_low);
1538
1539 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540}
1541
1542static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
1543 u8 *rate_low, u8 *prescaler, int portnum)
1544{
1545 u32 b16, /* baud rate times 16 (actual rate used internally) */
1546 clk, /* clock with 13/8 prescaler */
Alan Coxdeb91682008-07-22 11:13:08 +01001547 div, /* divisor using 13/8 prescaler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 res, /* resulting baud rate using 13/8 prescaler */
1549 diff, /* error using 13/8 prescaler */
1550 smallest_diff;
1551 u8 best_prescaler;
1552 int i;
1553
Alan Coxdeb91682008-07-22 11:13:08 +01001554 dbg("%s - %d.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555
Alan Coxdeb91682008-07-22 11:13:08 +01001556 /* prevent divide by zero */
1557 b16 = baud_rate * 16L;
1558 if (b16 == 0)
1559 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560
Alan Coxdeb91682008-07-22 11:13:08 +01001561 /* Calculate prescaler by trying them all and looking
1562 for best fit */
1563
1564 /* start with largest possible difference */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565 smallest_diff = 0xffffffff;
1566
1567 /* 0 is an invalid prescaler, used as a flag */
1568 best_prescaler = 0;
1569
Alan Coxdeb91682008-07-22 11:13:08 +01001570 for (i = 8; i <= 0xff; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571 clk = (baudclk * 8) / (u32) i;
Alan Coxdeb91682008-07-22 11:13:08 +01001572
1573 div = clk / b16;
1574 if (div == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576
1577 res = clk / div;
Alan Coxdeb91682008-07-22 11:13:08 +01001578 diff = (res > b16) ? (res-b16) : (b16-res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579
Alan Coxdeb91682008-07-22 11:13:08 +01001580 if (diff < smallest_diff) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 best_prescaler = i;
1582 smallest_diff = diff;
1583 }
1584 }
1585
Alan Coxdeb91682008-07-22 11:13:08 +01001586 if (best_prescaler == 0)
1587 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588
1589 clk = (baudclk * 8) / (u32) best_prescaler;
1590 div = clk / b16;
1591
Alan Coxdeb91682008-07-22 11:13:08 +01001592 /* return the divisor and prescaler if non-null */
1593 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001595 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 *rate_hi = (u8) ((div >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597 if (prescaler) {
1598 *prescaler = best_prescaler;
Harvey Harrison441b62c2008-03-03 16:08:34 -08001599 /* dbg("%s - %d %d", __func__, *prescaler, div); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600 }
Alan Coxdeb91682008-07-22 11:13:08 +01001601 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602}
1603
1604 /* USA-28 supports different maximum baud rates on each port */
1605static int keyspan_usa28_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
1606 u8 *rate_low, u8 *prescaler, int portnum)
1607{
1608 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001609 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 cnt; /* inverse of divisor (programmed into 8051) */
1611
Alan Coxdeb91682008-07-22 11:13:08 +01001612 dbg("%s - %d.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613
1614 /* prevent divide by zero */
Alan Coxdeb91682008-07-22 11:13:08 +01001615 b16 = baud_rate * 16L;
1616 if (b16 == 0)
1617 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618
Alan Coxdeb91682008-07-22 11:13:08 +01001619 /* calculate the divisor and the counter (its inverse) */
1620 div = KEYSPAN_USA28_BAUDCLK / b16;
1621 if (div == 0)
1622 return KEYSPAN_INVALID_BAUD_RATE;
1623 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625
Alan Coxdeb91682008-07-22 11:13:08 +01001626 /* check for out of range, based on portnum,
1627 and return result */
1628 if (portnum == 0) {
1629 if (div > 0xffff)
1630 return KEYSPAN_INVALID_BAUD_RATE;
1631 } else {
1632 if (portnum == 1) {
1633 if (div > 0xff)
1634 return KEYSPAN_INVALID_BAUD_RATE;
1635 } else
1636 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 }
1638
1639 /* return the counter values if not NULL
1640 (port 1 will ignore retHi) */
Alan Coxdeb91682008-07-22 11:13:08 +01001641 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001643 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001645 dbg("%s - %d OK.", __func__, baud_rate);
1646 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647}
1648
1649static int keyspan_usa26_send_setup(struct usb_serial *serial,
1650 struct usb_serial_port *port,
1651 int reset_port)
1652{
Alan Coxdeb91682008-07-22 11:13:08 +01001653 struct keyspan_usa26_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 struct keyspan_serial_private *s_priv;
1655 struct keyspan_port_private *p_priv;
1656 const struct keyspan_device_details *d_details;
1657 int outcont_urb;
1658 struct urb *this_urb;
1659 int device_port, err;
1660
Alan Coxdeb91682008-07-22 11:13:08 +01001661 dbg("%s reset=%d", __func__, reset_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662
1663 s_priv = usb_get_serial_data(serial);
1664 p_priv = usb_get_serial_port_data(port);
1665 d_details = s_priv->device_details;
1666 device_port = port->number - port->serial->minor;
1667
1668 outcont_urb = d_details->outcont_endpoints[port->number];
1669 this_urb = p_priv->outcont_urb;
1670
Harvey Harrison441b62c2008-03-03 16:08:34 -08001671 dbg("%s - endpoint %d", __func__, usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672
1673 /* Make sure we have an urb then send the message */
1674 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001675 dbg("%s - oops no urb.", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676 return -1;
1677 }
1678
1679 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001680 Don't overwrite resend for open/close condition. */
1681 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 p_priv->resend_cont = reset_port + 1;
1683 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +01001684 /* dbg("%s - already writing", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001686 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687 }
1688
Alan Coxdeb91682008-07-22 11:13:08 +01001689 memset(&msg, 0, sizeof(struct keyspan_usa26_portControlMessage));
1690
1691 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692 if (p_priv->old_baud != p_priv->baud) {
1693 p_priv->old_baud = p_priv->baud;
1694 msg.setClocking = 0xff;
1695 if (d_details->calculate_baud_rate
1696 (p_priv->baud, d_details->baudclk, &msg.baudHi,
Alan Coxdeb91682008-07-22 11:13:08 +01001697 &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1698 dbg("%s - Invalid baud rate %d requested, using 9600.",
1699 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 msg.baudLo = 0;
1701 msg.baudHi = 125; /* Values for 9600 baud */
1702 msg.prescaler = 10;
1703 }
1704 msg.setPrescaler = 0xff;
1705 }
1706
Ben Minerds2b982ab2012-07-12 00:10:16 +10001707 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 switch (p_priv->cflag & CSIZE) {
1709 case CS5:
1710 msg.lcr |= USA_DATABITS_5;
1711 break;
1712 case CS6:
1713 msg.lcr |= USA_DATABITS_6;
1714 break;
1715 case CS7:
1716 msg.lcr |= USA_DATABITS_7;
1717 break;
1718 case CS8:
1719 msg.lcr |= USA_DATABITS_8;
1720 break;
1721 }
1722 if (p_priv->cflag & PARENB) {
1723 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10001724 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01001725 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726 }
1727 msg.setLcr = 0xff;
1728
1729 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1730 msg.xonFlowControl = 0;
1731 msg.setFlowControl = 0xff;
1732 msg.forwardingLength = 16;
1733 msg.xonChar = 17;
1734 msg.xoffChar = 19;
1735
1736 /* Opening port */
1737 if (reset_port == 1) {
1738 msg._txOn = 1;
1739 msg._txOff = 0;
1740 msg.txFlush = 0;
1741 msg.txBreak = 0;
1742 msg.rxOn = 1;
1743 msg.rxOff = 0;
1744 msg.rxFlush = 1;
1745 msg.rxForward = 0;
1746 msg.returnStatus = 0;
1747 msg.resetDataToggle = 0xff;
1748 }
1749
1750 /* Closing port */
1751 else if (reset_port == 2) {
1752 msg._txOn = 0;
1753 msg._txOff = 1;
1754 msg.txFlush = 0;
1755 msg.txBreak = 0;
1756 msg.rxOn = 0;
1757 msg.rxOff = 1;
1758 msg.rxFlush = 1;
1759 msg.rxForward = 0;
1760 msg.returnStatus = 0;
1761 msg.resetDataToggle = 0;
1762 }
1763
1764 /* Sending intermediate configs */
1765 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001766 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767 msg._txOff = 0;
1768 msg.txFlush = 0;
1769 msg.txBreak = (p_priv->break_on);
1770 msg.rxOn = 0;
1771 msg.rxOff = 0;
1772 msg.rxFlush = 0;
1773 msg.rxForward = 0;
1774 msg.returnStatus = 0;
1775 msg.resetDataToggle = 0x0;
1776 }
1777
Alan Coxdeb91682008-07-22 11:13:08 +01001778 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779 msg.setTxTriState_setRts = 0xff;
1780 msg.txTriState_rts = p_priv->rts_state;
1781
1782 msg.setHskoa_setDtr = 0xff;
1783 msg.hskoa_dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01001784
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001786 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
1787
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788 /* send the data out the device on control endpoint */
1789 this_urb->transfer_buffer_length = sizeof(msg);
1790
Alan Coxdeb91682008-07-22 11:13:08 +01001791 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1792 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08001793 dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794#if 0
1795 else {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001796 dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797 outcont_urb, this_urb->transfer_buffer_length,
1798 usb_pipeendpoint(this_urb->pipe));
1799 }
1800#endif
1801
Alan Coxa5b6f602008-04-08 17:16:06 +01001802 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803}
1804
1805static int keyspan_usa28_send_setup(struct usb_serial *serial,
1806 struct usb_serial_port *port,
1807 int reset_port)
1808{
Alan Coxdeb91682008-07-22 11:13:08 +01001809 struct keyspan_usa28_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 struct keyspan_serial_private *s_priv;
1811 struct keyspan_port_private *p_priv;
1812 const struct keyspan_device_details *d_details;
1813 struct urb *this_urb;
1814 int device_port, err;
1815
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816 s_priv = usb_get_serial_data(serial);
1817 p_priv = usb_get_serial_port_data(port);
1818 d_details = s_priv->device_details;
1819 device_port = port->number - port->serial->minor;
1820
1821 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01001822 this_urb = p_priv->outcont_urb;
1823 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001824 dbg("%s - oops no urb.", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825 return -1;
1826 }
1827
1828 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001829 Don't overwrite resend for open/close condition. */
1830 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831 p_priv->resend_cont = reset_port + 1;
1832 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +01001833 dbg("%s already writing", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001835 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 }
1837
Alan Coxdeb91682008-07-22 11:13:08 +01001838 memset(&msg, 0, sizeof(struct keyspan_usa28_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839
1840 msg.setBaudRate = 1;
1841 if (d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk,
Alan Coxdeb91682008-07-22 11:13:08 +01001842 &msg.baudHi, &msg.baudLo, NULL, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1843 dbg("%s - Invalid baud rate requested %d.",
1844 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845 msg.baudLo = 0xff;
1846 msg.baudHi = 0xb2; /* Values for 9600 baud */
1847 }
1848
1849 /* If parity is enabled, we must calculate it ourselves. */
1850 msg.parity = 0; /* XXX for now */
1851
1852 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1853 msg.xonFlowControl = 0;
1854
Alan Coxdeb91682008-07-22 11:13:08 +01001855 /* Do handshaking outputs, DTR is inverted relative to RTS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856 msg.rts = p_priv->rts_state;
1857 msg.dtr = p_priv->dtr_state;
1858
1859 msg.forwardingLength = 16;
1860 msg.forwardMs = 10;
1861 msg.breakThreshold = 45;
1862 msg.xonChar = 17;
1863 msg.xoffChar = 19;
1864
1865 /*msg.returnStatus = 1;
1866 msg.resetDataToggle = 0xff;*/
1867 /* Opening port */
1868 if (reset_port == 1) {
1869 msg._txOn = 1;
1870 msg._txOff = 0;
1871 msg.txFlush = 0;
1872 msg.txForceXoff = 0;
1873 msg.txBreak = 0;
1874 msg.rxOn = 1;
1875 msg.rxOff = 0;
1876 msg.rxFlush = 1;
1877 msg.rxForward = 0;
1878 msg.returnStatus = 0;
1879 msg.resetDataToggle = 0xff;
1880 }
1881 /* Closing port */
1882 else if (reset_port == 2) {
1883 msg._txOn = 0;
1884 msg._txOff = 1;
1885 msg.txFlush = 0;
1886 msg.txForceXoff = 0;
1887 msg.txBreak = 0;
1888 msg.rxOn = 0;
1889 msg.rxOff = 1;
1890 msg.rxFlush = 1;
1891 msg.rxForward = 0;
1892 msg.returnStatus = 0;
1893 msg.resetDataToggle = 0;
1894 }
1895 /* Sending intermediate configs */
1896 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001897 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 msg._txOff = 0;
1899 msg.txFlush = 0;
1900 msg.txForceXoff = 0;
1901 msg.txBreak = (p_priv->break_on);
1902 msg.rxOn = 0;
1903 msg.rxOff = 0;
1904 msg.rxFlush = 0;
1905 msg.rxForward = 0;
1906 msg.returnStatus = 0;
1907 msg.resetDataToggle = 0x0;
1908 }
1909
1910 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001911 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912
1913 /* send the data out the device on control endpoint */
1914 this_urb->transfer_buffer_length = sizeof(msg);
1915
Alan Coxdeb91682008-07-22 11:13:08 +01001916 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1917 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08001918 dbg("%s - usb_submit_urb(setup) failed", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919#if 0
1920 else {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001921 dbg("%s - usb_submit_urb(setup) OK %d bytes", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922 this_urb->transfer_buffer_length);
1923 }
1924#endif
1925
Alan Coxa5b6f602008-04-08 17:16:06 +01001926 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927}
1928
1929static int keyspan_usa49_send_setup(struct usb_serial *serial,
1930 struct usb_serial_port *port,
1931 int reset_port)
1932{
Lucy McCoy0ca12682007-05-18 12:10:41 -07001933 struct keyspan_usa49_portControlMessage msg;
1934 struct usb_ctrlrequest *dr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935 struct keyspan_serial_private *s_priv;
1936 struct keyspan_port_private *p_priv;
1937 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 struct urb *this_urb;
1939 int err, device_port;
1940
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941 s_priv = usb_get_serial_data(serial);
1942 p_priv = usb_get_serial_port_data(port);
1943 d_details = s_priv->device_details;
1944
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 this_urb = s_priv->glocont_urb;
1946
Lucy McCoy0ca12682007-05-18 12:10:41 -07001947 /* Work out which port within the device is being setup */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948 device_port = port->number - port->serial->minor;
1949
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05301950 /* Make sure we have an urb then send the message */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001952 dbg("%s - oops no urb for port %d.", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953 return -1;
1954 }
1955
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05301956 dbg("%s - endpoint %d port %d (%d)",
1957 __func__, usb_pipeendpoint(this_urb->pipe),
1958 port->number, device_port);
1959
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001961 Don't overwrite resend for open/close condition. */
1962 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 p_priv->resend_cont = reset_port + 1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001964
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +01001966 /* dbg("%s - already writing", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001968 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 }
1970
Alan Coxdeb91682008-07-22 11:13:08 +01001971 memset(&msg, 0, sizeof(struct keyspan_usa49_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972
1973 /*msg.portNumber = port->number;*/
1974 msg.portNumber = device_port;
Alan Coxdeb91682008-07-22 11:13:08 +01001975
1976 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977 if (p_priv->old_baud != p_priv->baud) {
1978 p_priv->old_baud = p_priv->baud;
1979 msg.setClocking = 0xff;
1980 if (d_details->calculate_baud_rate
1981 (p_priv->baud, d_details->baudclk, &msg.baudHi,
Alan Coxdeb91682008-07-22 11:13:08 +01001982 &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1983 dbg("%s - Invalid baud rate %d requested, using 9600.",
1984 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 msg.baudLo = 0;
1986 msg.baudHi = 125; /* Values for 9600 baud */
1987 msg.prescaler = 10;
1988 }
Alan Coxdeb91682008-07-22 11:13:08 +01001989 /* msg.setPrescaler = 0xff; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 }
1991
Ben Minerds2b982ab2012-07-12 00:10:16 +10001992 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993 switch (p_priv->cflag & CSIZE) {
1994 case CS5:
1995 msg.lcr |= USA_DATABITS_5;
1996 break;
1997 case CS6:
1998 msg.lcr |= USA_DATABITS_6;
1999 break;
2000 case CS7:
2001 msg.lcr |= USA_DATABITS_7;
2002 break;
2003 case CS8:
2004 msg.lcr |= USA_DATABITS_8;
2005 break;
2006 }
2007 if (p_priv->cflag & PARENB) {
2008 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002009 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002010 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011 }
2012 msg.setLcr = 0xff;
2013
2014 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2015 msg.xonFlowControl = 0;
2016 msg.setFlowControl = 0xff;
Alan Coxdeb91682008-07-22 11:13:08 +01002017
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018 msg.forwardingLength = 16;
2019 msg.xonChar = 17;
2020 msg.xoffChar = 19;
2021
Alan Coxdeb91682008-07-22 11:13:08 +01002022 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023 if (reset_port == 1) {
2024 msg._txOn = 1;
2025 msg._txOff = 0;
2026 msg.txFlush = 0;
2027 msg.txBreak = 0;
2028 msg.rxOn = 1;
2029 msg.rxOff = 0;
2030 msg.rxFlush = 1;
2031 msg.rxForward = 0;
2032 msg.returnStatus = 0;
2033 msg.resetDataToggle = 0xff;
2034 msg.enablePort = 1;
2035 msg.disablePort = 0;
2036 }
2037 /* Closing port */
2038 else if (reset_port == 2) {
2039 msg._txOn = 0;
2040 msg._txOff = 1;
2041 msg.txFlush = 0;
2042 msg.txBreak = 0;
2043 msg.rxOn = 0;
2044 msg.rxOff = 1;
2045 msg.rxFlush = 1;
2046 msg.rxForward = 0;
2047 msg.returnStatus = 0;
2048 msg.resetDataToggle = 0;
2049 msg.enablePort = 0;
2050 msg.disablePort = 1;
2051 }
2052 /* Sending intermediate configs */
2053 else {
Alan Coxdeb91682008-07-22 11:13:08 +01002054 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055 msg._txOff = 0;
2056 msg.txFlush = 0;
2057 msg.txBreak = (p_priv->break_on);
2058 msg.rxOn = 0;
2059 msg.rxOff = 0;
2060 msg.rxFlush = 0;
2061 msg.rxForward = 0;
2062 msg.returnStatus = 0;
2063 msg.resetDataToggle = 0x0;
2064 msg.enablePort = 0;
2065 msg.disablePort = 0;
2066 }
2067
Alan Coxdeb91682008-07-22 11:13:08 +01002068 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069 msg.setRts = 0xff;
2070 msg.rts = p_priv->rts_state;
2071
2072 msg.setDtr = 0xff;
2073 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002074
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075 p_priv->resend_cont = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076
Alan Coxdeb91682008-07-22 11:13:08 +01002077 /* if the device is a 49wg, we send control message on usb
2078 control EP 0 */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002079
2080 if (d_details->product_id == keyspan_usa49wg_product_id) {
2081 dr = (void *)(s_priv->ctrl_buf);
2082 dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT;
2083 dr->bRequest = 0xB0; /* 49wg control message */;
2084 dr->wValue = 0;
2085 dr->wIndex = 0;
2086 dr->wLength = cpu_to_le16(sizeof(msg));
2087
Alan Coxdeb91682008-07-22 11:13:08 +01002088 memcpy(s_priv->glocont_buf, &msg, sizeof(msg));
Lucy McCoy0ca12682007-05-18 12:10:41 -07002089
Alan Coxdeb91682008-07-22 11:13:08 +01002090 usb_fill_control_urb(this_urb, serial->dev,
2091 usb_sndctrlpipe(serial->dev, 0),
2092 (unsigned char *)dr, s_priv->glocont_buf,
2093 sizeof(msg), usa49_glocont_callback, serial);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002094
2095 } else {
2096 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Alan Coxdeb91682008-07-22 11:13:08 +01002097
Lucy McCoy0ca12682007-05-18 12:10:41 -07002098 /* send the data out the device on control endpoint */
2099 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002100 }
Alan Coxdeb91682008-07-22 11:13:08 +01002101 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2102 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002103 dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104#if 0
2105 else {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002106 dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002107 outcont_urb, this_urb->transfer_buffer_length,
2108 usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109 }
2110#endif
2111
Alan Coxa5b6f602008-04-08 17:16:06 +01002112 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113}
2114
2115static int keyspan_usa90_send_setup(struct usb_serial *serial,
2116 struct usb_serial_port *port,
2117 int reset_port)
2118{
Alan Coxdeb91682008-07-22 11:13:08 +01002119 struct keyspan_usa90_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120 struct keyspan_serial_private *s_priv;
2121 struct keyspan_port_private *p_priv;
2122 const struct keyspan_device_details *d_details;
2123 struct urb *this_urb;
2124 int err;
2125 u8 prescaler;
2126
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 s_priv = usb_get_serial_data(serial);
2128 p_priv = usb_get_serial_port_data(port);
2129 d_details = s_priv->device_details;
2130
2131 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01002132 this_urb = p_priv->outcont_urb;
2133 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002134 dbg("%s - oops no urb.", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135 return -1;
2136 }
2137
2138 /* Save reset port val for resend.
2139 Don't overwrite resend for open/close condition. */
2140 if ((reset_port + 1) > p_priv->resend_cont)
2141 p_priv->resend_cont = reset_port + 1;
2142 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +01002143 dbg("%s already writing", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002145 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 }
2147
Alan Coxdeb91682008-07-22 11:13:08 +01002148 memset(&msg, 0, sizeof(struct keyspan_usa90_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149
Alan Coxdeb91682008-07-22 11:13:08 +01002150 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 if (p_priv->old_baud != p_priv->baud) {
2152 p_priv->old_baud = p_priv->baud;
2153 msg.setClocking = 0x01;
2154 if (d_details->calculate_baud_rate
2155 (p_priv->baud, d_details->baudclk, &msg.baudHi,
Alan Coxdeb91682008-07-22 11:13:08 +01002156 &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) {
2157 dbg("%s - Invalid baud rate %d requested, using 9600.",
2158 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159 p_priv->baud = 9600;
Alan Coxdeb91682008-07-22 11:13:08 +01002160 d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161 &msg.baudHi, &msg.baudLo, &prescaler, 0);
2162 }
2163 msg.setRxMode = 1;
2164 msg.setTxMode = 1;
2165 }
2166
2167 /* modes must always be correctly specified */
Alan Coxdeb91682008-07-22 11:13:08 +01002168 if (p_priv->baud > 57600) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 msg.rxMode = RXMODE_DMA;
2170 msg.txMode = TXMODE_DMA;
Alan Coxdeb91682008-07-22 11:13:08 +01002171 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172 msg.rxMode = RXMODE_BYHAND;
2173 msg.txMode = TXMODE_BYHAND;
2174 }
2175
Ben Minerds2b982ab2012-07-12 00:10:16 +10002176 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177 switch (p_priv->cflag & CSIZE) {
2178 case CS5:
2179 msg.lcr |= USA_DATABITS_5;
2180 break;
2181 case CS6:
2182 msg.lcr |= USA_DATABITS_6;
2183 break;
2184 case CS7:
2185 msg.lcr |= USA_DATABITS_7;
2186 break;
2187 case CS8:
2188 msg.lcr |= USA_DATABITS_8;
2189 break;
2190 }
2191 if (p_priv->cflag & PARENB) {
2192 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002193 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002194 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195 }
2196 if (p_priv->old_cflag != p_priv->cflag) {
2197 p_priv->old_cflag = p_priv->cflag;
2198 msg.setLcr = 0x01;
2199 }
2200
2201 if (p_priv->flow_control == flow_cts)
2202 msg.txFlowControl = TXFLOW_CTS;
2203 msg.setTxFlowControl = 0x01;
2204 msg.setRxFlowControl = 0x01;
Alan Coxdeb91682008-07-22 11:13:08 +01002205
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 msg.rxForwardingLength = 16;
Alan Coxdeb91682008-07-22 11:13:08 +01002207 msg.rxForwardingTimeout = 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 msg.txAckSetting = 0;
2209 msg.xonChar = 17;
2210 msg.xoffChar = 19;
2211
Alan Coxdeb91682008-07-22 11:13:08 +01002212 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213 if (reset_port == 1) {
2214 msg.portEnabled = 1;
2215 msg.rxFlush = 1;
2216 msg.txBreak = (p_priv->break_on);
2217 }
2218 /* Closing port */
Alan Coxdeb91682008-07-22 11:13:08 +01002219 else if (reset_port == 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220 msg.portEnabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221 /* Sending intermediate configs */
2222 else {
Alan Stern1f871582010-02-17 10:05:47 -05002223 msg.portEnabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224 msg.txBreak = (p_priv->break_on);
2225 }
2226
Alan Coxdeb91682008-07-22 11:13:08 +01002227 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228 msg.setRts = 0x01;
2229 msg.rts = p_priv->rts_state;
2230
2231 msg.setDtr = 0x01;
2232 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002233
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01002235 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2236
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237 /* send the data out the device on control endpoint */
2238 this_urb->transfer_buffer_length = sizeof(msg);
2239
Alan Coxdeb91682008-07-22 11:13:08 +01002240 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2241 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002242 dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002243 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244}
2245
Lucy McCoy0ca12682007-05-18 12:10:41 -07002246static int keyspan_usa67_send_setup(struct usb_serial *serial,
2247 struct usb_serial_port *port,
2248 int reset_port)
2249{
2250 struct keyspan_usa67_portControlMessage msg;
2251 struct keyspan_serial_private *s_priv;
2252 struct keyspan_port_private *p_priv;
2253 const struct keyspan_device_details *d_details;
2254 struct urb *this_urb;
2255 int err, device_port;
2256
Lucy McCoy0ca12682007-05-18 12:10:41 -07002257 s_priv = usb_get_serial_data(serial);
2258 p_priv = usb_get_serial_port_data(port);
2259 d_details = s_priv->device_details;
2260
2261 this_urb = s_priv->glocont_urb;
2262
2263 /* Work out which port within the device is being setup */
2264 device_port = port->number - port->serial->minor;
2265
2266 /* Make sure we have an urb then send the message */
2267 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002268 dbg("%s - oops no urb for port %d.", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002269 port->number);
2270 return -1;
2271 }
2272
2273 /* Save reset port val for resend.
2274 Don't overwrite resend for open/close condition. */
2275 if ((reset_port + 1) > p_priv->resend_cont)
2276 p_priv->resend_cont = reset_port + 1;
2277 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +01002278 /* dbg("%s - already writing", __func__); */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002279 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002280 return -1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002281 }
2282
2283 memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
2284
2285 msg.port = device_port;
2286
2287 /* Only set baud rate if it's changed */
2288 if (p_priv->old_baud != p_priv->baud) {
2289 p_priv->old_baud = p_priv->baud;
2290 msg.setClocking = 0xff;
2291 if (d_details->calculate_baud_rate
2292 (p_priv->baud, d_details->baudclk, &msg.baudHi,
Alan Coxdeb91682008-07-22 11:13:08 +01002293 &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2294 dbg("%s - Invalid baud rate %d requested, using 9600.",
2295 __func__, p_priv->baud);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002296 msg.baudLo = 0;
2297 msg.baudHi = 125; /* Values for 9600 baud */
2298 msg.prescaler = 10;
2299 }
2300 msg.setPrescaler = 0xff;
2301 }
2302
2303 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
2304 switch (p_priv->cflag & CSIZE) {
2305 case CS5:
2306 msg.lcr |= USA_DATABITS_5;
2307 break;
2308 case CS6:
2309 msg.lcr |= USA_DATABITS_6;
2310 break;
2311 case CS7:
2312 msg.lcr |= USA_DATABITS_7;
2313 break;
2314 case CS8:
2315 msg.lcr |= USA_DATABITS_8;
2316 break;
2317 }
2318 if (p_priv->cflag & PARENB) {
2319 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002320 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002321 USA_PARITY_ODD : USA_PARITY_EVEN;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002322 }
2323 msg.setLcr = 0xff;
2324
2325 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2326 msg.xonFlowControl = 0;
2327 msg.setFlowControl = 0xff;
2328 msg.forwardingLength = 16;
2329 msg.xonChar = 17;
2330 msg.xoffChar = 19;
2331
2332 if (reset_port == 1) {
2333 /* Opening port */
2334 msg._txOn = 1;
2335 msg._txOff = 0;
2336 msg.txFlush = 0;
2337 msg.txBreak = 0;
2338 msg.rxOn = 1;
2339 msg.rxOff = 0;
2340 msg.rxFlush = 1;
2341 msg.rxForward = 0;
2342 msg.returnStatus = 0;
2343 msg.resetDataToggle = 0xff;
2344 } else if (reset_port == 2) {
2345 /* Closing port */
2346 msg._txOn = 0;
2347 msg._txOff = 1;
2348 msg.txFlush = 0;
2349 msg.txBreak = 0;
2350 msg.rxOn = 0;
2351 msg.rxOff = 1;
2352 msg.rxFlush = 1;
2353 msg.rxForward = 0;
2354 msg.returnStatus = 0;
2355 msg.resetDataToggle = 0;
2356 } else {
2357 /* Sending intermediate configs */
Alan Coxdeb91682008-07-22 11:13:08 +01002358 msg._txOn = (!p_priv->break_on);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002359 msg._txOff = 0;
2360 msg.txFlush = 0;
2361 msg.txBreak = (p_priv->break_on);
2362 msg.rxOn = 0;
2363 msg.rxOff = 0;
2364 msg.rxFlush = 0;
2365 msg.rxForward = 0;
2366 msg.returnStatus = 0;
2367 msg.resetDataToggle = 0x0;
2368 }
2369
2370 /* Do handshaking outputs */
2371 msg.setTxTriState_setRts = 0xff;
2372 msg.txTriState_rts = p_priv->rts_state;
2373
2374 msg.setHskoa_setDtr = 0xff;
2375 msg.hskoa_dtr = p_priv->dtr_state;
2376
2377 p_priv->resend_cont = 0;
2378
2379 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2380
2381 /* send the data out the device on control endpoint */
2382 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002383
2384 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2385 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002386 dbg("%s - usb_submit_urb(setup) failed (%d)", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002387 err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002388 return 0;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002389}
2390
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
2392{
2393 struct usb_serial *serial = port->serial;
2394 struct keyspan_serial_private *s_priv;
2395 const struct keyspan_device_details *d_details;
2396
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397 s_priv = usb_get_serial_data(serial);
2398 d_details = s_priv->device_details;
2399
2400 switch (d_details->msg_format) {
2401 case msg_usa26:
2402 keyspan_usa26_send_setup(serial, port, reset_port);
2403 break;
2404 case msg_usa28:
2405 keyspan_usa28_send_setup(serial, port, reset_port);
2406 break;
2407 case msg_usa49:
2408 keyspan_usa49_send_setup(serial, port, reset_port);
2409 break;
2410 case msg_usa90:
2411 keyspan_usa90_send_setup(serial, port, reset_port);
2412 break;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002413 case msg_usa67:
2414 keyspan_usa67_send_setup(serial, port, reset_port);
2415 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002416 }
2417}
2418
2419
2420/* Gets called by the "real" driver (ie once firmware is loaded
2421 and renumeration has taken place. */
Alan Coxdeb91682008-07-22 11:13:08 +01002422static int keyspan_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423{
2424 int i, err;
2425 struct usb_serial_port *port;
2426 struct keyspan_serial_private *s_priv;
2427 struct keyspan_port_private *p_priv;
2428 const struct keyspan_device_details *d_details;
2429
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
Alan Coxdeb91682008-07-22 11:13:08 +01002431 if (d_details->product_id ==
2432 le16_to_cpu(serial->dev->descriptor.idProduct))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433 break;
2434 if (d_details == NULL) {
Alan Coxdeb91682008-07-22 11:13:08 +01002435 dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
2436 __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437 return 1;
2438 }
2439
2440 /* Setup private data for serial driver */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01002441 s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442 if (!s_priv) {
Alan Coxdeb91682008-07-22 11:13:08 +01002443 dbg("%s - kmalloc for keyspan_serial_private failed.",
2444 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445 return -ENOMEM;
2446 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447
2448 s_priv->device_details = d_details;
2449 usb_set_serial_data(serial, s_priv);
2450
2451 /* Now setup per port private data */
2452 for (i = 0; i < serial->num_ports; i++) {
2453 port = serial->port[i];
Alan Coxdeb91682008-07-22 11:13:08 +01002454 p_priv = kzalloc(sizeof(struct keyspan_port_private),
2455 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456 if (!p_priv) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002457 dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __func__, i);
Alan Coxdeb91682008-07-22 11:13:08 +01002458 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460 p_priv->device_details = d_details;
2461 usb_set_serial_port_data(port, p_priv);
2462 }
2463
2464 keyspan_setup_urbs(serial);
2465
Lucy McCoy0ca12682007-05-18 12:10:41 -07002466 if (s_priv->instat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002467 err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
2468 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002469 dbg("%s - submit instat urb failed %d", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002470 err);
2471 }
2472 if (s_priv->indat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002473 err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
2474 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002475 dbg("%s - submit indat urb failed %d", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002476 err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477 }
Alan Coxdeb91682008-07-22 11:13:08 +01002478
Alan Coxa5b6f602008-04-08 17:16:06 +01002479 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480}
2481
Alan Sternf9c99bb2009-06-02 11:53:55 -04002482static void keyspan_disconnect(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483{
2484 int i, j;
2485 struct usb_serial_port *port;
2486 struct keyspan_serial_private *s_priv;
2487 struct keyspan_port_private *p_priv;
2488
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489 s_priv = usb_get_serial_data(serial);
2490
2491 /* Stop reading/writing urbs */
2492 stop_urb(s_priv->instat_urb);
2493 stop_urb(s_priv->glocont_urb);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002494 stop_urb(s_priv->indat_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495 for (i = 0; i < serial->num_ports; ++i) {
2496 port = serial->port[i];
2497 p_priv = usb_get_serial_port_data(port);
2498 stop_urb(p_priv->inack_urb);
2499 stop_urb(p_priv->outcont_urb);
2500 for (j = 0; j < 2; j++) {
2501 stop_urb(p_priv->in_urbs[j]);
2502 stop_urb(p_priv->out_urbs[j]);
2503 }
2504 }
2505
2506 /* Now free them */
Mariusz Kozlowski1cadc132006-11-08 15:36:34 +01002507 usb_free_urb(s_priv->instat_urb);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002508 usb_free_urb(s_priv->indat_urb);
Mariusz Kozlowski1cadc132006-11-08 15:36:34 +01002509 usb_free_urb(s_priv->glocont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510 for (i = 0; i < serial->num_ports; ++i) {
2511 port = serial->port[i];
2512 p_priv = usb_get_serial_port_data(port);
Mariusz Kozlowski1cadc132006-11-08 15:36:34 +01002513 usb_free_urb(p_priv->inack_urb);
2514 usb_free_urb(p_priv->outcont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515 for (j = 0; j < 2; j++) {
Mariusz Kozlowski1cadc132006-11-08 15:36:34 +01002516 usb_free_urb(p_priv->in_urbs[j]);
2517 usb_free_urb(p_priv->out_urbs[j]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002518 }
2519 }
Alan Sternf9c99bb2009-06-02 11:53:55 -04002520}
2521
2522static void keyspan_release(struct usb_serial *serial)
2523{
2524 int i;
2525 struct usb_serial_port *port;
2526 struct keyspan_serial_private *s_priv;
2527
Alan Sternf9c99bb2009-06-02 11:53:55 -04002528 s_priv = usb_get_serial_data(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529
2530 /* dbg("Freeing serial->private."); */
2531 kfree(s_priv);
2532
2533 /* dbg("Freeing port->private."); */
2534 /* Now free per port private data */
2535 for (i = 0; i < serial->num_ports; i++) {
2536 port = serial->port[i];
2537 kfree(usb_get_serial_port_data(port));
2538 }
2539}
2540
Alan Coxdeb91682008-07-22 11:13:08 +01002541MODULE_AUTHOR(DRIVER_AUTHOR);
2542MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543MODULE_LICENSE("GPL");
2544
David Woodhouse2971c572008-05-30 14:04:03 +03002545MODULE_FIRMWARE("keyspan/usa28.fw");
2546MODULE_FIRMWARE("keyspan/usa28x.fw");
2547MODULE_FIRMWARE("keyspan/usa28xa.fw");
2548MODULE_FIRMWARE("keyspan/usa28xb.fw");
2549MODULE_FIRMWARE("keyspan/usa19.fw");
2550MODULE_FIRMWARE("keyspan/usa19qi.fw");
2551MODULE_FIRMWARE("keyspan/mpr.fw");
2552MODULE_FIRMWARE("keyspan/usa19qw.fw");
2553MODULE_FIRMWARE("keyspan/usa18x.fw");
2554MODULE_FIRMWARE("keyspan/usa19w.fw");
2555MODULE_FIRMWARE("keyspan/usa49w.fw");
2556MODULE_FIRMWARE("keyspan/usa49wlc.fw");
2557
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558module_param(debug, bool, S_IRUGO | S_IWUSR);
2559MODULE_PARM_DESC(debug, "Debug enabled or not");
2560