blob: cec377b8bb8be3a33e812f918c3ec0fab22efd53 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 Keyspan USB to Serial Converter driver
Alan Coxdeb91682008-07-22 11:13:08 +01003
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 (C) Copyright (C) 2000-2001 Hugh Blemings <hugh@blemings.org>
5 (C) Copyright (C) 2002 Greg Kroah-Hartman <greg@kroah.com>
Alan Coxdeb91682008-07-22 11:13:08 +01006
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
Justin P. Mattock631dd1a2010-10-18 11:03:14 +020012 See http://blemings.org/hugh/keyspan.html for more information.
Alan Coxdeb91682008-07-22 11:13:08 +010013
Linus Torvalds1da177e2005-04-16 15:20:36 -070014 Code in this driver inspired by and in a number of places taken
15 from Brian Warner's original Keyspan-PDA driver.
16
17 This driver has been put together with the support of Innosys, Inc.
18 and Keyspan, Inc the manufacturers of the Keyspan USB-serial products.
19 Thanks Guys :)
Alan Coxdeb91682008-07-22 11:13:08 +010020
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 Thanks to Paulus for miscellaneous tidy ups, some largish chunks
22 of much nicer and/or completely new code and (perhaps most uniquely)
23 having the patience to sit down and explain why and where he'd changed
Alan Coxdeb91682008-07-22 11:13:08 +010024 stuff.
25
26 Tip 'o the hat to IBM (and previously Linuxcare :) for supporting
Linus Torvalds1da177e2005-04-16 15:20:36 -070027 staff in their work on open source projects.
Linus Torvalds1da177e2005-04-16 15:20:36 -070028*/
29
30
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/kernel.h>
32#include <linux/jiffies.h>
33#include <linux/errno.h>
34#include <linux/init.h>
35#include <linux/slab.h>
36#include <linux/tty.h>
37#include <linux/tty_driver.h>
38#include <linux/tty_flip.h>
39#include <linux/module.h>
40#include <linux/spinlock.h>
Alan Coxdeb91682008-07-22 11:13:08 +010041#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <linux/usb.h>
Greg Kroah-Hartmana9698882006-07-11 21:22:58 -070043#include <linux/usb/serial.h>
Rene Buergelcc183e22012-09-18 09:00:41 +020044#include <linux/usb/ezusb.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include "keyspan.h"
46
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu"
48#define DRIVER_DESC "Keyspan USB to Serial Converter Driver"
49
50#define INSTAT_BUFLEN 32
51#define GLOCONT_BUFLEN 64
Lucy McCoy0ca12682007-05-18 12:10:41 -070052#define INDAT49W_BUFLEN 512
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
54 /* Per device and per port private data */
55struct keyspan_serial_private {
56 const struct keyspan_device_details *device_details;
57
58 struct urb *instat_urb;
59 char instat_buf[INSTAT_BUFLEN];
60
Alan Coxdeb91682008-07-22 11:13:08 +010061 /* added to support 49wg, where data from all 4 ports comes in
62 on 1 EP and high-speed supported */
Lucy McCoy0ca12682007-05-18 12:10:41 -070063 struct urb *indat_urb;
64 char indat_buf[INDAT49W_BUFLEN];
65
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 /* XXX this one probably will need a lock */
67 struct urb *glocont_urb;
68 char glocont_buf[GLOCONT_BUFLEN];
Alan Coxdeb91682008-07-22 11:13:08 +010069 char ctrl_buf[8]; /* for EP0 control message */
Linus Torvalds1da177e2005-04-16 15:20:36 -070070};
71
72struct keyspan_port_private {
73 /* Keep track of which input & output endpoints to use */
74 int in_flip;
75 int out_flip;
76
77 /* Keep duplicate of device details in each port
78 structure as well - simplifies some of the
79 callback functions etc. */
80 const struct keyspan_device_details *device_details;
81
82 /* Input endpoints and buffer for this port */
83 struct urb *in_urbs[2];
84 char in_buffer[2][64];
85 /* Output endpoints and buffer for this port */
86 struct urb *out_urbs[2];
87 char out_buffer[2][64];
88
89 /* Input ack endpoint */
90 struct urb *inack_urb;
91 char inack_buffer[1];
92
93 /* Output control endpoint */
94 struct urb *outcont_urb;
95 char outcont_buffer[64];
96
97 /* Settings for the port */
98 int baud;
99 int old_baud;
100 unsigned int cflag;
101 unsigned int old_cflag;
102 enum {flow_none, flow_cts, flow_xon} flow_control;
103 int rts_state; /* Handshaking pins (outputs) */
104 int dtr_state;
105 int cts_state; /* Handshaking pins (inputs) */
106 int dsr_state;
107 int dcd_state;
108 int ri_state;
109 int break_on;
110
111 unsigned long tx_start_time[2];
112 int resend_cont; /* need to resend control packet */
113};
114
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115/* Include Keyspan message headers. All current Keyspan Adapters
Lucy McCoy0ca12682007-05-18 12:10:41 -0700116 make use of one of five message formats which are referred
Alan Coxdeb91682008-07-22 11:13:08 +0100117 to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and
118 within this driver. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119#include "keyspan_usa26msg.h"
120#include "keyspan_usa28msg.h"
121#include "keyspan_usa49msg.h"
122#include "keyspan_usa90msg.h"
Lucy McCoy0ca12682007-05-18 12:10:41 -0700123#include "keyspan_usa67msg.h"
Alan Coxdeb91682008-07-22 11:13:08 +0100124
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -0700126module_usb_serial_driver(serial_drivers, keyspan_ids_combined);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127
Alan Cox95da3102008-07-22 11:09:07 +0100128static void keyspan_break_ctl(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129{
Alan Cox95da3102008-07-22 11:09:07 +0100130 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 struct keyspan_port_private *p_priv;
132
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133 p_priv = usb_get_serial_port_data(port);
134
135 if (break_state == -1)
136 p_priv->break_on = 1;
137 else
138 p_priv->break_on = 0;
139
140 keyspan_send_setup(port, 0);
141}
142
143
Alan Coxdeb91682008-07-22 11:13:08 +0100144static void keyspan_set_termios(struct tty_struct *tty,
Alan Cox95da3102008-07-22 11:09:07 +0100145 struct usb_serial_port *port, struct ktermios *old_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146{
147 int baud_rate, device_port;
148 struct keyspan_port_private *p_priv;
149 const struct keyspan_device_details *d_details;
150 unsigned int cflag;
151
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 p_priv = usb_get_serial_port_data(port);
153 d_details = p_priv->device_details;
Alan Coxadc8d742012-07-14 15:31:47 +0100154 cflag = tty->termios.c_cflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 device_port = port->number - port->serial->minor;
156
157 /* Baud rate calculation takes baud rate as an integer
158 so other rates can be generated if desired. */
Alan Cox74240b02007-10-18 01:24:20 -0700159 baud_rate = tty_get_baud_rate(tty);
Alan Coxdeb91682008-07-22 11:13:08 +0100160 /* If no match or invalid, don't change */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700161 if (d_details->calculate_baud_rate(port, baud_rate, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
163 /* FIXME - more to do here to ensure rate changes cleanly */
Alan Cox74240b02007-10-18 01:24:20 -0700164 /* FIXME - calcuate exact rate from divisor ? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 p_priv->baud = baud_rate;
Alan Cox74240b02007-10-18 01:24:20 -0700166 } else
167 baud_rate = tty_termios_baud_rate(old_termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168
Alan Cox74240b02007-10-18 01:24:20 -0700169 tty_encode_baud_rate(tty, baud_rate, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 /* set CTS/RTS handshake etc. */
171 p_priv->cflag = cflag;
Ben Minerds2b982ab2012-07-12 00:10:16 +1000172 p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173
Alan Cox74240b02007-10-18 01:24:20 -0700174 /* Mark/Space not supported */
Alan Coxadc8d742012-07-14 15:31:47 +0100175 tty->termios.c_cflag &= ~CMSPAR;
Alan Cox74240b02007-10-18 01:24:20 -0700176
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 keyspan_send_setup(port, 0);
178}
179
Alan Cox60b33c12011-02-14 16:26:14 +0000180static int keyspan_tiocmget(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181{
Alan Cox95da3102008-07-22 11:09:07 +0100182 struct usb_serial_port *port = tty->driver_data;
183 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 unsigned int value;
Alan Coxdeb91682008-07-22 11:13:08 +0100185
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 value = ((p_priv->rts_state) ? TIOCM_RTS : 0) |
187 ((p_priv->dtr_state) ? TIOCM_DTR : 0) |
188 ((p_priv->cts_state) ? TIOCM_CTS : 0) |
189 ((p_priv->dsr_state) ? TIOCM_DSR : 0) |
190 ((p_priv->dcd_state) ? TIOCM_CAR : 0) |
Alan Coxdeb91682008-07-22 11:13:08 +0100191 ((p_priv->ri_state) ? TIOCM_RNG : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192
193 return value;
194}
195
Alan Cox20b9d172011-02-14 16:26:50 +0000196static int keyspan_tiocmset(struct tty_struct *tty,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 unsigned int set, unsigned int clear)
198{
Alan Cox95da3102008-07-22 11:09:07 +0100199 struct usb_serial_port *port = tty->driver_data;
200 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100201
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 if (set & TIOCM_RTS)
203 p_priv->rts_state = 1;
204 if (set & TIOCM_DTR)
205 p_priv->dtr_state = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 if (clear & TIOCM_RTS)
207 p_priv->rts_state = 0;
208 if (clear & TIOCM_DTR)
209 p_priv->dtr_state = 0;
210 keyspan_send_setup(port, 0);
211 return 0;
212}
213
Alan Cox95da3102008-07-22 11:09:07 +0100214/* Write function is similar for the four protocols used
215 with only a minor change for usa90 (usa19hs) required */
216static int keyspan_write(struct tty_struct *tty,
217 struct usb_serial_port *port, const unsigned char *buf, int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218{
219 struct keyspan_port_private *p_priv;
220 const struct keyspan_device_details *d_details;
221 int flip;
222 int left, todo;
223 struct urb *this_urb;
Alan Coxdeb91682008-07-22 11:13:08 +0100224 int err, maxDataLen, dataOffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225
226 p_priv = usb_get_serial_port_data(port);
227 d_details = p_priv->device_details;
228
229 if (d_details->msg_format == msg_usa90) {
Alan Coxdeb91682008-07-22 11:13:08 +0100230 maxDataLen = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 dataOffset = 0;
232 } else {
233 maxDataLen = 63;
234 dataOffset = 1;
235 }
Alan Coxdeb91682008-07-22 11:13:08 +0100236
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700237 dev_dbg(&port->dev, "%s - for port %d (%d chars), flip=%d\n",
238 __func__, port->number, count, p_priv->out_flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239
240 for (left = count; left > 0; left -= todo) {
241 todo = left;
242 if (todo > maxDataLen)
243 todo = maxDataLen;
244
245 flip = p_priv->out_flip;
Alan Coxdeb91682008-07-22 11:13:08 +0100246
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 /* Check we have a valid urb/endpoint before we use it... */
Alan Coxdeb91682008-07-22 11:13:08 +0100248 this_urb = p_priv->out_urbs[flip];
249 if (this_urb == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 /* no bulk out, so return 0 bytes written */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700251 dev_dbg(&port->dev, "%s - no output urb :(\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 return count;
253 }
254
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700255 dev_dbg(&port->dev, "%s - endpoint %d flip %d\n",
Alan Coxdeb91682008-07-22 11:13:08 +0100256 __func__, usb_pipeendpoint(this_urb->pipe), flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257
258 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +0100259 if (time_before(jiffies,
260 p_priv->tx_start_time[flip] + 10 * HZ))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 usb_unlink_urb(this_urb);
263 break;
264 }
265
Alan Coxdeb91682008-07-22 11:13:08 +0100266 /* First byte in buffer is "last flag" (except for usa19hx)
267 - unused so for now so set to zero */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 ((char *)this_urb->transfer_buffer)[0] = 0;
269
Alan Coxdeb91682008-07-22 11:13:08 +0100270 memcpy(this_urb->transfer_buffer + dataOffset, buf, todo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 buf += todo;
272
273 /* send the data out the bulk port */
274 this_urb->transfer_buffer_length = todo + dataOffset;
275
Alan Coxdeb91682008-07-22 11:13:08 +0100276 err = usb_submit_urb(this_urb, GFP_ATOMIC);
277 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700278 dev_dbg(&port->dev, "usb_submit_urb(write bulk) failed (%d)\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 p_priv->tx_start_time[flip] = jiffies;
280
281 /* Flip for next time if usa26 or usa28 interface
282 (not used on usa49) */
283 p_priv->out_flip = (flip + 1) & d_details->outdat_endp_flip;
284 }
285
286 return count - left;
287}
288
David Howells7d12e782006-10-05 14:55:46 +0100289static void usa26_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290{
291 int i, err;
292 int endpoint;
293 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700295 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 endpoint = usb_pipeendpoint(urb->pipe);
298
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700299 if (status) {
Stefan Hubnera8ffa0b2012-12-13 22:45:00 +0100300 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700301 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 return;
303 }
304
Ming Leicdc97792008-02-24 18:41:47 +0800305 port = urb->context;
Jiri Slaby2e124b42013-01-03 15:53:06 +0100306 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 /* 0x80 bit is error flag */
308 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100309 /* no errors on individual bytes, only
310 possible overrun err */
Johan Hovold6230c462014-11-18 11:25:20 +0100311 if (data[0] & RXERROR_OVERRUN) {
312 tty_insert_flip_char(&port->port, 0,
313 TTY_OVERRUN);
314 }
Alan Coxdeb91682008-07-22 11:13:08 +0100315 for (i = 1; i < urb->actual_length ; ++i)
Johan Hovold6230c462014-11-18 11:25:20 +0100316 tty_insert_flip_char(&port->port, data[i],
317 TTY_NORMAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 } else {
319 /* some bytes had errors, every byte has status */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700320 dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 for (i = 0; i + 1 < urb->actual_length; i += 2) {
Johan Hovoldaf8fbc22014-11-18 11:25:19 +0100322 int stat = data[i];
323 int flag = TTY_NORMAL;
324
325 if (stat & RXERROR_OVERRUN) {
326 tty_insert_flip_char(&port->port, 0,
327 TTY_OVERRUN);
328 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 /* XXX should handle break (0x10) */
Johan Hovoldaf8fbc22014-11-18 11:25:19 +0100330 if (stat & RXERROR_PARITY)
331 flag = TTY_PARITY;
332 else if (stat & RXERROR_FRAMING)
333 flag = TTY_FRAME;
334
Jiri Slaby92a19f92013-01-03 15:53:03 +0100335 tty_insert_flip_char(&port->port, data[i+1],
336 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 }
338 }
Jiri Slaby2e124b42013-01-03 15:53:06 +0100339 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 }
Alan Coxdeb91682008-07-22 11:13:08 +0100341
342 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500343 err = usb_submit_urb(urb, GFP_ATOMIC);
344 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700345 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346}
347
Alan Coxdeb91682008-07-22 11:13:08 +0100348/* Outdat handling is common for all devices */
David Howells7d12e782006-10-05 14:55:46 +0100349static void usa2x_outdat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350{
351 struct usb_serial_port *port;
352 struct keyspan_port_private *p_priv;
353
Ming Leicdc97792008-02-24 18:41:47 +0800354 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 p_priv = usb_get_serial_port_data(port);
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700356 dev_dbg(&port->dev, "%s - urb %d\n", __func__, urb == p_priv->out_urbs[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357
Alan Stern1f871582010-02-17 10:05:47 -0500358 usb_serial_port_softint(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359}
360
David Howells7d12e782006-10-05 14:55:46 +0100361static void usa26_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363}
364
David Howells7d12e782006-10-05 14:55:46 +0100365static void usa26_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366{
367 struct usb_serial_port *port;
368 struct keyspan_port_private *p_priv;
369
Ming Leicdc97792008-02-24 18:41:47 +0800370 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 p_priv = usb_get_serial_port_data(port);
372
373 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700374 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100375 keyspan_usa26_send_setup(port->serial, port,
376 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 }
378}
379
David Howells7d12e782006-10-05 14:55:46 +0100380static void usa26_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381{
382 unsigned char *data = urb->transfer_buffer;
383 struct keyspan_usa26_portStatusMessage *msg;
384 struct usb_serial *serial;
385 struct usb_serial_port *port;
386 struct keyspan_port_private *p_priv;
387 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700388 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389
Ming Leicdc97792008-02-24 18:41:47 +0800390 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700392 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700393 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 return;
395 }
396 if (urb->actual_length != 9) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700397 dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 goto exit;
399 }
400
401 msg = (struct keyspan_usa26_portStatusMessage *)data;
402
403#if 0
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700404 dev_dbg(&urb->dev->dev,
405 "%s - port status: port %d cts %d dcd %d dsr %d ri %d toff %d txoff %d rxen %d cr %d",
406 __func__, msg->port, msg->hskia_cts, msg->gpia_dcd, msg->dsr,
407 msg->ri, msg->_txOff, msg->_txXoff, msg->rxEnabled,
408 msg->controlResponse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409#endif
410
411 /* Now do something useful with the data */
412
413
Alan Coxdeb91682008-07-22 11:13:08 +0100414 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700416 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 goto exit;
418 }
419 port = serial->port[msg->port];
420 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb9e33b22014-12-22 18:39:39 +0100421 if (!p_priv)
422 goto resubmit;
Alan Coxdeb91682008-07-22 11:13:08 +0100423
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 /* Update handshaking pin state information */
425 old_dcd_state = p_priv->dcd_state;
426 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
427 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
428 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
429 p_priv->ri_state = ((msg->ri) ? 1 : 0);
430
Jiri Slabyaa27a092013-03-07 13:12:30 +0100431 if (old_dcd_state != p_priv->dcd_state)
432 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb9e33b22014-12-22 18:39:39 +0100433resubmit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100435 err = usb_submit_urb(urb, GFP_ATOMIC);
436 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700437 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438exit: ;
439}
440
David Howells7d12e782006-10-05 14:55:46 +0100441static void usa26_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443}
444
445
David Howells7d12e782006-10-05 14:55:46 +0100446static void usa28_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447{
Alan Coxf035a8a2008-07-22 11:13:32 +0100448 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 unsigned char *data;
451 struct keyspan_port_private *p_priv;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700452 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453
Ming Leicdc97792008-02-24 18:41:47 +0800454 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 p_priv = usb_get_serial_port_data(port);
456 data = urb->transfer_buffer;
457
458 if (urb != p_priv->in_urbs[p_priv->in_flip])
459 return;
460
461 do {
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700462 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700463 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
464 __func__, status, usb_pipeendpoint(urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 return;
466 }
467
Ming Leicdc97792008-02-24 18:41:47 +0800468 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 p_priv = usb_get_serial_port_data(port);
470 data = urb->transfer_buffer;
471
Jiri Slaby2e124b42013-01-03 15:53:06 +0100472 if (urb->actual_length) {
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100473 tty_insert_flip_string(&port->port, data,
474 urb->actual_length);
Jiri Slaby2e124b42013-01-03 15:53:06 +0100475 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 }
477
478 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500479 err = usb_submit_urb(urb, GFP_ATOMIC);
480 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700481 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n",
Alan Stern1f871582010-02-17 10:05:47 -0500482 __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 p_priv->in_flip ^= 1;
484
485 urb = p_priv->in_urbs[p_priv->in_flip];
486 } while (urb->status != -EINPROGRESS);
487}
488
David Howells7d12e782006-10-05 14:55:46 +0100489static void usa28_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491}
492
David Howells7d12e782006-10-05 14:55:46 +0100493static void usa28_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494{
495 struct usb_serial_port *port;
496 struct keyspan_port_private *p_priv;
497
Ming Leicdc97792008-02-24 18:41:47 +0800498 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 p_priv = usb_get_serial_port_data(port);
500
501 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700502 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100503 keyspan_usa28_send_setup(port->serial, port,
504 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 }
506}
507
David Howells7d12e782006-10-05 14:55:46 +0100508static void usa28_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509{
510 int err;
511 unsigned char *data = urb->transfer_buffer;
512 struct keyspan_usa28_portStatusMessage *msg;
513 struct usb_serial *serial;
514 struct usb_serial_port *port;
515 struct keyspan_port_private *p_priv;
516 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700517 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518
Ming Leicdc97792008-02-24 18:41:47 +0800519 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700521 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700522 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 return;
524 }
525
526 if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700527 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 goto exit;
529 }
530
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700531 /*
532 dev_dbg(&urb->dev->dev,
Stefan Hubnera8ffa0b2012-12-13 22:45:00 +0100533 "%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__,
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700534 data[0], data[1], data[2], data[3], data[4], data[5],
535 data[6], data[7], data[8], data[9], data[10], data[11]);
536 */
Alan Coxdeb91682008-07-22 11:13:08 +0100537
538 /* Now do something useful with the data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 msg = (struct keyspan_usa28_portStatusMessage *)data;
540
Alan Coxdeb91682008-07-22 11:13:08 +0100541 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700543 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 goto exit;
545 }
546 port = serial->port[msg->port];
547 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb9e33b22014-12-22 18:39:39 +0100548 if (!p_priv)
549 goto resubmit;
Alan Coxdeb91682008-07-22 11:13:08 +0100550
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 /* Update handshaking pin state information */
552 old_dcd_state = p_priv->dcd_state;
553 p_priv->cts_state = ((msg->cts) ? 1 : 0);
554 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
555 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
556 p_priv->ri_state = ((msg->ri) ? 1 : 0);
557
Jiri Slabyaa27a092013-03-07 13:12:30 +0100558 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
559 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb9e33b22014-12-22 18:39:39 +0100560resubmit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100562 err = usb_submit_urb(urb, GFP_ATOMIC);
563 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700564 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565exit: ;
566}
567
David Howells7d12e782006-10-05 14:55:46 +0100568static void usa28_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570}
571
572
David Howells7d12e782006-10-05 14:55:46 +0100573static void usa49_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574{
575 struct usb_serial *serial;
576 struct usb_serial_port *port;
577 struct keyspan_port_private *p_priv;
578 int i;
579
Ming Leicdc97792008-02-24 18:41:47 +0800580 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 for (i = 0; i < serial->num_ports; ++i) {
582 port = serial->port[i];
583 p_priv = usb_get_serial_port_data(port);
584
585 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700586 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100587 keyspan_usa49_send_setup(serial, port,
588 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 break;
590 }
591 }
592}
593
594 /* This is actually called glostat in the Keyspan
595 doco */
David Howells7d12e782006-10-05 14:55:46 +0100596static void usa49_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597{
598 int err;
599 unsigned char *data = urb->transfer_buffer;
600 struct keyspan_usa49_portStatusMessage *msg;
601 struct usb_serial *serial;
602 struct usb_serial_port *port;
603 struct keyspan_port_private *p_priv;
604 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700605 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606
Ming Leicdc97792008-02-24 18:41:47 +0800607 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700609 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700610 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 return;
612 }
613
Alan Coxdeb91682008-07-22 11:13:08 +0100614 if (urb->actual_length !=
615 sizeof(struct keyspan_usa49_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700616 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 goto exit;
618 }
619
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700620 /*
621 dev_dbg(&urb->dev->dev, "%s: %x %x %x %x %x %x %x %x %x %x %x",
622 __func__, data[0], data[1], data[2], data[3], data[4],
623 data[5], data[6], data[7], data[8], data[9], data[10]);
624 */
Alan Coxdeb91682008-07-22 11:13:08 +0100625
626 /* Now do something useful with the data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 msg = (struct keyspan_usa49_portStatusMessage *)data;
628
Alan Coxdeb91682008-07-22 11:13:08 +0100629 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 if (msg->portNumber >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700631 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
632 __func__, msg->portNumber);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 goto exit;
634 }
635 port = serial->port[msg->portNumber];
636 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb9e33b22014-12-22 18:39:39 +0100637 if (!p_priv)
638 goto resubmit;
Alan Coxdeb91682008-07-22 11:13:08 +0100639
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 /* Update handshaking pin state information */
641 old_dcd_state = p_priv->dcd_state;
642 p_priv->cts_state = ((msg->cts) ? 1 : 0);
643 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
644 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
645 p_priv->ri_state = ((msg->ri) ? 1 : 0);
646
Jiri Slabyaa27a092013-03-07 13:12:30 +0100647 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
648 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb9e33b22014-12-22 18:39:39 +0100649resubmit:
Alan Coxdeb91682008-07-22 11:13:08 +0100650 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100651 err = usb_submit_urb(urb, GFP_ATOMIC);
652 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700653 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654exit: ;
655}
656
David Howells7d12e782006-10-05 14:55:46 +0100657static void usa49_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659}
660
David Howells7d12e782006-10-05 14:55:46 +0100661static void usa49_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662{
663 int i, err;
664 int endpoint;
665 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700667 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669 endpoint = usb_pipeendpoint(urb->pipe);
670
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700671 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700672 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
673 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 return;
675 }
676
Ming Leicdc97792008-02-24 18:41:47 +0800677 port = urb->context;
Jiri Slaby2e124b42013-01-03 15:53:06 +0100678 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 /* 0x80 bit is error flag */
680 if ((data[0] & 0x80) == 0) {
681 /* no error on any byte */
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100682 tty_insert_flip_string(&port->port, data + 1,
Alan Coxf035a8a2008-07-22 11:13:32 +0100683 urb->actual_length - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 } else {
685 /* some bytes had errors, every byte has status */
686 for (i = 0; i + 1 < urb->actual_length; i += 2) {
Johan Hovoldaf8fbc22014-11-18 11:25:19 +0100687 int stat = data[i];
688 int flag = TTY_NORMAL;
689
690 if (stat & RXERROR_OVERRUN) {
691 tty_insert_flip_char(&port->port, 0,
692 TTY_OVERRUN);
693 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 /* XXX should handle break (0x10) */
Johan Hovoldaf8fbc22014-11-18 11:25:19 +0100695 if (stat & RXERROR_PARITY)
696 flag = TTY_PARITY;
697 else if (stat & RXERROR_FRAMING)
698 flag = TTY_FRAME;
699
Jiri Slaby92a19f92013-01-03 15:53:03 +0100700 tty_insert_flip_char(&port->port, data[i+1],
701 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 }
703 }
Jiri Slaby2e124b42013-01-03 15:53:06 +0100704 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 }
Alan Coxdeb91682008-07-22 11:13:08 +0100706
707 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500708 err = usb_submit_urb(urb, GFP_ATOMIC);
709 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700710 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711}
712
Lucy McCoy0ca12682007-05-18 12:10:41 -0700713static void usa49wg_indat_callback(struct urb *urb)
714{
715 int i, len, x, err;
716 struct usb_serial *serial;
717 struct usb_serial_port *port;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700718 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700719 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700720
Lucy McCoy0ca12682007-05-18 12:10:41 -0700721 serial = urb->context;
722
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700723 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700724 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700725 return;
726 }
727
728 /* inbound data is in the form P#, len, status, data */
729 i = 0;
730 len = 0;
731
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300732 while (i < urb->actual_length) {
Lucy McCoy0ca12682007-05-18 12:10:41 -0700733
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300734 /* Check port number from message */
735 if (data[i] >= serial->num_ports) {
736 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
737 __func__, data[i]);
738 return;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700739 }
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300740 port = serial->port[data[i++]];
741 len = data[i++];
742
743 /* 0x80 bit is error flag */
744 if ((data[i] & 0x80) == 0) {
745 /* no error on any byte */
746 i++;
Dan Carpenter01a60e72013-04-05 08:43:20 +0300747 for (x = 1; x < len && i < urb->actual_length; ++x)
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300748 tty_insert_flip_char(&port->port,
749 data[i++], 0);
750 } else {
751 /*
752 * some bytes had errors, every byte has status
753 */
Dan Carpenter01a60e72013-04-05 08:43:20 +0300754 for (x = 0; x + 1 < len &&
755 i + 1 < urb->actual_length; x += 2) {
Johan Hovoldaf8fbc22014-11-18 11:25:19 +0100756 int stat = data[i];
757 int flag = TTY_NORMAL;
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300758
Johan Hovoldaf8fbc22014-11-18 11:25:19 +0100759 if (stat & RXERROR_OVERRUN) {
760 tty_insert_flip_char(&port->port, 0,
761 TTY_OVERRUN);
762 }
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300763 /* XXX should handle break (0x10) */
Johan Hovoldaf8fbc22014-11-18 11:25:19 +0100764 if (stat & RXERROR_PARITY)
765 flag = TTY_PARITY;
766 else if (stat & RXERROR_FRAMING)
767 flag = TTY_FRAME;
768
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300769 tty_insert_flip_char(&port->port, data[i+1],
770 flag);
771 i += 2;
772 }
773 }
774 tty_flip_buffer_push(&port->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700775 }
776
777 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700778 err = usb_submit_urb(urb, GFP_ATOMIC);
779 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700780 dev_dbg(&urb->dev->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700781}
782
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783/* not used, usa-49 doesn't have per-port control endpoints */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700784static void usa49_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786}
787
Lucy McCoy0ca12682007-05-18 12:10:41 -0700788static void usa90_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789{
790 int i, err;
791 int endpoint;
792 struct usb_serial_port *port;
793 struct keyspan_port_private *p_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700795 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 endpoint = usb_pipeendpoint(urb->pipe);
798
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700799 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700800 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800801 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 return;
803 }
804
Ming Leicdc97792008-02-24 18:41:47 +0800805 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 p_priv = usb_get_serial_port_data(port);
807
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 /* if current mode is DMA, looks like usa28 format
Alan Coxdeb91682008-07-22 11:13:08 +0100810 otherwise looks like usa26 data format */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811
Alan Coxf035a8a2008-07-22 11:13:32 +0100812 if (p_priv->baud > 57600)
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100813 tty_insert_flip_string(&port->port, data,
814 urb->actual_length);
Alan Coxf035a8a2008-07-22 11:13:32 +0100815 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 /* 0x80 bit is error flag */
817 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100818 /* no errors on individual bytes, only
819 possible overrun err*/
Johan Hovold6230c462014-11-18 11:25:20 +0100820 if (data[0] & RXERROR_OVERRUN) {
821 tty_insert_flip_char(&port->port, 0,
822 TTY_OVERRUN);
823 }
Alan Coxdeb91682008-07-22 11:13:08 +0100824 for (i = 1; i < urb->actual_length ; ++i)
Jiri Slaby92a19f92013-01-03 15:53:03 +0100825 tty_insert_flip_char(&port->port,
Johan Hovold6230c462014-11-18 11:25:20 +0100826 data[i], TTY_NORMAL);
Alan Coxdeb91682008-07-22 11:13:08 +0100827 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 /* some bytes had errors, every byte has status */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700829 dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 for (i = 0; i + 1 < urb->actual_length; i += 2) {
Johan Hovoldaf8fbc22014-11-18 11:25:19 +0100831 int stat = data[i];
832 int flag = TTY_NORMAL;
833
834 if (stat & RXERROR_OVERRUN) {
835 tty_insert_flip_char(
836 &port->port, 0,
837 TTY_OVERRUN);
838 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 /* XXX should handle break (0x10) */
Johan Hovoldaf8fbc22014-11-18 11:25:19 +0100840 if (stat & RXERROR_PARITY)
841 flag = TTY_PARITY;
842 else if (stat & RXERROR_FRAMING)
843 flag = TTY_FRAME;
844
Jiri Slaby92a19f92013-01-03 15:53:03 +0100845 tty_insert_flip_char(&port->port,
846 data[i+1], flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 }
848 }
849 }
Jiri Slaby2e124b42013-01-03 15:53:06 +0100850 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 }
Alan Coxdeb91682008-07-22 11:13:08 +0100852
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500854 err = usb_submit_urb(urb, GFP_ATOMIC);
855 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700856 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857}
858
859
David Howells7d12e782006-10-05 14:55:46 +0100860static void usa90_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861{
862 unsigned char *data = urb->transfer_buffer;
863 struct keyspan_usa90_portStatusMessage *msg;
864 struct usb_serial *serial;
865 struct usb_serial_port *port;
866 struct keyspan_port_private *p_priv;
867 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700868 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869
Ming Leicdc97792008-02-24 18:41:47 +0800870 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700872 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700873 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 return;
875 }
876 if (urb->actual_length < 14) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700877 dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 goto exit;
879 }
880
881 msg = (struct keyspan_usa90_portStatusMessage *)data;
882
883 /* Now do something useful with the data */
884
885 port = serial->port[0];
886 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb9e33b22014-12-22 18:39:39 +0100887 if (!p_priv)
888 goto resubmit;
Alan Coxdeb91682008-07-22 11:13:08 +0100889
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 /* Update handshaking pin state information */
891 old_dcd_state = p_priv->dcd_state;
892 p_priv->cts_state = ((msg->cts) ? 1 : 0);
893 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
894 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
895 p_priv->ri_state = ((msg->ri) ? 1 : 0);
896
Jiri Slabyaa27a092013-03-07 13:12:30 +0100897 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
898 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb9e33b22014-12-22 18:39:39 +0100899resubmit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100901 err = usb_submit_urb(urb, GFP_ATOMIC);
902 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700903 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904exit:
905 ;
906}
907
David Howells7d12e782006-10-05 14:55:46 +0100908static void usa90_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909{
910 struct usb_serial_port *port;
911 struct keyspan_port_private *p_priv;
912
Ming Leicdc97792008-02-24 18:41:47 +0800913 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 p_priv = usb_get_serial_port_data(port);
915
916 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700917 dev_dbg(&urb->dev->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100918 keyspan_usa90_send_setup(port->serial, port,
919 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 }
921}
922
Lucy McCoy0ca12682007-05-18 12:10:41 -0700923/* Status messages from the 28xg */
924static void usa67_instat_callback(struct urb *urb)
925{
926 int err;
927 unsigned char *data = urb->transfer_buffer;
928 struct keyspan_usa67_portStatusMessage *msg;
929 struct usb_serial *serial;
930 struct usb_serial_port *port;
931 struct keyspan_port_private *p_priv;
932 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700933 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700934
Lucy McCoy0ca12682007-05-18 12:10:41 -0700935 serial = urb->context;
936
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700937 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700938 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700939 return;
940 }
941
Alan Coxdeb91682008-07-22 11:13:08 +0100942 if (urb->actual_length !=
943 sizeof(struct keyspan_usa67_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700944 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700945 return;
946 }
947
948
949 /* Now do something useful with the data */
950 msg = (struct keyspan_usa67_portStatusMessage *)data;
951
952 /* Check port number from message and retrieve private data */
953 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700954 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700955 return;
956 }
957
958 port = serial->port[msg->port];
959 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb9e33b22014-12-22 18:39:39 +0100960 if (!p_priv)
961 goto resubmit;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700962
963 /* Update handshaking pin state information */
964 old_dcd_state = p_priv->dcd_state;
965 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
966 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
967
Jiri Slabyaa27a092013-03-07 13:12:30 +0100968 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
969 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb9e33b22014-12-22 18:39:39 +0100970resubmit:
Lucy McCoy0ca12682007-05-18 12:10:41 -0700971 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700972 err = usb_submit_urb(urb, GFP_ATOMIC);
973 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700974 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700975}
976
977static void usa67_glocont_callback(struct urb *urb)
978{
979 struct usb_serial *serial;
980 struct usb_serial_port *port;
981 struct keyspan_port_private *p_priv;
982 int i;
983
Lucy McCoy0ca12682007-05-18 12:10:41 -0700984 serial = urb->context;
985 for (i = 0; i < serial->num_ports; ++i) {
986 port = serial->port[i];
987 p_priv = usb_get_serial_port_data(port);
988
989 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700990 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700991 keyspan_usa67_send_setup(serial, port,
992 p_priv->resend_cont - 1);
993 break;
994 }
995 }
996}
997
Alan Cox95da3102008-07-22 11:09:07 +0100998static int keyspan_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999{
Alan Cox95da3102008-07-22 11:09:07 +01001000 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 struct keyspan_port_private *p_priv;
1002 const struct keyspan_device_details *d_details;
1003 int flip;
1004 int data_len;
1005 struct urb *this_urb;
1006
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 p_priv = usb_get_serial_port_data(port);
1008 d_details = p_priv->device_details;
1009
Alan Coxa5b6f602008-04-08 17:16:06 +01001010 /* FIXME: locking */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 if (d_details->msg_format == msg_usa90)
Alan Coxdeb91682008-07-22 11:13:08 +01001012 data_len = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 else
1014 data_len = 63;
1015
1016 flip = p_priv->out_flip;
1017
1018 /* Check both endpoints to see if any are available. */
Alan Coxdeb91682008-07-22 11:13:08 +01001019 this_urb = p_priv->out_urbs[flip];
1020 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001022 return data_len;
1023 flip = (flip + 1) & d_details->outdat_endp_flip;
1024 this_urb = p_priv->out_urbs[flip];
1025 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001027 return data_len;
1028 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 }
Alan Coxa5b6f602008-04-08 17:16:06 +01001030 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031}
1032
1033
Alan Coxa509a7e2009-09-19 13:13:26 -07001034static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035{
Andrew Mortonf78ba152007-11-28 16:21:54 -08001036 struct keyspan_port_private *p_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 const struct keyspan_device_details *d_details;
1038 int i, err;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001039 int baud_rate, device_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 struct urb *urb;
Alan Cox95da3102008-07-22 11:09:07 +01001041 unsigned int cflag = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 p_priv = usb_get_serial_port_data(port);
1044 d_details = p_priv->device_details;
Borislav Petkov7eea4362007-11-14 17:00:39 -08001045
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 /* Set some sane defaults */
1047 p_priv->rts_state = 1;
1048 p_priv->dtr_state = 1;
1049 p_priv->baud = 9600;
1050
1051 /* force baud and lcr to be set on open */
1052 p_priv->old_baud = 0;
1053 p_priv->old_cflag = 0;
1054
1055 p_priv->out_flip = 0;
1056 p_priv->in_flip = 0;
1057
1058 /* Reset low level data toggle and start reading from endpoints */
1059 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001060 urb = p_priv->in_urbs[i];
1061 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063
Alan Coxdeb91682008-07-22 11:13:08 +01001064 /* make sure endpoint data toggle is synchronized
1065 with the device */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 usb_clear_halt(urb->dev, urb->pipe);
Alan Coxdeb91682008-07-22 11:13:08 +01001067 err = usb_submit_urb(urb, GFP_KERNEL);
1068 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001069 dev_dbg(&port->dev, "%s - submit urb %d failed (%d)\n", __func__, i, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 }
1071
1072 /* Reset low level data toggle on out endpoints */
1073 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001074 urb = p_priv->out_urbs[i];
1075 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 continue;
Alan Coxdeb91682008-07-22 11:13:08 +01001077 /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
1078 usb_pipeout(urb->pipe), 0); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 }
1080
Andrew Mortonf78ba152007-11-28 16:21:54 -08001081 /* get the terminal config for the setup message now so we don't
1082 * need to send 2 of them */
1083
Andrew Mortonf78ba152007-11-28 16:21:54 -08001084 device_port = port->number - port->serial->minor;
Alan Cox95da3102008-07-22 11:09:07 +01001085 if (tty) {
Alan Coxadc8d742012-07-14 15:31:47 +01001086 cflag = tty->termios.c_cflag;
Alan Cox95da3102008-07-22 11:09:07 +01001087 /* Baud rate calculation takes baud rate as an integer
1088 so other rates can be generated if desired. */
1089 baud_rate = tty_get_baud_rate(tty);
1090 /* If no match or invalid, leave as default */
1091 if (baud_rate >= 0
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001092 && d_details->calculate_baud_rate(port, baud_rate, d_details->baudclk,
Alan Cox95da3102008-07-22 11:09:07 +01001093 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
1094 p_priv->baud = baud_rate;
1095 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001096 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001097 /* set CTS/RTS handshake etc. */
1098 p_priv->cflag = cflag;
Ben Minerds2b982ab2012-07-12 00:10:16 +10001099 p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001100
1101 keyspan_send_setup(port, 1);
Alan Coxdeb91682008-07-22 11:13:08 +01001102 /* mdelay(100); */
1103 /* keyspan_set_termios(port, NULL); */
Andrew Mortonf78ba152007-11-28 16:21:54 -08001104
Alan Coxa5b6f602008-04-08 17:16:06 +01001105 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106}
1107
1108static inline void stop_urb(struct urb *urb)
1109{
Greg Kroah-Hartman242cf672005-07-29 16:11:07 -04001110 if (urb && urb->status == -EINPROGRESS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 usb_kill_urb(urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112}
1113
Alan Cox335f8512009-06-11 12:26:29 +01001114static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
1115{
1116 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
1117
1118 p_priv->rts_state = on;
1119 p_priv->dtr_state = on;
1120 keyspan_send_setup(port, 0);
1121}
1122
1123static void keyspan_close(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124{
1125 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 struct keyspan_port_private *p_priv;
1127
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +01001129
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 p_priv->rts_state = 0;
1131 p_priv->dtr_state = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001132
Johan Hovold80dfe0c2013-03-21 12:36:32 +01001133 keyspan_send_setup(port, 2);
1134 /* pilot-xfer seems to work best with this delay */
1135 mdelay(100);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136
1137 p_priv->out_flip = 0;
1138 p_priv->in_flip = 0;
1139
Johan Hovold80dfe0c2013-03-21 12:36:32 +01001140 stop_urb(p_priv->inack_urb);
1141 for (i = 0; i < 2; i++) {
1142 stop_urb(p_priv->in_urbs[i]);
1143 stop_urb(p_priv->out_urbs[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145}
1146
Alan Coxdeb91682008-07-22 11:13:08 +01001147/* download the firmware to a pre-renumeration device */
1148static int keyspan_fake_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149{
Rene Buergel8d733e22012-09-18 09:02:01 +02001150 char *fw_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001152 dev_dbg(&serial->dev->dev, "Keyspan startup version %04x product %04x\n",
1153 le16_to_cpu(serial->dev->descriptor.bcdDevice),
1154 le16_to_cpu(serial->dev->descriptor.idProduct));
Alan Coxdeb91682008-07-22 11:13:08 +01001155
1156 if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000)
1157 != 0x8000) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001158 dev_dbg(&serial->dev->dev, "Firmware already loaded. Quitting.\n");
Alan Coxdeb91682008-07-22 11:13:08 +01001159 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 }
1161
1162 /* Select firmware image on the basis of idProduct */
1163 switch (le16_to_cpu(serial->dev->descriptor.idProduct)) {
1164 case keyspan_usa28_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001165 fw_name = "keyspan/usa28.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 break;
1167
1168 case keyspan_usa28x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001169 fw_name = "keyspan/usa28x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 break;
1171
1172 case keyspan_usa28xa_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001173 fw_name = "keyspan/usa28xa.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 break;
1175
1176 case keyspan_usa28xb_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001177 fw_name = "keyspan/usa28xb.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 break;
1179
1180 case keyspan_usa19_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001181 fw_name = "keyspan/usa19.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001183
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 case keyspan_usa19qi_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001185 fw_name = "keyspan/usa19qi.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001187
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 case keyspan_mpr_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001189 fw_name = "keyspan/mpr.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 break;
1191
1192 case keyspan_usa19qw_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001193 fw_name = "keyspan/usa19qw.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001195
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 case keyspan_usa18x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001197 fw_name = "keyspan/usa18x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001199
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 case keyspan_usa19w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001201 fw_name = "keyspan/usa19w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001203
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 case keyspan_usa49w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001205 fw_name = "keyspan/usa49w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 break;
1207
1208 case keyspan_usa49wlc_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001209 fw_name = "keyspan/usa49wlc.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 break;
1211
1212 default:
David Woodhouse2971c572008-05-30 14:04:03 +03001213 dev_err(&serial->dev->dev, "Unknown product ID (%04x)\n",
1214 le16_to_cpu(serial->dev->descriptor.idProduct));
1215 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 }
1217
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001218 dev_dbg(&serial->dev->dev, "Uploading Keyspan %s firmware.\n", fw_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219
Rene Buergel8d733e22012-09-18 09:02:01 +02001220 if (ezusb_fx1_ihex_firmware_download(serial->dev, fw_name) < 0) {
1221 dev_err(&serial->dev->dev, "failed to load firmware \"%s\"\n",
1222 fw_name);
1223 return -ENOENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 }
1225
Rene Buergel8d733e22012-09-18 09:02:01 +02001226 /* after downloading firmware Renumeration will occur in a
1227 moment and the new device will bind to the real driver */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228
1229 /* we don't want this device to have a driver assigned to it. */
Alan Coxdeb91682008-07-22 11:13:08 +01001230 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231}
1232
1233/* Helper functions used by keyspan_setup_urbs */
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001234static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *serial,
1235 int endpoint)
1236{
1237 struct usb_host_interface *iface_desc;
1238 struct usb_endpoint_descriptor *ep;
1239 int i;
1240
1241 iface_desc = serial->interface->cur_altsetting;
1242 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1243 ep = &iface_desc->endpoint[i].desc;
1244 if (ep->bEndpointAddress == endpoint)
1245 return ep;
1246 }
1247 dev_warn(&serial->interface->dev, "found no endpoint descriptor for "
1248 "endpoint %x\n", endpoint);
1249 return NULL;
1250}
1251
Alan Coxdeb91682008-07-22 11:13:08 +01001252static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 int dir, void *ctx, char *buf, int len,
David Howells7d12e782006-10-05 14:55:46 +01001254 void (*callback)(struct urb *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255{
1256 struct urb *urb;
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001257 struct usb_endpoint_descriptor const *ep_desc;
1258 char const *ep_type_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259
1260 if (endpoint == -1)
1261 return NULL; /* endpoint not needed */
1262
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001263 dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %d.\n", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
1265 if (urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001266 dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %d failed.\n", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267 return NULL;
1268 }
1269
Lucy McCoy0ca12682007-05-18 12:10:41 -07001270 if (endpoint == 0) {
1271 /* control EP filled in when used */
1272 return urb;
1273 }
1274
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001275 ep_desc = find_ep(serial, endpoint);
1276 if (!ep_desc) {
1277 /* leak the urb, something's wrong and the callers don't care */
1278 return urb;
1279 }
1280 if (usb_endpoint_xfer_int(ep_desc)) {
1281 ep_type_name = "INT";
1282 usb_fill_int_urb(urb, serial->dev,
1283 usb_sndintpipe(serial->dev, endpoint) | dir,
1284 buf, len, callback, ctx,
1285 ep_desc->bInterval);
1286 } else if (usb_endpoint_xfer_bulk(ep_desc)) {
1287 ep_type_name = "BULK";
1288 usb_fill_bulk_urb(urb, serial->dev,
1289 usb_sndbulkpipe(serial->dev, endpoint) | dir,
1290 buf, len, callback, ctx);
1291 } else {
1292 dev_warn(&serial->interface->dev,
1293 "unsupported endpoint type %x\n",
Julia Lawall2e0fe702008-12-29 11:22:14 +01001294 usb_endpoint_type(ep_desc));
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001295 usb_free_urb(urb);
1296 return NULL;
1297 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001299 dev_dbg(&serial->interface->dev, "%s - using urb %p for %s endpoint %x\n",
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001300 __func__, urb, ep_type_name, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 return urb;
1302}
1303
1304static struct callbacks {
David Howells7d12e782006-10-05 14:55:46 +01001305 void (*instat_callback)(struct urb *);
1306 void (*glocont_callback)(struct urb *);
1307 void (*indat_callback)(struct urb *);
1308 void (*outdat_callback)(struct urb *);
1309 void (*inack_callback)(struct urb *);
1310 void (*outcont_callback)(struct urb *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311} keyspan_callbacks[] = {
1312 {
1313 /* msg_usa26 callbacks */
1314 .instat_callback = usa26_instat_callback,
1315 .glocont_callback = usa26_glocont_callback,
1316 .indat_callback = usa26_indat_callback,
1317 .outdat_callback = usa2x_outdat_callback,
1318 .inack_callback = usa26_inack_callback,
1319 .outcont_callback = usa26_outcont_callback,
1320 }, {
1321 /* msg_usa28 callbacks */
1322 .instat_callback = usa28_instat_callback,
1323 .glocont_callback = usa28_glocont_callback,
1324 .indat_callback = usa28_indat_callback,
1325 .outdat_callback = usa2x_outdat_callback,
1326 .inack_callback = usa28_inack_callback,
1327 .outcont_callback = usa28_outcont_callback,
1328 }, {
1329 /* msg_usa49 callbacks */
1330 .instat_callback = usa49_instat_callback,
1331 .glocont_callback = usa49_glocont_callback,
1332 .indat_callback = usa49_indat_callback,
1333 .outdat_callback = usa2x_outdat_callback,
1334 .inack_callback = usa49_inack_callback,
1335 .outcont_callback = usa49_outcont_callback,
1336 }, {
1337 /* msg_usa90 callbacks */
1338 .instat_callback = usa90_instat_callback,
Alan Coxdeb91682008-07-22 11:13:08 +01001339 .glocont_callback = usa28_glocont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 .indat_callback = usa90_indat_callback,
1341 .outdat_callback = usa2x_outdat_callback,
1342 .inack_callback = usa28_inack_callback,
1343 .outcont_callback = usa90_outcont_callback,
Lucy McCoy0ca12682007-05-18 12:10:41 -07001344 }, {
1345 /* msg_usa67 callbacks */
1346 .instat_callback = usa67_instat_callback,
1347 .glocont_callback = usa67_glocont_callback,
1348 .indat_callback = usa26_indat_callback,
1349 .outdat_callback = usa2x_outdat_callback,
1350 .inack_callback = usa26_inack_callback,
1351 .outcont_callback = usa26_outcont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 }
1353};
1354
1355 /* Generic setup urbs function that uses
1356 data in device_details */
1357static void keyspan_setup_urbs(struct usb_serial *serial)
1358{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 struct keyspan_serial_private *s_priv;
1360 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 struct callbacks *cback;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 s_priv = usb_get_serial_data(serial);
1364 d_details = s_priv->device_details;
1365
Alan Coxdeb91682008-07-22 11:13:08 +01001366 /* Setup values for the various callback routines */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 cback = &keyspan_callbacks[d_details->msg_format];
1368
Alan Coxdeb91682008-07-22 11:13:08 +01001369 /* Allocate and set up urbs for each one that is in use,
1370 starting with instat endpoints */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 s_priv->instat_urb = keyspan_setup_urb
1372 (serial, d_details->instat_endpoint, USB_DIR_IN,
1373 serial, s_priv->instat_buf, INSTAT_BUFLEN,
1374 cback->instat_callback);
1375
Lucy McCoy0ca12682007-05-18 12:10:41 -07001376 s_priv->indat_urb = keyspan_setup_urb
1377 (serial, d_details->indat_endpoint, USB_DIR_IN,
1378 serial, s_priv->indat_buf, INDAT49W_BUFLEN,
1379 usa49wg_indat_callback);
1380
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 s_priv->glocont_urb = keyspan_setup_urb
1382 (serial, d_details->glocont_endpoint, USB_DIR_OUT,
1383 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
1384 cback->glocont_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385}
1386
1387/* usa19 function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001388static int keyspan_usa19_calc_baud(struct usb_serial_port *port,
1389 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 u8 *rate_low, u8 *prescaler, int portnum)
1391{
1392 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001393 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 cnt; /* inverse of divisor (programmed into 8051) */
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;
1402 /* Any "standard" rate over 57k6 is marginal on the USA-19
1403 as we run out of divisor resolution. */
1404 if (baud_rate > 57600)
1405 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406
Alan Coxdeb91682008-07-22 11:13:08 +01001407 /* calculate the divisor and the counter (its inverse) */
1408 div = baudclk / b16;
1409 if (div == 0)
1410 return KEYSPAN_INVALID_BAUD_RATE;
1411 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413
Alan Coxdeb91682008-07-22 11:13:08 +01001414 if (div > 0xffff)
1415 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416
Alan Coxdeb91682008-07-22 11:13:08 +01001417 /* return the counter values if non-null */
1418 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001420 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001422 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001423 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001424 __func__, baud_rate, *rate_hi, *rate_low);
1425 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426}
1427
1428/* usa19hs function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001429static int keyspan_usa19hs_calc_baud(struct usb_serial_port *port,
1430 u32 baud_rate, u32 baudclk, u8 *rate_hi,
1431 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432{
1433 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001434 div; /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001436 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437
Alan Coxdeb91682008-07-22 11:13:08 +01001438 /* prevent divide by zero... */
1439 b16 = baud_rate * 16L;
1440 if (b16 == 0)
1441 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442
Alan Coxdeb91682008-07-22 11:13:08 +01001443 /* calculate the divisor */
1444 div = baudclk / b16;
1445 if (div == 0)
1446 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447
Alan Coxdeb91682008-07-22 11:13:08 +01001448 if (div > 0xffff)
1449 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450
Alan Coxdeb91682008-07-22 11:13:08 +01001451 /* return the counter values if non-null */
1452 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001454
1455 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 *rate_hi = (u8) ((div >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001457
1458 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001459 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001460 __func__, baud_rate, *rate_hi, *rate_low);
1461
1462 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463}
1464
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001465static int keyspan_usa19w_calc_baud(struct usb_serial_port *port,
1466 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 u8 *rate_low, u8 *prescaler, int portnum)
1468{
1469 u32 b16, /* baud rate times 16 (actual rate used internally) */
1470 clk, /* clock with 13/8 prescaler */
Alan Coxdeb91682008-07-22 11:13:08 +01001471 div, /* divisor using 13/8 prescaler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 res, /* resulting baud rate using 13/8 prescaler */
1473 diff, /* error using 13/8 prescaler */
1474 smallest_diff;
1475 u8 best_prescaler;
1476 int i;
1477
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001478 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479
Alan Coxdeb91682008-07-22 11:13:08 +01001480 /* prevent divide by zero */
1481 b16 = baud_rate * 16L;
1482 if (b16 == 0)
1483 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484
Alan Coxdeb91682008-07-22 11:13:08 +01001485 /* Calculate prescaler by trying them all and looking
1486 for best fit */
1487
1488 /* start with largest possible difference */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 smallest_diff = 0xffffffff;
1490
1491 /* 0 is an invalid prescaler, used as a flag */
1492 best_prescaler = 0;
1493
Alan Coxdeb91682008-07-22 11:13:08 +01001494 for (i = 8; i <= 0xff; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 clk = (baudclk * 8) / (u32) i;
Alan Coxdeb91682008-07-22 11:13:08 +01001496
1497 div = clk / b16;
1498 if (div == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500
1501 res = clk / div;
Alan Coxdeb91682008-07-22 11:13:08 +01001502 diff = (res > b16) ? (res-b16) : (b16-res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503
Alan Coxdeb91682008-07-22 11:13:08 +01001504 if (diff < smallest_diff) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505 best_prescaler = i;
1506 smallest_diff = diff;
1507 }
1508 }
1509
Alan Coxdeb91682008-07-22 11:13:08 +01001510 if (best_prescaler == 0)
1511 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512
1513 clk = (baudclk * 8) / (u32) best_prescaler;
1514 div = clk / b16;
1515
Alan Coxdeb91682008-07-22 11:13:08 +01001516 /* return the divisor and prescaler if non-null */
1517 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001519 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520 *rate_hi = (u8) ((div >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 if (prescaler) {
1522 *prescaler = best_prescaler;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001523 /* dev_dbg(&port->dev, "%s - %d %d\n", __func__, *prescaler, div); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 }
Alan Coxdeb91682008-07-22 11:13:08 +01001525 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526}
1527
1528 /* USA-28 supports different maximum baud rates on each port */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001529static int keyspan_usa28_calc_baud(struct usb_serial_port *port,
1530 u32 baud_rate, u32 baudclk, u8 *rate_hi,
1531 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532{
1533 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001534 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535 cnt; /* inverse of divisor (programmed into 8051) */
1536
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001537 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538
1539 /* prevent divide by zero */
Alan Coxdeb91682008-07-22 11:13:08 +01001540 b16 = baud_rate * 16L;
1541 if (b16 == 0)
1542 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543
Alan Coxdeb91682008-07-22 11:13:08 +01001544 /* calculate the divisor and the counter (its inverse) */
1545 div = KEYSPAN_USA28_BAUDCLK / b16;
1546 if (div == 0)
1547 return KEYSPAN_INVALID_BAUD_RATE;
1548 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550
Alan Coxdeb91682008-07-22 11:13:08 +01001551 /* check for out of range, based on portnum,
1552 and return result */
1553 if (portnum == 0) {
1554 if (div > 0xffff)
1555 return KEYSPAN_INVALID_BAUD_RATE;
1556 } else {
1557 if (portnum == 1) {
1558 if (div > 0xff)
1559 return KEYSPAN_INVALID_BAUD_RATE;
1560 } else
1561 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562 }
1563
1564 /* return the counter values if not NULL
1565 (port 1 will ignore retHi) */
Alan Coxdeb91682008-07-22 11:13:08 +01001566 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001568 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001570 dev_dbg(&port->dev, "%s - %d OK.\n", __func__, baud_rate);
Alan Coxdeb91682008-07-22 11:13:08 +01001571 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572}
1573
1574static int keyspan_usa26_send_setup(struct usb_serial *serial,
1575 struct usb_serial_port *port,
1576 int reset_port)
1577{
Alan Coxdeb91682008-07-22 11:13:08 +01001578 struct keyspan_usa26_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 struct keyspan_serial_private *s_priv;
1580 struct keyspan_port_private *p_priv;
1581 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582 struct urb *this_urb;
1583 int device_port, err;
1584
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001585 dev_dbg(&port->dev, "%s reset=%d\n", __func__, reset_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586
1587 s_priv = usb_get_serial_data(serial);
1588 p_priv = usb_get_serial_port_data(port);
1589 d_details = s_priv->device_details;
1590 device_port = port->number - port->serial->minor;
1591
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 this_urb = p_priv->outcont_urb;
1593
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001594 dev_dbg(&port->dev, "%s - endpoint %d\n", __func__, usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595
1596 /* Make sure we have an urb then send the message */
1597 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001598 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 return -1;
1600 }
1601
1602 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001603 Don't overwrite resend for open/close condition. */
1604 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 p_priv->resend_cont = reset_port + 1;
1606 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001607 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001609 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 }
1611
Alan Coxdeb91682008-07-22 11:13:08 +01001612 memset(&msg, 0, sizeof(struct keyspan_usa26_portControlMessage));
1613
1614 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 if (p_priv->old_baud != p_priv->baud) {
1616 p_priv->old_baud = p_priv->baud;
1617 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001618 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1619 &msg.baudHi, &msg.baudLo, &msg.prescaler,
1620 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1621 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
1622 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623 msg.baudLo = 0;
1624 msg.baudHi = 125; /* Values for 9600 baud */
1625 msg.prescaler = 10;
1626 }
1627 msg.setPrescaler = 0xff;
1628 }
1629
Ben Minerds2b982ab2012-07-12 00:10:16 +10001630 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 switch (p_priv->cflag & CSIZE) {
1632 case CS5:
1633 msg.lcr |= USA_DATABITS_5;
1634 break;
1635 case CS6:
1636 msg.lcr |= USA_DATABITS_6;
1637 break;
1638 case CS7:
1639 msg.lcr |= USA_DATABITS_7;
1640 break;
1641 case CS8:
1642 msg.lcr |= USA_DATABITS_8;
1643 break;
1644 }
1645 if (p_priv->cflag & PARENB) {
1646 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10001647 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01001648 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649 }
1650 msg.setLcr = 0xff;
1651
1652 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1653 msg.xonFlowControl = 0;
1654 msg.setFlowControl = 0xff;
1655 msg.forwardingLength = 16;
1656 msg.xonChar = 17;
1657 msg.xoffChar = 19;
1658
1659 /* Opening port */
1660 if (reset_port == 1) {
1661 msg._txOn = 1;
1662 msg._txOff = 0;
1663 msg.txFlush = 0;
1664 msg.txBreak = 0;
1665 msg.rxOn = 1;
1666 msg.rxOff = 0;
1667 msg.rxFlush = 1;
1668 msg.rxForward = 0;
1669 msg.returnStatus = 0;
1670 msg.resetDataToggle = 0xff;
1671 }
1672
1673 /* Closing port */
1674 else if (reset_port == 2) {
1675 msg._txOn = 0;
1676 msg._txOff = 1;
1677 msg.txFlush = 0;
1678 msg.txBreak = 0;
1679 msg.rxOn = 0;
1680 msg.rxOff = 1;
1681 msg.rxFlush = 1;
1682 msg.rxForward = 0;
1683 msg.returnStatus = 0;
1684 msg.resetDataToggle = 0;
1685 }
1686
1687 /* Sending intermediate configs */
1688 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001689 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 msg._txOff = 0;
1691 msg.txFlush = 0;
1692 msg.txBreak = (p_priv->break_on);
1693 msg.rxOn = 0;
1694 msg.rxOff = 0;
1695 msg.rxFlush = 0;
1696 msg.rxForward = 0;
1697 msg.returnStatus = 0;
1698 msg.resetDataToggle = 0x0;
1699 }
1700
Alan Coxdeb91682008-07-22 11:13:08 +01001701 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 msg.setTxTriState_setRts = 0xff;
1703 msg.txTriState_rts = p_priv->rts_state;
1704
1705 msg.setHskoa_setDtr = 0xff;
1706 msg.hskoa_dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01001707
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001709 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
1710
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 /* send the data out the device on control endpoint */
1712 this_urb->transfer_buffer_length = sizeof(msg);
1713
Alan Coxdeb91682008-07-22 11:13:08 +01001714 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1715 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001716 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01001717 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718}
1719
1720static int keyspan_usa28_send_setup(struct usb_serial *serial,
1721 struct usb_serial_port *port,
1722 int reset_port)
1723{
Alan Coxdeb91682008-07-22 11:13:08 +01001724 struct keyspan_usa28_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725 struct keyspan_serial_private *s_priv;
1726 struct keyspan_port_private *p_priv;
1727 const struct keyspan_device_details *d_details;
1728 struct urb *this_urb;
1729 int device_port, err;
1730
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 s_priv = usb_get_serial_data(serial);
1732 p_priv = usb_get_serial_port_data(port);
1733 d_details = s_priv->device_details;
1734 device_port = port->number - port->serial->minor;
1735
1736 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01001737 this_urb = p_priv->outcont_urb;
1738 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001739 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 return -1;
1741 }
1742
1743 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001744 Don't overwrite resend for open/close condition. */
1745 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746 p_priv->resend_cont = reset_port + 1;
1747 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001748 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001750 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751 }
1752
Alan Coxdeb91682008-07-22 11:13:08 +01001753 memset(&msg, 0, sizeof(struct keyspan_usa28_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754
1755 msg.setBaudRate = 1;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001756 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1757 &msg.baudHi, &msg.baudLo, NULL,
1758 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1759 dev_dbg(&port->dev, "%s - Invalid baud rate requested %d.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001760 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761 msg.baudLo = 0xff;
1762 msg.baudHi = 0xb2; /* Values for 9600 baud */
1763 }
1764
1765 /* If parity is enabled, we must calculate it ourselves. */
1766 msg.parity = 0; /* XXX for now */
1767
1768 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1769 msg.xonFlowControl = 0;
1770
Alan Coxdeb91682008-07-22 11:13:08 +01001771 /* Do handshaking outputs, DTR is inverted relative to RTS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772 msg.rts = p_priv->rts_state;
1773 msg.dtr = p_priv->dtr_state;
1774
1775 msg.forwardingLength = 16;
1776 msg.forwardMs = 10;
1777 msg.breakThreshold = 45;
1778 msg.xonChar = 17;
1779 msg.xoffChar = 19;
1780
1781 /*msg.returnStatus = 1;
1782 msg.resetDataToggle = 0xff;*/
1783 /* Opening port */
1784 if (reset_port == 1) {
1785 msg._txOn = 1;
1786 msg._txOff = 0;
1787 msg.txFlush = 0;
1788 msg.txForceXoff = 0;
1789 msg.txBreak = 0;
1790 msg.rxOn = 1;
1791 msg.rxOff = 0;
1792 msg.rxFlush = 1;
1793 msg.rxForward = 0;
1794 msg.returnStatus = 0;
1795 msg.resetDataToggle = 0xff;
1796 }
1797 /* Closing port */
1798 else if (reset_port == 2) {
1799 msg._txOn = 0;
1800 msg._txOff = 1;
1801 msg.txFlush = 0;
1802 msg.txForceXoff = 0;
1803 msg.txBreak = 0;
1804 msg.rxOn = 0;
1805 msg.rxOff = 1;
1806 msg.rxFlush = 1;
1807 msg.rxForward = 0;
1808 msg.returnStatus = 0;
1809 msg.resetDataToggle = 0;
1810 }
1811 /* Sending intermediate configs */
1812 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001813 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814 msg._txOff = 0;
1815 msg.txFlush = 0;
1816 msg.txForceXoff = 0;
1817 msg.txBreak = (p_priv->break_on);
1818 msg.rxOn = 0;
1819 msg.rxOff = 0;
1820 msg.rxFlush = 0;
1821 msg.rxForward = 0;
1822 msg.returnStatus = 0;
1823 msg.resetDataToggle = 0x0;
1824 }
1825
1826 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001827 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828
1829 /* send the data out the device on control endpoint */
1830 this_urb->transfer_buffer_length = sizeof(msg);
1831
Alan Coxdeb91682008-07-22 11:13:08 +01001832 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1833 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001834 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835#if 0
1836 else {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001837 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) OK %d bytes\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 this_urb->transfer_buffer_length);
1839 }
1840#endif
1841
Alan Coxa5b6f602008-04-08 17:16:06 +01001842 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843}
1844
1845static int keyspan_usa49_send_setup(struct usb_serial *serial,
1846 struct usb_serial_port *port,
1847 int reset_port)
1848{
Lucy McCoy0ca12682007-05-18 12:10:41 -07001849 struct keyspan_usa49_portControlMessage msg;
1850 struct usb_ctrlrequest *dr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851 struct keyspan_serial_private *s_priv;
1852 struct keyspan_port_private *p_priv;
1853 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854 struct urb *this_urb;
1855 int err, device_port;
1856
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857 s_priv = usb_get_serial_data(serial);
1858 p_priv = usb_get_serial_port_data(port);
1859 d_details = s_priv->device_details;
1860
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 this_urb = s_priv->glocont_urb;
1862
Lucy McCoy0ca12682007-05-18 12:10:41 -07001863 /* Work out which port within the device is being setup */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 device_port = port->number - port->serial->minor;
1865
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05301866 /* Make sure we have an urb then send the message */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001868 dev_dbg(&port->dev, "%s - oops no urb for port %d.\n", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869 return -1;
1870 }
1871
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001872 dev_dbg(&port->dev, "%s - endpoint %d port %d (%d)\n",
1873 __func__, usb_pipeendpoint(this_urb->pipe),
1874 port->number, device_port);
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05301875
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001877 Don't overwrite resend for open/close condition. */
1878 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879 p_priv->resend_cont = reset_port + 1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001880
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001882 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001884 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 }
1886
Alan Coxdeb91682008-07-22 11:13:08 +01001887 memset(&msg, 0, sizeof(struct keyspan_usa49_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888
1889 /*msg.portNumber = port->number;*/
1890 msg.portNumber = device_port;
Alan Coxdeb91682008-07-22 11:13:08 +01001891
1892 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 if (p_priv->old_baud != p_priv->baud) {
1894 p_priv->old_baud = p_priv->baud;
1895 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001896 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1897 &msg.baudHi, &msg.baudLo, &msg.prescaler,
1898 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1899 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
1900 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 msg.baudLo = 0;
1902 msg.baudHi = 125; /* Values for 9600 baud */
1903 msg.prescaler = 10;
1904 }
Alan Coxdeb91682008-07-22 11:13:08 +01001905 /* msg.setPrescaler = 0xff; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906 }
1907
Ben Minerds2b982ab2012-07-12 00:10:16 +10001908 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909 switch (p_priv->cflag & CSIZE) {
1910 case CS5:
1911 msg.lcr |= USA_DATABITS_5;
1912 break;
1913 case CS6:
1914 msg.lcr |= USA_DATABITS_6;
1915 break;
1916 case CS7:
1917 msg.lcr |= USA_DATABITS_7;
1918 break;
1919 case CS8:
1920 msg.lcr |= USA_DATABITS_8;
1921 break;
1922 }
1923 if (p_priv->cflag & PARENB) {
1924 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10001925 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01001926 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927 }
1928 msg.setLcr = 0xff;
1929
1930 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1931 msg.xonFlowControl = 0;
1932 msg.setFlowControl = 0xff;
Alan Coxdeb91682008-07-22 11:13:08 +01001933
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934 msg.forwardingLength = 16;
1935 msg.xonChar = 17;
1936 msg.xoffChar = 19;
1937
Alan Coxdeb91682008-07-22 11:13:08 +01001938 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 if (reset_port == 1) {
1940 msg._txOn = 1;
1941 msg._txOff = 0;
1942 msg.txFlush = 0;
1943 msg.txBreak = 0;
1944 msg.rxOn = 1;
1945 msg.rxOff = 0;
1946 msg.rxFlush = 1;
1947 msg.rxForward = 0;
1948 msg.returnStatus = 0;
1949 msg.resetDataToggle = 0xff;
1950 msg.enablePort = 1;
1951 msg.disablePort = 0;
1952 }
1953 /* Closing port */
1954 else if (reset_port == 2) {
1955 msg._txOn = 0;
1956 msg._txOff = 1;
1957 msg.txFlush = 0;
1958 msg.txBreak = 0;
1959 msg.rxOn = 0;
1960 msg.rxOff = 1;
1961 msg.rxFlush = 1;
1962 msg.rxForward = 0;
1963 msg.returnStatus = 0;
1964 msg.resetDataToggle = 0;
1965 msg.enablePort = 0;
1966 msg.disablePort = 1;
1967 }
1968 /* Sending intermediate configs */
1969 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001970 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971 msg._txOff = 0;
1972 msg.txFlush = 0;
1973 msg.txBreak = (p_priv->break_on);
1974 msg.rxOn = 0;
1975 msg.rxOff = 0;
1976 msg.rxFlush = 0;
1977 msg.rxForward = 0;
1978 msg.returnStatus = 0;
1979 msg.resetDataToggle = 0x0;
1980 msg.enablePort = 0;
1981 msg.disablePort = 0;
1982 }
1983
Alan Coxdeb91682008-07-22 11:13:08 +01001984 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 msg.setRts = 0xff;
1986 msg.rts = p_priv->rts_state;
1987
1988 msg.setDtr = 0xff;
1989 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01001990
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991 p_priv->resend_cont = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992
Alan Coxdeb91682008-07-22 11:13:08 +01001993 /* if the device is a 49wg, we send control message on usb
1994 control EP 0 */
Lucy McCoy0ca12682007-05-18 12:10:41 -07001995
1996 if (d_details->product_id == keyspan_usa49wg_product_id) {
1997 dr = (void *)(s_priv->ctrl_buf);
1998 dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT;
1999 dr->bRequest = 0xB0; /* 49wg control message */;
2000 dr->wValue = 0;
2001 dr->wIndex = 0;
2002 dr->wLength = cpu_to_le16(sizeof(msg));
2003
Alan Coxdeb91682008-07-22 11:13:08 +01002004 memcpy(s_priv->glocont_buf, &msg, sizeof(msg));
Lucy McCoy0ca12682007-05-18 12:10:41 -07002005
Alan Coxdeb91682008-07-22 11:13:08 +01002006 usb_fill_control_urb(this_urb, serial->dev,
2007 usb_sndctrlpipe(serial->dev, 0),
2008 (unsigned char *)dr, s_priv->glocont_buf,
2009 sizeof(msg), usa49_glocont_callback, serial);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002010
2011 } else {
2012 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Alan Coxdeb91682008-07-22 11:13:08 +01002013
Lucy McCoy0ca12682007-05-18 12:10:41 -07002014 /* send the data out the device on control endpoint */
2015 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002016 }
Alan Coxdeb91682008-07-22 11:13:08 +01002017 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2018 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002019 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020#if 0
2021 else {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002022 dev_dbg(&port->dev, "%s - usb_submit_urb(%d) OK %d bytes (end %d)\n", __func__,
2023 outcont_urb, this_urb->transfer_buffer_length,
2024 usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025 }
2026#endif
2027
Alan Coxa5b6f602008-04-08 17:16:06 +01002028 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029}
2030
2031static int keyspan_usa90_send_setup(struct usb_serial *serial,
2032 struct usb_serial_port *port,
2033 int reset_port)
2034{
Alan Coxdeb91682008-07-22 11:13:08 +01002035 struct keyspan_usa90_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 struct keyspan_serial_private *s_priv;
2037 struct keyspan_port_private *p_priv;
2038 const struct keyspan_device_details *d_details;
2039 struct urb *this_urb;
2040 int err;
2041 u8 prescaler;
2042
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043 s_priv = usb_get_serial_data(serial);
2044 p_priv = usb_get_serial_port_data(port);
2045 d_details = s_priv->device_details;
2046
2047 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01002048 this_urb = p_priv->outcont_urb;
2049 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002050 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051 return -1;
2052 }
2053
2054 /* Save reset port val for resend.
2055 Don't overwrite resend for open/close condition. */
2056 if ((reset_port + 1) > p_priv->resend_cont)
2057 p_priv->resend_cont = reset_port + 1;
2058 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002059 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002061 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062 }
2063
Alan Coxdeb91682008-07-22 11:13:08 +01002064 memset(&msg, 0, sizeof(struct keyspan_usa90_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065
Alan Coxdeb91682008-07-22 11:13:08 +01002066 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067 if (p_priv->old_baud != p_priv->baud) {
2068 p_priv->old_baud = p_priv->baud;
2069 msg.setClocking = 0x01;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002070 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2071 &msg.baudHi, &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) {
2072 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2073 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074 p_priv->baud = 9600;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002075 d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076 &msg.baudHi, &msg.baudLo, &prescaler, 0);
2077 }
2078 msg.setRxMode = 1;
2079 msg.setTxMode = 1;
2080 }
2081
2082 /* modes must always be correctly specified */
Alan Coxdeb91682008-07-22 11:13:08 +01002083 if (p_priv->baud > 57600) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084 msg.rxMode = RXMODE_DMA;
2085 msg.txMode = TXMODE_DMA;
Alan Coxdeb91682008-07-22 11:13:08 +01002086 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 msg.rxMode = RXMODE_BYHAND;
2088 msg.txMode = TXMODE_BYHAND;
2089 }
2090
Ben Minerds2b982ab2012-07-12 00:10:16 +10002091 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092 switch (p_priv->cflag & CSIZE) {
2093 case CS5:
2094 msg.lcr |= USA_DATABITS_5;
2095 break;
2096 case CS6:
2097 msg.lcr |= USA_DATABITS_6;
2098 break;
2099 case CS7:
2100 msg.lcr |= USA_DATABITS_7;
2101 break;
2102 case CS8:
2103 msg.lcr |= USA_DATABITS_8;
2104 break;
2105 }
2106 if (p_priv->cflag & PARENB) {
2107 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002108 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002109 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110 }
2111 if (p_priv->old_cflag != p_priv->cflag) {
2112 p_priv->old_cflag = p_priv->cflag;
2113 msg.setLcr = 0x01;
2114 }
2115
2116 if (p_priv->flow_control == flow_cts)
2117 msg.txFlowControl = TXFLOW_CTS;
2118 msg.setTxFlowControl = 0x01;
2119 msg.setRxFlowControl = 0x01;
Alan Coxdeb91682008-07-22 11:13:08 +01002120
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 msg.rxForwardingLength = 16;
Alan Coxdeb91682008-07-22 11:13:08 +01002122 msg.rxForwardingTimeout = 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123 msg.txAckSetting = 0;
2124 msg.xonChar = 17;
2125 msg.xoffChar = 19;
2126
Alan Coxdeb91682008-07-22 11:13:08 +01002127 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128 if (reset_port == 1) {
2129 msg.portEnabled = 1;
2130 msg.rxFlush = 1;
2131 msg.txBreak = (p_priv->break_on);
2132 }
2133 /* Closing port */
Alan Coxdeb91682008-07-22 11:13:08 +01002134 else if (reset_port == 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135 msg.portEnabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 /* Sending intermediate configs */
2137 else {
Alan Stern1f871582010-02-17 10:05:47 -05002138 msg.portEnabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 msg.txBreak = (p_priv->break_on);
2140 }
2141
Alan Coxdeb91682008-07-22 11:13:08 +01002142 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143 msg.setRts = 0x01;
2144 msg.rts = p_priv->rts_state;
2145
2146 msg.setDtr = 0x01;
2147 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002148
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01002150 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2151
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 /* send the data out the device on control endpoint */
2153 this_urb->transfer_buffer_length = sizeof(msg);
2154
Alan Coxdeb91682008-07-22 11:13:08 +01002155 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2156 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002157 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002158 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159}
2160
Lucy McCoy0ca12682007-05-18 12:10:41 -07002161static int keyspan_usa67_send_setup(struct usb_serial *serial,
2162 struct usb_serial_port *port,
2163 int reset_port)
2164{
2165 struct keyspan_usa67_portControlMessage msg;
2166 struct keyspan_serial_private *s_priv;
2167 struct keyspan_port_private *p_priv;
2168 const struct keyspan_device_details *d_details;
2169 struct urb *this_urb;
2170 int err, device_port;
2171
Lucy McCoy0ca12682007-05-18 12:10:41 -07002172 s_priv = usb_get_serial_data(serial);
2173 p_priv = usb_get_serial_port_data(port);
2174 d_details = s_priv->device_details;
2175
2176 this_urb = s_priv->glocont_urb;
2177
2178 /* Work out which port within the device is being setup */
2179 device_port = port->number - port->serial->minor;
2180
2181 /* Make sure we have an urb then send the message */
2182 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002183 dev_dbg(&port->dev, "%s - oops no urb for port %d.\n", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002184 port->number);
2185 return -1;
2186 }
2187
2188 /* Save reset port val for resend.
2189 Don't overwrite resend for open/close condition. */
2190 if ((reset_port + 1) > p_priv->resend_cont)
2191 p_priv->resend_cont = reset_port + 1;
2192 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002193 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002194 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002195 return -1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002196 }
2197
2198 memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
2199
2200 msg.port = device_port;
2201
2202 /* Only set baud rate if it's changed */
2203 if (p_priv->old_baud != p_priv->baud) {
2204 p_priv->old_baud = p_priv->baud;
2205 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002206 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2207 &msg.baudHi, &msg.baudLo, &msg.prescaler,
2208 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2209 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2210 __func__, p_priv->baud);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002211 msg.baudLo = 0;
2212 msg.baudHi = 125; /* Values for 9600 baud */
2213 msg.prescaler = 10;
2214 }
2215 msg.setPrescaler = 0xff;
2216 }
2217
2218 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
2219 switch (p_priv->cflag & CSIZE) {
2220 case CS5:
2221 msg.lcr |= USA_DATABITS_5;
2222 break;
2223 case CS6:
2224 msg.lcr |= USA_DATABITS_6;
2225 break;
2226 case CS7:
2227 msg.lcr |= USA_DATABITS_7;
2228 break;
2229 case CS8:
2230 msg.lcr |= USA_DATABITS_8;
2231 break;
2232 }
2233 if (p_priv->cflag & PARENB) {
2234 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002235 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002236 USA_PARITY_ODD : USA_PARITY_EVEN;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002237 }
2238 msg.setLcr = 0xff;
2239
2240 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2241 msg.xonFlowControl = 0;
2242 msg.setFlowControl = 0xff;
2243 msg.forwardingLength = 16;
2244 msg.xonChar = 17;
2245 msg.xoffChar = 19;
2246
2247 if (reset_port == 1) {
2248 /* Opening port */
2249 msg._txOn = 1;
2250 msg._txOff = 0;
2251 msg.txFlush = 0;
2252 msg.txBreak = 0;
2253 msg.rxOn = 1;
2254 msg.rxOff = 0;
2255 msg.rxFlush = 1;
2256 msg.rxForward = 0;
2257 msg.returnStatus = 0;
2258 msg.resetDataToggle = 0xff;
2259 } else if (reset_port == 2) {
2260 /* Closing port */
2261 msg._txOn = 0;
2262 msg._txOff = 1;
2263 msg.txFlush = 0;
2264 msg.txBreak = 0;
2265 msg.rxOn = 0;
2266 msg.rxOff = 1;
2267 msg.rxFlush = 1;
2268 msg.rxForward = 0;
2269 msg.returnStatus = 0;
2270 msg.resetDataToggle = 0;
2271 } else {
2272 /* Sending intermediate configs */
Alan Coxdeb91682008-07-22 11:13:08 +01002273 msg._txOn = (!p_priv->break_on);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002274 msg._txOff = 0;
2275 msg.txFlush = 0;
2276 msg.txBreak = (p_priv->break_on);
2277 msg.rxOn = 0;
2278 msg.rxOff = 0;
2279 msg.rxFlush = 0;
2280 msg.rxForward = 0;
2281 msg.returnStatus = 0;
2282 msg.resetDataToggle = 0x0;
2283 }
2284
2285 /* Do handshaking outputs */
2286 msg.setTxTriState_setRts = 0xff;
2287 msg.txTriState_rts = p_priv->rts_state;
2288
2289 msg.setHskoa_setDtr = 0xff;
2290 msg.hskoa_dtr = p_priv->dtr_state;
2291
2292 p_priv->resend_cont = 0;
2293
2294 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2295
2296 /* send the data out the device on control endpoint */
2297 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002298
2299 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2300 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002301 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002302 return 0;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002303}
2304
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
2306{
2307 struct usb_serial *serial = port->serial;
2308 struct keyspan_serial_private *s_priv;
2309 const struct keyspan_device_details *d_details;
2310
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311 s_priv = usb_get_serial_data(serial);
2312 d_details = s_priv->device_details;
2313
2314 switch (d_details->msg_format) {
2315 case msg_usa26:
2316 keyspan_usa26_send_setup(serial, port, reset_port);
2317 break;
2318 case msg_usa28:
2319 keyspan_usa28_send_setup(serial, port, reset_port);
2320 break;
2321 case msg_usa49:
2322 keyspan_usa49_send_setup(serial, port, reset_port);
2323 break;
2324 case msg_usa90:
2325 keyspan_usa90_send_setup(serial, port, reset_port);
2326 break;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002327 case msg_usa67:
2328 keyspan_usa67_send_setup(serial, port, reset_port);
2329 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330 }
2331}
2332
2333
2334/* Gets called by the "real" driver (ie once firmware is loaded
2335 and renumeration has taken place. */
Alan Coxdeb91682008-07-22 11:13:08 +01002336static int keyspan_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337{
2338 int i, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340 const struct keyspan_device_details *d_details;
2341
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342 for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
Alan Coxdeb91682008-07-22 11:13:08 +01002343 if (d_details->product_id ==
2344 le16_to_cpu(serial->dev->descriptor.idProduct))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345 break;
2346 if (d_details == NULL) {
Alan Coxdeb91682008-07-22 11:13:08 +01002347 dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
2348 __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
Johan Hovold91508a92013-08-13 13:27:35 +02002349 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 }
2351
2352 /* Setup private data for serial driver */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01002353 s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 if (!s_priv) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002355 dev_dbg(&serial->dev->dev, "%s - kmalloc for keyspan_serial_private failed.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 return -ENOMEM;
2357 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358
2359 s_priv->device_details = d_details;
2360 usb_set_serial_data(serial, s_priv);
2361
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362 keyspan_setup_urbs(serial);
2363
Lucy McCoy0ca12682007-05-18 12:10:41 -07002364 if (s_priv->instat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002365 err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
2366 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002367 dev_dbg(&serial->dev->dev, "%s - submit instat urb failed %d\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002368 }
2369 if (s_priv->indat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002370 err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
2371 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002372 dev_dbg(&serial->dev->dev, "%s - submit indat urb failed %d\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373 }
Alan Coxdeb91682008-07-22 11:13:08 +01002374
Alan Coxa5b6f602008-04-08 17:16:06 +01002375 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376}
2377
Alan Sternf9c99bb2009-06-02 11:53:55 -04002378static void keyspan_disconnect(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002380 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381
Linus Torvalds1da177e2005-04-16 15:20:36 -07002382 s_priv = usb_get_serial_data(serial);
2383
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384 stop_urb(s_priv->instat_urb);
2385 stop_urb(s_priv->glocont_urb);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002386 stop_urb(s_priv->indat_urb);
Alan Sternf9c99bb2009-06-02 11:53:55 -04002387}
2388
2389static void keyspan_release(struct usb_serial *serial)
2390{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002391 struct keyspan_serial_private *s_priv;
Alan Sternf9c99bb2009-06-02 11:53:55 -04002392
Alan Sternf9c99bb2009-06-02 11:53:55 -04002393 s_priv = usb_get_serial_data(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002394
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002395 usb_free_urb(s_priv->instat_urb);
2396 usb_free_urb(s_priv->indat_urb);
2397 usb_free_urb(s_priv->glocont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002399 kfree(s_priv);
2400}
2401
2402static int keyspan_port_probe(struct usb_serial_port *port)
2403{
2404 struct usb_serial *serial = port->serial;
Bjørn Morkf0e3e352012-11-10 10:13:42 +01002405 struct keyspan_serial_private *s_priv;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002406 struct keyspan_port_private *p_priv;
2407 const struct keyspan_device_details *d_details;
2408 struct callbacks *cback;
2409 int endp;
2410 int port_num;
2411 int i;
2412
2413 s_priv = usb_get_serial_data(serial);
2414 d_details = s_priv->device_details;
2415
2416 p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL);
2417 if (!p_priv)
2418 return -ENOMEM;
2419
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002420 p_priv->device_details = d_details;
2421
2422 /* Setup values for the various callback routines */
2423 cback = &keyspan_callbacks[d_details->msg_format];
2424
2425 port_num = port->number - port->serial->minor;
2426
2427 /* Do indat endpoints first, once for each flip */
2428 endp = d_details->indat_endpoints[port_num];
2429 for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) {
2430 p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp,
2431 USB_DIR_IN, port,
2432 p_priv->in_buffer[i], 64,
2433 cback->indat_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434 }
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002435 /* outdat endpoints also have flip */
2436 endp = d_details->outdat_endpoints[port_num];
2437 for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) {
2438 p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp,
2439 USB_DIR_OUT, port,
2440 p_priv->out_buffer[i], 64,
2441 cback->outdat_callback);
2442 }
2443 /* inack endpoint */
2444 p_priv->inack_urb = keyspan_setup_urb(serial,
2445 d_details->inack_endpoints[port_num],
2446 USB_DIR_IN, port,
2447 p_priv->inack_buffer, 1,
2448 cback->inack_callback);
2449 /* outcont endpoint */
2450 p_priv->outcont_urb = keyspan_setup_urb(serial,
2451 d_details->outcont_endpoints[port_num],
2452 USB_DIR_OUT, port,
2453 p_priv->outcont_buffer, 64,
2454 cback->outcont_callback);
2455
2456 usb_set_serial_port_data(port, p_priv);
2457
2458 return 0;
2459}
2460
2461static int keyspan_port_remove(struct usb_serial_port *port)
2462{
2463 struct keyspan_port_private *p_priv;
2464 int i;
2465
2466 p_priv = usb_get_serial_port_data(port);
2467
2468 stop_urb(p_priv->inack_urb);
2469 stop_urb(p_priv->outcont_urb);
2470 for (i = 0; i < 2; i++) {
2471 stop_urb(p_priv->in_urbs[i]);
2472 stop_urb(p_priv->out_urbs[i]);
2473 }
2474
2475 usb_free_urb(p_priv->inack_urb);
2476 usb_free_urb(p_priv->outcont_urb);
2477 for (i = 0; i < 2; i++) {
2478 usb_free_urb(p_priv->in_urbs[i]);
2479 usb_free_urb(p_priv->out_urbs[i]);
2480 }
2481
2482 kfree(p_priv);
2483
2484 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485}
2486
Alan Coxdeb91682008-07-22 11:13:08 +01002487MODULE_AUTHOR(DRIVER_AUTHOR);
2488MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489MODULE_LICENSE("GPL");
2490
David Woodhouse2971c572008-05-30 14:04:03 +03002491MODULE_FIRMWARE("keyspan/usa28.fw");
2492MODULE_FIRMWARE("keyspan/usa28x.fw");
2493MODULE_FIRMWARE("keyspan/usa28xa.fw");
2494MODULE_FIRMWARE("keyspan/usa28xb.fw");
2495MODULE_FIRMWARE("keyspan/usa19.fw");
2496MODULE_FIRMWARE("keyspan/usa19qi.fw");
2497MODULE_FIRMWARE("keyspan/mpr.fw");
2498MODULE_FIRMWARE("keyspan/usa19qw.fw");
2499MODULE_FIRMWARE("keyspan/usa18x.fw");
2500MODULE_FIRMWARE("keyspan/usa19w.fw");
2501MODULE_FIRMWARE("keyspan/usa49w.fw");
2502MODULE_FIRMWARE("keyspan/usa49wlc.fw");