blob: 3d2ce56e10098329e09970510d54d342ec92a524 [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;
Johan Hovold2fcd1c92013-08-13 13:27:36 +020059 char *instat_buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -070060
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;
Johan Hovold2fcd1c92013-08-13 13:27:36 +020064 char *indat_buf;
Lucy McCoy0ca12682007-05-18 12:10:41 -070065
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 /* XXX this one probably will need a lock */
67 struct urb *glocont_urb;
Johan Hovold2fcd1c92013-08-13 13:27:36 +020068 char *glocont_buf;
69 char *ctrl_buf; /* 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;
Greg Kroah-Hartman11438322013-06-06 10:32:00 -0700155 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156
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-Hartman11438322013-06-06 10:32:00 -0700237 dev_dbg(&port->dev, "%s - %d chars, flip=%d\n", __func__, count,
238 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
Andy Shevchenko715cf922013-05-28 12:49:17 +0300523 /*dev_dbg(&urb->dev->dev, "%s %12ph", __func__, data);*/
Alan Coxdeb91682008-07-22 11:13:08 +0100524
525 /* Now do something useful with the data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 msg = (struct keyspan_usa28_portStatusMessage *)data;
527
Alan Coxdeb91682008-07-22 11:13:08 +0100528 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700530 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 goto exit;
532 }
533 port = serial->port[msg->port];
534 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100535
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 /* Update handshaking pin state information */
537 old_dcd_state = p_priv->dcd_state;
538 p_priv->cts_state = ((msg->cts) ? 1 : 0);
539 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
540 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
541 p_priv->ri_state = ((msg->ri) ? 1 : 0);
542
Jiri Slabyaa27a092013-03-07 13:12:30 +0100543 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
544 tty_port_tty_hangup(&port->port, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545
546 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100547 err = usb_submit_urb(urb, GFP_ATOMIC);
548 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700549 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550exit: ;
551}
552
David Howells7d12e782006-10-05 14:55:46 +0100553static void usa28_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555}
556
557
David Howells7d12e782006-10-05 14:55:46 +0100558static void usa49_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559{
560 struct usb_serial *serial;
561 struct usb_serial_port *port;
562 struct keyspan_port_private *p_priv;
563 int i;
564
Ming Leicdc97792008-02-24 18:41:47 +0800565 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 for (i = 0; i < serial->num_ports; ++i) {
567 port = serial->port[i];
568 p_priv = usb_get_serial_port_data(port);
569
570 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700571 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100572 keyspan_usa49_send_setup(serial, port,
573 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 break;
575 }
576 }
577}
578
579 /* This is actually called glostat in the Keyspan
580 doco */
David Howells7d12e782006-10-05 14:55:46 +0100581static void usa49_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582{
583 int err;
584 unsigned char *data = urb->transfer_buffer;
585 struct keyspan_usa49_portStatusMessage *msg;
586 struct usb_serial *serial;
587 struct usb_serial_port *port;
588 struct keyspan_port_private *p_priv;
589 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700590 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591
Ming Leicdc97792008-02-24 18:41:47 +0800592 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700594 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700595 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 return;
597 }
598
Alan Coxdeb91682008-07-22 11:13:08 +0100599 if (urb->actual_length !=
600 sizeof(struct keyspan_usa49_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700601 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 goto exit;
603 }
604
Andy Shevchenko715cf922013-05-28 12:49:17 +0300605 /*dev_dbg(&urb->dev->dev, "%s: %11ph", __func__, data);*/
Alan Coxdeb91682008-07-22 11:13:08 +0100606
607 /* Now do something useful with the data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 msg = (struct keyspan_usa49_portStatusMessage *)data;
609
Alan Coxdeb91682008-07-22 11:13:08 +0100610 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 if (msg->portNumber >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700612 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
613 __func__, msg->portNumber);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 goto exit;
615 }
616 port = serial->port[msg->portNumber];
617 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100618
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 /* Update handshaking pin state information */
620 old_dcd_state = p_priv->dcd_state;
621 p_priv->cts_state = ((msg->cts) ? 1 : 0);
622 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
623 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
624 p_priv->ri_state = ((msg->ri) ? 1 : 0);
625
Jiri Slabyaa27a092013-03-07 13:12:30 +0100626 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
627 tty_port_tty_hangup(&port->port, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628
Alan Coxdeb91682008-07-22 11:13:08 +0100629 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100630 err = usb_submit_urb(urb, GFP_ATOMIC);
631 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700632 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633exit: ;
634}
635
David Howells7d12e782006-10-05 14:55:46 +0100636static void usa49_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638}
639
David Howells7d12e782006-10-05 14:55:46 +0100640static void usa49_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641{
642 int i, err;
643 int endpoint;
644 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700646 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 endpoint = usb_pipeendpoint(urb->pipe);
649
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700650 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700651 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
652 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 return;
654 }
655
Ming Leicdc97792008-02-24 18:41:47 +0800656 port = urb->context;
Jiri Slaby2e124b42013-01-03 15:53:06 +0100657 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 /* 0x80 bit is error flag */
659 if ((data[0] & 0x80) == 0) {
660 /* no error on any byte */
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100661 tty_insert_flip_string(&port->port, data + 1,
Alan Coxf035a8a2008-07-22 11:13:32 +0100662 urb->actual_length - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 } else {
664 /* some bytes had errors, every byte has status */
665 for (i = 0; i + 1 < urb->actual_length; i += 2) {
666 int stat = data[i], flag = 0;
667 if (stat & RXERROR_OVERRUN)
668 flag |= TTY_OVERRUN;
669 if (stat & RXERROR_FRAMING)
670 flag |= TTY_FRAME;
671 if (stat & RXERROR_PARITY)
672 flag |= TTY_PARITY;
673 /* XXX should handle break (0x10) */
Jiri Slaby92a19f92013-01-03 15:53:03 +0100674 tty_insert_flip_char(&port->port, data[i+1],
675 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 }
677 }
Jiri Slaby2e124b42013-01-03 15:53:06 +0100678 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 }
Alan Coxdeb91682008-07-22 11:13:08 +0100680
681 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500682 err = usb_submit_urb(urb, GFP_ATOMIC);
683 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700684 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685}
686
Lucy McCoy0ca12682007-05-18 12:10:41 -0700687static void usa49wg_indat_callback(struct urb *urb)
688{
689 int i, len, x, err;
690 struct usb_serial *serial;
691 struct usb_serial_port *port;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700692 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700693 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700694
Lucy McCoy0ca12682007-05-18 12:10:41 -0700695 serial = urb->context;
696
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700697 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700698 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700699 return;
700 }
701
702 /* inbound data is in the form P#, len, status, data */
703 i = 0;
704 len = 0;
705
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300706 while (i < urb->actual_length) {
Lucy McCoy0ca12682007-05-18 12:10:41 -0700707
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300708 /* Check port number from message */
709 if (data[i] >= serial->num_ports) {
710 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
711 __func__, data[i]);
712 return;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700713 }
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300714 port = serial->port[data[i++]];
715 len = data[i++];
716
717 /* 0x80 bit is error flag */
718 if ((data[i] & 0x80) == 0) {
719 /* no error on any byte */
720 i++;
Dan Carpenter01a60e72013-04-05 08:43:20 +0300721 for (x = 1; x < len && i < urb->actual_length; ++x)
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300722 tty_insert_flip_char(&port->port,
723 data[i++], 0);
724 } else {
725 /*
726 * some bytes had errors, every byte has status
727 */
Dan Carpenter01a60e72013-04-05 08:43:20 +0300728 for (x = 0; x + 1 < len &&
729 i + 1 < urb->actual_length; x += 2) {
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300730 int stat = data[i], flag = 0;
731
732 if (stat & RXERROR_OVERRUN)
733 flag |= TTY_OVERRUN;
734 if (stat & RXERROR_FRAMING)
735 flag |= TTY_FRAME;
736 if (stat & RXERROR_PARITY)
737 flag |= TTY_PARITY;
738 /* XXX should handle break (0x10) */
739 tty_insert_flip_char(&port->port, data[i+1],
740 flag);
741 i += 2;
742 }
743 }
744 tty_flip_buffer_push(&port->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700745 }
746
747 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700748 err = usb_submit_urb(urb, GFP_ATOMIC);
749 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700750 dev_dbg(&urb->dev->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700751}
752
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753/* not used, usa-49 doesn't have per-port control endpoints */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700754static void usa49_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756}
757
Lucy McCoy0ca12682007-05-18 12:10:41 -0700758static void usa90_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759{
760 int i, err;
761 int endpoint;
762 struct usb_serial_port *port;
763 struct keyspan_port_private *p_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700765 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767 endpoint = usb_pipeendpoint(urb->pipe);
768
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700769 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700770 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800771 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 return;
773 }
774
Ming Leicdc97792008-02-24 18:41:47 +0800775 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 p_priv = usb_get_serial_port_data(port);
777
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 /* if current mode is DMA, looks like usa28 format
Alan Coxdeb91682008-07-22 11:13:08 +0100780 otherwise looks like usa26 data format */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781
Alan Coxf035a8a2008-07-22 11:13:32 +0100782 if (p_priv->baud > 57600)
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100783 tty_insert_flip_string(&port->port, data,
784 urb->actual_length);
Alan Coxf035a8a2008-07-22 11:13:32 +0100785 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 /* 0x80 bit is error flag */
787 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100788 /* no errors on individual bytes, only
789 possible overrun err*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 if (data[0] & RXERROR_OVERRUN)
Alan Coxdeb91682008-07-22 11:13:08 +0100791 err = TTY_OVERRUN;
792 else
793 err = 0;
794 for (i = 1; i < urb->actual_length ; ++i)
Jiri Slaby92a19f92013-01-03 15:53:03 +0100795 tty_insert_flip_char(&port->port,
796 data[i], err);
Alan Coxdeb91682008-07-22 11:13:08 +0100797 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 /* some bytes had errors, every byte has status */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700799 dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 for (i = 0; i + 1 < urb->actual_length; i += 2) {
801 int stat = data[i], flag = 0;
802 if (stat & RXERROR_OVERRUN)
803 flag |= TTY_OVERRUN;
804 if (stat & RXERROR_FRAMING)
805 flag |= TTY_FRAME;
806 if (stat & RXERROR_PARITY)
807 flag |= TTY_PARITY;
808 /* XXX should handle break (0x10) */
Jiri Slaby92a19f92013-01-03 15:53:03 +0100809 tty_insert_flip_char(&port->port,
810 data[i+1], flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 }
812 }
813 }
Jiri Slaby2e124b42013-01-03 15:53:06 +0100814 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 }
Alan Coxdeb91682008-07-22 11:13:08 +0100816
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500818 err = usb_submit_urb(urb, GFP_ATOMIC);
819 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700820 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821}
822
823
David Howells7d12e782006-10-05 14:55:46 +0100824static void usa90_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825{
826 unsigned char *data = urb->transfer_buffer;
827 struct keyspan_usa90_portStatusMessage *msg;
828 struct usb_serial *serial;
829 struct usb_serial_port *port;
830 struct keyspan_port_private *p_priv;
831 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700832 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833
Ming Leicdc97792008-02-24 18:41:47 +0800834 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700836 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700837 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 return;
839 }
840 if (urb->actual_length < 14) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700841 dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 goto exit;
843 }
844
845 msg = (struct keyspan_usa90_portStatusMessage *)data;
846
847 /* Now do something useful with the data */
848
849 port = serial->port[0];
850 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100851
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 /* Update handshaking pin state information */
853 old_dcd_state = p_priv->dcd_state;
854 p_priv->cts_state = ((msg->cts) ? 1 : 0);
855 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
856 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
857 p_priv->ri_state = ((msg->ri) ? 1 : 0);
858
Jiri Slabyaa27a092013-03-07 13:12:30 +0100859 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
860 tty_port_tty_hangup(&port->port, true);
Alan Coxdeb91682008-07-22 11:13:08 +0100861
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100863 err = usb_submit_urb(urb, GFP_ATOMIC);
864 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700865 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866exit:
867 ;
868}
869
David Howells7d12e782006-10-05 14:55:46 +0100870static void usa90_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871{
872 struct usb_serial_port *port;
873 struct keyspan_port_private *p_priv;
874
Ming Leicdc97792008-02-24 18:41:47 +0800875 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 p_priv = usb_get_serial_port_data(port);
877
878 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700879 dev_dbg(&urb->dev->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100880 keyspan_usa90_send_setup(port->serial, port,
881 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 }
883}
884
Lucy McCoy0ca12682007-05-18 12:10:41 -0700885/* Status messages from the 28xg */
886static void usa67_instat_callback(struct urb *urb)
887{
888 int err;
889 unsigned char *data = urb->transfer_buffer;
890 struct keyspan_usa67_portStatusMessage *msg;
891 struct usb_serial *serial;
892 struct usb_serial_port *port;
893 struct keyspan_port_private *p_priv;
894 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700895 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700896
Lucy McCoy0ca12682007-05-18 12:10:41 -0700897 serial = urb->context;
898
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700899 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700900 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700901 return;
902 }
903
Alan Coxdeb91682008-07-22 11:13:08 +0100904 if (urb->actual_length !=
905 sizeof(struct keyspan_usa67_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700906 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700907 return;
908 }
909
910
911 /* Now do something useful with the data */
912 msg = (struct keyspan_usa67_portStatusMessage *)data;
913
914 /* Check port number from message and retrieve private data */
915 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700916 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700917 return;
918 }
919
920 port = serial->port[msg->port];
921 p_priv = usb_get_serial_port_data(port);
922
923 /* Update handshaking pin state information */
924 old_dcd_state = p_priv->dcd_state;
925 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
926 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
927
Jiri Slabyaa27a092013-03-07 13:12:30 +0100928 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
929 tty_port_tty_hangup(&port->port, true);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700930
931 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700932 err = usb_submit_urb(urb, GFP_ATOMIC);
933 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700934 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700935}
936
937static void usa67_glocont_callback(struct urb *urb)
938{
939 struct usb_serial *serial;
940 struct usb_serial_port *port;
941 struct keyspan_port_private *p_priv;
942 int i;
943
Lucy McCoy0ca12682007-05-18 12:10:41 -0700944 serial = urb->context;
945 for (i = 0; i < serial->num_ports; ++i) {
946 port = serial->port[i];
947 p_priv = usb_get_serial_port_data(port);
948
949 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700950 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700951 keyspan_usa67_send_setup(serial, port,
952 p_priv->resend_cont - 1);
953 break;
954 }
955 }
956}
957
Alan Cox95da3102008-07-22 11:09:07 +0100958static int keyspan_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959{
Alan Cox95da3102008-07-22 11:09:07 +0100960 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 struct keyspan_port_private *p_priv;
962 const struct keyspan_device_details *d_details;
963 int flip;
964 int data_len;
965 struct urb *this_urb;
966
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 p_priv = usb_get_serial_port_data(port);
968 d_details = p_priv->device_details;
969
Alan Coxa5b6f602008-04-08 17:16:06 +0100970 /* FIXME: locking */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 if (d_details->msg_format == msg_usa90)
Alan Coxdeb91682008-07-22 11:13:08 +0100972 data_len = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 else
974 data_len = 63;
975
976 flip = p_priv->out_flip;
977
978 /* Check both endpoints to see if any are available. */
Alan Coxdeb91682008-07-22 11:13:08 +0100979 this_urb = p_priv->out_urbs[flip];
980 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +0100982 return data_len;
983 flip = (flip + 1) & d_details->outdat_endp_flip;
984 this_urb = p_priv->out_urbs[flip];
985 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +0100987 return data_len;
988 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 }
Alan Coxa5b6f602008-04-08 17:16:06 +0100990 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991}
992
993
Alan Coxa509a7e2009-09-19 13:13:26 -0700994static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995{
Andrew Mortonf78ba152007-11-28 16:21:54 -0800996 struct keyspan_port_private *p_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 const struct keyspan_device_details *d_details;
998 int i, err;
Andrew Mortonf78ba152007-11-28 16:21:54 -0800999 int baud_rate, device_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 struct urb *urb;
Alan Cox95da3102008-07-22 11:09:07 +01001001 unsigned int cflag = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 p_priv = usb_get_serial_port_data(port);
1004 d_details = p_priv->device_details;
Borislav Petkov7eea4362007-11-14 17:00:39 -08001005
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 /* Set some sane defaults */
1007 p_priv->rts_state = 1;
1008 p_priv->dtr_state = 1;
1009 p_priv->baud = 9600;
1010
1011 /* force baud and lcr to be set on open */
1012 p_priv->old_baud = 0;
1013 p_priv->old_cflag = 0;
1014
1015 p_priv->out_flip = 0;
1016 p_priv->in_flip = 0;
1017
1018 /* Reset low level data toggle and start reading from endpoints */
1019 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001020 urb = p_priv->in_urbs[i];
1021 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023
Alan Coxdeb91682008-07-22 11:13:08 +01001024 /* make sure endpoint data toggle is synchronized
1025 with the device */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 usb_clear_halt(urb->dev, urb->pipe);
Alan Coxdeb91682008-07-22 11:13:08 +01001027 err = usb_submit_urb(urb, GFP_KERNEL);
1028 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001029 dev_dbg(&port->dev, "%s - submit urb %d failed (%d)\n", __func__, i, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 }
1031
1032 /* Reset low level data toggle on out endpoints */
1033 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001034 urb = p_priv->out_urbs[i];
1035 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 continue;
Alan Coxdeb91682008-07-22 11:13:08 +01001037 /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
1038 usb_pipeout(urb->pipe), 0); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 }
1040
Andrew Mortonf78ba152007-11-28 16:21:54 -08001041 /* get the terminal config for the setup message now so we don't
1042 * need to send 2 of them */
1043
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001044 device_port = port->port_number;
Alan Cox95da3102008-07-22 11:09:07 +01001045 if (tty) {
Alan Coxadc8d742012-07-14 15:31:47 +01001046 cflag = tty->termios.c_cflag;
Alan Cox95da3102008-07-22 11:09:07 +01001047 /* Baud rate calculation takes baud rate as an integer
1048 so other rates can be generated if desired. */
1049 baud_rate = tty_get_baud_rate(tty);
1050 /* If no match or invalid, leave as default */
1051 if (baud_rate >= 0
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001052 && d_details->calculate_baud_rate(port, baud_rate, d_details->baudclk,
Alan Cox95da3102008-07-22 11:09:07 +01001053 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
1054 p_priv->baud = baud_rate;
1055 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001056 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001057 /* set CTS/RTS handshake etc. */
1058 p_priv->cflag = cflag;
Ben Minerds2b982ab2012-07-12 00:10:16 +10001059 p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001060
1061 keyspan_send_setup(port, 1);
Alan Coxdeb91682008-07-22 11:13:08 +01001062 /* mdelay(100); */
1063 /* keyspan_set_termios(port, NULL); */
Andrew Mortonf78ba152007-11-28 16:21:54 -08001064
Alan Coxa5b6f602008-04-08 17:16:06 +01001065 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066}
1067
1068static inline void stop_urb(struct urb *urb)
1069{
Greg Kroah-Hartman242cf672005-07-29 16:11:07 -04001070 if (urb && urb->status == -EINPROGRESS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 usb_kill_urb(urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072}
1073
Alan Cox335f8512009-06-11 12:26:29 +01001074static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
1075{
1076 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
1077
1078 p_priv->rts_state = on;
1079 p_priv->dtr_state = on;
1080 keyspan_send_setup(port, 0);
1081}
1082
1083static void keyspan_close(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084{
1085 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 struct keyspan_port_private *p_priv;
1087
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +01001089
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 p_priv->rts_state = 0;
1091 p_priv->dtr_state = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001092
Johan Hovold80dfe0c2013-03-21 12:36:32 +01001093 keyspan_send_setup(port, 2);
1094 /* pilot-xfer seems to work best with this delay */
1095 mdelay(100);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096
1097 p_priv->out_flip = 0;
1098 p_priv->in_flip = 0;
1099
Johan Hovold80dfe0c2013-03-21 12:36:32 +01001100 stop_urb(p_priv->inack_urb);
1101 for (i = 0; i < 2; i++) {
1102 stop_urb(p_priv->in_urbs[i]);
1103 stop_urb(p_priv->out_urbs[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105}
1106
Alan Coxdeb91682008-07-22 11:13:08 +01001107/* download the firmware to a pre-renumeration device */
1108static int keyspan_fake_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109{
Rene Buergel8d733e22012-09-18 09:02:01 +02001110 char *fw_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001112 dev_dbg(&serial->dev->dev, "Keyspan startup version %04x product %04x\n",
1113 le16_to_cpu(serial->dev->descriptor.bcdDevice),
1114 le16_to_cpu(serial->dev->descriptor.idProduct));
Alan Coxdeb91682008-07-22 11:13:08 +01001115
1116 if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000)
1117 != 0x8000) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001118 dev_dbg(&serial->dev->dev, "Firmware already loaded. Quitting.\n");
Alan Coxdeb91682008-07-22 11:13:08 +01001119 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 }
1121
1122 /* Select firmware image on the basis of idProduct */
1123 switch (le16_to_cpu(serial->dev->descriptor.idProduct)) {
1124 case keyspan_usa28_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001125 fw_name = "keyspan/usa28.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 break;
1127
1128 case keyspan_usa28x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001129 fw_name = "keyspan/usa28x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 break;
1131
1132 case keyspan_usa28xa_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001133 fw_name = "keyspan/usa28xa.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 break;
1135
1136 case keyspan_usa28xb_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001137 fw_name = "keyspan/usa28xb.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 break;
1139
1140 case keyspan_usa19_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001141 fw_name = "keyspan/usa19.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001143
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 case keyspan_usa19qi_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001145 fw_name = "keyspan/usa19qi.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001147
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 case keyspan_mpr_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001149 fw_name = "keyspan/mpr.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 break;
1151
1152 case keyspan_usa19qw_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001153 fw_name = "keyspan/usa19qw.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001155
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 case keyspan_usa18x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001157 fw_name = "keyspan/usa18x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001159
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 case keyspan_usa19w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001161 fw_name = "keyspan/usa19w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001163
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 case keyspan_usa49w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001165 fw_name = "keyspan/usa49w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 break;
1167
1168 case keyspan_usa49wlc_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001169 fw_name = "keyspan/usa49wlc.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 break;
1171
1172 default:
David Woodhouse2971c572008-05-30 14:04:03 +03001173 dev_err(&serial->dev->dev, "Unknown product ID (%04x)\n",
1174 le16_to_cpu(serial->dev->descriptor.idProduct));
1175 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 }
1177
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001178 dev_dbg(&serial->dev->dev, "Uploading Keyspan %s firmware.\n", fw_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179
Rene Buergel8d733e22012-09-18 09:02:01 +02001180 if (ezusb_fx1_ihex_firmware_download(serial->dev, fw_name) < 0) {
1181 dev_err(&serial->dev->dev, "failed to load firmware \"%s\"\n",
1182 fw_name);
1183 return -ENOENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 }
1185
Rene Buergel8d733e22012-09-18 09:02:01 +02001186 /* after downloading firmware Renumeration will occur in a
1187 moment and the new device will bind to the real driver */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188
1189 /* we don't want this device to have a driver assigned to it. */
Alan Coxdeb91682008-07-22 11:13:08 +01001190 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191}
1192
1193/* Helper functions used by keyspan_setup_urbs */
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001194static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *serial,
1195 int endpoint)
1196{
1197 struct usb_host_interface *iface_desc;
1198 struct usb_endpoint_descriptor *ep;
1199 int i;
1200
1201 iface_desc = serial->interface->cur_altsetting;
1202 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1203 ep = &iface_desc->endpoint[i].desc;
1204 if (ep->bEndpointAddress == endpoint)
1205 return ep;
1206 }
1207 dev_warn(&serial->interface->dev, "found no endpoint descriptor for "
1208 "endpoint %x\n", endpoint);
1209 return NULL;
1210}
1211
Alan Coxdeb91682008-07-22 11:13:08 +01001212static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 int dir, void *ctx, char *buf, int len,
David Howells7d12e782006-10-05 14:55:46 +01001214 void (*callback)(struct urb *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215{
1216 struct urb *urb;
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001217 struct usb_endpoint_descriptor const *ep_desc;
1218 char const *ep_type_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219
1220 if (endpoint == -1)
1221 return NULL; /* endpoint not needed */
1222
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001223 dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %d.\n", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
1225 if (urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001226 dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %d failed.\n", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 return NULL;
1228 }
1229
Lucy McCoy0ca12682007-05-18 12:10:41 -07001230 if (endpoint == 0) {
1231 /* control EP filled in when used */
1232 return urb;
1233 }
1234
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001235 ep_desc = find_ep(serial, endpoint);
1236 if (!ep_desc) {
1237 /* leak the urb, something's wrong and the callers don't care */
1238 return urb;
1239 }
1240 if (usb_endpoint_xfer_int(ep_desc)) {
1241 ep_type_name = "INT";
1242 usb_fill_int_urb(urb, serial->dev,
1243 usb_sndintpipe(serial->dev, endpoint) | dir,
1244 buf, len, callback, ctx,
1245 ep_desc->bInterval);
1246 } else if (usb_endpoint_xfer_bulk(ep_desc)) {
1247 ep_type_name = "BULK";
1248 usb_fill_bulk_urb(urb, serial->dev,
1249 usb_sndbulkpipe(serial->dev, endpoint) | dir,
1250 buf, len, callback, ctx);
1251 } else {
1252 dev_warn(&serial->interface->dev,
1253 "unsupported endpoint type %x\n",
Julia Lawall2e0fe702008-12-29 11:22:14 +01001254 usb_endpoint_type(ep_desc));
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001255 usb_free_urb(urb);
1256 return NULL;
1257 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001259 dev_dbg(&serial->interface->dev, "%s - using urb %p for %s endpoint %x\n",
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001260 __func__, urb, ep_type_name, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 return urb;
1262}
1263
1264static struct callbacks {
David Howells7d12e782006-10-05 14:55:46 +01001265 void (*instat_callback)(struct urb *);
1266 void (*glocont_callback)(struct urb *);
1267 void (*indat_callback)(struct urb *);
1268 void (*outdat_callback)(struct urb *);
1269 void (*inack_callback)(struct urb *);
1270 void (*outcont_callback)(struct urb *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271} keyspan_callbacks[] = {
1272 {
1273 /* msg_usa26 callbacks */
1274 .instat_callback = usa26_instat_callback,
1275 .glocont_callback = usa26_glocont_callback,
1276 .indat_callback = usa26_indat_callback,
1277 .outdat_callback = usa2x_outdat_callback,
1278 .inack_callback = usa26_inack_callback,
1279 .outcont_callback = usa26_outcont_callback,
1280 }, {
1281 /* msg_usa28 callbacks */
1282 .instat_callback = usa28_instat_callback,
1283 .glocont_callback = usa28_glocont_callback,
1284 .indat_callback = usa28_indat_callback,
1285 .outdat_callback = usa2x_outdat_callback,
1286 .inack_callback = usa28_inack_callback,
1287 .outcont_callback = usa28_outcont_callback,
1288 }, {
1289 /* msg_usa49 callbacks */
1290 .instat_callback = usa49_instat_callback,
1291 .glocont_callback = usa49_glocont_callback,
1292 .indat_callback = usa49_indat_callback,
1293 .outdat_callback = usa2x_outdat_callback,
1294 .inack_callback = usa49_inack_callback,
1295 .outcont_callback = usa49_outcont_callback,
1296 }, {
1297 /* msg_usa90 callbacks */
1298 .instat_callback = usa90_instat_callback,
Alan Coxdeb91682008-07-22 11:13:08 +01001299 .glocont_callback = usa28_glocont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 .indat_callback = usa90_indat_callback,
1301 .outdat_callback = usa2x_outdat_callback,
1302 .inack_callback = usa28_inack_callback,
1303 .outcont_callback = usa90_outcont_callback,
Lucy McCoy0ca12682007-05-18 12:10:41 -07001304 }, {
1305 /* msg_usa67 callbacks */
1306 .instat_callback = usa67_instat_callback,
1307 .glocont_callback = usa67_glocont_callback,
1308 .indat_callback = usa26_indat_callback,
1309 .outdat_callback = usa2x_outdat_callback,
1310 .inack_callback = usa26_inack_callback,
1311 .outcont_callback = usa26_outcont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 }
1313};
1314
1315 /* Generic setup urbs function that uses
1316 data in device_details */
1317static void keyspan_setup_urbs(struct usb_serial *serial)
1318{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 struct keyspan_serial_private *s_priv;
1320 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 struct callbacks *cback;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 s_priv = usb_get_serial_data(serial);
1324 d_details = s_priv->device_details;
1325
Alan Coxdeb91682008-07-22 11:13:08 +01001326 /* Setup values for the various callback routines */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 cback = &keyspan_callbacks[d_details->msg_format];
1328
Alan Coxdeb91682008-07-22 11:13:08 +01001329 /* Allocate and set up urbs for each one that is in use,
1330 starting with instat endpoints */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331 s_priv->instat_urb = keyspan_setup_urb
1332 (serial, d_details->instat_endpoint, USB_DIR_IN,
1333 serial, s_priv->instat_buf, INSTAT_BUFLEN,
1334 cback->instat_callback);
1335
Lucy McCoy0ca12682007-05-18 12:10:41 -07001336 s_priv->indat_urb = keyspan_setup_urb
1337 (serial, d_details->indat_endpoint, USB_DIR_IN,
1338 serial, s_priv->indat_buf, INDAT49W_BUFLEN,
1339 usa49wg_indat_callback);
1340
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 s_priv->glocont_urb = keyspan_setup_urb
1342 (serial, d_details->glocont_endpoint, USB_DIR_OUT,
1343 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
1344 cback->glocont_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345}
1346
1347/* usa19 function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001348static int keyspan_usa19_calc_baud(struct usb_serial_port *port,
1349 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 u8 *rate_low, u8 *prescaler, int portnum)
1351{
1352 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001353 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 cnt; /* inverse of divisor (programmed into 8051) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001356 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357
Alan Coxdeb91682008-07-22 11:13:08 +01001358 /* prevent divide by zero... */
1359 b16 = baud_rate * 16L;
1360 if (b16 == 0)
1361 return KEYSPAN_INVALID_BAUD_RATE;
1362 /* Any "standard" rate over 57k6 is marginal on the USA-19
1363 as we run out of divisor resolution. */
1364 if (baud_rate > 57600)
1365 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366
Alan Coxdeb91682008-07-22 11:13:08 +01001367 /* calculate the divisor and the counter (its inverse) */
1368 div = baudclk / b16;
1369 if (div == 0)
1370 return KEYSPAN_INVALID_BAUD_RATE;
1371 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373
Alan Coxdeb91682008-07-22 11:13:08 +01001374 if (div > 0xffff)
1375 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376
Alan Coxdeb91682008-07-22 11:13:08 +01001377 /* return the counter values if non-null */
1378 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001380 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001382 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001383 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001384 __func__, baud_rate, *rate_hi, *rate_low);
1385 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386}
1387
1388/* usa19hs function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001389static int keyspan_usa19hs_calc_baud(struct usb_serial_port *port,
1390 u32 baud_rate, u32 baudclk, u8 *rate_hi,
1391 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392{
1393 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001394 div; /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001396 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397
Alan Coxdeb91682008-07-22 11:13:08 +01001398 /* prevent divide by zero... */
1399 b16 = baud_rate * 16L;
1400 if (b16 == 0)
1401 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402
Alan Coxdeb91682008-07-22 11:13:08 +01001403 /* calculate the divisor */
1404 div = baudclk / b16;
1405 if (div == 0)
1406 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407
Alan Coxdeb91682008-07-22 11:13:08 +01001408 if (div > 0xffff)
1409 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410
Alan Coxdeb91682008-07-22 11:13:08 +01001411 /* return the counter values if non-null */
1412 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001414
1415 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 *rate_hi = (u8) ((div >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001417
1418 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001419 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001420 __func__, baud_rate, *rate_hi, *rate_low);
1421
1422 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423}
1424
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001425static int keyspan_usa19w_calc_baud(struct usb_serial_port *port,
1426 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 u8 *rate_low, u8 *prescaler, int portnum)
1428{
1429 u32 b16, /* baud rate times 16 (actual rate used internally) */
1430 clk, /* clock with 13/8 prescaler */
Alan Coxdeb91682008-07-22 11:13:08 +01001431 div, /* divisor using 13/8 prescaler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 res, /* resulting baud rate using 13/8 prescaler */
1433 diff, /* error using 13/8 prescaler */
1434 smallest_diff;
1435 u8 best_prescaler;
1436 int i;
1437
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001438 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439
Alan Coxdeb91682008-07-22 11:13:08 +01001440 /* prevent divide by zero */
1441 b16 = baud_rate * 16L;
1442 if (b16 == 0)
1443 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
Alan Coxdeb91682008-07-22 11:13:08 +01001445 /* Calculate prescaler by trying them all and looking
1446 for best fit */
1447
1448 /* start with largest possible difference */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 smallest_diff = 0xffffffff;
1450
1451 /* 0 is an invalid prescaler, used as a flag */
1452 best_prescaler = 0;
1453
Alan Coxdeb91682008-07-22 11:13:08 +01001454 for (i = 8; i <= 0xff; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 clk = (baudclk * 8) / (u32) i;
Alan Coxdeb91682008-07-22 11:13:08 +01001456
1457 div = clk / b16;
1458 if (div == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460
1461 res = clk / div;
Alan Coxdeb91682008-07-22 11:13:08 +01001462 diff = (res > b16) ? (res-b16) : (b16-res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463
Alan Coxdeb91682008-07-22 11:13:08 +01001464 if (diff < smallest_diff) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 best_prescaler = i;
1466 smallest_diff = diff;
1467 }
1468 }
1469
Alan Coxdeb91682008-07-22 11:13:08 +01001470 if (best_prescaler == 0)
1471 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472
1473 clk = (baudclk * 8) / (u32) best_prescaler;
1474 div = clk / b16;
1475
Alan Coxdeb91682008-07-22 11:13:08 +01001476 /* return the divisor and prescaler if non-null */
1477 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001479 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 *rate_hi = (u8) ((div >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 if (prescaler) {
1482 *prescaler = best_prescaler;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001483 /* dev_dbg(&port->dev, "%s - %d %d\n", __func__, *prescaler, div); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 }
Alan Coxdeb91682008-07-22 11:13:08 +01001485 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486}
1487
1488 /* USA-28 supports different maximum baud rates on each port */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001489static int keyspan_usa28_calc_baud(struct usb_serial_port *port,
1490 u32 baud_rate, u32 baudclk, u8 *rate_hi,
1491 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492{
1493 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001494 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 cnt; /* inverse of divisor (programmed into 8051) */
1496
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001497 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498
1499 /* prevent divide by zero */
Alan Coxdeb91682008-07-22 11:13:08 +01001500 b16 = baud_rate * 16L;
1501 if (b16 == 0)
1502 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503
Alan Coxdeb91682008-07-22 11:13:08 +01001504 /* calculate the divisor and the counter (its inverse) */
1505 div = KEYSPAN_USA28_BAUDCLK / b16;
1506 if (div == 0)
1507 return KEYSPAN_INVALID_BAUD_RATE;
1508 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510
Alan Coxdeb91682008-07-22 11:13:08 +01001511 /* check for out of range, based on portnum,
1512 and return result */
1513 if (portnum == 0) {
1514 if (div > 0xffff)
1515 return KEYSPAN_INVALID_BAUD_RATE;
1516 } else {
1517 if (portnum == 1) {
1518 if (div > 0xff)
1519 return KEYSPAN_INVALID_BAUD_RATE;
1520 } else
1521 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 }
1523
1524 /* return the counter values if not NULL
1525 (port 1 will ignore retHi) */
Alan Coxdeb91682008-07-22 11:13:08 +01001526 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001528 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001530 dev_dbg(&port->dev, "%s - %d OK.\n", __func__, baud_rate);
Alan Coxdeb91682008-07-22 11:13:08 +01001531 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532}
1533
1534static int keyspan_usa26_send_setup(struct usb_serial *serial,
1535 struct usb_serial_port *port,
1536 int reset_port)
1537{
Alan Coxdeb91682008-07-22 11:13:08 +01001538 struct keyspan_usa26_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 struct keyspan_serial_private *s_priv;
1540 struct keyspan_port_private *p_priv;
1541 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 struct urb *this_urb;
1543 int device_port, err;
1544
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001545 dev_dbg(&port->dev, "%s reset=%d\n", __func__, reset_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546
1547 s_priv = usb_get_serial_data(serial);
1548 p_priv = usb_get_serial_port_data(port);
1549 d_details = s_priv->device_details;
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001550 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 this_urb = p_priv->outcont_urb;
1553
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001554 dev_dbg(&port->dev, "%s - endpoint %d\n", __func__, usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555
1556 /* Make sure we have an urb then send the message */
1557 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001558 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 return -1;
1560 }
1561
1562 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001563 Don't overwrite resend for open/close condition. */
1564 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565 p_priv->resend_cont = reset_port + 1;
1566 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001567 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001569 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570 }
1571
Alan Coxdeb91682008-07-22 11:13:08 +01001572 memset(&msg, 0, sizeof(struct keyspan_usa26_portControlMessage));
1573
1574 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575 if (p_priv->old_baud != p_priv->baud) {
1576 p_priv->old_baud = p_priv->baud;
1577 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001578 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1579 &msg.baudHi, &msg.baudLo, &msg.prescaler,
1580 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1581 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
1582 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583 msg.baudLo = 0;
1584 msg.baudHi = 125; /* Values for 9600 baud */
1585 msg.prescaler = 10;
1586 }
1587 msg.setPrescaler = 0xff;
1588 }
1589
Ben Minerds2b982ab2012-07-12 00:10:16 +10001590 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 switch (p_priv->cflag & CSIZE) {
1592 case CS5:
1593 msg.lcr |= USA_DATABITS_5;
1594 break;
1595 case CS6:
1596 msg.lcr |= USA_DATABITS_6;
1597 break;
1598 case CS7:
1599 msg.lcr |= USA_DATABITS_7;
1600 break;
1601 case CS8:
1602 msg.lcr |= USA_DATABITS_8;
1603 break;
1604 }
1605 if (p_priv->cflag & PARENB) {
1606 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10001607 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01001608 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609 }
1610 msg.setLcr = 0xff;
1611
1612 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1613 msg.xonFlowControl = 0;
1614 msg.setFlowControl = 0xff;
1615 msg.forwardingLength = 16;
1616 msg.xonChar = 17;
1617 msg.xoffChar = 19;
1618
1619 /* Opening port */
1620 if (reset_port == 1) {
1621 msg._txOn = 1;
1622 msg._txOff = 0;
1623 msg.txFlush = 0;
1624 msg.txBreak = 0;
1625 msg.rxOn = 1;
1626 msg.rxOff = 0;
1627 msg.rxFlush = 1;
1628 msg.rxForward = 0;
1629 msg.returnStatus = 0;
1630 msg.resetDataToggle = 0xff;
1631 }
1632
1633 /* Closing port */
1634 else if (reset_port == 2) {
1635 msg._txOn = 0;
1636 msg._txOff = 1;
1637 msg.txFlush = 0;
1638 msg.txBreak = 0;
1639 msg.rxOn = 0;
1640 msg.rxOff = 1;
1641 msg.rxFlush = 1;
1642 msg.rxForward = 0;
1643 msg.returnStatus = 0;
1644 msg.resetDataToggle = 0;
1645 }
1646
1647 /* Sending intermediate configs */
1648 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001649 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650 msg._txOff = 0;
1651 msg.txFlush = 0;
1652 msg.txBreak = (p_priv->break_on);
1653 msg.rxOn = 0;
1654 msg.rxOff = 0;
1655 msg.rxFlush = 0;
1656 msg.rxForward = 0;
1657 msg.returnStatus = 0;
1658 msg.resetDataToggle = 0x0;
1659 }
1660
Alan Coxdeb91682008-07-22 11:13:08 +01001661 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 msg.setTxTriState_setRts = 0xff;
1663 msg.txTriState_rts = p_priv->rts_state;
1664
1665 msg.setHskoa_setDtr = 0xff;
1666 msg.hskoa_dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01001667
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001669 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
1670
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 /* send the data out the device on control endpoint */
1672 this_urb->transfer_buffer_length = sizeof(msg);
1673
Alan Coxdeb91682008-07-22 11:13:08 +01001674 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1675 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001676 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01001677 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678}
1679
1680static int keyspan_usa28_send_setup(struct usb_serial *serial,
1681 struct usb_serial_port *port,
1682 int reset_port)
1683{
Alan Coxdeb91682008-07-22 11:13:08 +01001684 struct keyspan_usa28_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 struct keyspan_serial_private *s_priv;
1686 struct keyspan_port_private *p_priv;
1687 const struct keyspan_device_details *d_details;
1688 struct urb *this_urb;
1689 int device_port, err;
1690
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 s_priv = usb_get_serial_data(serial);
1692 p_priv = usb_get_serial_port_data(port);
1693 d_details = s_priv->device_details;
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001694 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695
1696 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01001697 this_urb = p_priv->outcont_urb;
1698 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001699 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 return -1;
1701 }
1702
1703 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001704 Don't overwrite resend for open/close condition. */
1705 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 p_priv->resend_cont = reset_port + 1;
1707 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001708 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001710 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 }
1712
Alan Coxdeb91682008-07-22 11:13:08 +01001713 memset(&msg, 0, sizeof(struct keyspan_usa28_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714
1715 msg.setBaudRate = 1;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001716 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1717 &msg.baudHi, &msg.baudLo, NULL,
1718 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1719 dev_dbg(&port->dev, "%s - Invalid baud rate requested %d.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001720 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721 msg.baudLo = 0xff;
1722 msg.baudHi = 0xb2; /* Values for 9600 baud */
1723 }
1724
1725 /* If parity is enabled, we must calculate it ourselves. */
1726 msg.parity = 0; /* XXX for now */
1727
1728 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1729 msg.xonFlowControl = 0;
1730
Alan Coxdeb91682008-07-22 11:13:08 +01001731 /* Do handshaking outputs, DTR is inverted relative to RTS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 msg.rts = p_priv->rts_state;
1733 msg.dtr = p_priv->dtr_state;
1734
1735 msg.forwardingLength = 16;
1736 msg.forwardMs = 10;
1737 msg.breakThreshold = 45;
1738 msg.xonChar = 17;
1739 msg.xoffChar = 19;
1740
1741 /*msg.returnStatus = 1;
1742 msg.resetDataToggle = 0xff;*/
1743 /* Opening port */
1744 if (reset_port == 1) {
1745 msg._txOn = 1;
1746 msg._txOff = 0;
1747 msg.txFlush = 0;
1748 msg.txForceXoff = 0;
1749 msg.txBreak = 0;
1750 msg.rxOn = 1;
1751 msg.rxOff = 0;
1752 msg.rxFlush = 1;
1753 msg.rxForward = 0;
1754 msg.returnStatus = 0;
1755 msg.resetDataToggle = 0xff;
1756 }
1757 /* Closing port */
1758 else if (reset_port == 2) {
1759 msg._txOn = 0;
1760 msg._txOff = 1;
1761 msg.txFlush = 0;
1762 msg.txForceXoff = 0;
1763 msg.txBreak = 0;
1764 msg.rxOn = 0;
1765 msg.rxOff = 1;
1766 msg.rxFlush = 1;
1767 msg.rxForward = 0;
1768 msg.returnStatus = 0;
1769 msg.resetDataToggle = 0;
1770 }
1771 /* Sending intermediate configs */
1772 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001773 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774 msg._txOff = 0;
1775 msg.txFlush = 0;
1776 msg.txForceXoff = 0;
1777 msg.txBreak = (p_priv->break_on);
1778 msg.rxOn = 0;
1779 msg.rxOff = 0;
1780 msg.rxFlush = 0;
1781 msg.rxForward = 0;
1782 msg.returnStatus = 0;
1783 msg.resetDataToggle = 0x0;
1784 }
1785
1786 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001787 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788
1789 /* send the data out the device on control endpoint */
1790 this_urb->transfer_buffer_length = sizeof(msg);
1791
Alan Coxdeb91682008-07-22 11:13:08 +01001792 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1793 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001794 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795#if 0
1796 else {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001797 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) OK %d bytes\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798 this_urb->transfer_buffer_length);
1799 }
1800#endif
1801
Alan Coxa5b6f602008-04-08 17:16:06 +01001802 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803}
1804
1805static int keyspan_usa49_send_setup(struct usb_serial *serial,
1806 struct usb_serial_port *port,
1807 int reset_port)
1808{
Lucy McCoy0ca12682007-05-18 12:10:41 -07001809 struct keyspan_usa49_portControlMessage msg;
1810 struct usb_ctrlrequest *dr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811 struct keyspan_serial_private *s_priv;
1812 struct keyspan_port_private *p_priv;
1813 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814 struct urb *this_urb;
1815 int err, device_port;
1816
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817 s_priv = usb_get_serial_data(serial);
1818 p_priv = usb_get_serial_port_data(port);
1819 d_details = s_priv->device_details;
1820
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821 this_urb = s_priv->glocont_urb;
1822
Lucy McCoy0ca12682007-05-18 12:10:41 -07001823 /* Work out which port within the device is being setup */
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001824 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05301826 /* Make sure we have an urb then send the message */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827 if (this_urb == NULL) {
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001828 dev_dbg(&port->dev, "%s - oops no urb for port.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829 return -1;
1830 }
1831
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001832 dev_dbg(&port->dev, "%s - endpoint %d (%d)\n",
1833 __func__, usb_pipeendpoint(this_urb->pipe), device_port);
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05301834
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001836 Don't overwrite resend for open/close condition. */
1837 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 p_priv->resend_cont = reset_port + 1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001839
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001841 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001843 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844 }
1845
Alan Coxdeb91682008-07-22 11:13:08 +01001846 memset(&msg, 0, sizeof(struct keyspan_usa49_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 msg.portNumber = device_port;
Alan Coxdeb91682008-07-22 11:13:08 +01001849
1850 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851 if (p_priv->old_baud != p_priv->baud) {
1852 p_priv->old_baud = p_priv->baud;
1853 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001854 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1855 &msg.baudHi, &msg.baudLo, &msg.prescaler,
1856 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1857 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
1858 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 msg.baudLo = 0;
1860 msg.baudHi = 125; /* Values for 9600 baud */
1861 msg.prescaler = 10;
1862 }
Alan Coxdeb91682008-07-22 11:13:08 +01001863 /* msg.setPrescaler = 0xff; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 }
1865
Ben Minerds2b982ab2012-07-12 00:10:16 +10001866 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867 switch (p_priv->cflag & CSIZE) {
1868 case CS5:
1869 msg.lcr |= USA_DATABITS_5;
1870 break;
1871 case CS6:
1872 msg.lcr |= USA_DATABITS_6;
1873 break;
1874 case CS7:
1875 msg.lcr |= USA_DATABITS_7;
1876 break;
1877 case CS8:
1878 msg.lcr |= USA_DATABITS_8;
1879 break;
1880 }
1881 if (p_priv->cflag & PARENB) {
1882 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10001883 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01001884 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 }
1886 msg.setLcr = 0xff;
1887
1888 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1889 msg.xonFlowControl = 0;
1890 msg.setFlowControl = 0xff;
Alan Coxdeb91682008-07-22 11:13:08 +01001891
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 msg.forwardingLength = 16;
1893 msg.xonChar = 17;
1894 msg.xoffChar = 19;
1895
Alan Coxdeb91682008-07-22 11:13:08 +01001896 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897 if (reset_port == 1) {
1898 msg._txOn = 1;
1899 msg._txOff = 0;
1900 msg.txFlush = 0;
1901 msg.txBreak = 0;
1902 msg.rxOn = 1;
1903 msg.rxOff = 0;
1904 msg.rxFlush = 1;
1905 msg.rxForward = 0;
1906 msg.returnStatus = 0;
1907 msg.resetDataToggle = 0xff;
1908 msg.enablePort = 1;
1909 msg.disablePort = 0;
1910 }
1911 /* Closing port */
1912 else if (reset_port == 2) {
1913 msg._txOn = 0;
1914 msg._txOff = 1;
1915 msg.txFlush = 0;
1916 msg.txBreak = 0;
1917 msg.rxOn = 0;
1918 msg.rxOff = 1;
1919 msg.rxFlush = 1;
1920 msg.rxForward = 0;
1921 msg.returnStatus = 0;
1922 msg.resetDataToggle = 0;
1923 msg.enablePort = 0;
1924 msg.disablePort = 1;
1925 }
1926 /* Sending intermediate configs */
1927 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001928 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929 msg._txOff = 0;
1930 msg.txFlush = 0;
1931 msg.txBreak = (p_priv->break_on);
1932 msg.rxOn = 0;
1933 msg.rxOff = 0;
1934 msg.rxFlush = 0;
1935 msg.rxForward = 0;
1936 msg.returnStatus = 0;
1937 msg.resetDataToggle = 0x0;
1938 msg.enablePort = 0;
1939 msg.disablePort = 0;
1940 }
1941
Alan Coxdeb91682008-07-22 11:13:08 +01001942 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943 msg.setRts = 0xff;
1944 msg.rts = p_priv->rts_state;
1945
1946 msg.setDtr = 0xff;
1947 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01001948
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949 p_priv->resend_cont = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950
Alan Coxdeb91682008-07-22 11:13:08 +01001951 /* if the device is a 49wg, we send control message on usb
1952 control EP 0 */
Lucy McCoy0ca12682007-05-18 12:10:41 -07001953
1954 if (d_details->product_id == keyspan_usa49wg_product_id) {
1955 dr = (void *)(s_priv->ctrl_buf);
1956 dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT;
1957 dr->bRequest = 0xB0; /* 49wg control message */;
1958 dr->wValue = 0;
1959 dr->wIndex = 0;
1960 dr->wLength = cpu_to_le16(sizeof(msg));
1961
Alan Coxdeb91682008-07-22 11:13:08 +01001962 memcpy(s_priv->glocont_buf, &msg, sizeof(msg));
Lucy McCoy0ca12682007-05-18 12:10:41 -07001963
Alan Coxdeb91682008-07-22 11:13:08 +01001964 usb_fill_control_urb(this_urb, serial->dev,
1965 usb_sndctrlpipe(serial->dev, 0),
1966 (unsigned char *)dr, s_priv->glocont_buf,
1967 sizeof(msg), usa49_glocont_callback, serial);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001968
1969 } else {
1970 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Alan Coxdeb91682008-07-22 11:13:08 +01001971
Lucy McCoy0ca12682007-05-18 12:10:41 -07001972 /* send the data out the device on control endpoint */
1973 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001974 }
Alan Coxdeb91682008-07-22 11:13:08 +01001975 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1976 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001977 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978#if 0
1979 else {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001980 dev_dbg(&port->dev, "%s - usb_submit_urb(%d) OK %d bytes (end %d)\n", __func__,
1981 outcont_urb, this_urb->transfer_buffer_length,
1982 usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983 }
1984#endif
1985
Alan Coxa5b6f602008-04-08 17:16:06 +01001986 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987}
1988
1989static int keyspan_usa90_send_setup(struct usb_serial *serial,
1990 struct usb_serial_port *port,
1991 int reset_port)
1992{
Alan Coxdeb91682008-07-22 11:13:08 +01001993 struct keyspan_usa90_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994 struct keyspan_serial_private *s_priv;
1995 struct keyspan_port_private *p_priv;
1996 const struct keyspan_device_details *d_details;
1997 struct urb *this_urb;
1998 int err;
1999 u8 prescaler;
2000
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 s_priv = usb_get_serial_data(serial);
2002 p_priv = usb_get_serial_port_data(port);
2003 d_details = s_priv->device_details;
2004
2005 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01002006 this_urb = p_priv->outcont_urb;
2007 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002008 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 return -1;
2010 }
2011
2012 /* Save reset port val for resend.
2013 Don't overwrite resend for open/close condition. */
2014 if ((reset_port + 1) > p_priv->resend_cont)
2015 p_priv->resend_cont = reset_port + 1;
2016 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002017 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002019 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 }
2021
Alan Coxdeb91682008-07-22 11:13:08 +01002022 memset(&msg, 0, sizeof(struct keyspan_usa90_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023
Alan Coxdeb91682008-07-22 11:13:08 +01002024 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025 if (p_priv->old_baud != p_priv->baud) {
2026 p_priv->old_baud = p_priv->baud;
2027 msg.setClocking = 0x01;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002028 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2029 &msg.baudHi, &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) {
2030 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2031 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032 p_priv->baud = 9600;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002033 d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034 &msg.baudHi, &msg.baudLo, &prescaler, 0);
2035 }
2036 msg.setRxMode = 1;
2037 msg.setTxMode = 1;
2038 }
2039
2040 /* modes must always be correctly specified */
Alan Coxdeb91682008-07-22 11:13:08 +01002041 if (p_priv->baud > 57600) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042 msg.rxMode = RXMODE_DMA;
2043 msg.txMode = TXMODE_DMA;
Alan Coxdeb91682008-07-22 11:13:08 +01002044 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045 msg.rxMode = RXMODE_BYHAND;
2046 msg.txMode = TXMODE_BYHAND;
2047 }
2048
Ben Minerds2b982ab2012-07-12 00:10:16 +10002049 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050 switch (p_priv->cflag & CSIZE) {
2051 case CS5:
2052 msg.lcr |= USA_DATABITS_5;
2053 break;
2054 case CS6:
2055 msg.lcr |= USA_DATABITS_6;
2056 break;
2057 case CS7:
2058 msg.lcr |= USA_DATABITS_7;
2059 break;
2060 case CS8:
2061 msg.lcr |= USA_DATABITS_8;
2062 break;
2063 }
2064 if (p_priv->cflag & PARENB) {
2065 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002066 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002067 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068 }
2069 if (p_priv->old_cflag != p_priv->cflag) {
2070 p_priv->old_cflag = p_priv->cflag;
2071 msg.setLcr = 0x01;
2072 }
2073
2074 if (p_priv->flow_control == flow_cts)
2075 msg.txFlowControl = TXFLOW_CTS;
2076 msg.setTxFlowControl = 0x01;
2077 msg.setRxFlowControl = 0x01;
Alan Coxdeb91682008-07-22 11:13:08 +01002078
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079 msg.rxForwardingLength = 16;
Alan Coxdeb91682008-07-22 11:13:08 +01002080 msg.rxForwardingTimeout = 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081 msg.txAckSetting = 0;
2082 msg.xonChar = 17;
2083 msg.xoffChar = 19;
2084
Alan Coxdeb91682008-07-22 11:13:08 +01002085 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086 if (reset_port == 1) {
2087 msg.portEnabled = 1;
2088 msg.rxFlush = 1;
2089 msg.txBreak = (p_priv->break_on);
2090 }
2091 /* Closing port */
Alan Coxdeb91682008-07-22 11:13:08 +01002092 else if (reset_port == 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093 msg.portEnabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094 /* Sending intermediate configs */
2095 else {
Alan Stern1f871582010-02-17 10:05:47 -05002096 msg.portEnabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097 msg.txBreak = (p_priv->break_on);
2098 }
2099
Alan Coxdeb91682008-07-22 11:13:08 +01002100 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101 msg.setRts = 0x01;
2102 msg.rts = p_priv->rts_state;
2103
2104 msg.setDtr = 0x01;
2105 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002106
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01002108 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2109
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110 /* send the data out the device on control endpoint */
2111 this_urb->transfer_buffer_length = sizeof(msg);
2112
Alan Coxdeb91682008-07-22 11:13:08 +01002113 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2114 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002115 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002116 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117}
2118
Lucy McCoy0ca12682007-05-18 12:10:41 -07002119static int keyspan_usa67_send_setup(struct usb_serial *serial,
2120 struct usb_serial_port *port,
2121 int reset_port)
2122{
2123 struct keyspan_usa67_portControlMessage msg;
2124 struct keyspan_serial_private *s_priv;
2125 struct keyspan_port_private *p_priv;
2126 const struct keyspan_device_details *d_details;
2127 struct urb *this_urb;
2128 int err, device_port;
2129
Lucy McCoy0ca12682007-05-18 12:10:41 -07002130 s_priv = usb_get_serial_data(serial);
2131 p_priv = usb_get_serial_port_data(port);
2132 d_details = s_priv->device_details;
2133
2134 this_urb = s_priv->glocont_urb;
2135
2136 /* Work out which port within the device is being setup */
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002137 device_port = port->port_number;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002138
2139 /* Make sure we have an urb then send the message */
2140 if (this_urb == NULL) {
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002141 dev_dbg(&port->dev, "%s - oops no urb for port.\n", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002142 return -1;
2143 }
2144
2145 /* Save reset port val for resend.
2146 Don't overwrite resend for open/close condition. */
2147 if ((reset_port + 1) > p_priv->resend_cont)
2148 p_priv->resend_cont = reset_port + 1;
2149 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002150 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002151 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002152 return -1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002153 }
2154
2155 memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
2156
2157 msg.port = device_port;
2158
2159 /* Only set baud rate if it's changed */
2160 if (p_priv->old_baud != p_priv->baud) {
2161 p_priv->old_baud = p_priv->baud;
2162 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002163 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2164 &msg.baudHi, &msg.baudLo, &msg.prescaler,
2165 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2166 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2167 __func__, p_priv->baud);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002168 msg.baudLo = 0;
2169 msg.baudHi = 125; /* Values for 9600 baud */
2170 msg.prescaler = 10;
2171 }
2172 msg.setPrescaler = 0xff;
2173 }
2174
2175 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
2176 switch (p_priv->cflag & CSIZE) {
2177 case CS5:
2178 msg.lcr |= USA_DATABITS_5;
2179 break;
2180 case CS6:
2181 msg.lcr |= USA_DATABITS_6;
2182 break;
2183 case CS7:
2184 msg.lcr |= USA_DATABITS_7;
2185 break;
2186 case CS8:
2187 msg.lcr |= USA_DATABITS_8;
2188 break;
2189 }
2190 if (p_priv->cflag & PARENB) {
2191 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002192 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002193 USA_PARITY_ODD : USA_PARITY_EVEN;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002194 }
2195 msg.setLcr = 0xff;
2196
2197 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2198 msg.xonFlowControl = 0;
2199 msg.setFlowControl = 0xff;
2200 msg.forwardingLength = 16;
2201 msg.xonChar = 17;
2202 msg.xoffChar = 19;
2203
2204 if (reset_port == 1) {
2205 /* Opening port */
2206 msg._txOn = 1;
2207 msg._txOff = 0;
2208 msg.txFlush = 0;
2209 msg.txBreak = 0;
2210 msg.rxOn = 1;
2211 msg.rxOff = 0;
2212 msg.rxFlush = 1;
2213 msg.rxForward = 0;
2214 msg.returnStatus = 0;
2215 msg.resetDataToggle = 0xff;
2216 } else if (reset_port == 2) {
2217 /* Closing port */
2218 msg._txOn = 0;
2219 msg._txOff = 1;
2220 msg.txFlush = 0;
2221 msg.txBreak = 0;
2222 msg.rxOn = 0;
2223 msg.rxOff = 1;
2224 msg.rxFlush = 1;
2225 msg.rxForward = 0;
2226 msg.returnStatus = 0;
2227 msg.resetDataToggle = 0;
2228 } else {
2229 /* Sending intermediate configs */
Alan Coxdeb91682008-07-22 11:13:08 +01002230 msg._txOn = (!p_priv->break_on);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002231 msg._txOff = 0;
2232 msg.txFlush = 0;
2233 msg.txBreak = (p_priv->break_on);
2234 msg.rxOn = 0;
2235 msg.rxOff = 0;
2236 msg.rxFlush = 0;
2237 msg.rxForward = 0;
2238 msg.returnStatus = 0;
2239 msg.resetDataToggle = 0x0;
2240 }
2241
2242 /* Do handshaking outputs */
2243 msg.setTxTriState_setRts = 0xff;
2244 msg.txTriState_rts = p_priv->rts_state;
2245
2246 msg.setHskoa_setDtr = 0xff;
2247 msg.hskoa_dtr = p_priv->dtr_state;
2248
2249 p_priv->resend_cont = 0;
2250
2251 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2252
2253 /* send the data out the device on control endpoint */
2254 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002255
2256 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2257 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002258 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002259 return 0;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002260}
2261
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
2263{
2264 struct usb_serial *serial = port->serial;
2265 struct keyspan_serial_private *s_priv;
2266 const struct keyspan_device_details *d_details;
2267
Linus Torvalds1da177e2005-04-16 15:20:36 -07002268 s_priv = usb_get_serial_data(serial);
2269 d_details = s_priv->device_details;
2270
2271 switch (d_details->msg_format) {
2272 case msg_usa26:
2273 keyspan_usa26_send_setup(serial, port, reset_port);
2274 break;
2275 case msg_usa28:
2276 keyspan_usa28_send_setup(serial, port, reset_port);
2277 break;
2278 case msg_usa49:
2279 keyspan_usa49_send_setup(serial, port, reset_port);
2280 break;
2281 case msg_usa90:
2282 keyspan_usa90_send_setup(serial, port, reset_port);
2283 break;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002284 case msg_usa67:
2285 keyspan_usa67_send_setup(serial, port, reset_port);
2286 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 }
2288}
2289
2290
2291/* Gets called by the "real" driver (ie once firmware is loaded
2292 and renumeration has taken place. */
Alan Coxdeb91682008-07-22 11:13:08 +01002293static int keyspan_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294{
2295 int i, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297 const struct keyspan_device_details *d_details;
2298
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299 for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
Alan Coxdeb91682008-07-22 11:13:08 +01002300 if (d_details->product_id ==
2301 le16_to_cpu(serial->dev->descriptor.idProduct))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 break;
2303 if (d_details == NULL) {
Alan Coxdeb91682008-07-22 11:13:08 +01002304 dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
2305 __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 return 1;
2307 }
2308
2309 /* Setup private data for serial driver */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01002310 s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311 if (!s_priv) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002312 dev_dbg(&serial->dev->dev, "%s - kmalloc for keyspan_serial_private failed.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313 return -ENOMEM;
2314 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315
Johan Hovold2fcd1c92013-08-13 13:27:36 +02002316 s_priv->instat_buf = kzalloc(INSTAT_BUFLEN, GFP_KERNEL);
2317 if (!s_priv->instat_buf)
2318 goto err_instat_buf;
2319
2320 s_priv->indat_buf = kzalloc(INDAT49W_BUFLEN, GFP_KERNEL);
2321 if (!s_priv->indat_buf)
2322 goto err_indat_buf;
2323
2324 s_priv->glocont_buf = kzalloc(GLOCONT_BUFLEN, GFP_KERNEL);
2325 if (!s_priv->glocont_buf)
2326 goto err_glocont_buf;
2327
2328 s_priv->ctrl_buf = kzalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
2329 if (!s_priv->ctrl_buf)
2330 goto err_ctrl_buf;
2331
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 s_priv->device_details = d_details;
2333 usb_set_serial_data(serial, s_priv);
2334
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 keyspan_setup_urbs(serial);
2336
Lucy McCoy0ca12682007-05-18 12:10:41 -07002337 if (s_priv->instat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002338 err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
2339 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002340 dev_dbg(&serial->dev->dev, "%s - submit instat urb failed %d\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002341 }
2342 if (s_priv->indat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002343 err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
2344 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002345 dev_dbg(&serial->dev->dev, "%s - submit indat urb failed %d\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346 }
Alan Coxdeb91682008-07-22 11:13:08 +01002347
Alan Coxa5b6f602008-04-08 17:16:06 +01002348 return 0;
Johan Hovold2fcd1c92013-08-13 13:27:36 +02002349
2350err_ctrl_buf:
2351 kfree(s_priv->glocont_buf);
2352err_glocont_buf:
2353 kfree(s_priv->indat_buf);
2354err_indat_buf:
2355 kfree(s_priv->instat_buf);
2356err_instat_buf:
2357 kfree(s_priv);
2358
2359 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360}
2361
Alan Sternf9c99bb2009-06-02 11:53:55 -04002362static void keyspan_disconnect(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002364 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366 s_priv = usb_get_serial_data(serial);
2367
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368 stop_urb(s_priv->instat_urb);
2369 stop_urb(s_priv->glocont_urb);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002370 stop_urb(s_priv->indat_urb);
Alan Sternf9c99bb2009-06-02 11:53:55 -04002371}
2372
2373static void keyspan_release(struct usb_serial *serial)
2374{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002375 struct keyspan_serial_private *s_priv;
Alan Sternf9c99bb2009-06-02 11:53:55 -04002376
Alan Sternf9c99bb2009-06-02 11:53:55 -04002377 s_priv = usb_get_serial_data(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002379 usb_free_urb(s_priv->instat_urb);
2380 usb_free_urb(s_priv->indat_urb);
2381 usb_free_urb(s_priv->glocont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002382
Johan Hovold2fcd1c92013-08-13 13:27:36 +02002383 kfree(s_priv->ctrl_buf);
2384 kfree(s_priv->glocont_buf);
2385 kfree(s_priv->indat_buf);
2386 kfree(s_priv->instat_buf);
2387
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002388 kfree(s_priv);
2389}
2390
2391static int keyspan_port_probe(struct usb_serial_port *port)
2392{
2393 struct usb_serial *serial = port->serial;
Bjørn Morkf0e3e352012-11-10 10:13:42 +01002394 struct keyspan_serial_private *s_priv;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002395 struct keyspan_port_private *p_priv;
2396 const struct keyspan_device_details *d_details;
2397 struct callbacks *cback;
2398 int endp;
2399 int port_num;
2400 int i;
2401
2402 s_priv = usb_get_serial_data(serial);
2403 d_details = s_priv->device_details;
2404
2405 p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL);
2406 if (!p_priv)
2407 return -ENOMEM;
2408
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002409 p_priv->device_details = d_details;
2410
2411 /* Setup values for the various callback routines */
2412 cback = &keyspan_callbacks[d_details->msg_format];
2413
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002414 port_num = port->port_number;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002415
2416 /* Do indat endpoints first, once for each flip */
2417 endp = d_details->indat_endpoints[port_num];
2418 for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) {
2419 p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp,
2420 USB_DIR_IN, port,
2421 p_priv->in_buffer[i], 64,
2422 cback->indat_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423 }
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002424 /* outdat endpoints also have flip */
2425 endp = d_details->outdat_endpoints[port_num];
2426 for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) {
2427 p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp,
2428 USB_DIR_OUT, port,
2429 p_priv->out_buffer[i], 64,
2430 cback->outdat_callback);
2431 }
2432 /* inack endpoint */
2433 p_priv->inack_urb = keyspan_setup_urb(serial,
2434 d_details->inack_endpoints[port_num],
2435 USB_DIR_IN, port,
2436 p_priv->inack_buffer, 1,
2437 cback->inack_callback);
2438 /* outcont endpoint */
2439 p_priv->outcont_urb = keyspan_setup_urb(serial,
2440 d_details->outcont_endpoints[port_num],
2441 USB_DIR_OUT, port,
2442 p_priv->outcont_buffer, 64,
2443 cback->outcont_callback);
2444
2445 usb_set_serial_port_data(port, p_priv);
2446
2447 return 0;
2448}
2449
2450static int keyspan_port_remove(struct usb_serial_port *port)
2451{
2452 struct keyspan_port_private *p_priv;
2453 int i;
2454
2455 p_priv = usb_get_serial_port_data(port);
2456
2457 stop_urb(p_priv->inack_urb);
2458 stop_urb(p_priv->outcont_urb);
2459 for (i = 0; i < 2; i++) {
2460 stop_urb(p_priv->in_urbs[i]);
2461 stop_urb(p_priv->out_urbs[i]);
2462 }
2463
2464 usb_free_urb(p_priv->inack_urb);
2465 usb_free_urb(p_priv->outcont_urb);
2466 for (i = 0; i < 2; i++) {
2467 usb_free_urb(p_priv->in_urbs[i]);
2468 usb_free_urb(p_priv->out_urbs[i]);
2469 }
2470
2471 kfree(p_priv);
2472
2473 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474}
2475
Alan Coxdeb91682008-07-22 11:13:08 +01002476MODULE_AUTHOR(DRIVER_AUTHOR);
2477MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478MODULE_LICENSE("GPL");
2479
David Woodhouse2971c572008-05-30 14:04:03 +03002480MODULE_FIRMWARE("keyspan/usa28.fw");
2481MODULE_FIRMWARE("keyspan/usa28x.fw");
2482MODULE_FIRMWARE("keyspan/usa28xa.fw");
2483MODULE_FIRMWARE("keyspan/usa28xb.fw");
2484MODULE_FIRMWARE("keyspan/usa19.fw");
2485MODULE_FIRMWARE("keyspan/usa19qi.fw");
2486MODULE_FIRMWARE("keyspan/mpr.fw");
2487MODULE_FIRMWARE("keyspan/usa19qw.fw");
2488MODULE_FIRMWARE("keyspan/usa18x.fw");
2489MODULE_FIRMWARE("keyspan/usa19w.fw");
2490MODULE_FIRMWARE("keyspan/usa49w.fw");
2491MODULE_FIRMWARE("keyspan/usa49wlc.fw");