blob: eb30d7b01f3681bd00c7fe73827533a613f162b6 [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>
Alan Coxdeb91682008-07-22 11:13:08 +010041#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <linux/usb.h>
Greg Kroah-Hartmana9698882006-07-11 21:22:58 -070043#include <linux/usb/serial.h>
Rene Buergelcc183e22012-09-18 09:00:41 +020044#include <linux/usb/ezusb.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include "keyspan.h"
46
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu"
48#define DRIVER_DESC "Keyspan USB to Serial Converter Driver"
49
50#define INSTAT_BUFLEN 32
51#define GLOCONT_BUFLEN 64
Lucy McCoy0ca12682007-05-18 12:10:41 -070052#define INDAT49W_BUFLEN 512
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
54 /* Per device and per port private data */
55struct keyspan_serial_private {
56 const struct keyspan_device_details *device_details;
57
58 struct urb *instat_urb;
59 char instat_buf[INSTAT_BUFLEN];
60
Alan Coxdeb91682008-07-22 11:13:08 +010061 /* added to support 49wg, where data from all 4 ports comes in
62 on 1 EP and high-speed supported */
Lucy McCoy0ca12682007-05-18 12:10:41 -070063 struct urb *indat_urb;
64 char indat_buf[INDAT49W_BUFLEN];
65
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 /* XXX this one probably will need a lock */
67 struct urb *glocont_urb;
68 char glocont_buf[GLOCONT_BUFLEN];
Alan Coxdeb91682008-07-22 11:13:08 +010069 char ctrl_buf[8]; /* for EP0 control message */
Linus Torvalds1da177e2005-04-16 15:20:36 -070070};
71
72struct keyspan_port_private {
73 /* Keep track of which input & output endpoints to use */
74 int in_flip;
75 int out_flip;
76
77 /* Keep duplicate of device details in each port
78 structure as well - simplifies some of the
79 callback functions etc. */
80 const struct keyspan_device_details *device_details;
81
82 /* Input endpoints and buffer for this port */
83 struct urb *in_urbs[2];
84 char in_buffer[2][64];
85 /* Output endpoints and buffer for this port */
86 struct urb *out_urbs[2];
87 char out_buffer[2][64];
88
89 /* Input ack endpoint */
90 struct urb *inack_urb;
91 char inack_buffer[1];
92
93 /* Output control endpoint */
94 struct urb *outcont_urb;
95 char outcont_buffer[64];
96
97 /* Settings for the port */
98 int baud;
99 int old_baud;
100 unsigned int cflag;
101 unsigned int old_cflag;
102 enum {flow_none, flow_cts, flow_xon} flow_control;
103 int rts_state; /* Handshaking pins (outputs) */
104 int dtr_state;
105 int cts_state; /* Handshaking pins (inputs) */
106 int dsr_state;
107 int dcd_state;
108 int ri_state;
109 int break_on;
110
111 unsigned long tx_start_time[2];
112 int resend_cont; /* need to resend control packet */
113};
114
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115/* Include Keyspan message headers. All current Keyspan Adapters
Lucy McCoy0ca12682007-05-18 12:10:41 -0700116 make use of one of five message formats which are referred
Alan Coxdeb91682008-07-22 11:13:08 +0100117 to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and
118 within this driver. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119#include "keyspan_usa26msg.h"
120#include "keyspan_usa28msg.h"
121#include "keyspan_usa49msg.h"
122#include "keyspan_usa90msg.h"
Lucy McCoy0ca12682007-05-18 12:10:41 -0700123#include "keyspan_usa67msg.h"
Alan Coxdeb91682008-07-22 11:13:08 +0100124
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -0700126module_usb_serial_driver(serial_drivers, keyspan_ids_combined);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127
Alan Cox95da3102008-07-22 11:09:07 +0100128static void keyspan_break_ctl(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129{
Alan Cox95da3102008-07-22 11:09:07 +0100130 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 struct keyspan_port_private *p_priv;
132
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133 p_priv = usb_get_serial_port_data(port);
134
135 if (break_state == -1)
136 p_priv->break_on = 1;
137 else
138 p_priv->break_on = 0;
139
140 keyspan_send_setup(port, 0);
141}
142
143
Alan Coxdeb91682008-07-22 11:13:08 +0100144static void keyspan_set_termios(struct tty_struct *tty,
Alan Cox95da3102008-07-22 11:09:07 +0100145 struct usb_serial_port *port, struct ktermios *old_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146{
147 int baud_rate, device_port;
148 struct keyspan_port_private *p_priv;
149 const struct keyspan_device_details *d_details;
150 unsigned int cflag;
151
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 p_priv = usb_get_serial_port_data(port);
153 d_details = p_priv->device_details;
Alan Coxadc8d742012-07-14 15:31:47 +0100154 cflag = tty->termios.c_cflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 device_port = port->number - port->serial->minor;
156
157 /* Baud rate calculation takes baud rate as an integer
158 so other rates can be generated if desired. */
Alan Cox74240b02007-10-18 01:24:20 -0700159 baud_rate = tty_get_baud_rate(tty);
Alan Coxdeb91682008-07-22 11:13:08 +0100160 /* If no match or invalid, don't change */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700161 if (d_details->calculate_baud_rate(port, baud_rate, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
163 /* FIXME - more to do here to ensure rate changes cleanly */
Alan Cox74240b02007-10-18 01:24:20 -0700164 /* FIXME - calcuate exact rate from divisor ? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 p_priv->baud = baud_rate;
Alan Cox74240b02007-10-18 01:24:20 -0700166 } else
167 baud_rate = tty_termios_baud_rate(old_termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168
Alan Cox74240b02007-10-18 01:24:20 -0700169 tty_encode_baud_rate(tty, baud_rate, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 /* set CTS/RTS handshake etc. */
171 p_priv->cflag = cflag;
Ben Minerds2b982ab2012-07-12 00:10:16 +1000172 p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173
Alan Cox74240b02007-10-18 01:24:20 -0700174 /* Mark/Space not supported */
Alan Coxadc8d742012-07-14 15:31:47 +0100175 tty->termios.c_cflag &= ~CMSPAR;
Alan Cox74240b02007-10-18 01:24:20 -0700176
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 keyspan_send_setup(port, 0);
178}
179
Alan Cox60b33c12011-02-14 16:26:14 +0000180static int keyspan_tiocmget(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181{
Alan Cox95da3102008-07-22 11:09:07 +0100182 struct usb_serial_port *port = tty->driver_data;
183 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 unsigned int value;
Alan Coxdeb91682008-07-22 11:13:08 +0100185
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 value = ((p_priv->rts_state) ? TIOCM_RTS : 0) |
187 ((p_priv->dtr_state) ? TIOCM_DTR : 0) |
188 ((p_priv->cts_state) ? TIOCM_CTS : 0) |
189 ((p_priv->dsr_state) ? TIOCM_DSR : 0) |
190 ((p_priv->dcd_state) ? TIOCM_CAR : 0) |
Alan Coxdeb91682008-07-22 11:13:08 +0100191 ((p_priv->ri_state) ? TIOCM_RNG : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192
193 return value;
194}
195
Alan Cox20b9d172011-02-14 16:26:50 +0000196static int keyspan_tiocmset(struct tty_struct *tty,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 unsigned int set, unsigned int clear)
198{
Alan Cox95da3102008-07-22 11:09:07 +0100199 struct usb_serial_port *port = tty->driver_data;
200 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100201
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 if (set & TIOCM_RTS)
203 p_priv->rts_state = 1;
204 if (set & TIOCM_DTR)
205 p_priv->dtr_state = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 if (clear & TIOCM_RTS)
207 p_priv->rts_state = 0;
208 if (clear & TIOCM_DTR)
209 p_priv->dtr_state = 0;
210 keyspan_send_setup(port, 0);
211 return 0;
212}
213
Alan Cox95da3102008-07-22 11:09:07 +0100214/* Write function is similar for the four protocols used
215 with only a minor change for usa90 (usa19hs) required */
216static int keyspan_write(struct tty_struct *tty,
217 struct usb_serial_port *port, const unsigned char *buf, int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218{
219 struct keyspan_port_private *p_priv;
220 const struct keyspan_device_details *d_details;
221 int flip;
222 int left, todo;
223 struct urb *this_urb;
Alan Coxdeb91682008-07-22 11:13:08 +0100224 int err, maxDataLen, dataOffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225
226 p_priv = usb_get_serial_port_data(port);
227 d_details = p_priv->device_details;
228
229 if (d_details->msg_format == msg_usa90) {
Alan Coxdeb91682008-07-22 11:13:08 +0100230 maxDataLen = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 dataOffset = 0;
232 } else {
233 maxDataLen = 63;
234 dataOffset = 1;
235 }
Alan Coxdeb91682008-07-22 11:13:08 +0100236
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700237 dev_dbg(&port->dev, "%s - for port %d (%d chars), flip=%d\n",
238 __func__, port->number, count, p_priv->out_flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239
240 for (left = count; left > 0; left -= todo) {
241 todo = left;
242 if (todo > maxDataLen)
243 todo = maxDataLen;
244
245 flip = p_priv->out_flip;
Alan Coxdeb91682008-07-22 11:13:08 +0100246
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 /* Check we have a valid urb/endpoint before we use it... */
Alan Coxdeb91682008-07-22 11:13:08 +0100248 this_urb = p_priv->out_urbs[flip];
249 if (this_urb == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 /* no bulk out, so return 0 bytes written */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700251 dev_dbg(&port->dev, "%s - no output urb :(\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 return count;
253 }
254
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700255 dev_dbg(&port->dev, "%s - endpoint %d flip %d\n",
Alan Coxdeb91682008-07-22 11:13:08 +0100256 __func__, usb_pipeendpoint(this_urb->pipe), flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257
258 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +0100259 if (time_before(jiffies,
260 p_priv->tx_start_time[flip] + 10 * HZ))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 usb_unlink_urb(this_urb);
263 break;
264 }
265
Alan Coxdeb91682008-07-22 11:13:08 +0100266 /* First byte in buffer is "last flag" (except for usa19hx)
267 - unused so for now so set to zero */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 ((char *)this_urb->transfer_buffer)[0] = 0;
269
Alan Coxdeb91682008-07-22 11:13:08 +0100270 memcpy(this_urb->transfer_buffer + dataOffset, buf, todo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 buf += todo;
272
273 /* send the data out the bulk port */
274 this_urb->transfer_buffer_length = todo + dataOffset;
275
Alan Coxdeb91682008-07-22 11:13:08 +0100276 err = usb_submit_urb(this_urb, GFP_ATOMIC);
277 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700278 dev_dbg(&port->dev, "usb_submit_urb(write bulk) failed (%d)\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 p_priv->tx_start_time[flip] = jiffies;
280
281 /* Flip for next time if usa26 or usa28 interface
282 (not used on usa49) */
283 p_priv->out_flip = (flip + 1) & d_details->outdat_endp_flip;
284 }
285
286 return count - left;
287}
288
David Howells7d12e782006-10-05 14:55:46 +0100289static void usa26_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290{
291 int i, err;
292 int endpoint;
293 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700295 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 endpoint = usb_pipeendpoint(urb->pipe);
298
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700299 if (status) {
Stefan Hubnera8ffa0b2012-12-13 22:45:00 +0100300 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700301 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 return;
303 }
304
Ming Leicdc97792008-02-24 18:41:47 +0800305 port = urb->context;
Jiri Slaby2e124b42013-01-03 15:53:06 +0100306 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 /* 0x80 bit is error flag */
308 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100309 /* no errors on individual bytes, only
310 possible overrun err */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 if (data[0] & RXERROR_OVERRUN)
Alan Coxdeb91682008-07-22 11:13:08 +0100312 err = TTY_OVERRUN;
313 else
314 err = 0;
315 for (i = 1; i < urb->actual_length ; ++i)
Jiri Slaby92a19f92013-01-03 15:53:03 +0100316 tty_insert_flip_char(&port->port, data[i], err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 } else {
318 /* some bytes had errors, every byte has status */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700319 dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 for (i = 0; i + 1 < urb->actual_length; i += 2) {
321 int stat = data[i], flag = 0;
322 if (stat & RXERROR_OVERRUN)
323 flag |= TTY_OVERRUN;
324 if (stat & RXERROR_FRAMING)
325 flag |= TTY_FRAME;
326 if (stat & RXERROR_PARITY)
327 flag |= TTY_PARITY;
328 /* XXX should handle break (0x10) */
Jiri Slaby92a19f92013-01-03 15:53:03 +0100329 tty_insert_flip_char(&port->port, data[i+1],
330 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 }
332 }
Jiri Slaby2e124b42013-01-03 15:53:06 +0100333 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 }
Alan Coxdeb91682008-07-22 11:13:08 +0100335
336 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500337 err = usb_submit_urb(urb, GFP_ATOMIC);
338 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700339 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340}
341
Alan Coxdeb91682008-07-22 11:13:08 +0100342/* Outdat handling is common for all devices */
David Howells7d12e782006-10-05 14:55:46 +0100343static void usa2x_outdat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344{
345 struct usb_serial_port *port;
346 struct keyspan_port_private *p_priv;
347
Ming Leicdc97792008-02-24 18:41:47 +0800348 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 p_priv = usb_get_serial_port_data(port);
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700350 dev_dbg(&port->dev, "%s - urb %d\n", __func__, urb == p_priv->out_urbs[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351
Alan Stern1f871582010-02-17 10:05:47 -0500352 usb_serial_port_softint(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353}
354
David Howells7d12e782006-10-05 14:55:46 +0100355static void usa26_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357}
358
David Howells7d12e782006-10-05 14:55:46 +0100359static void usa26_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360{
361 struct usb_serial_port *port;
362 struct keyspan_port_private *p_priv;
363
Ming Leicdc97792008-02-24 18:41:47 +0800364 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 p_priv = usb_get_serial_port_data(port);
366
367 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700368 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100369 keyspan_usa26_send_setup(port->serial, port,
370 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 }
372}
373
David Howells7d12e782006-10-05 14:55:46 +0100374static void usa26_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375{
376 unsigned char *data = urb->transfer_buffer;
377 struct keyspan_usa26_portStatusMessage *msg;
378 struct usb_serial *serial;
379 struct usb_serial_port *port;
380 struct keyspan_port_private *p_priv;
381 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700382 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
Ming Leicdc97792008-02-24 18:41:47 +0800384 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700386 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700387 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 return;
389 }
390 if (urb->actual_length != 9) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700391 dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 goto exit;
393 }
394
395 msg = (struct keyspan_usa26_portStatusMessage *)data;
396
397#if 0
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700398 dev_dbg(&urb->dev->dev,
399 "%s - port status: port %d cts %d dcd %d dsr %d ri %d toff %d txoff %d rxen %d cr %d",
400 __func__, msg->port, msg->hskia_cts, msg->gpia_dcd, msg->dsr,
401 msg->ri, msg->_txOff, msg->_txXoff, msg->rxEnabled,
402 msg->controlResponse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403#endif
404
405 /* Now do something useful with the data */
406
407
Alan Coxdeb91682008-07-22 11:13:08 +0100408 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700410 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 goto exit;
412 }
413 port = serial->port[msg->port];
414 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100415
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 /* Update handshaking pin state information */
417 old_dcd_state = p_priv->dcd_state;
418 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
419 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
420 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
421 p_priv->ri_state = ((msg->ri) ? 1 : 0);
422
Jiri Slabyaa27a092013-03-07 13:12:30 +0100423 if (old_dcd_state != p_priv->dcd_state)
424 tty_port_tty_hangup(&port->port, true);
Alan Coxdeb91682008-07-22 11:13:08 +0100425
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100427 err = usb_submit_urb(urb, GFP_ATOMIC);
428 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700429 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430exit: ;
431}
432
David Howells7d12e782006-10-05 14:55:46 +0100433static void usa26_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435}
436
437
David Howells7d12e782006-10-05 14:55:46 +0100438static void usa28_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439{
Alan Coxf035a8a2008-07-22 11:13:32 +0100440 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 unsigned char *data;
443 struct keyspan_port_private *p_priv;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700444 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445
Ming Leicdc97792008-02-24 18:41:47 +0800446 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 p_priv = usb_get_serial_port_data(port);
448 data = urb->transfer_buffer;
449
450 if (urb != p_priv->in_urbs[p_priv->in_flip])
451 return;
452
453 do {
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700454 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700455 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
456 __func__, status, usb_pipeendpoint(urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 return;
458 }
459
Ming Leicdc97792008-02-24 18:41:47 +0800460 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 p_priv = usb_get_serial_port_data(port);
462 data = urb->transfer_buffer;
463
Jiri Slaby2e124b42013-01-03 15:53:06 +0100464 if (urb->actual_length) {
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100465 tty_insert_flip_string(&port->port, data,
466 urb->actual_length);
Jiri Slaby2e124b42013-01-03 15:53:06 +0100467 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 }
469
470 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500471 err = usb_submit_urb(urb, GFP_ATOMIC);
472 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700473 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n",
Alan Stern1f871582010-02-17 10:05:47 -0500474 __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 p_priv->in_flip ^= 1;
476
477 urb = p_priv->in_urbs[p_priv->in_flip];
478 } while (urb->status != -EINPROGRESS);
479}
480
David Howells7d12e782006-10-05 14:55:46 +0100481static void usa28_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483}
484
David Howells7d12e782006-10-05 14:55:46 +0100485static void usa28_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486{
487 struct usb_serial_port *port;
488 struct keyspan_port_private *p_priv;
489
Ming Leicdc97792008-02-24 18:41:47 +0800490 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 p_priv = usb_get_serial_port_data(port);
492
493 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700494 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100495 keyspan_usa28_send_setup(port->serial, port,
496 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 }
498}
499
David Howells7d12e782006-10-05 14:55:46 +0100500static void usa28_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501{
502 int err;
503 unsigned char *data = urb->transfer_buffer;
504 struct keyspan_usa28_portStatusMessage *msg;
505 struct usb_serial *serial;
506 struct usb_serial_port *port;
507 struct keyspan_port_private *p_priv;
508 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700509 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510
Ming Leicdc97792008-02-24 18:41:47 +0800511 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700513 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700514 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 return;
516 }
517
518 if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700519 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 goto exit;
521 }
522
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700523 /*
524 dev_dbg(&urb->dev->dev,
Stefan Hubnera8ffa0b2012-12-13 22:45:00 +0100525 "%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__,
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700526 data[0], data[1], data[2], data[3], data[4], data[5],
527 data[6], data[7], data[8], data[9], data[10], data[11]);
528 */
Alan Coxdeb91682008-07-22 11:13:08 +0100529
530 /* Now do something useful with the data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 msg = (struct keyspan_usa28_portStatusMessage *)data;
532
Alan Coxdeb91682008-07-22 11:13:08 +0100533 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700535 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 goto exit;
537 }
538 port = serial->port[msg->port];
539 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100540
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 /* Update handshaking pin state information */
542 old_dcd_state = p_priv->dcd_state;
543 p_priv->cts_state = ((msg->cts) ? 1 : 0);
544 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
545 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
546 p_priv->ri_state = ((msg->ri) ? 1 : 0);
547
Jiri Slabyaa27a092013-03-07 13:12:30 +0100548 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
549 tty_port_tty_hangup(&port->port, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550
551 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100552 err = usb_submit_urb(urb, GFP_ATOMIC);
553 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700554 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555exit: ;
556}
557
David Howells7d12e782006-10-05 14:55:46 +0100558static void usa28_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560}
561
562
David Howells7d12e782006-10-05 14:55:46 +0100563static void usa49_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564{
565 struct usb_serial *serial;
566 struct usb_serial_port *port;
567 struct keyspan_port_private *p_priv;
568 int i;
569
Ming Leicdc97792008-02-24 18:41:47 +0800570 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 for (i = 0; i < serial->num_ports; ++i) {
572 port = serial->port[i];
573 p_priv = usb_get_serial_port_data(port);
574
575 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700576 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100577 keyspan_usa49_send_setup(serial, port,
578 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 break;
580 }
581 }
582}
583
584 /* This is actually called glostat in the Keyspan
585 doco */
David Howells7d12e782006-10-05 14:55:46 +0100586static void usa49_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587{
588 int err;
589 unsigned char *data = urb->transfer_buffer;
590 struct keyspan_usa49_portStatusMessage *msg;
591 struct usb_serial *serial;
592 struct usb_serial_port *port;
593 struct keyspan_port_private *p_priv;
594 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700595 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596
Ming Leicdc97792008-02-24 18:41:47 +0800597 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700599 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700600 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 return;
602 }
603
Alan Coxdeb91682008-07-22 11:13:08 +0100604 if (urb->actual_length !=
605 sizeof(struct keyspan_usa49_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700606 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 goto exit;
608 }
609
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700610 /*
611 dev_dbg(&urb->dev->dev, "%s: %x %x %x %x %x %x %x %x %x %x %x",
612 __func__, data[0], data[1], data[2], data[3], data[4],
613 data[5], data[6], data[7], data[8], data[9], data[10]);
614 */
Alan Coxdeb91682008-07-22 11:13:08 +0100615
616 /* Now do something useful with the data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 msg = (struct keyspan_usa49_portStatusMessage *)data;
618
Alan Coxdeb91682008-07-22 11:13:08 +0100619 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 if (msg->portNumber >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700621 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
622 __func__, msg->portNumber);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 goto exit;
624 }
625 port = serial->port[msg->portNumber];
626 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100627
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 /* Update handshaking pin state information */
629 old_dcd_state = p_priv->dcd_state;
630 p_priv->cts_state = ((msg->cts) ? 1 : 0);
631 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
632 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
633 p_priv->ri_state = ((msg->ri) ? 1 : 0);
634
Jiri Slabyaa27a092013-03-07 13:12:30 +0100635 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
636 tty_port_tty_hangup(&port->port, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637
Alan Coxdeb91682008-07-22 11:13:08 +0100638 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100639 err = usb_submit_urb(urb, GFP_ATOMIC);
640 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700641 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642exit: ;
643}
644
David Howells7d12e782006-10-05 14:55:46 +0100645static void usa49_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647}
648
David Howells7d12e782006-10-05 14:55:46 +0100649static void usa49_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650{
651 int i, err;
652 int endpoint;
653 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700655 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 endpoint = usb_pipeendpoint(urb->pipe);
658
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700659 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700660 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
661 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 return;
663 }
664
Ming Leicdc97792008-02-24 18:41:47 +0800665 port = urb->context;
Jiri Slaby2e124b42013-01-03 15:53:06 +0100666 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667 /* 0x80 bit is error flag */
668 if ((data[0] & 0x80) == 0) {
669 /* no error on any byte */
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100670 tty_insert_flip_string(&port->port, data + 1,
Alan Coxf035a8a2008-07-22 11:13:32 +0100671 urb->actual_length - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 } else {
673 /* some bytes had errors, every byte has status */
674 for (i = 0; i + 1 < urb->actual_length; i += 2) {
675 int stat = data[i], flag = 0;
676 if (stat & RXERROR_OVERRUN)
677 flag |= TTY_OVERRUN;
678 if (stat & RXERROR_FRAMING)
679 flag |= TTY_FRAME;
680 if (stat & RXERROR_PARITY)
681 flag |= TTY_PARITY;
682 /* XXX should handle break (0x10) */
Jiri Slaby92a19f92013-01-03 15:53:03 +0100683 tty_insert_flip_char(&port->port, data[i+1],
684 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 }
686 }
Jiri Slaby2e124b42013-01-03 15:53:06 +0100687 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 }
Alan Coxdeb91682008-07-22 11:13:08 +0100689
690 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500691 err = usb_submit_urb(urb, GFP_ATOMIC);
692 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700693 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694}
695
Lucy McCoy0ca12682007-05-18 12:10:41 -0700696static void usa49wg_indat_callback(struct urb *urb)
697{
698 int i, len, x, err;
699 struct usb_serial *serial;
700 struct usb_serial_port *port;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700701 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700702 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700703
Lucy McCoy0ca12682007-05-18 12:10:41 -0700704 serial = urb->context;
705
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700706 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700707 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700708 return;
709 }
710
711 /* inbound data is in the form P#, len, status, data */
712 i = 0;
713 len = 0;
714
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300715 while (i < urb->actual_length) {
Lucy McCoy0ca12682007-05-18 12:10:41 -0700716
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300717 /* Check port number from message */
718 if (data[i] >= serial->num_ports) {
719 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
720 __func__, data[i]);
721 return;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700722 }
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300723 port = serial->port[data[i++]];
724 len = data[i++];
725
726 /* 0x80 bit is error flag */
727 if ((data[i] & 0x80) == 0) {
728 /* no error on any byte */
729 i++;
Dan Carpenter01a60e72013-04-05 08:43:20 +0300730 for (x = 1; x < len && i < urb->actual_length; ++x)
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300731 tty_insert_flip_char(&port->port,
732 data[i++], 0);
733 } else {
734 /*
735 * some bytes had errors, every byte has status
736 */
Dan Carpenter01a60e72013-04-05 08:43:20 +0300737 for (x = 0; x + 1 < len &&
738 i + 1 < urb->actual_length; x += 2) {
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300739 int stat = data[i], flag = 0;
740
741 if (stat & RXERROR_OVERRUN)
742 flag |= TTY_OVERRUN;
743 if (stat & RXERROR_FRAMING)
744 flag |= TTY_FRAME;
745 if (stat & RXERROR_PARITY)
746 flag |= TTY_PARITY;
747 /* XXX should handle break (0x10) */
748 tty_insert_flip_char(&port->port, data[i+1],
749 flag);
750 i += 2;
751 }
752 }
753 tty_flip_buffer_push(&port->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700754 }
755
756 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700757 err = usb_submit_urb(urb, GFP_ATOMIC);
758 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700759 dev_dbg(&urb->dev->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700760}
761
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762/* not used, usa-49 doesn't have per-port control endpoints */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700763static void usa49_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765}
766
Lucy McCoy0ca12682007-05-18 12:10:41 -0700767static void usa90_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768{
769 int i, err;
770 int endpoint;
771 struct usb_serial_port *port;
772 struct keyspan_port_private *p_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700774 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 endpoint = usb_pipeendpoint(urb->pipe);
777
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700778 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700779 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800780 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 return;
782 }
783
Ming Leicdc97792008-02-24 18:41:47 +0800784 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 p_priv = usb_get_serial_port_data(port);
786
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 /* if current mode is DMA, looks like usa28 format
Alan Coxdeb91682008-07-22 11:13:08 +0100789 otherwise looks like usa26 data format */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790
Alan Coxf035a8a2008-07-22 11:13:32 +0100791 if (p_priv->baud > 57600)
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100792 tty_insert_flip_string(&port->port, data,
793 urb->actual_length);
Alan Coxf035a8a2008-07-22 11:13:32 +0100794 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 /* 0x80 bit is error flag */
796 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100797 /* no errors on individual bytes, only
798 possible overrun err*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 if (data[0] & RXERROR_OVERRUN)
Alan Coxdeb91682008-07-22 11:13:08 +0100800 err = TTY_OVERRUN;
801 else
802 err = 0;
803 for (i = 1; i < urb->actual_length ; ++i)
Jiri Slaby92a19f92013-01-03 15:53:03 +0100804 tty_insert_flip_char(&port->port,
805 data[i], err);
Alan Coxdeb91682008-07-22 11:13:08 +0100806 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 /* some bytes had errors, every byte has status */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700808 dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 for (i = 0; i + 1 < urb->actual_length; i += 2) {
810 int stat = data[i], flag = 0;
811 if (stat & RXERROR_OVERRUN)
812 flag |= TTY_OVERRUN;
813 if (stat & RXERROR_FRAMING)
814 flag |= TTY_FRAME;
815 if (stat & RXERROR_PARITY)
816 flag |= TTY_PARITY;
817 /* XXX should handle break (0x10) */
Jiri Slaby92a19f92013-01-03 15:53:03 +0100818 tty_insert_flip_char(&port->port,
819 data[i+1], flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 }
821 }
822 }
Jiri Slaby2e124b42013-01-03 15:53:06 +0100823 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 }
Alan Coxdeb91682008-07-22 11:13:08 +0100825
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500827 err = usb_submit_urb(urb, GFP_ATOMIC);
828 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700829 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830}
831
832
David Howells7d12e782006-10-05 14:55:46 +0100833static void usa90_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834{
835 unsigned char *data = urb->transfer_buffer;
836 struct keyspan_usa90_portStatusMessage *msg;
837 struct usb_serial *serial;
838 struct usb_serial_port *port;
839 struct keyspan_port_private *p_priv;
840 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700841 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842
Ming Leicdc97792008-02-24 18:41:47 +0800843 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700845 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700846 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 return;
848 }
849 if (urb->actual_length < 14) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700850 dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 goto exit;
852 }
853
854 msg = (struct keyspan_usa90_portStatusMessage *)data;
855
856 /* Now do something useful with the data */
857
858 port = serial->port[0];
859 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100860
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 /* Update handshaking pin state information */
862 old_dcd_state = p_priv->dcd_state;
863 p_priv->cts_state = ((msg->cts) ? 1 : 0);
864 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
865 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
866 p_priv->ri_state = ((msg->ri) ? 1 : 0);
867
Jiri Slabyaa27a092013-03-07 13:12:30 +0100868 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
869 tty_port_tty_hangup(&port->port, true);
Alan Coxdeb91682008-07-22 11:13:08 +0100870
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100872 err = usb_submit_urb(urb, GFP_ATOMIC);
873 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700874 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875exit:
876 ;
877}
878
David Howells7d12e782006-10-05 14:55:46 +0100879static void usa90_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880{
881 struct usb_serial_port *port;
882 struct keyspan_port_private *p_priv;
883
Ming Leicdc97792008-02-24 18:41:47 +0800884 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 p_priv = usb_get_serial_port_data(port);
886
887 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700888 dev_dbg(&urb->dev->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100889 keyspan_usa90_send_setup(port->serial, port,
890 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 }
892}
893
Lucy McCoy0ca12682007-05-18 12:10:41 -0700894/* Status messages from the 28xg */
895static void usa67_instat_callback(struct urb *urb)
896{
897 int err;
898 unsigned char *data = urb->transfer_buffer;
899 struct keyspan_usa67_portStatusMessage *msg;
900 struct usb_serial *serial;
901 struct usb_serial_port *port;
902 struct keyspan_port_private *p_priv;
903 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700904 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700905
Lucy McCoy0ca12682007-05-18 12:10:41 -0700906 serial = urb->context;
907
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700908 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700909 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700910 return;
911 }
912
Alan Coxdeb91682008-07-22 11:13:08 +0100913 if (urb->actual_length !=
914 sizeof(struct keyspan_usa67_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700915 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700916 return;
917 }
918
919
920 /* Now do something useful with the data */
921 msg = (struct keyspan_usa67_portStatusMessage *)data;
922
923 /* Check port number from message and retrieve private data */
924 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700925 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700926 return;
927 }
928
929 port = serial->port[msg->port];
930 p_priv = usb_get_serial_port_data(port);
931
932 /* Update handshaking pin state information */
933 old_dcd_state = p_priv->dcd_state;
934 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
935 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
936
Jiri Slabyaa27a092013-03-07 13:12:30 +0100937 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
938 tty_port_tty_hangup(&port->port, true);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700939
940 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700941 err = usb_submit_urb(urb, GFP_ATOMIC);
942 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700943 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700944}
945
946static void usa67_glocont_callback(struct urb *urb)
947{
948 struct usb_serial *serial;
949 struct usb_serial_port *port;
950 struct keyspan_port_private *p_priv;
951 int i;
952
Lucy McCoy0ca12682007-05-18 12:10:41 -0700953 serial = urb->context;
954 for (i = 0; i < serial->num_ports; ++i) {
955 port = serial->port[i];
956 p_priv = usb_get_serial_port_data(port);
957
958 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700959 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700960 keyspan_usa67_send_setup(serial, port,
961 p_priv->resend_cont - 1);
962 break;
963 }
964 }
965}
966
Alan Cox95da3102008-07-22 11:09:07 +0100967static int keyspan_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968{
Alan Cox95da3102008-07-22 11:09:07 +0100969 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 struct keyspan_port_private *p_priv;
971 const struct keyspan_device_details *d_details;
972 int flip;
973 int data_len;
974 struct urb *this_urb;
975
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 p_priv = usb_get_serial_port_data(port);
977 d_details = p_priv->device_details;
978
Alan Coxa5b6f602008-04-08 17:16:06 +0100979 /* FIXME: locking */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 if (d_details->msg_format == msg_usa90)
Alan Coxdeb91682008-07-22 11:13:08 +0100981 data_len = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 else
983 data_len = 63;
984
985 flip = p_priv->out_flip;
986
987 /* Check both endpoints to see if any are available. */
Alan Coxdeb91682008-07-22 11:13:08 +0100988 this_urb = p_priv->out_urbs[flip];
989 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +0100991 return data_len;
992 flip = (flip + 1) & d_details->outdat_endp_flip;
993 this_urb = p_priv->out_urbs[flip];
994 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +0100996 return data_len;
997 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 }
Alan Coxa5b6f602008-04-08 17:16:06 +0100999 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000}
1001
1002
Alan Coxa509a7e2009-09-19 13:13:26 -07001003static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004{
Andrew Mortonf78ba152007-11-28 16:21:54 -08001005 struct keyspan_port_private *p_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 const struct keyspan_device_details *d_details;
1007 int i, err;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001008 int baud_rate, device_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 struct urb *urb;
Alan Cox95da3102008-07-22 11:09:07 +01001010 unsigned int cflag = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 p_priv = usb_get_serial_port_data(port);
1013 d_details = p_priv->device_details;
Borislav Petkov7eea4362007-11-14 17:00:39 -08001014
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 /* Set some sane defaults */
1016 p_priv->rts_state = 1;
1017 p_priv->dtr_state = 1;
1018 p_priv->baud = 9600;
1019
1020 /* force baud and lcr to be set on open */
1021 p_priv->old_baud = 0;
1022 p_priv->old_cflag = 0;
1023
1024 p_priv->out_flip = 0;
1025 p_priv->in_flip = 0;
1026
1027 /* Reset low level data toggle and start reading from endpoints */
1028 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001029 urb = p_priv->in_urbs[i];
1030 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032
Alan Coxdeb91682008-07-22 11:13:08 +01001033 /* make sure endpoint data toggle is synchronized
1034 with the device */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 usb_clear_halt(urb->dev, urb->pipe);
Alan Coxdeb91682008-07-22 11:13:08 +01001036 err = usb_submit_urb(urb, GFP_KERNEL);
1037 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001038 dev_dbg(&port->dev, "%s - submit urb %d failed (%d)\n", __func__, i, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 }
1040
1041 /* Reset low level data toggle on out endpoints */
1042 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001043 urb = p_priv->out_urbs[i];
1044 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 continue;
Alan Coxdeb91682008-07-22 11:13:08 +01001046 /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
1047 usb_pipeout(urb->pipe), 0); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 }
1049
Andrew Mortonf78ba152007-11-28 16:21:54 -08001050 /* get the terminal config for the setup message now so we don't
1051 * need to send 2 of them */
1052
Andrew Mortonf78ba152007-11-28 16:21:54 -08001053 device_port = port->number - port->serial->minor;
Alan Cox95da3102008-07-22 11:09:07 +01001054 if (tty) {
Alan Coxadc8d742012-07-14 15:31:47 +01001055 cflag = tty->termios.c_cflag;
Alan Cox95da3102008-07-22 11:09:07 +01001056 /* Baud rate calculation takes baud rate as an integer
1057 so other rates can be generated if desired. */
1058 baud_rate = tty_get_baud_rate(tty);
1059 /* If no match or invalid, leave as default */
1060 if (baud_rate >= 0
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001061 && d_details->calculate_baud_rate(port, baud_rate, d_details->baudclk,
Alan Cox95da3102008-07-22 11:09:07 +01001062 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
1063 p_priv->baud = baud_rate;
1064 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001065 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001066 /* set CTS/RTS handshake etc. */
1067 p_priv->cflag = cflag;
Ben Minerds2b982ab2012-07-12 00:10:16 +10001068 p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001069
1070 keyspan_send_setup(port, 1);
Alan Coxdeb91682008-07-22 11:13:08 +01001071 /* mdelay(100); */
1072 /* keyspan_set_termios(port, NULL); */
Andrew Mortonf78ba152007-11-28 16:21:54 -08001073
Alan Coxa5b6f602008-04-08 17:16:06 +01001074 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075}
1076
1077static inline void stop_urb(struct urb *urb)
1078{
Greg Kroah-Hartman242cf672005-07-29 16:11:07 -04001079 if (urb && urb->status == -EINPROGRESS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 usb_kill_urb(urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081}
1082
Alan Cox335f8512009-06-11 12:26:29 +01001083static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
1084{
1085 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
1086
1087 p_priv->rts_state = on;
1088 p_priv->dtr_state = on;
1089 keyspan_send_setup(port, 0);
1090}
1091
1092static void keyspan_close(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093{
1094 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 struct keyspan_port_private *p_priv;
1096
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +01001098
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 p_priv->rts_state = 0;
1100 p_priv->dtr_state = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001101
Johan Hovold80dfe0c2013-03-21 12:36:32 +01001102 keyspan_send_setup(port, 2);
1103 /* pilot-xfer seems to work best with this delay */
1104 mdelay(100);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105
1106 p_priv->out_flip = 0;
1107 p_priv->in_flip = 0;
1108
Johan Hovold80dfe0c2013-03-21 12:36:32 +01001109 stop_urb(p_priv->inack_urb);
1110 for (i = 0; i < 2; i++) {
1111 stop_urb(p_priv->in_urbs[i]);
1112 stop_urb(p_priv->out_urbs[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114}
1115
Alan Coxdeb91682008-07-22 11:13:08 +01001116/* download the firmware to a pre-renumeration device */
1117static int keyspan_fake_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118{
Rene Buergel8d733e22012-09-18 09:02:01 +02001119 char *fw_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001121 dev_dbg(&serial->dev->dev, "Keyspan startup version %04x product %04x\n",
1122 le16_to_cpu(serial->dev->descriptor.bcdDevice),
1123 le16_to_cpu(serial->dev->descriptor.idProduct));
Alan Coxdeb91682008-07-22 11:13:08 +01001124
1125 if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000)
1126 != 0x8000) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001127 dev_dbg(&serial->dev->dev, "Firmware already loaded. Quitting.\n");
Alan Coxdeb91682008-07-22 11:13:08 +01001128 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 }
1130
1131 /* Select firmware image on the basis of idProduct */
1132 switch (le16_to_cpu(serial->dev->descriptor.idProduct)) {
1133 case keyspan_usa28_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001134 fw_name = "keyspan/usa28.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 break;
1136
1137 case keyspan_usa28x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001138 fw_name = "keyspan/usa28x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139 break;
1140
1141 case keyspan_usa28xa_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001142 fw_name = "keyspan/usa28xa.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 break;
1144
1145 case keyspan_usa28xb_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001146 fw_name = "keyspan/usa28xb.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 break;
1148
1149 case keyspan_usa19_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001150 fw_name = "keyspan/usa19.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001152
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 case keyspan_usa19qi_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001154 fw_name = "keyspan/usa19qi.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001156
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 case keyspan_mpr_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001158 fw_name = "keyspan/mpr.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 break;
1160
1161 case keyspan_usa19qw_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001162 fw_name = "keyspan/usa19qw.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001164
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 case keyspan_usa18x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001166 fw_name = "keyspan/usa18x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001168
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 case keyspan_usa19w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001170 fw_name = "keyspan/usa19w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001172
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 case keyspan_usa49w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001174 fw_name = "keyspan/usa49w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 break;
1176
1177 case keyspan_usa49wlc_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001178 fw_name = "keyspan/usa49wlc.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 break;
1180
1181 default:
David Woodhouse2971c572008-05-30 14:04:03 +03001182 dev_err(&serial->dev->dev, "Unknown product ID (%04x)\n",
1183 le16_to_cpu(serial->dev->descriptor.idProduct));
1184 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 }
1186
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001187 dev_dbg(&serial->dev->dev, "Uploading Keyspan %s firmware.\n", fw_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188
Rene Buergel8d733e22012-09-18 09:02:01 +02001189 if (ezusb_fx1_ihex_firmware_download(serial->dev, fw_name) < 0) {
1190 dev_err(&serial->dev->dev, "failed to load firmware \"%s\"\n",
1191 fw_name);
1192 return -ENOENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193 }
1194
Rene Buergel8d733e22012-09-18 09:02:01 +02001195 /* after downloading firmware Renumeration will occur in a
1196 moment and the new device will bind to the real driver */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197
1198 /* we don't want this device to have a driver assigned to it. */
Alan Coxdeb91682008-07-22 11:13:08 +01001199 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200}
1201
1202/* Helper functions used by keyspan_setup_urbs */
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001203static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *serial,
1204 int endpoint)
1205{
1206 struct usb_host_interface *iface_desc;
1207 struct usb_endpoint_descriptor *ep;
1208 int i;
1209
1210 iface_desc = serial->interface->cur_altsetting;
1211 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1212 ep = &iface_desc->endpoint[i].desc;
1213 if (ep->bEndpointAddress == endpoint)
1214 return ep;
1215 }
1216 dev_warn(&serial->interface->dev, "found no endpoint descriptor for "
1217 "endpoint %x\n", endpoint);
1218 return NULL;
1219}
1220
Alan Coxdeb91682008-07-22 11:13:08 +01001221static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 int dir, void *ctx, char *buf, int len,
David Howells7d12e782006-10-05 14:55:46 +01001223 void (*callback)(struct urb *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224{
1225 struct urb *urb;
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001226 struct usb_endpoint_descriptor const *ep_desc;
1227 char const *ep_type_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228
1229 if (endpoint == -1)
1230 return NULL; /* endpoint not needed */
1231
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001232 dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %d.\n", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
1234 if (urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001235 dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %d failed.\n", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 return NULL;
1237 }
1238
Lucy McCoy0ca12682007-05-18 12:10:41 -07001239 if (endpoint == 0) {
1240 /* control EP filled in when used */
1241 return urb;
1242 }
1243
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001244 ep_desc = find_ep(serial, endpoint);
1245 if (!ep_desc) {
1246 /* leak the urb, something's wrong and the callers don't care */
1247 return urb;
1248 }
1249 if (usb_endpoint_xfer_int(ep_desc)) {
1250 ep_type_name = "INT";
1251 usb_fill_int_urb(urb, serial->dev,
1252 usb_sndintpipe(serial->dev, endpoint) | dir,
1253 buf, len, callback, ctx,
1254 ep_desc->bInterval);
1255 } else if (usb_endpoint_xfer_bulk(ep_desc)) {
1256 ep_type_name = "BULK";
1257 usb_fill_bulk_urb(urb, serial->dev,
1258 usb_sndbulkpipe(serial->dev, endpoint) | dir,
1259 buf, len, callback, ctx);
1260 } else {
1261 dev_warn(&serial->interface->dev,
1262 "unsupported endpoint type %x\n",
Julia Lawall2e0fe702008-12-29 11:22:14 +01001263 usb_endpoint_type(ep_desc));
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001264 usb_free_urb(urb);
1265 return NULL;
1266 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001268 dev_dbg(&serial->interface->dev, "%s - using urb %p for %s endpoint %x\n",
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001269 __func__, urb, ep_type_name, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 return urb;
1271}
1272
1273static struct callbacks {
David Howells7d12e782006-10-05 14:55:46 +01001274 void (*instat_callback)(struct urb *);
1275 void (*glocont_callback)(struct urb *);
1276 void (*indat_callback)(struct urb *);
1277 void (*outdat_callback)(struct urb *);
1278 void (*inack_callback)(struct urb *);
1279 void (*outcont_callback)(struct urb *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280} keyspan_callbacks[] = {
1281 {
1282 /* msg_usa26 callbacks */
1283 .instat_callback = usa26_instat_callback,
1284 .glocont_callback = usa26_glocont_callback,
1285 .indat_callback = usa26_indat_callback,
1286 .outdat_callback = usa2x_outdat_callback,
1287 .inack_callback = usa26_inack_callback,
1288 .outcont_callback = usa26_outcont_callback,
1289 }, {
1290 /* msg_usa28 callbacks */
1291 .instat_callback = usa28_instat_callback,
1292 .glocont_callback = usa28_glocont_callback,
1293 .indat_callback = usa28_indat_callback,
1294 .outdat_callback = usa2x_outdat_callback,
1295 .inack_callback = usa28_inack_callback,
1296 .outcont_callback = usa28_outcont_callback,
1297 }, {
1298 /* msg_usa49 callbacks */
1299 .instat_callback = usa49_instat_callback,
1300 .glocont_callback = usa49_glocont_callback,
1301 .indat_callback = usa49_indat_callback,
1302 .outdat_callback = usa2x_outdat_callback,
1303 .inack_callback = usa49_inack_callback,
1304 .outcont_callback = usa49_outcont_callback,
1305 }, {
1306 /* msg_usa90 callbacks */
1307 .instat_callback = usa90_instat_callback,
Alan Coxdeb91682008-07-22 11:13:08 +01001308 .glocont_callback = usa28_glocont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 .indat_callback = usa90_indat_callback,
1310 .outdat_callback = usa2x_outdat_callback,
1311 .inack_callback = usa28_inack_callback,
1312 .outcont_callback = usa90_outcont_callback,
Lucy McCoy0ca12682007-05-18 12:10:41 -07001313 }, {
1314 /* msg_usa67 callbacks */
1315 .instat_callback = usa67_instat_callback,
1316 .glocont_callback = usa67_glocont_callback,
1317 .indat_callback = usa26_indat_callback,
1318 .outdat_callback = usa2x_outdat_callback,
1319 .inack_callback = usa26_inack_callback,
1320 .outcont_callback = usa26_outcont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 }
1322};
1323
1324 /* Generic setup urbs function that uses
1325 data in device_details */
1326static void keyspan_setup_urbs(struct usb_serial *serial)
1327{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328 struct keyspan_serial_private *s_priv;
1329 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 struct callbacks *cback;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 s_priv = usb_get_serial_data(serial);
1333 d_details = s_priv->device_details;
1334
Alan Coxdeb91682008-07-22 11:13:08 +01001335 /* Setup values for the various callback routines */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 cback = &keyspan_callbacks[d_details->msg_format];
1337
Alan Coxdeb91682008-07-22 11:13:08 +01001338 /* Allocate and set up urbs for each one that is in use,
1339 starting with instat endpoints */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 s_priv->instat_urb = keyspan_setup_urb
1341 (serial, d_details->instat_endpoint, USB_DIR_IN,
1342 serial, s_priv->instat_buf, INSTAT_BUFLEN,
1343 cback->instat_callback);
1344
Lucy McCoy0ca12682007-05-18 12:10:41 -07001345 s_priv->indat_urb = keyspan_setup_urb
1346 (serial, d_details->indat_endpoint, USB_DIR_IN,
1347 serial, s_priv->indat_buf, INDAT49W_BUFLEN,
1348 usa49wg_indat_callback);
1349
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 s_priv->glocont_urb = keyspan_setup_urb
1351 (serial, d_details->glocont_endpoint, USB_DIR_OUT,
1352 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
1353 cback->glocont_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354}
1355
1356/* usa19 function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001357static int keyspan_usa19_calc_baud(struct usb_serial_port *port,
1358 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 u8 *rate_low, u8 *prescaler, int portnum)
1360{
1361 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001362 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 cnt; /* inverse of divisor (programmed into 8051) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001365 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366
Alan Coxdeb91682008-07-22 11:13:08 +01001367 /* prevent divide by zero... */
1368 b16 = baud_rate * 16L;
1369 if (b16 == 0)
1370 return KEYSPAN_INVALID_BAUD_RATE;
1371 /* Any "standard" rate over 57k6 is marginal on the USA-19
1372 as we run out of divisor resolution. */
1373 if (baud_rate > 57600)
1374 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375
Alan Coxdeb91682008-07-22 11:13:08 +01001376 /* calculate the divisor and the counter (its inverse) */
1377 div = baudclk / b16;
1378 if (div == 0)
1379 return KEYSPAN_INVALID_BAUD_RATE;
1380 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382
Alan Coxdeb91682008-07-22 11:13:08 +01001383 if (div > 0xffff)
1384 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385
Alan Coxdeb91682008-07-22 11:13:08 +01001386 /* return the counter values if non-null */
1387 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001389 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001391 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001392 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001393 __func__, baud_rate, *rate_hi, *rate_low);
1394 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395}
1396
1397/* usa19hs function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001398static int keyspan_usa19hs_calc_baud(struct usb_serial_port *port,
1399 u32 baud_rate, u32 baudclk, u8 *rate_hi,
1400 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401{
1402 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001403 div; /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001405 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406
Alan Coxdeb91682008-07-22 11:13:08 +01001407 /* prevent divide by zero... */
1408 b16 = baud_rate * 16L;
1409 if (b16 == 0)
1410 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411
Alan Coxdeb91682008-07-22 11:13:08 +01001412 /* calculate the divisor */
1413 div = baudclk / b16;
1414 if (div == 0)
1415 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416
Alan Coxdeb91682008-07-22 11:13:08 +01001417 if (div > 0xffff)
1418 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419
Alan Coxdeb91682008-07-22 11:13:08 +01001420 /* return the counter values if non-null */
1421 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001423
1424 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 *rate_hi = (u8) ((div >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001426
1427 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001428 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001429 __func__, baud_rate, *rate_hi, *rate_low);
1430
1431 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432}
1433
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001434static int keyspan_usa19w_calc_baud(struct usb_serial_port *port,
1435 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 u8 *rate_low, u8 *prescaler, int portnum)
1437{
1438 u32 b16, /* baud rate times 16 (actual rate used internally) */
1439 clk, /* clock with 13/8 prescaler */
Alan Coxdeb91682008-07-22 11:13:08 +01001440 div, /* divisor using 13/8 prescaler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 res, /* resulting baud rate using 13/8 prescaler */
1442 diff, /* error using 13/8 prescaler */
1443 smallest_diff;
1444 u8 best_prescaler;
1445 int i;
1446
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001447 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448
Alan Coxdeb91682008-07-22 11:13:08 +01001449 /* prevent divide by zero */
1450 b16 = baud_rate * 16L;
1451 if (b16 == 0)
1452 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453
Alan Coxdeb91682008-07-22 11:13:08 +01001454 /* Calculate prescaler by trying them all and looking
1455 for best fit */
1456
1457 /* start with largest possible difference */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 smallest_diff = 0xffffffff;
1459
1460 /* 0 is an invalid prescaler, used as a flag */
1461 best_prescaler = 0;
1462
Alan Coxdeb91682008-07-22 11:13:08 +01001463 for (i = 8; i <= 0xff; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 clk = (baudclk * 8) / (u32) i;
Alan Coxdeb91682008-07-22 11:13:08 +01001465
1466 div = clk / b16;
1467 if (div == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469
1470 res = clk / div;
Alan Coxdeb91682008-07-22 11:13:08 +01001471 diff = (res > b16) ? (res-b16) : (b16-res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472
Alan Coxdeb91682008-07-22 11:13:08 +01001473 if (diff < smallest_diff) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 best_prescaler = i;
1475 smallest_diff = diff;
1476 }
1477 }
1478
Alan Coxdeb91682008-07-22 11:13:08 +01001479 if (best_prescaler == 0)
1480 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481
1482 clk = (baudclk * 8) / (u32) best_prescaler;
1483 div = clk / b16;
1484
Alan Coxdeb91682008-07-22 11:13:08 +01001485 /* return the divisor and prescaler if non-null */
1486 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001488 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 *rate_hi = (u8) ((div >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 if (prescaler) {
1491 *prescaler = best_prescaler;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001492 /* dev_dbg(&port->dev, "%s - %d %d\n", __func__, *prescaler, div); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 }
Alan Coxdeb91682008-07-22 11:13:08 +01001494 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495}
1496
1497 /* USA-28 supports different maximum baud rates on each port */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001498static int keyspan_usa28_calc_baud(struct usb_serial_port *port,
1499 u32 baud_rate, u32 baudclk, u8 *rate_hi,
1500 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501{
1502 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001503 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 cnt; /* inverse of divisor (programmed into 8051) */
1505
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001506 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507
1508 /* prevent divide by zero */
Alan Coxdeb91682008-07-22 11:13:08 +01001509 b16 = baud_rate * 16L;
1510 if (b16 == 0)
1511 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512
Alan Coxdeb91682008-07-22 11:13:08 +01001513 /* calculate the divisor and the counter (its inverse) */
1514 div = KEYSPAN_USA28_BAUDCLK / b16;
1515 if (div == 0)
1516 return KEYSPAN_INVALID_BAUD_RATE;
1517 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519
Alan Coxdeb91682008-07-22 11:13:08 +01001520 /* check for out of range, based on portnum,
1521 and return result */
1522 if (portnum == 0) {
1523 if (div > 0xffff)
1524 return KEYSPAN_INVALID_BAUD_RATE;
1525 } else {
1526 if (portnum == 1) {
1527 if (div > 0xff)
1528 return KEYSPAN_INVALID_BAUD_RATE;
1529 } else
1530 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531 }
1532
1533 /* return the counter values if not NULL
1534 (port 1 will ignore retHi) */
Alan Coxdeb91682008-07-22 11:13:08 +01001535 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001537 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001539 dev_dbg(&port->dev, "%s - %d OK.\n", __func__, baud_rate);
Alan Coxdeb91682008-07-22 11:13:08 +01001540 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541}
1542
1543static int keyspan_usa26_send_setup(struct usb_serial *serial,
1544 struct usb_serial_port *port,
1545 int reset_port)
1546{
Alan Coxdeb91682008-07-22 11:13:08 +01001547 struct keyspan_usa26_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 struct keyspan_serial_private *s_priv;
1549 struct keyspan_port_private *p_priv;
1550 const struct keyspan_device_details *d_details;
1551 int outcont_urb;
1552 struct urb *this_urb;
1553 int device_port, err;
1554
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001555 dev_dbg(&port->dev, "%s reset=%d\n", __func__, reset_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556
1557 s_priv = usb_get_serial_data(serial);
1558 p_priv = usb_get_serial_port_data(port);
1559 d_details = s_priv->device_details;
1560 device_port = port->number - port->serial->minor;
1561
1562 outcont_urb = d_details->outcont_endpoints[port->number];
1563 this_urb = p_priv->outcont_urb;
1564
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001565 dev_dbg(&port->dev, "%s - endpoint %d\n", __func__, usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566
1567 /* Make sure we have an urb then send the message */
1568 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001569 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570 return -1;
1571 }
1572
1573 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001574 Don't overwrite resend for open/close condition. */
1575 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576 p_priv->resend_cont = reset_port + 1;
1577 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001578 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001580 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 }
1582
Alan Coxdeb91682008-07-22 11:13:08 +01001583 memset(&msg, 0, sizeof(struct keyspan_usa26_portControlMessage));
1584
1585 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586 if (p_priv->old_baud != p_priv->baud) {
1587 p_priv->old_baud = p_priv->baud;
1588 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001589 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1590 &msg.baudHi, &msg.baudLo, &msg.prescaler,
1591 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1592 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
1593 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 msg.baudLo = 0;
1595 msg.baudHi = 125; /* Values for 9600 baud */
1596 msg.prescaler = 10;
1597 }
1598 msg.setPrescaler = 0xff;
1599 }
1600
Ben Minerds2b982ab2012-07-12 00:10:16 +10001601 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602 switch (p_priv->cflag & CSIZE) {
1603 case CS5:
1604 msg.lcr |= USA_DATABITS_5;
1605 break;
1606 case CS6:
1607 msg.lcr |= USA_DATABITS_6;
1608 break;
1609 case CS7:
1610 msg.lcr |= USA_DATABITS_7;
1611 break;
1612 case CS8:
1613 msg.lcr |= USA_DATABITS_8;
1614 break;
1615 }
1616 if (p_priv->cflag & PARENB) {
1617 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10001618 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01001619 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620 }
1621 msg.setLcr = 0xff;
1622
1623 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1624 msg.xonFlowControl = 0;
1625 msg.setFlowControl = 0xff;
1626 msg.forwardingLength = 16;
1627 msg.xonChar = 17;
1628 msg.xoffChar = 19;
1629
1630 /* Opening port */
1631 if (reset_port == 1) {
1632 msg._txOn = 1;
1633 msg._txOff = 0;
1634 msg.txFlush = 0;
1635 msg.txBreak = 0;
1636 msg.rxOn = 1;
1637 msg.rxOff = 0;
1638 msg.rxFlush = 1;
1639 msg.rxForward = 0;
1640 msg.returnStatus = 0;
1641 msg.resetDataToggle = 0xff;
1642 }
1643
1644 /* Closing port */
1645 else if (reset_port == 2) {
1646 msg._txOn = 0;
1647 msg._txOff = 1;
1648 msg.txFlush = 0;
1649 msg.txBreak = 0;
1650 msg.rxOn = 0;
1651 msg.rxOff = 1;
1652 msg.rxFlush = 1;
1653 msg.rxForward = 0;
1654 msg.returnStatus = 0;
1655 msg.resetDataToggle = 0;
1656 }
1657
1658 /* Sending intermediate configs */
1659 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001660 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 msg._txOff = 0;
1662 msg.txFlush = 0;
1663 msg.txBreak = (p_priv->break_on);
1664 msg.rxOn = 0;
1665 msg.rxOff = 0;
1666 msg.rxFlush = 0;
1667 msg.rxForward = 0;
1668 msg.returnStatus = 0;
1669 msg.resetDataToggle = 0x0;
1670 }
1671
Alan Coxdeb91682008-07-22 11:13:08 +01001672 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 msg.setTxTriState_setRts = 0xff;
1674 msg.txTriState_rts = p_priv->rts_state;
1675
1676 msg.setHskoa_setDtr = 0xff;
1677 msg.hskoa_dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01001678
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001680 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
1681
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 /* send the data out the device on control endpoint */
1683 this_urb->transfer_buffer_length = sizeof(msg);
1684
Alan Coxdeb91682008-07-22 11:13:08 +01001685 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1686 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001687 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688#if 0
1689 else {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001690 dev_dbg(&port->dev, "%s - usb_submit_urb(%d) OK %d bytes (end %d)\n", __func__
1691 outcont_urb, this_urb->transfer_buffer_length,
1692 usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 }
1694#endif
1695
Alan Coxa5b6f602008-04-08 17:16:06 +01001696 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697}
1698
1699static int keyspan_usa28_send_setup(struct usb_serial *serial,
1700 struct usb_serial_port *port,
1701 int reset_port)
1702{
Alan Coxdeb91682008-07-22 11:13:08 +01001703 struct keyspan_usa28_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 struct keyspan_serial_private *s_priv;
1705 struct keyspan_port_private *p_priv;
1706 const struct keyspan_device_details *d_details;
1707 struct urb *this_urb;
1708 int device_port, err;
1709
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 s_priv = usb_get_serial_data(serial);
1711 p_priv = usb_get_serial_port_data(port);
1712 d_details = s_priv->device_details;
1713 device_port = port->number - port->serial->minor;
1714
1715 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01001716 this_urb = p_priv->outcont_urb;
1717 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001718 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 return -1;
1720 }
1721
1722 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001723 Don't overwrite resend for open/close condition. */
1724 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725 p_priv->resend_cont = reset_port + 1;
1726 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001727 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001729 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730 }
1731
Alan Coxdeb91682008-07-22 11:13:08 +01001732 memset(&msg, 0, sizeof(struct keyspan_usa28_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733
1734 msg.setBaudRate = 1;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001735 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1736 &msg.baudHi, &msg.baudLo, NULL,
1737 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1738 dev_dbg(&port->dev, "%s - Invalid baud rate requested %d.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001739 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 msg.baudLo = 0xff;
1741 msg.baudHi = 0xb2; /* Values for 9600 baud */
1742 }
1743
1744 /* If parity is enabled, we must calculate it ourselves. */
1745 msg.parity = 0; /* XXX for now */
1746
1747 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1748 msg.xonFlowControl = 0;
1749
Alan Coxdeb91682008-07-22 11:13:08 +01001750 /* Do handshaking outputs, DTR is inverted relative to RTS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751 msg.rts = p_priv->rts_state;
1752 msg.dtr = p_priv->dtr_state;
1753
1754 msg.forwardingLength = 16;
1755 msg.forwardMs = 10;
1756 msg.breakThreshold = 45;
1757 msg.xonChar = 17;
1758 msg.xoffChar = 19;
1759
1760 /*msg.returnStatus = 1;
1761 msg.resetDataToggle = 0xff;*/
1762 /* Opening port */
1763 if (reset_port == 1) {
1764 msg._txOn = 1;
1765 msg._txOff = 0;
1766 msg.txFlush = 0;
1767 msg.txForceXoff = 0;
1768 msg.txBreak = 0;
1769 msg.rxOn = 1;
1770 msg.rxOff = 0;
1771 msg.rxFlush = 1;
1772 msg.rxForward = 0;
1773 msg.returnStatus = 0;
1774 msg.resetDataToggle = 0xff;
1775 }
1776 /* Closing port */
1777 else if (reset_port == 2) {
1778 msg._txOn = 0;
1779 msg._txOff = 1;
1780 msg.txFlush = 0;
1781 msg.txForceXoff = 0;
1782 msg.txBreak = 0;
1783 msg.rxOn = 0;
1784 msg.rxOff = 1;
1785 msg.rxFlush = 1;
1786 msg.rxForward = 0;
1787 msg.returnStatus = 0;
1788 msg.resetDataToggle = 0;
1789 }
1790 /* Sending intermediate configs */
1791 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001792 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793 msg._txOff = 0;
1794 msg.txFlush = 0;
1795 msg.txForceXoff = 0;
1796 msg.txBreak = (p_priv->break_on);
1797 msg.rxOn = 0;
1798 msg.rxOff = 0;
1799 msg.rxFlush = 0;
1800 msg.rxForward = 0;
1801 msg.returnStatus = 0;
1802 msg.resetDataToggle = 0x0;
1803 }
1804
1805 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001806 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807
1808 /* send the data out the device on control endpoint */
1809 this_urb->transfer_buffer_length = sizeof(msg);
1810
Alan Coxdeb91682008-07-22 11:13:08 +01001811 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1812 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001813 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814#if 0
1815 else {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001816 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) OK %d bytes\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817 this_urb->transfer_buffer_length);
1818 }
1819#endif
1820
Alan Coxa5b6f602008-04-08 17:16:06 +01001821 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822}
1823
1824static int keyspan_usa49_send_setup(struct usb_serial *serial,
1825 struct usb_serial_port *port,
1826 int reset_port)
1827{
Lucy McCoy0ca12682007-05-18 12:10:41 -07001828 struct keyspan_usa49_portControlMessage msg;
1829 struct usb_ctrlrequest *dr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 struct keyspan_serial_private *s_priv;
1831 struct keyspan_port_private *p_priv;
1832 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833 struct urb *this_urb;
1834 int err, device_port;
1835
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 s_priv = usb_get_serial_data(serial);
1837 p_priv = usb_get_serial_port_data(port);
1838 d_details = s_priv->device_details;
1839
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840 this_urb = s_priv->glocont_urb;
1841
Lucy McCoy0ca12682007-05-18 12:10:41 -07001842 /* Work out which port within the device is being setup */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 device_port = port->number - port->serial->minor;
1844
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05301845 /* Make sure we have an urb then send the message */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001847 dev_dbg(&port->dev, "%s - oops no urb for port %d.\n", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 return -1;
1849 }
1850
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001851 dev_dbg(&port->dev, "%s - endpoint %d port %d (%d)\n",
1852 __func__, usb_pipeendpoint(this_urb->pipe),
1853 port->number, device_port);
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05301854
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001856 Don't overwrite resend for open/close condition. */
1857 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858 p_priv->resend_cont = reset_port + 1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001859
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001861 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001863 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 }
1865
Alan Coxdeb91682008-07-22 11:13:08 +01001866 memset(&msg, 0, sizeof(struct keyspan_usa49_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867
1868 /*msg.portNumber = port->number;*/
1869 msg.portNumber = device_port;
Alan Coxdeb91682008-07-22 11:13:08 +01001870
1871 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872 if (p_priv->old_baud != p_priv->baud) {
1873 p_priv->old_baud = p_priv->baud;
1874 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001875 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1876 &msg.baudHi, &msg.baudLo, &msg.prescaler,
1877 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1878 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
1879 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880 msg.baudLo = 0;
1881 msg.baudHi = 125; /* Values for 9600 baud */
1882 msg.prescaler = 10;
1883 }
Alan Coxdeb91682008-07-22 11:13:08 +01001884 /* msg.setPrescaler = 0xff; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 }
1886
Ben Minerds2b982ab2012-07-12 00:10:16 +10001887 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888 switch (p_priv->cflag & CSIZE) {
1889 case CS5:
1890 msg.lcr |= USA_DATABITS_5;
1891 break;
1892 case CS6:
1893 msg.lcr |= USA_DATABITS_6;
1894 break;
1895 case CS7:
1896 msg.lcr |= USA_DATABITS_7;
1897 break;
1898 case CS8:
1899 msg.lcr |= USA_DATABITS_8;
1900 break;
1901 }
1902 if (p_priv->cflag & PARENB) {
1903 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10001904 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01001905 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906 }
1907 msg.setLcr = 0xff;
1908
1909 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1910 msg.xonFlowControl = 0;
1911 msg.setFlowControl = 0xff;
Alan Coxdeb91682008-07-22 11:13:08 +01001912
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 msg.forwardingLength = 16;
1914 msg.xonChar = 17;
1915 msg.xoffChar = 19;
1916
Alan Coxdeb91682008-07-22 11:13:08 +01001917 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918 if (reset_port == 1) {
1919 msg._txOn = 1;
1920 msg._txOff = 0;
1921 msg.txFlush = 0;
1922 msg.txBreak = 0;
1923 msg.rxOn = 1;
1924 msg.rxOff = 0;
1925 msg.rxFlush = 1;
1926 msg.rxForward = 0;
1927 msg.returnStatus = 0;
1928 msg.resetDataToggle = 0xff;
1929 msg.enablePort = 1;
1930 msg.disablePort = 0;
1931 }
1932 /* Closing port */
1933 else if (reset_port == 2) {
1934 msg._txOn = 0;
1935 msg._txOff = 1;
1936 msg.txFlush = 0;
1937 msg.txBreak = 0;
1938 msg.rxOn = 0;
1939 msg.rxOff = 1;
1940 msg.rxFlush = 1;
1941 msg.rxForward = 0;
1942 msg.returnStatus = 0;
1943 msg.resetDataToggle = 0;
1944 msg.enablePort = 0;
1945 msg.disablePort = 1;
1946 }
1947 /* Sending intermediate configs */
1948 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001949 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 msg._txOff = 0;
1951 msg.txFlush = 0;
1952 msg.txBreak = (p_priv->break_on);
1953 msg.rxOn = 0;
1954 msg.rxOff = 0;
1955 msg.rxFlush = 0;
1956 msg.rxForward = 0;
1957 msg.returnStatus = 0;
1958 msg.resetDataToggle = 0x0;
1959 msg.enablePort = 0;
1960 msg.disablePort = 0;
1961 }
1962
Alan Coxdeb91682008-07-22 11:13:08 +01001963 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964 msg.setRts = 0xff;
1965 msg.rts = p_priv->rts_state;
1966
1967 msg.setDtr = 0xff;
1968 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01001969
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 p_priv->resend_cont = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971
Alan Coxdeb91682008-07-22 11:13:08 +01001972 /* if the device is a 49wg, we send control message on usb
1973 control EP 0 */
Lucy McCoy0ca12682007-05-18 12:10:41 -07001974
1975 if (d_details->product_id == keyspan_usa49wg_product_id) {
1976 dr = (void *)(s_priv->ctrl_buf);
1977 dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT;
1978 dr->bRequest = 0xB0; /* 49wg control message */;
1979 dr->wValue = 0;
1980 dr->wIndex = 0;
1981 dr->wLength = cpu_to_le16(sizeof(msg));
1982
Alan Coxdeb91682008-07-22 11:13:08 +01001983 memcpy(s_priv->glocont_buf, &msg, sizeof(msg));
Lucy McCoy0ca12682007-05-18 12:10:41 -07001984
Alan Coxdeb91682008-07-22 11:13:08 +01001985 usb_fill_control_urb(this_urb, serial->dev,
1986 usb_sndctrlpipe(serial->dev, 0),
1987 (unsigned char *)dr, s_priv->glocont_buf,
1988 sizeof(msg), usa49_glocont_callback, serial);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001989
1990 } else {
1991 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Alan Coxdeb91682008-07-22 11:13:08 +01001992
Lucy McCoy0ca12682007-05-18 12:10:41 -07001993 /* send the data out the device on control endpoint */
1994 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001995 }
Alan Coxdeb91682008-07-22 11:13:08 +01001996 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1997 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001998 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999#if 0
2000 else {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002001 dev_dbg(&port->dev, "%s - usb_submit_urb(%d) OK %d bytes (end %d)\n", __func__,
2002 outcont_urb, this_urb->transfer_buffer_length,
2003 usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004 }
2005#endif
2006
Alan Coxa5b6f602008-04-08 17:16:06 +01002007 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008}
2009
2010static int keyspan_usa90_send_setup(struct usb_serial *serial,
2011 struct usb_serial_port *port,
2012 int reset_port)
2013{
Alan Coxdeb91682008-07-22 11:13:08 +01002014 struct keyspan_usa90_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015 struct keyspan_serial_private *s_priv;
2016 struct keyspan_port_private *p_priv;
2017 const struct keyspan_device_details *d_details;
2018 struct urb *this_urb;
2019 int err;
2020 u8 prescaler;
2021
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022 s_priv = usb_get_serial_data(serial);
2023 p_priv = usb_get_serial_port_data(port);
2024 d_details = s_priv->device_details;
2025
2026 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01002027 this_urb = p_priv->outcont_urb;
2028 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002029 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030 return -1;
2031 }
2032
2033 /* Save reset port val for resend.
2034 Don't overwrite resend for open/close condition. */
2035 if ((reset_port + 1) > p_priv->resend_cont)
2036 p_priv->resend_cont = reset_port + 1;
2037 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002038 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002040 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041 }
2042
Alan Coxdeb91682008-07-22 11:13:08 +01002043 memset(&msg, 0, sizeof(struct keyspan_usa90_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044
Alan Coxdeb91682008-07-22 11:13:08 +01002045 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046 if (p_priv->old_baud != p_priv->baud) {
2047 p_priv->old_baud = p_priv->baud;
2048 msg.setClocking = 0x01;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002049 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2050 &msg.baudHi, &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) {
2051 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2052 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 p_priv->baud = 9600;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002054 d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055 &msg.baudHi, &msg.baudLo, &prescaler, 0);
2056 }
2057 msg.setRxMode = 1;
2058 msg.setTxMode = 1;
2059 }
2060
2061 /* modes must always be correctly specified */
Alan Coxdeb91682008-07-22 11:13:08 +01002062 if (p_priv->baud > 57600) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 msg.rxMode = RXMODE_DMA;
2064 msg.txMode = TXMODE_DMA;
Alan Coxdeb91682008-07-22 11:13:08 +01002065 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066 msg.rxMode = RXMODE_BYHAND;
2067 msg.txMode = TXMODE_BYHAND;
2068 }
2069
Ben Minerds2b982ab2012-07-12 00:10:16 +10002070 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071 switch (p_priv->cflag & CSIZE) {
2072 case CS5:
2073 msg.lcr |= USA_DATABITS_5;
2074 break;
2075 case CS6:
2076 msg.lcr |= USA_DATABITS_6;
2077 break;
2078 case CS7:
2079 msg.lcr |= USA_DATABITS_7;
2080 break;
2081 case CS8:
2082 msg.lcr |= USA_DATABITS_8;
2083 break;
2084 }
2085 if (p_priv->cflag & PARENB) {
2086 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002087 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002088 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089 }
2090 if (p_priv->old_cflag != p_priv->cflag) {
2091 p_priv->old_cflag = p_priv->cflag;
2092 msg.setLcr = 0x01;
2093 }
2094
2095 if (p_priv->flow_control == flow_cts)
2096 msg.txFlowControl = TXFLOW_CTS;
2097 msg.setTxFlowControl = 0x01;
2098 msg.setRxFlowControl = 0x01;
Alan Coxdeb91682008-07-22 11:13:08 +01002099
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100 msg.rxForwardingLength = 16;
Alan Coxdeb91682008-07-22 11:13:08 +01002101 msg.rxForwardingTimeout = 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102 msg.txAckSetting = 0;
2103 msg.xonChar = 17;
2104 msg.xoffChar = 19;
2105
Alan Coxdeb91682008-07-22 11:13:08 +01002106 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 if (reset_port == 1) {
2108 msg.portEnabled = 1;
2109 msg.rxFlush = 1;
2110 msg.txBreak = (p_priv->break_on);
2111 }
2112 /* Closing port */
Alan Coxdeb91682008-07-22 11:13:08 +01002113 else if (reset_port == 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 msg.portEnabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 /* Sending intermediate configs */
2116 else {
Alan Stern1f871582010-02-17 10:05:47 -05002117 msg.portEnabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 msg.txBreak = (p_priv->break_on);
2119 }
2120
Alan Coxdeb91682008-07-22 11:13:08 +01002121 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122 msg.setRts = 0x01;
2123 msg.rts = p_priv->rts_state;
2124
2125 msg.setDtr = 0x01;
2126 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002127
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01002129 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2130
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 /* send the data out the device on control endpoint */
2132 this_urb->transfer_buffer_length = sizeof(msg);
2133
Alan Coxdeb91682008-07-22 11:13:08 +01002134 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2135 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002136 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002137 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138}
2139
Lucy McCoy0ca12682007-05-18 12:10:41 -07002140static int keyspan_usa67_send_setup(struct usb_serial *serial,
2141 struct usb_serial_port *port,
2142 int reset_port)
2143{
2144 struct keyspan_usa67_portControlMessage msg;
2145 struct keyspan_serial_private *s_priv;
2146 struct keyspan_port_private *p_priv;
2147 const struct keyspan_device_details *d_details;
2148 struct urb *this_urb;
2149 int err, device_port;
2150
Lucy McCoy0ca12682007-05-18 12:10:41 -07002151 s_priv = usb_get_serial_data(serial);
2152 p_priv = usb_get_serial_port_data(port);
2153 d_details = s_priv->device_details;
2154
2155 this_urb = s_priv->glocont_urb;
2156
2157 /* Work out which port within the device is being setup */
2158 device_port = port->number - port->serial->minor;
2159
2160 /* Make sure we have an urb then send the message */
2161 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002162 dev_dbg(&port->dev, "%s - oops no urb for port %d.\n", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002163 port->number);
2164 return -1;
2165 }
2166
2167 /* Save reset port val for resend.
2168 Don't overwrite resend for open/close condition. */
2169 if ((reset_port + 1) > p_priv->resend_cont)
2170 p_priv->resend_cont = reset_port + 1;
2171 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002172 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002173 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002174 return -1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002175 }
2176
2177 memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
2178
2179 msg.port = device_port;
2180
2181 /* Only set baud rate if it's changed */
2182 if (p_priv->old_baud != p_priv->baud) {
2183 p_priv->old_baud = p_priv->baud;
2184 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002185 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2186 &msg.baudHi, &msg.baudLo, &msg.prescaler,
2187 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2188 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2189 __func__, p_priv->baud);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002190 msg.baudLo = 0;
2191 msg.baudHi = 125; /* Values for 9600 baud */
2192 msg.prescaler = 10;
2193 }
2194 msg.setPrescaler = 0xff;
2195 }
2196
2197 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
2198 switch (p_priv->cflag & CSIZE) {
2199 case CS5:
2200 msg.lcr |= USA_DATABITS_5;
2201 break;
2202 case CS6:
2203 msg.lcr |= USA_DATABITS_6;
2204 break;
2205 case CS7:
2206 msg.lcr |= USA_DATABITS_7;
2207 break;
2208 case CS8:
2209 msg.lcr |= USA_DATABITS_8;
2210 break;
2211 }
2212 if (p_priv->cflag & PARENB) {
2213 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002214 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002215 USA_PARITY_ODD : USA_PARITY_EVEN;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002216 }
2217 msg.setLcr = 0xff;
2218
2219 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2220 msg.xonFlowControl = 0;
2221 msg.setFlowControl = 0xff;
2222 msg.forwardingLength = 16;
2223 msg.xonChar = 17;
2224 msg.xoffChar = 19;
2225
2226 if (reset_port == 1) {
2227 /* Opening port */
2228 msg._txOn = 1;
2229 msg._txOff = 0;
2230 msg.txFlush = 0;
2231 msg.txBreak = 0;
2232 msg.rxOn = 1;
2233 msg.rxOff = 0;
2234 msg.rxFlush = 1;
2235 msg.rxForward = 0;
2236 msg.returnStatus = 0;
2237 msg.resetDataToggle = 0xff;
2238 } else if (reset_port == 2) {
2239 /* Closing port */
2240 msg._txOn = 0;
2241 msg._txOff = 1;
2242 msg.txFlush = 0;
2243 msg.txBreak = 0;
2244 msg.rxOn = 0;
2245 msg.rxOff = 1;
2246 msg.rxFlush = 1;
2247 msg.rxForward = 0;
2248 msg.returnStatus = 0;
2249 msg.resetDataToggle = 0;
2250 } else {
2251 /* Sending intermediate configs */
Alan Coxdeb91682008-07-22 11:13:08 +01002252 msg._txOn = (!p_priv->break_on);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002253 msg._txOff = 0;
2254 msg.txFlush = 0;
2255 msg.txBreak = (p_priv->break_on);
2256 msg.rxOn = 0;
2257 msg.rxOff = 0;
2258 msg.rxFlush = 0;
2259 msg.rxForward = 0;
2260 msg.returnStatus = 0;
2261 msg.resetDataToggle = 0x0;
2262 }
2263
2264 /* Do handshaking outputs */
2265 msg.setTxTriState_setRts = 0xff;
2266 msg.txTriState_rts = p_priv->rts_state;
2267
2268 msg.setHskoa_setDtr = 0xff;
2269 msg.hskoa_dtr = p_priv->dtr_state;
2270
2271 p_priv->resend_cont = 0;
2272
2273 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2274
2275 /* send the data out the device on control endpoint */
2276 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002277
2278 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2279 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002280 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002281 return 0;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002282}
2283
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
2285{
2286 struct usb_serial *serial = port->serial;
2287 struct keyspan_serial_private *s_priv;
2288 const struct keyspan_device_details *d_details;
2289
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290 s_priv = usb_get_serial_data(serial);
2291 d_details = s_priv->device_details;
2292
2293 switch (d_details->msg_format) {
2294 case msg_usa26:
2295 keyspan_usa26_send_setup(serial, port, reset_port);
2296 break;
2297 case msg_usa28:
2298 keyspan_usa28_send_setup(serial, port, reset_port);
2299 break;
2300 case msg_usa49:
2301 keyspan_usa49_send_setup(serial, port, reset_port);
2302 break;
2303 case msg_usa90:
2304 keyspan_usa90_send_setup(serial, port, reset_port);
2305 break;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002306 case msg_usa67:
2307 keyspan_usa67_send_setup(serial, port, reset_port);
2308 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309 }
2310}
2311
2312
2313/* Gets called by the "real" driver (ie once firmware is loaded
2314 and renumeration has taken place. */
Alan Coxdeb91682008-07-22 11:13:08 +01002315static int keyspan_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316{
2317 int i, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319 const struct keyspan_device_details *d_details;
2320
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321 for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
Alan Coxdeb91682008-07-22 11:13:08 +01002322 if (d_details->product_id ==
2323 le16_to_cpu(serial->dev->descriptor.idProduct))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324 break;
2325 if (d_details == NULL) {
Alan Coxdeb91682008-07-22 11:13:08 +01002326 dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
2327 __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 return 1;
2329 }
2330
2331 /* Setup private data for serial driver */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01002332 s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333 if (!s_priv) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002334 dev_dbg(&serial->dev->dev, "%s - kmalloc for keyspan_serial_private failed.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 return -ENOMEM;
2336 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337
2338 s_priv->device_details = d_details;
2339 usb_set_serial_data(serial, s_priv);
2340
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341 keyspan_setup_urbs(serial);
2342
Lucy McCoy0ca12682007-05-18 12:10:41 -07002343 if (s_priv->instat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002344 err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
2345 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002346 dev_dbg(&serial->dev->dev, "%s - submit instat urb failed %d\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002347 }
2348 if (s_priv->indat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002349 err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
2350 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002351 dev_dbg(&serial->dev->dev, "%s - submit indat urb failed %d\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 }
Alan Coxdeb91682008-07-22 11:13:08 +01002353
Alan Coxa5b6f602008-04-08 17:16:06 +01002354 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355}
2356
Alan Sternf9c99bb2009-06-02 11:53:55 -04002357static void keyspan_disconnect(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002359 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361 s_priv = usb_get_serial_data(serial);
2362
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 stop_urb(s_priv->instat_urb);
2364 stop_urb(s_priv->glocont_urb);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002365 stop_urb(s_priv->indat_urb);
Alan Sternf9c99bb2009-06-02 11:53:55 -04002366}
2367
2368static void keyspan_release(struct usb_serial *serial)
2369{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002370 struct keyspan_serial_private *s_priv;
Alan Sternf9c99bb2009-06-02 11:53:55 -04002371
Alan Sternf9c99bb2009-06-02 11:53:55 -04002372 s_priv = usb_get_serial_data(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002374 usb_free_urb(s_priv->instat_urb);
2375 usb_free_urb(s_priv->indat_urb);
2376 usb_free_urb(s_priv->glocont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002378 kfree(s_priv);
2379}
2380
2381static int keyspan_port_probe(struct usb_serial_port *port)
2382{
2383 struct usb_serial *serial = port->serial;
Bjørn Morkf0e3e352012-11-10 10:13:42 +01002384 struct keyspan_serial_private *s_priv;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002385 struct keyspan_port_private *p_priv;
2386 const struct keyspan_device_details *d_details;
2387 struct callbacks *cback;
2388 int endp;
2389 int port_num;
2390 int i;
2391
2392 s_priv = usb_get_serial_data(serial);
2393 d_details = s_priv->device_details;
2394
2395 p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL);
2396 if (!p_priv)
2397 return -ENOMEM;
2398
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002399 p_priv->device_details = d_details;
2400
2401 /* Setup values for the various callback routines */
2402 cback = &keyspan_callbacks[d_details->msg_format];
2403
2404 port_num = port->number - port->serial->minor;
2405
2406 /* Do indat endpoints first, once for each flip */
2407 endp = d_details->indat_endpoints[port_num];
2408 for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) {
2409 p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp,
2410 USB_DIR_IN, port,
2411 p_priv->in_buffer[i], 64,
2412 cback->indat_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413 }
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002414 /* outdat endpoints also have flip */
2415 endp = d_details->outdat_endpoints[port_num];
2416 for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) {
2417 p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp,
2418 USB_DIR_OUT, port,
2419 p_priv->out_buffer[i], 64,
2420 cback->outdat_callback);
2421 }
2422 /* inack endpoint */
2423 p_priv->inack_urb = keyspan_setup_urb(serial,
2424 d_details->inack_endpoints[port_num],
2425 USB_DIR_IN, port,
2426 p_priv->inack_buffer, 1,
2427 cback->inack_callback);
2428 /* outcont endpoint */
2429 p_priv->outcont_urb = keyspan_setup_urb(serial,
2430 d_details->outcont_endpoints[port_num],
2431 USB_DIR_OUT, port,
2432 p_priv->outcont_buffer, 64,
2433 cback->outcont_callback);
2434
2435 usb_set_serial_port_data(port, p_priv);
2436
2437 return 0;
2438}
2439
2440static int keyspan_port_remove(struct usb_serial_port *port)
2441{
2442 struct keyspan_port_private *p_priv;
2443 int i;
2444
2445 p_priv = usb_get_serial_port_data(port);
2446
2447 stop_urb(p_priv->inack_urb);
2448 stop_urb(p_priv->outcont_urb);
2449 for (i = 0; i < 2; i++) {
2450 stop_urb(p_priv->in_urbs[i]);
2451 stop_urb(p_priv->out_urbs[i]);
2452 }
2453
2454 usb_free_urb(p_priv->inack_urb);
2455 usb_free_urb(p_priv->outcont_urb);
2456 for (i = 0; i < 2; i++) {
2457 usb_free_urb(p_priv->in_urbs[i]);
2458 usb_free_urb(p_priv->out_urbs[i]);
2459 }
2460
2461 kfree(p_priv);
2462
2463 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464}
2465
Alan Coxdeb91682008-07-22 11:13:08 +01002466MODULE_AUTHOR(DRIVER_AUTHOR);
2467MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468MODULE_LICENSE("GPL");
2469
David Woodhouse2971c572008-05-30 14:04:03 +03002470MODULE_FIRMWARE("keyspan/usa28.fw");
2471MODULE_FIRMWARE("keyspan/usa28x.fw");
2472MODULE_FIRMWARE("keyspan/usa28xa.fw");
2473MODULE_FIRMWARE("keyspan/usa28xb.fw");
2474MODULE_FIRMWARE("keyspan/usa19.fw");
2475MODULE_FIRMWARE("keyspan/usa19qi.fw");
2476MODULE_FIRMWARE("keyspan/mpr.fw");
2477MODULE_FIRMWARE("keyspan/usa19qw.fw");
2478MODULE_FIRMWARE("keyspan/usa18x.fw");
2479MODULE_FIRMWARE("keyspan/usa19w.fw");
2480MODULE_FIRMWARE("keyspan/usa49w.fw");
2481MODULE_FIRMWARE("keyspan/usa49wlc.fw");