blob: 1fd1935c8316f525e5795c22fa0dada0093b6be9 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 Keyspan USB to Serial Converter driver
Alan Coxdeb91682008-07-22 11:13:08 +01003
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 (C) Copyright (C) 2000-2001 Hugh Blemings <hugh@blemings.org>
5 (C) Copyright (C) 2002 Greg Kroah-Hartman <greg@kroah.com>
Alan Coxdeb91682008-07-22 11:13:08 +01006
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
Justin P. Mattock631dd1a2010-10-18 11:03:14 +020012 See http://blemings.org/hugh/keyspan.html for more information.
Alan Coxdeb91682008-07-22 11:13:08 +010013
Linus Torvalds1da177e2005-04-16 15:20:36 -070014 Code in this driver inspired by and in a number of places taken
15 from Brian Warner's original Keyspan-PDA driver.
16
17 This driver has been put together with the support of Innosys, Inc.
18 and Keyspan, Inc the manufacturers of the Keyspan USB-serial products.
19 Thanks Guys :)
Alan Coxdeb91682008-07-22 11:13:08 +010020
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 Thanks to Paulus for miscellaneous tidy ups, some largish chunks
22 of much nicer and/or completely new code and (perhaps most uniquely)
23 having the patience to sit down and explain why and where he'd changed
Alan Coxdeb91682008-07-22 11:13:08 +010024 stuff.
25
26 Tip 'o the hat to IBM (and previously Linuxcare :) for supporting
Linus Torvalds1da177e2005-04-16 15:20:36 -070027 staff in their work on open source projects.
Linus Torvalds1da177e2005-04-16 15:20:36 -070028*/
29
30
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/kernel.h>
32#include <linux/jiffies.h>
33#include <linux/errno.h>
34#include <linux/init.h>
35#include <linux/slab.h>
36#include <linux/tty.h>
37#include <linux/tty_driver.h>
38#include <linux/tty_flip.h>
39#include <linux/module.h>
40#include <linux/spinlock.h>
Alan Coxdeb91682008-07-22 11:13:08 +010041#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <linux/usb.h>
Greg Kroah-Hartmana9698882006-07-11 21:22:58 -070043#include <linux/usb/serial.h>
Rene Buergelcc183e22012-09-18 09:00:41 +020044#include <linux/usb/ezusb.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include "keyspan.h"
46
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu"
48#define DRIVER_DESC "Keyspan USB to Serial Converter Driver"
49
50#define INSTAT_BUFLEN 32
51#define GLOCONT_BUFLEN 64
Lucy McCoy0ca12682007-05-18 12:10:41 -070052#define INDAT49W_BUFLEN 512
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
54 /* Per device and per port private data */
55struct keyspan_serial_private {
56 const struct keyspan_device_details *device_details;
57
58 struct urb *instat_urb;
59 char instat_buf[INSTAT_BUFLEN];
60
Alan Coxdeb91682008-07-22 11:13:08 +010061 /* added to support 49wg, where data from all 4 ports comes in
62 on 1 EP and high-speed supported */
Lucy McCoy0ca12682007-05-18 12:10:41 -070063 struct urb *indat_urb;
64 char indat_buf[INDAT49W_BUFLEN];
65
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 /* XXX this one probably will need a lock */
67 struct urb *glocont_urb;
68 char glocont_buf[GLOCONT_BUFLEN];
Alan Coxdeb91682008-07-22 11:13:08 +010069 char ctrl_buf[8]; /* for EP0 control message */
Linus Torvalds1da177e2005-04-16 15:20:36 -070070};
71
72struct keyspan_port_private {
73 /* Keep track of which input & output endpoints to use */
74 int in_flip;
75 int out_flip;
76
77 /* Keep duplicate of device details in each port
78 structure as well - simplifies some of the
79 callback functions etc. */
80 const struct keyspan_device_details *device_details;
81
82 /* Input endpoints and buffer for this port */
83 struct urb *in_urbs[2];
84 char in_buffer[2][64];
85 /* Output endpoints and buffer for this port */
86 struct urb *out_urbs[2];
87 char out_buffer[2][64];
88
89 /* Input ack endpoint */
90 struct urb *inack_urb;
91 char inack_buffer[1];
92
93 /* Output control endpoint */
94 struct urb *outcont_urb;
95 char outcont_buffer[64];
96
97 /* Settings for the port */
98 int baud;
99 int old_baud;
100 unsigned int cflag;
101 unsigned int old_cflag;
102 enum {flow_none, flow_cts, flow_xon} flow_control;
103 int rts_state; /* Handshaking pins (outputs) */
104 int dtr_state;
105 int cts_state; /* Handshaking pins (inputs) */
106 int dsr_state;
107 int dcd_state;
108 int ri_state;
109 int break_on;
110
111 unsigned long tx_start_time[2];
112 int resend_cont; /* need to resend control packet */
113};
114
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115/* Include Keyspan message headers. All current Keyspan Adapters
Lucy McCoy0ca12682007-05-18 12:10:41 -0700116 make use of one of five message formats which are referred
Alan Coxdeb91682008-07-22 11:13:08 +0100117 to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and
118 within this driver. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119#include "keyspan_usa26msg.h"
120#include "keyspan_usa28msg.h"
121#include "keyspan_usa49msg.h"
122#include "keyspan_usa90msg.h"
Lucy McCoy0ca12682007-05-18 12:10:41 -0700123#include "keyspan_usa67msg.h"
Alan Coxdeb91682008-07-22 11:13:08 +0100124
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -0700126module_usb_serial_driver(serial_drivers, keyspan_ids_combined);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127
Alan Cox95da3102008-07-22 11:09:07 +0100128static void keyspan_break_ctl(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129{
Alan Cox95da3102008-07-22 11:09:07 +0100130 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 struct keyspan_port_private *p_priv;
132
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133 p_priv = usb_get_serial_port_data(port);
134
135 if (break_state == -1)
136 p_priv->break_on = 1;
137 else
138 p_priv->break_on = 0;
139
140 keyspan_send_setup(port, 0);
141}
142
143
Alan Coxdeb91682008-07-22 11:13:08 +0100144static void keyspan_set_termios(struct tty_struct *tty,
Alan Cox95da3102008-07-22 11:09:07 +0100145 struct usb_serial_port *port, struct ktermios *old_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146{
147 int baud_rate, device_port;
148 struct keyspan_port_private *p_priv;
149 const struct keyspan_device_details *d_details;
150 unsigned int cflag;
151
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 p_priv = usb_get_serial_port_data(port);
153 d_details = p_priv->device_details;
Alan Coxadc8d742012-07-14 15:31:47 +0100154 cflag = tty->termios.c_cflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 device_port = port->number - port->serial->minor;
156
157 /* Baud rate calculation takes baud rate as an integer
158 so other rates can be generated if desired. */
Alan Cox74240b02007-10-18 01:24:20 -0700159 baud_rate = tty_get_baud_rate(tty);
Alan Coxdeb91682008-07-22 11:13:08 +0100160 /* If no match or invalid, don't change */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700161 if (d_details->calculate_baud_rate(port, baud_rate, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
163 /* FIXME - more to do here to ensure rate changes cleanly */
Alan Cox74240b02007-10-18 01:24:20 -0700164 /* FIXME - calcuate exact rate from divisor ? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 p_priv->baud = baud_rate;
Alan Cox74240b02007-10-18 01:24:20 -0700166 } else
167 baud_rate = tty_termios_baud_rate(old_termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168
Alan Cox74240b02007-10-18 01:24:20 -0700169 tty_encode_baud_rate(tty, baud_rate, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 /* set CTS/RTS handshake etc. */
171 p_priv->cflag = cflag;
Ben Minerds2b982ab2012-07-12 00:10:16 +1000172 p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173
Alan Cox74240b02007-10-18 01:24:20 -0700174 /* Mark/Space not supported */
Alan Coxadc8d742012-07-14 15:31:47 +0100175 tty->termios.c_cflag &= ~CMSPAR;
Alan Cox74240b02007-10-18 01:24:20 -0700176
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 keyspan_send_setup(port, 0);
178}
179
Alan Cox60b33c12011-02-14 16:26:14 +0000180static int keyspan_tiocmget(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181{
Alan Cox95da3102008-07-22 11:09:07 +0100182 struct usb_serial_port *port = tty->driver_data;
183 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 unsigned int value;
Alan Coxdeb91682008-07-22 11:13:08 +0100185
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 value = ((p_priv->rts_state) ? TIOCM_RTS : 0) |
187 ((p_priv->dtr_state) ? TIOCM_DTR : 0) |
188 ((p_priv->cts_state) ? TIOCM_CTS : 0) |
189 ((p_priv->dsr_state) ? TIOCM_DSR : 0) |
190 ((p_priv->dcd_state) ? TIOCM_CAR : 0) |
Alan Coxdeb91682008-07-22 11:13:08 +0100191 ((p_priv->ri_state) ? TIOCM_RNG : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192
193 return value;
194}
195
Alan Cox20b9d172011-02-14 16:26:50 +0000196static int keyspan_tiocmset(struct tty_struct *tty,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 unsigned int set, unsigned int clear)
198{
Alan Cox95da3102008-07-22 11:09:07 +0100199 struct usb_serial_port *port = tty->driver_data;
200 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100201
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 if (set & TIOCM_RTS)
203 p_priv->rts_state = 1;
204 if (set & TIOCM_DTR)
205 p_priv->dtr_state = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 if (clear & TIOCM_RTS)
207 p_priv->rts_state = 0;
208 if (clear & TIOCM_DTR)
209 p_priv->dtr_state = 0;
210 keyspan_send_setup(port, 0);
211 return 0;
212}
213
Alan Cox95da3102008-07-22 11:09:07 +0100214/* Write function is similar for the four protocols used
215 with only a minor change for usa90 (usa19hs) required */
216static int keyspan_write(struct tty_struct *tty,
217 struct usb_serial_port *port, const unsigned char *buf, int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218{
219 struct keyspan_port_private *p_priv;
220 const struct keyspan_device_details *d_details;
221 int flip;
222 int left, todo;
223 struct urb *this_urb;
Alan Coxdeb91682008-07-22 11:13:08 +0100224 int err, maxDataLen, dataOffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225
226 p_priv = usb_get_serial_port_data(port);
227 d_details = p_priv->device_details;
228
229 if (d_details->msg_format == msg_usa90) {
Alan Coxdeb91682008-07-22 11:13:08 +0100230 maxDataLen = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 dataOffset = 0;
232 } else {
233 maxDataLen = 63;
234 dataOffset = 1;
235 }
Alan Coxdeb91682008-07-22 11:13:08 +0100236
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700237 dev_dbg(&port->dev, "%s - for port %d (%d chars), flip=%d\n",
238 __func__, port->number, count, p_priv->out_flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239
240 for (left = count; left > 0; left -= todo) {
241 todo = left;
242 if (todo > maxDataLen)
243 todo = maxDataLen;
244
245 flip = p_priv->out_flip;
Alan Coxdeb91682008-07-22 11:13:08 +0100246
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 /* Check we have a valid urb/endpoint before we use it... */
Alan Coxdeb91682008-07-22 11:13:08 +0100248 this_urb = p_priv->out_urbs[flip];
249 if (this_urb == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 /* no bulk out, so return 0 bytes written */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700251 dev_dbg(&port->dev, "%s - no output urb :(\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 return count;
253 }
254
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700255 dev_dbg(&port->dev, "%s - endpoint %d flip %d\n",
Alan Coxdeb91682008-07-22 11:13:08 +0100256 __func__, usb_pipeendpoint(this_urb->pipe), flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257
258 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +0100259 if (time_before(jiffies,
260 p_priv->tx_start_time[flip] + 10 * HZ))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 usb_unlink_urb(this_urb);
263 break;
264 }
265
Alan Coxdeb91682008-07-22 11:13:08 +0100266 /* First byte in buffer is "last flag" (except for usa19hx)
267 - unused so for now so set to zero */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 ((char *)this_urb->transfer_buffer)[0] = 0;
269
Alan Coxdeb91682008-07-22 11:13:08 +0100270 memcpy(this_urb->transfer_buffer + dataOffset, buf, todo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 buf += todo;
272
273 /* send the data out the bulk port */
274 this_urb->transfer_buffer_length = todo + dataOffset;
275
Alan Coxdeb91682008-07-22 11:13:08 +0100276 err = usb_submit_urb(this_urb, GFP_ATOMIC);
277 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700278 dev_dbg(&port->dev, "usb_submit_urb(write bulk) failed (%d)\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 p_priv->tx_start_time[flip] = jiffies;
280
281 /* Flip for next time if usa26 or usa28 interface
282 (not used on usa49) */
283 p_priv->out_flip = (flip + 1) & d_details->outdat_endp_flip;
284 }
285
286 return count - left;
287}
288
David Howells7d12e782006-10-05 14:55:46 +0100289static void usa26_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290{
291 int i, err;
292 int endpoint;
293 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700295 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 endpoint = usb_pipeendpoint(urb->pipe);
298
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700299 if (status) {
Stefan Hubnera8ffa0b2012-12-13 22:45:00 +0100300 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700301 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 return;
303 }
304
Ming Leicdc97792008-02-24 18:41:47 +0800305 port = urb->context;
Jiri Slaby2e124b42013-01-03 15:53:06 +0100306 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 /* 0x80 bit is error flag */
308 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100309 /* no errors on individual bytes, only
310 possible overrun err */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 if (data[0] & RXERROR_OVERRUN)
Alan Coxdeb91682008-07-22 11:13:08 +0100312 err = TTY_OVERRUN;
313 else
314 err = 0;
315 for (i = 1; i < urb->actual_length ; ++i)
Jiri Slaby92a19f92013-01-03 15:53:03 +0100316 tty_insert_flip_char(&port->port, data[i], err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 } else {
318 /* some bytes had errors, every byte has status */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700319 dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 for (i = 0; i + 1 < urb->actual_length; i += 2) {
321 int stat = data[i], flag = 0;
322 if (stat & RXERROR_OVERRUN)
323 flag |= TTY_OVERRUN;
324 if (stat & RXERROR_FRAMING)
325 flag |= TTY_FRAME;
326 if (stat & RXERROR_PARITY)
327 flag |= TTY_PARITY;
328 /* XXX should handle break (0x10) */
Jiri Slaby92a19f92013-01-03 15:53:03 +0100329 tty_insert_flip_char(&port->port, data[i+1],
330 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 }
332 }
Jiri Slaby2e124b42013-01-03 15:53:06 +0100333 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 }
Alan Coxdeb91682008-07-22 11:13:08 +0100335
336 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500337 err = usb_submit_urb(urb, GFP_ATOMIC);
338 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700339 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340}
341
Alan Coxdeb91682008-07-22 11:13:08 +0100342/* Outdat handling is common for all devices */
David Howells7d12e782006-10-05 14:55:46 +0100343static void usa2x_outdat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344{
345 struct usb_serial_port *port;
346 struct keyspan_port_private *p_priv;
347
Ming Leicdc97792008-02-24 18:41:47 +0800348 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 p_priv = usb_get_serial_port_data(port);
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700350 dev_dbg(&port->dev, "%s - urb %d\n", __func__, urb == p_priv->out_urbs[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351
Alan Stern1f871582010-02-17 10:05:47 -0500352 usb_serial_port_softint(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353}
354
David Howells7d12e782006-10-05 14:55:46 +0100355static void usa26_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357}
358
David Howells7d12e782006-10-05 14:55:46 +0100359static void usa26_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360{
361 struct usb_serial_port *port;
362 struct keyspan_port_private *p_priv;
363
Ming Leicdc97792008-02-24 18:41:47 +0800364 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 p_priv = usb_get_serial_port_data(port);
366
367 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700368 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100369 keyspan_usa26_send_setup(port->serial, port,
370 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 }
372}
373
David Howells7d12e782006-10-05 14:55:46 +0100374static void usa26_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375{
376 unsigned char *data = urb->transfer_buffer;
377 struct keyspan_usa26_portStatusMessage *msg;
378 struct usb_serial *serial;
379 struct usb_serial_port *port;
380 struct keyspan_port_private *p_priv;
Alan Cox4a90f092008-10-13 10:39:46 +0100381 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700383 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384
Ming Leicdc97792008-02-24 18:41:47 +0800385 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700387 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700388 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 return;
390 }
391 if (urb->actual_length != 9) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700392 dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 goto exit;
394 }
395
396 msg = (struct keyspan_usa26_portStatusMessage *)data;
397
398#if 0
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700399 dev_dbg(&urb->dev->dev,
400 "%s - port status: port %d cts %d dcd %d dsr %d ri %d toff %d txoff %d rxen %d cr %d",
401 __func__, msg->port, msg->hskia_cts, msg->gpia_dcd, msg->dsr,
402 msg->ri, msg->_txOff, msg->_txXoff, msg->rxEnabled,
403 msg->controlResponse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404#endif
405
406 /* Now do something useful with the data */
407
408
Alan Coxdeb91682008-07-22 11:13:08 +0100409 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700411 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 goto exit;
413 }
414 port = serial->port[msg->port];
415 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100416
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 /* Update handshaking pin state information */
418 old_dcd_state = p_priv->dcd_state;
419 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
420 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
421 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
422 p_priv->ri_state = ((msg->ri) ? 1 : 0);
423
Alan Cox4a90f092008-10-13 10:39:46 +0100424 if (old_dcd_state != p_priv->dcd_state) {
425 tty = tty_port_tty_get(&port->port);
426 if (tty && !C_CLOCAL(tty))
427 tty_hangup(tty);
428 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 }
Alan Coxdeb91682008-07-22 11:13:08 +0100430
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100432 err = usb_submit_urb(urb, GFP_ATOMIC);
433 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700434 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435exit: ;
436}
437
David Howells7d12e782006-10-05 14:55:46 +0100438static void usa26_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440}
441
442
David Howells7d12e782006-10-05 14:55:46 +0100443static void usa28_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444{
Alan Coxf035a8a2008-07-22 11:13:32 +0100445 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 unsigned char *data;
448 struct keyspan_port_private *p_priv;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700449 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450
Ming Leicdc97792008-02-24 18:41:47 +0800451 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 p_priv = usb_get_serial_port_data(port);
453 data = urb->transfer_buffer;
454
455 if (urb != p_priv->in_urbs[p_priv->in_flip])
456 return;
457
458 do {
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700459 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700460 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
461 __func__, status, usb_pipeendpoint(urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 return;
463 }
464
Ming Leicdc97792008-02-24 18:41:47 +0800465 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 p_priv = usb_get_serial_port_data(port);
467 data = urb->transfer_buffer;
468
Jiri Slaby2e124b42013-01-03 15:53:06 +0100469 if (urb->actual_length) {
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100470 tty_insert_flip_string(&port->port, data,
471 urb->actual_length);
Jiri Slaby2e124b42013-01-03 15:53:06 +0100472 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 }
474
475 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500476 err = usb_submit_urb(urb, GFP_ATOMIC);
477 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700478 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n",
Alan Stern1f871582010-02-17 10:05:47 -0500479 __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 p_priv->in_flip ^= 1;
481
482 urb = p_priv->in_urbs[p_priv->in_flip];
483 } while (urb->status != -EINPROGRESS);
484}
485
David Howells7d12e782006-10-05 14:55:46 +0100486static void usa28_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488}
489
David Howells7d12e782006-10-05 14:55:46 +0100490static void usa28_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491{
492 struct usb_serial_port *port;
493 struct keyspan_port_private *p_priv;
494
Ming Leicdc97792008-02-24 18:41:47 +0800495 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 p_priv = usb_get_serial_port_data(port);
497
498 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700499 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100500 keyspan_usa28_send_setup(port->serial, port,
501 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 }
503}
504
David Howells7d12e782006-10-05 14:55:46 +0100505static void usa28_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506{
507 int err;
508 unsigned char *data = urb->transfer_buffer;
509 struct keyspan_usa28_portStatusMessage *msg;
510 struct usb_serial *serial;
511 struct usb_serial_port *port;
512 struct keyspan_port_private *p_priv;
Alan Cox4a90f092008-10-13 10:39:46 +0100513 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700515 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516
Ming Leicdc97792008-02-24 18:41:47 +0800517 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700519 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700520 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 return;
522 }
523
524 if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700525 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 goto exit;
527 }
528
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700529 /*
530 dev_dbg(&urb->dev->dev,
Stefan Hubnera8ffa0b2012-12-13 22:45:00 +0100531 "%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__,
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700532 data[0], data[1], data[2], data[3], data[4], data[5],
533 data[6], data[7], data[8], data[9], data[10], data[11]);
534 */
Alan Coxdeb91682008-07-22 11:13:08 +0100535
536 /* Now do something useful with the data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 msg = (struct keyspan_usa28_portStatusMessage *)data;
538
Alan Coxdeb91682008-07-22 11:13:08 +0100539 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700541 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 goto exit;
543 }
544 port = serial->port[msg->port];
545 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100546
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 /* Update handshaking pin state information */
548 old_dcd_state = p_priv->dcd_state;
549 p_priv->cts_state = ((msg->cts) ? 1 : 0);
550 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
551 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
552 p_priv->ri_state = ((msg->ri) ? 1 : 0);
553
Ben Minerdsddc04ae2012-07-12 00:10:18 +1000554 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
Alan Cox4a90f092008-10-13 10:39:46 +0100555 tty = tty_port_tty_get(&port->port);
Ben Minerds878b5fd2012-07-12 00:10:19 +1000556 if (tty && !C_CLOCAL(tty))
Alan Cox4a90f092008-10-13 10:39:46 +0100557 tty_hangup(tty);
558 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 }
560
561 /* 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);
Alan Coxdeb91682008-07-22 11:13:08 +0100637
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 /* Update handshaking pin state information */
639 old_dcd_state = p_priv->dcd_state;
640 p_priv->cts_state = ((msg->cts) ? 1 : 0);
641 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
642 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
643 p_priv->ri_state = ((msg->ri) ? 1 : 0);
644
Alan Cox4a90f092008-10-13 10:39:46 +0100645 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
646 struct tty_struct *tty = tty_port_tty_get(&port->port);
647 if (tty && !C_CLOCAL(tty))
648 tty_hangup(tty);
649 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 }
651
Alan Coxdeb91682008-07-22 11:13:08 +0100652 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100653 err = usb_submit_urb(urb, GFP_ATOMIC);
654 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700655 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656exit: ;
657}
658
David Howells7d12e782006-10-05 14:55:46 +0100659static void usa49_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661}
662
David Howells7d12e782006-10-05 14:55:46 +0100663static void usa49_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664{
665 int i, err;
666 int endpoint;
667 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700669 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 endpoint = usb_pipeendpoint(urb->pipe);
672
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700673 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700674 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
675 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 return;
677 }
678
Ming Leicdc97792008-02-24 18:41:47 +0800679 port = urb->context;
Jiri Slaby2e124b42013-01-03 15:53:06 +0100680 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681 /* 0x80 bit is error flag */
682 if ((data[0] & 0x80) == 0) {
683 /* no error on any byte */
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100684 tty_insert_flip_string(&port->port, data + 1,
Alan Coxf035a8a2008-07-22 11:13:32 +0100685 urb->actual_length - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 } else {
687 /* some bytes had errors, every byte has status */
688 for (i = 0; i + 1 < urb->actual_length; i += 2) {
689 int stat = data[i], flag = 0;
690 if (stat & RXERROR_OVERRUN)
691 flag |= TTY_OVERRUN;
692 if (stat & RXERROR_FRAMING)
693 flag |= TTY_FRAME;
694 if (stat & RXERROR_PARITY)
695 flag |= TTY_PARITY;
696 /* XXX should handle break (0x10) */
Jiri Slaby92a19f92013-01-03 15:53:03 +0100697 tty_insert_flip_char(&port->port, data[i+1],
698 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 }
700 }
Jiri Slaby2e124b42013-01-03 15:53:06 +0100701 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 }
Alan Coxdeb91682008-07-22 11:13:08 +0100703
704 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500705 err = usb_submit_urb(urb, GFP_ATOMIC);
706 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700707 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708}
709
Lucy McCoy0ca12682007-05-18 12:10:41 -0700710static void usa49wg_indat_callback(struct urb *urb)
711{
712 int i, len, x, err;
713 struct usb_serial *serial;
714 struct usb_serial_port *port;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700715 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700716 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700717
Lucy McCoy0ca12682007-05-18 12:10:41 -0700718 serial = urb->context;
719
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700720 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700721 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700722 return;
723 }
724
725 /* inbound data is in the form P#, len, status, data */
726 i = 0;
727 len = 0;
728
729 if (urb->actual_length) {
730 while (i < urb->actual_length) {
731
732 /* Check port number from message*/
733 if (data[i] >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700734 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800735 __func__, data[i]);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700736 return;
737 }
738 port = serial->port[data[i++]];
Lucy McCoy0ca12682007-05-18 12:10:41 -0700739 len = data[i++];
740
741 /* 0x80 bit is error flag */
742 if ((data[i] & 0x80) == 0) {
743 /* no error on any byte */
744 i++;
745 for (x = 1; x < len ; ++x)
Jiri Slaby92a19f92013-01-03 15:53:03 +0100746 tty_insert_flip_char(&port->port,
747 data[i++], 0);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700748 } else {
749 /*
750 * some bytes had errors, every byte has status
751 */
752 for (x = 0; x + 1 < len; x += 2) {
753 int stat = data[i], flag = 0;
754 if (stat & RXERROR_OVERRUN)
755 flag |= TTY_OVERRUN;
756 if (stat & RXERROR_FRAMING)
757 flag |= TTY_FRAME;
758 if (stat & RXERROR_PARITY)
759 flag |= TTY_PARITY;
760 /* XXX should handle break (0x10) */
Jiri Slaby92a19f92013-01-03 15:53:03 +0100761 tty_insert_flip_char(&port->port,
Lucy McCoy0ca12682007-05-18 12:10:41 -0700762 data[i+1], flag);
763 i += 2;
764 }
765 }
Jiri Slaby2e124b42013-01-03 15:53:06 +0100766 tty_flip_buffer_push(&port->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700767 }
768 }
769
770 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700771 err = usb_submit_urb(urb, GFP_ATOMIC);
772 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700773 dev_dbg(&urb->dev->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700774}
775
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776/* not used, usa-49 doesn't have per-port control endpoints */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700777static void usa49_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779}
780
Lucy McCoy0ca12682007-05-18 12:10:41 -0700781static void usa90_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782{
783 int i, err;
784 int endpoint;
785 struct usb_serial_port *port;
786 struct keyspan_port_private *p_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700788 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 endpoint = usb_pipeendpoint(urb->pipe);
791
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700792 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700793 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800794 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 return;
796 }
797
Ming Leicdc97792008-02-24 18:41:47 +0800798 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 p_priv = usb_get_serial_port_data(port);
800
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 /* if current mode is DMA, looks like usa28 format
Alan Coxdeb91682008-07-22 11:13:08 +0100803 otherwise looks like usa26 data format */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804
Alan Coxf035a8a2008-07-22 11:13:32 +0100805 if (p_priv->baud > 57600)
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100806 tty_insert_flip_string(&port->port, data,
807 urb->actual_length);
Alan Coxf035a8a2008-07-22 11:13:32 +0100808 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 /* 0x80 bit is error flag */
810 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100811 /* no errors on individual bytes, only
812 possible overrun err*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 if (data[0] & RXERROR_OVERRUN)
Alan Coxdeb91682008-07-22 11:13:08 +0100814 err = TTY_OVERRUN;
815 else
816 err = 0;
817 for (i = 1; i < urb->actual_length ; ++i)
Jiri Slaby92a19f92013-01-03 15:53:03 +0100818 tty_insert_flip_char(&port->port,
819 data[i], err);
Alan Coxdeb91682008-07-22 11:13:08 +0100820 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 /* some bytes had errors, every byte has status */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700822 dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 for (i = 0; i + 1 < urb->actual_length; i += 2) {
824 int stat = data[i], flag = 0;
825 if (stat & RXERROR_OVERRUN)
826 flag |= TTY_OVERRUN;
827 if (stat & RXERROR_FRAMING)
828 flag |= TTY_FRAME;
829 if (stat & RXERROR_PARITY)
830 flag |= TTY_PARITY;
831 /* XXX should handle break (0x10) */
Jiri Slaby92a19f92013-01-03 15:53:03 +0100832 tty_insert_flip_char(&port->port,
833 data[i+1], flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 }
835 }
836 }
Jiri Slaby2e124b42013-01-03 15:53:06 +0100837 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 }
Alan Coxdeb91682008-07-22 11:13:08 +0100839
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500841 err = usb_submit_urb(urb, GFP_ATOMIC);
842 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700843 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844}
845
846
David Howells7d12e782006-10-05 14:55:46 +0100847static void usa90_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848{
849 unsigned char *data = urb->transfer_buffer;
850 struct keyspan_usa90_portStatusMessage *msg;
851 struct usb_serial *serial;
852 struct usb_serial_port *port;
853 struct keyspan_port_private *p_priv;
Alan Cox4a90f092008-10-13 10:39:46 +0100854 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700856 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857
Ming Leicdc97792008-02-24 18:41:47 +0800858 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700860 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700861 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 return;
863 }
864 if (urb->actual_length < 14) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700865 dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 goto exit;
867 }
868
869 msg = (struct keyspan_usa90_portStatusMessage *)data;
870
871 /* Now do something useful with the data */
872
873 port = serial->port[0];
874 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100875
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 /* Update handshaking pin state information */
877 old_dcd_state = p_priv->dcd_state;
878 p_priv->cts_state = ((msg->cts) ? 1 : 0);
879 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
880 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
881 p_priv->ri_state = ((msg->ri) ? 1 : 0);
882
Alan Cox4a90f092008-10-13 10:39:46 +0100883 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
884 tty = tty_port_tty_get(&port->port);
885 if (tty && !C_CLOCAL(tty))
886 tty_hangup(tty);
887 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 }
Alan Coxdeb91682008-07-22 11:13:08 +0100889
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100891 err = usb_submit_urb(urb, GFP_ATOMIC);
892 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700893 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894exit:
895 ;
896}
897
David Howells7d12e782006-10-05 14:55:46 +0100898static void usa90_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899{
900 struct usb_serial_port *port;
901 struct keyspan_port_private *p_priv;
902
Ming Leicdc97792008-02-24 18:41:47 +0800903 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 p_priv = usb_get_serial_port_data(port);
905
906 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700907 dev_dbg(&urb->dev->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100908 keyspan_usa90_send_setup(port->serial, port,
909 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 }
911}
912
Lucy McCoy0ca12682007-05-18 12:10:41 -0700913/* Status messages from the 28xg */
914static void usa67_instat_callback(struct urb *urb)
915{
916 int err;
917 unsigned char *data = urb->transfer_buffer;
918 struct keyspan_usa67_portStatusMessage *msg;
919 struct usb_serial *serial;
920 struct usb_serial_port *port;
921 struct keyspan_port_private *p_priv;
922 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700923 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700924
Lucy McCoy0ca12682007-05-18 12:10:41 -0700925 serial = urb->context;
926
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700927 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700928 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700929 return;
930 }
931
Alan Coxdeb91682008-07-22 11:13:08 +0100932 if (urb->actual_length !=
933 sizeof(struct keyspan_usa67_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700934 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700935 return;
936 }
937
938
939 /* Now do something useful with the data */
940 msg = (struct keyspan_usa67_portStatusMessage *)data;
941
942 /* Check port number from message and retrieve private data */
943 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700944 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700945 return;
946 }
947
948 port = serial->port[msg->port];
949 p_priv = usb_get_serial_port_data(port);
950
951 /* Update handshaking pin state information */
952 old_dcd_state = p_priv->dcd_state;
953 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
954 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
955
Alan Cox4a90f092008-10-13 10:39:46 +0100956 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
957 struct tty_struct *tty = tty_port_tty_get(&port->port);
958 if (tty && !C_CLOCAL(tty))
959 tty_hangup(tty);
960 tty_kref_put(tty);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700961 }
962
963 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700964 err = usb_submit_urb(urb, GFP_ATOMIC);
965 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700966 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700967}
968
969static void usa67_glocont_callback(struct urb *urb)
970{
971 struct usb_serial *serial;
972 struct usb_serial_port *port;
973 struct keyspan_port_private *p_priv;
974 int i;
975
Lucy McCoy0ca12682007-05-18 12:10:41 -0700976 serial = urb->context;
977 for (i = 0; i < serial->num_ports; ++i) {
978 port = serial->port[i];
979 p_priv = usb_get_serial_port_data(port);
980
981 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700982 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700983 keyspan_usa67_send_setup(serial, port,
984 p_priv->resend_cont - 1);
985 break;
986 }
987 }
988}
989
Alan Cox95da3102008-07-22 11:09:07 +0100990static int keyspan_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991{
Alan Cox95da3102008-07-22 11:09:07 +0100992 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 struct keyspan_port_private *p_priv;
994 const struct keyspan_device_details *d_details;
995 int flip;
996 int data_len;
997 struct urb *this_urb;
998
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 p_priv = usb_get_serial_port_data(port);
1000 d_details = p_priv->device_details;
1001
Alan Coxa5b6f602008-04-08 17:16:06 +01001002 /* FIXME: locking */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 if (d_details->msg_format == msg_usa90)
Alan Coxdeb91682008-07-22 11:13:08 +01001004 data_len = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 else
1006 data_len = 63;
1007
1008 flip = p_priv->out_flip;
1009
1010 /* Check both endpoints to see if any are available. */
Alan Coxdeb91682008-07-22 11:13:08 +01001011 this_urb = p_priv->out_urbs[flip];
1012 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001014 return data_len;
1015 flip = (flip + 1) & d_details->outdat_endp_flip;
1016 this_urb = p_priv->out_urbs[flip];
1017 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001019 return data_len;
1020 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 }
Alan Coxa5b6f602008-04-08 17:16:06 +01001022 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023}
1024
1025
Alan Coxa509a7e2009-09-19 13:13:26 -07001026static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027{
Andrew Mortonf78ba152007-11-28 16:21:54 -08001028 struct keyspan_port_private *p_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 const struct keyspan_device_details *d_details;
1030 int i, err;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001031 int baud_rate, device_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 struct urb *urb;
Alan Cox95da3102008-07-22 11:09:07 +01001033 unsigned int cflag = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 p_priv = usb_get_serial_port_data(port);
1036 d_details = p_priv->device_details;
Borislav Petkov7eea4362007-11-14 17:00:39 -08001037
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 /* Set some sane defaults */
1039 p_priv->rts_state = 1;
1040 p_priv->dtr_state = 1;
1041 p_priv->baud = 9600;
1042
1043 /* force baud and lcr to be set on open */
1044 p_priv->old_baud = 0;
1045 p_priv->old_cflag = 0;
1046
1047 p_priv->out_flip = 0;
1048 p_priv->in_flip = 0;
1049
1050 /* Reset low level data toggle and start reading from endpoints */
1051 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001052 urb = p_priv->in_urbs[i];
1053 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055
Alan Coxdeb91682008-07-22 11:13:08 +01001056 /* make sure endpoint data toggle is synchronized
1057 with the device */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 usb_clear_halt(urb->dev, urb->pipe);
Alan Coxdeb91682008-07-22 11:13:08 +01001059 err = usb_submit_urb(urb, GFP_KERNEL);
1060 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001061 dev_dbg(&port->dev, "%s - submit urb %d failed (%d)\n", __func__, i, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 }
1063
1064 /* Reset low level data toggle on out endpoints */
1065 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001066 urb = p_priv->out_urbs[i];
1067 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 continue;
Alan Coxdeb91682008-07-22 11:13:08 +01001069 /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
1070 usb_pipeout(urb->pipe), 0); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 }
1072
Andrew Mortonf78ba152007-11-28 16:21:54 -08001073 /* get the terminal config for the setup message now so we don't
1074 * need to send 2 of them */
1075
Andrew Mortonf78ba152007-11-28 16:21:54 -08001076 device_port = port->number - port->serial->minor;
Alan Cox95da3102008-07-22 11:09:07 +01001077 if (tty) {
Alan Coxadc8d742012-07-14 15:31:47 +01001078 cflag = tty->termios.c_cflag;
Alan Cox95da3102008-07-22 11:09:07 +01001079 /* Baud rate calculation takes baud rate as an integer
1080 so other rates can be generated if desired. */
1081 baud_rate = tty_get_baud_rate(tty);
1082 /* If no match or invalid, leave as default */
1083 if (baud_rate >= 0
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001084 && d_details->calculate_baud_rate(port, baud_rate, d_details->baudclk,
Alan Cox95da3102008-07-22 11:09:07 +01001085 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
1086 p_priv->baud = baud_rate;
1087 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001088 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001089 /* set CTS/RTS handshake etc. */
1090 p_priv->cflag = cflag;
Ben Minerds2b982ab2012-07-12 00:10:16 +10001091 p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001092
1093 keyspan_send_setup(port, 1);
Alan Coxdeb91682008-07-22 11:13:08 +01001094 /* mdelay(100); */
1095 /* keyspan_set_termios(port, NULL); */
Andrew Mortonf78ba152007-11-28 16:21:54 -08001096
Alan Coxa5b6f602008-04-08 17:16:06 +01001097 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098}
1099
1100static inline void stop_urb(struct urb *urb)
1101{
Greg Kroah-Hartman242cf672005-07-29 16:11:07 -04001102 if (urb && urb->status == -EINPROGRESS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 usb_kill_urb(urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104}
1105
Alan Cox335f8512009-06-11 12:26:29 +01001106static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
1107{
1108 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
1109
1110 p_priv->rts_state = on;
1111 p_priv->dtr_state = on;
1112 keyspan_send_setup(port, 0);
1113}
1114
1115static void keyspan_close(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116{
1117 int i;
1118 struct usb_serial *serial = port->serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 struct keyspan_port_private *p_priv;
1120
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +01001122
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 p_priv->rts_state = 0;
1124 p_priv->dtr_state = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001125
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 if (serial->dev) {
1127 keyspan_send_setup(port, 2);
1128 /* pilot-xfer seems to work best with this delay */
1129 mdelay(100);
Alan Coxdeb91682008-07-22 11:13:08 +01001130 /* keyspan_set_termios(port, NULL); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 }
1132
1133 /*while (p_priv->outcont_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001134 dev_dbg(&port->dev, "%s - urb in progress\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 }*/
1136
1137 p_priv->out_flip = 0;
1138 p_priv->in_flip = 0;
1139
1140 if (serial->dev) {
1141 /* Stop reading/writing urbs */
1142 stop_urb(p_priv->inack_urb);
1143 /* stop_urb(p_priv->outcont_urb); */
1144 for (i = 0; i < 2; i++) {
1145 stop_urb(p_priv->in_urbs[i]);
1146 stop_urb(p_priv->out_urbs[i]);
1147 }
1148 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149}
1150
Alan Coxdeb91682008-07-22 11:13:08 +01001151/* download the firmware to a pre-renumeration device */
1152static int keyspan_fake_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153{
Rene Buergel8d733e22012-09-18 09:02:01 +02001154 char *fw_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001156 dev_dbg(&serial->dev->dev, "Keyspan startup version %04x product %04x\n",
1157 le16_to_cpu(serial->dev->descriptor.bcdDevice),
1158 le16_to_cpu(serial->dev->descriptor.idProduct));
Alan Coxdeb91682008-07-22 11:13:08 +01001159
1160 if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000)
1161 != 0x8000) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001162 dev_dbg(&serial->dev->dev, "Firmware already loaded. Quitting.\n");
Alan Coxdeb91682008-07-22 11:13:08 +01001163 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 }
1165
1166 /* Select firmware image on the basis of idProduct */
1167 switch (le16_to_cpu(serial->dev->descriptor.idProduct)) {
1168 case keyspan_usa28_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001169 fw_name = "keyspan/usa28.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 break;
1171
1172 case keyspan_usa28x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001173 fw_name = "keyspan/usa28x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 break;
1175
1176 case keyspan_usa28xa_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001177 fw_name = "keyspan/usa28xa.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 break;
1179
1180 case keyspan_usa28xb_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001181 fw_name = "keyspan/usa28xb.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 break;
1183
1184 case keyspan_usa19_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001185 fw_name = "keyspan/usa19.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_usa19qi_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001189 fw_name = "keyspan/usa19qi.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001191
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 case keyspan_mpr_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001193 fw_name = "keyspan/mpr.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 break;
1195
1196 case keyspan_usa19qw_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001197 fw_name = "keyspan/usa19qw.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_usa18x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001201 fw_name = "keyspan/usa18x.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_usa19w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001205 fw_name = "keyspan/usa19w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001207
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 case keyspan_usa49w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001209 fw_name = "keyspan/usa49w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 break;
1211
1212 case keyspan_usa49wlc_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001213 fw_name = "keyspan/usa49wlc.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 break;
1215
1216 default:
David Woodhouse2971c572008-05-30 14:04:03 +03001217 dev_err(&serial->dev->dev, "Unknown product ID (%04x)\n",
1218 le16_to_cpu(serial->dev->descriptor.idProduct));
1219 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 }
1221
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001222 dev_dbg(&serial->dev->dev, "Uploading Keyspan %s firmware.\n", fw_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223
Rene Buergel8d733e22012-09-18 09:02:01 +02001224 if (ezusb_fx1_ihex_firmware_download(serial->dev, fw_name) < 0) {
1225 dev_err(&serial->dev->dev, "failed to load firmware \"%s\"\n",
1226 fw_name);
1227 return -ENOENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 }
1229
Rene Buergel8d733e22012-09-18 09:02:01 +02001230 /* after downloading firmware Renumeration will occur in a
1231 moment and the new device will bind to the real driver */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232
1233 /* we don't want this device to have a driver assigned to it. */
Alan Coxdeb91682008-07-22 11:13:08 +01001234 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235}
1236
1237/* Helper functions used by keyspan_setup_urbs */
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001238static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *serial,
1239 int endpoint)
1240{
1241 struct usb_host_interface *iface_desc;
1242 struct usb_endpoint_descriptor *ep;
1243 int i;
1244
1245 iface_desc = serial->interface->cur_altsetting;
1246 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1247 ep = &iface_desc->endpoint[i].desc;
1248 if (ep->bEndpointAddress == endpoint)
1249 return ep;
1250 }
1251 dev_warn(&serial->interface->dev, "found no endpoint descriptor for "
1252 "endpoint %x\n", endpoint);
1253 return NULL;
1254}
1255
Alan Coxdeb91682008-07-22 11:13:08 +01001256static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 int dir, void *ctx, char *buf, int len,
David Howells7d12e782006-10-05 14:55:46 +01001258 void (*callback)(struct urb *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259{
1260 struct urb *urb;
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001261 struct usb_endpoint_descriptor const *ep_desc;
1262 char const *ep_type_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263
1264 if (endpoint == -1)
1265 return NULL; /* endpoint not needed */
1266
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001267 dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %d.\n", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
1269 if (urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001270 dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %d failed.\n", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 return NULL;
1272 }
1273
Lucy McCoy0ca12682007-05-18 12:10:41 -07001274 if (endpoint == 0) {
1275 /* control EP filled in when used */
1276 return urb;
1277 }
1278
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001279 ep_desc = find_ep(serial, endpoint);
1280 if (!ep_desc) {
1281 /* leak the urb, something's wrong and the callers don't care */
1282 return urb;
1283 }
1284 if (usb_endpoint_xfer_int(ep_desc)) {
1285 ep_type_name = "INT";
1286 usb_fill_int_urb(urb, serial->dev,
1287 usb_sndintpipe(serial->dev, endpoint) | dir,
1288 buf, len, callback, ctx,
1289 ep_desc->bInterval);
1290 } else if (usb_endpoint_xfer_bulk(ep_desc)) {
1291 ep_type_name = "BULK";
1292 usb_fill_bulk_urb(urb, serial->dev,
1293 usb_sndbulkpipe(serial->dev, endpoint) | dir,
1294 buf, len, callback, ctx);
1295 } else {
1296 dev_warn(&serial->interface->dev,
1297 "unsupported endpoint type %x\n",
Julia Lawall2e0fe702008-12-29 11:22:14 +01001298 usb_endpoint_type(ep_desc));
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001299 usb_free_urb(urb);
1300 return NULL;
1301 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001303 dev_dbg(&serial->interface->dev, "%s - using urb %p for %s endpoint %x\n",
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001304 __func__, urb, ep_type_name, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305 return urb;
1306}
1307
1308static struct callbacks {
David Howells7d12e782006-10-05 14:55:46 +01001309 void (*instat_callback)(struct urb *);
1310 void (*glocont_callback)(struct urb *);
1311 void (*indat_callback)(struct urb *);
1312 void (*outdat_callback)(struct urb *);
1313 void (*inack_callback)(struct urb *);
1314 void (*outcont_callback)(struct urb *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315} keyspan_callbacks[] = {
1316 {
1317 /* msg_usa26 callbacks */
1318 .instat_callback = usa26_instat_callback,
1319 .glocont_callback = usa26_glocont_callback,
1320 .indat_callback = usa26_indat_callback,
1321 .outdat_callback = usa2x_outdat_callback,
1322 .inack_callback = usa26_inack_callback,
1323 .outcont_callback = usa26_outcont_callback,
1324 }, {
1325 /* msg_usa28 callbacks */
1326 .instat_callback = usa28_instat_callback,
1327 .glocont_callback = usa28_glocont_callback,
1328 .indat_callback = usa28_indat_callback,
1329 .outdat_callback = usa2x_outdat_callback,
1330 .inack_callback = usa28_inack_callback,
1331 .outcont_callback = usa28_outcont_callback,
1332 }, {
1333 /* msg_usa49 callbacks */
1334 .instat_callback = usa49_instat_callback,
1335 .glocont_callback = usa49_glocont_callback,
1336 .indat_callback = usa49_indat_callback,
1337 .outdat_callback = usa2x_outdat_callback,
1338 .inack_callback = usa49_inack_callback,
1339 .outcont_callback = usa49_outcont_callback,
1340 }, {
1341 /* msg_usa90 callbacks */
1342 .instat_callback = usa90_instat_callback,
Alan Coxdeb91682008-07-22 11:13:08 +01001343 .glocont_callback = usa28_glocont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344 .indat_callback = usa90_indat_callback,
1345 .outdat_callback = usa2x_outdat_callback,
1346 .inack_callback = usa28_inack_callback,
1347 .outcont_callback = usa90_outcont_callback,
Lucy McCoy0ca12682007-05-18 12:10:41 -07001348 }, {
1349 /* msg_usa67 callbacks */
1350 .instat_callback = usa67_instat_callback,
1351 .glocont_callback = usa67_glocont_callback,
1352 .indat_callback = usa26_indat_callback,
1353 .outdat_callback = usa2x_outdat_callback,
1354 .inack_callback = usa26_inack_callback,
1355 .outcont_callback = usa26_outcont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 }
1357};
1358
1359 /* Generic setup urbs function that uses
1360 data in device_details */
1361static void keyspan_setup_urbs(struct usb_serial *serial)
1362{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 struct keyspan_serial_private *s_priv;
1364 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 struct callbacks *cback;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 s_priv = usb_get_serial_data(serial);
1368 d_details = s_priv->device_details;
1369
Alan Coxdeb91682008-07-22 11:13:08 +01001370 /* Setup values for the various callback routines */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 cback = &keyspan_callbacks[d_details->msg_format];
1372
Alan Coxdeb91682008-07-22 11:13:08 +01001373 /* Allocate and set up urbs for each one that is in use,
1374 starting with instat endpoints */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 s_priv->instat_urb = keyspan_setup_urb
1376 (serial, d_details->instat_endpoint, USB_DIR_IN,
1377 serial, s_priv->instat_buf, INSTAT_BUFLEN,
1378 cback->instat_callback);
1379
Lucy McCoy0ca12682007-05-18 12:10:41 -07001380 s_priv->indat_urb = keyspan_setup_urb
1381 (serial, d_details->indat_endpoint, USB_DIR_IN,
1382 serial, s_priv->indat_buf, INDAT49W_BUFLEN,
1383 usa49wg_indat_callback);
1384
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 s_priv->glocont_urb = keyspan_setup_urb
1386 (serial, d_details->glocont_endpoint, USB_DIR_OUT,
1387 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
1388 cback->glocont_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389}
1390
1391/* usa19 function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001392static int keyspan_usa19_calc_baud(struct usb_serial_port *port,
1393 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 u8 *rate_low, u8 *prescaler, int portnum)
1395{
1396 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001397 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398 cnt; /* inverse of divisor (programmed into 8051) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001400 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401
Alan Coxdeb91682008-07-22 11:13:08 +01001402 /* prevent divide by zero... */
1403 b16 = baud_rate * 16L;
1404 if (b16 == 0)
1405 return KEYSPAN_INVALID_BAUD_RATE;
1406 /* Any "standard" rate over 57k6 is marginal on the USA-19
1407 as we run out of divisor resolution. */
1408 if (baud_rate > 57600)
1409 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410
Alan Coxdeb91682008-07-22 11:13:08 +01001411 /* calculate the divisor and the counter (its inverse) */
1412 div = baudclk / b16;
1413 if (div == 0)
1414 return KEYSPAN_INVALID_BAUD_RATE;
1415 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417
Alan Coxdeb91682008-07-22 11:13:08 +01001418 if (div > 0xffff)
1419 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420
Alan Coxdeb91682008-07-22 11:13:08 +01001421 /* return the counter values if non-null */
1422 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001424 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001426 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001427 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001428 __func__, baud_rate, *rate_hi, *rate_low);
1429 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430}
1431
1432/* usa19hs function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001433static int keyspan_usa19hs_calc_baud(struct usb_serial_port *port,
1434 u32 baud_rate, u32 baudclk, u8 *rate_hi,
1435 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436{
1437 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001438 div; /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001440 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441
Alan Coxdeb91682008-07-22 11:13:08 +01001442 /* prevent divide by zero... */
1443 b16 = baud_rate * 16L;
1444 if (b16 == 0)
1445 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446
Alan Coxdeb91682008-07-22 11:13:08 +01001447 /* calculate the divisor */
1448 div = baudclk / b16;
1449 if (div == 0)
1450 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451
Alan Coxdeb91682008-07-22 11:13:08 +01001452 if (div > 0xffff)
1453 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454
Alan Coxdeb91682008-07-22 11:13:08 +01001455 /* return the counter values if non-null */
1456 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001458
1459 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460 *rate_hi = (u8) ((div >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001461
1462 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001463 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001464 __func__, baud_rate, *rate_hi, *rate_low);
1465
1466 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467}
1468
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001469static int keyspan_usa19w_calc_baud(struct usb_serial_port *port,
1470 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 u8 *rate_low, u8 *prescaler, int portnum)
1472{
1473 u32 b16, /* baud rate times 16 (actual rate used internally) */
1474 clk, /* clock with 13/8 prescaler */
Alan Coxdeb91682008-07-22 11:13:08 +01001475 div, /* divisor using 13/8 prescaler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476 res, /* resulting baud rate using 13/8 prescaler */
1477 diff, /* error using 13/8 prescaler */
1478 smallest_diff;
1479 u8 best_prescaler;
1480 int i;
1481
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001482 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483
Alan Coxdeb91682008-07-22 11:13:08 +01001484 /* prevent divide by zero */
1485 b16 = baud_rate * 16L;
1486 if (b16 == 0)
1487 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488
Alan Coxdeb91682008-07-22 11:13:08 +01001489 /* Calculate prescaler by trying them all and looking
1490 for best fit */
1491
1492 /* start with largest possible difference */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 smallest_diff = 0xffffffff;
1494
1495 /* 0 is an invalid prescaler, used as a flag */
1496 best_prescaler = 0;
1497
Alan Coxdeb91682008-07-22 11:13:08 +01001498 for (i = 8; i <= 0xff; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499 clk = (baudclk * 8) / (u32) i;
Alan Coxdeb91682008-07-22 11:13:08 +01001500
1501 div = clk / b16;
1502 if (div == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504
1505 res = clk / div;
Alan Coxdeb91682008-07-22 11:13:08 +01001506 diff = (res > b16) ? (res-b16) : (b16-res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507
Alan Coxdeb91682008-07-22 11:13:08 +01001508 if (diff < smallest_diff) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509 best_prescaler = i;
1510 smallest_diff = diff;
1511 }
1512 }
1513
Alan Coxdeb91682008-07-22 11:13:08 +01001514 if (best_prescaler == 0)
1515 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516
1517 clk = (baudclk * 8) / (u32) best_prescaler;
1518 div = clk / b16;
1519
Alan Coxdeb91682008-07-22 11:13:08 +01001520 /* return the divisor and prescaler if non-null */
1521 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001523 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 *rate_hi = (u8) ((div >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525 if (prescaler) {
1526 *prescaler = best_prescaler;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001527 /* dev_dbg(&port->dev, "%s - %d %d\n", __func__, *prescaler, div); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 }
Alan Coxdeb91682008-07-22 11:13:08 +01001529 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530}
1531
1532 /* USA-28 supports different maximum baud rates on each port */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001533static int keyspan_usa28_calc_baud(struct usb_serial_port *port,
1534 u32 baud_rate, u32 baudclk, u8 *rate_hi,
1535 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536{
1537 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001538 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 cnt; /* inverse of divisor (programmed into 8051) */
1540
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001541 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542
1543 /* prevent divide by zero */
Alan Coxdeb91682008-07-22 11:13:08 +01001544 b16 = baud_rate * 16L;
1545 if (b16 == 0)
1546 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547
Alan Coxdeb91682008-07-22 11:13:08 +01001548 /* calculate the divisor and the counter (its inverse) */
1549 div = KEYSPAN_USA28_BAUDCLK / b16;
1550 if (div == 0)
1551 return KEYSPAN_INVALID_BAUD_RATE;
1552 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554
Alan Coxdeb91682008-07-22 11:13:08 +01001555 /* check for out of range, based on portnum,
1556 and return result */
1557 if (portnum == 0) {
1558 if (div > 0xffff)
1559 return KEYSPAN_INVALID_BAUD_RATE;
1560 } else {
1561 if (portnum == 1) {
1562 if (div > 0xff)
1563 return KEYSPAN_INVALID_BAUD_RATE;
1564 } else
1565 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 }
1567
1568 /* return the counter values if not NULL
1569 (port 1 will ignore retHi) */
Alan Coxdeb91682008-07-22 11:13:08 +01001570 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001572 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001574 dev_dbg(&port->dev, "%s - %d OK.\n", __func__, baud_rate);
Alan Coxdeb91682008-07-22 11:13:08 +01001575 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576}
1577
1578static int keyspan_usa26_send_setup(struct usb_serial *serial,
1579 struct usb_serial_port *port,
1580 int reset_port)
1581{
Alan Coxdeb91682008-07-22 11:13:08 +01001582 struct keyspan_usa26_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583 struct keyspan_serial_private *s_priv;
1584 struct keyspan_port_private *p_priv;
1585 const struct keyspan_device_details *d_details;
1586 int outcont_urb;
1587 struct urb *this_urb;
1588 int device_port, err;
1589
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001590 dev_dbg(&port->dev, "%s reset=%d\n", __func__, reset_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591
1592 s_priv = usb_get_serial_data(serial);
1593 p_priv = usb_get_serial_port_data(port);
1594 d_details = s_priv->device_details;
1595 device_port = port->number - port->serial->minor;
1596
1597 outcont_urb = d_details->outcont_endpoints[port->number];
1598 this_urb = p_priv->outcont_urb;
1599
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001600 dev_dbg(&port->dev, "%s - endpoint %d\n", __func__, usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601
1602 /* Make sure we have an urb then send the message */
1603 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001604 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 return -1;
1606 }
1607
1608 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001609 Don't overwrite resend for open/close condition. */
1610 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611 p_priv->resend_cont = reset_port + 1;
1612 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001613 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001615 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616 }
1617
Alan Coxdeb91682008-07-22 11:13:08 +01001618 memset(&msg, 0, sizeof(struct keyspan_usa26_portControlMessage));
1619
1620 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621 if (p_priv->old_baud != p_priv->baud) {
1622 p_priv->old_baud = p_priv->baud;
1623 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001624 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1625 &msg.baudHi, &msg.baudLo, &msg.prescaler,
1626 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1627 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
1628 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 msg.baudLo = 0;
1630 msg.baudHi = 125; /* Values for 9600 baud */
1631 msg.prescaler = 10;
1632 }
1633 msg.setPrescaler = 0xff;
1634 }
1635
Ben Minerds2b982ab2012-07-12 00:10:16 +10001636 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 switch (p_priv->cflag & CSIZE) {
1638 case CS5:
1639 msg.lcr |= USA_DATABITS_5;
1640 break;
1641 case CS6:
1642 msg.lcr |= USA_DATABITS_6;
1643 break;
1644 case CS7:
1645 msg.lcr |= USA_DATABITS_7;
1646 break;
1647 case CS8:
1648 msg.lcr |= USA_DATABITS_8;
1649 break;
1650 }
1651 if (p_priv->cflag & PARENB) {
1652 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10001653 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01001654 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 }
1656 msg.setLcr = 0xff;
1657
1658 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1659 msg.xonFlowControl = 0;
1660 msg.setFlowControl = 0xff;
1661 msg.forwardingLength = 16;
1662 msg.xonChar = 17;
1663 msg.xoffChar = 19;
1664
1665 /* Opening port */
1666 if (reset_port == 1) {
1667 msg._txOn = 1;
1668 msg._txOff = 0;
1669 msg.txFlush = 0;
1670 msg.txBreak = 0;
1671 msg.rxOn = 1;
1672 msg.rxOff = 0;
1673 msg.rxFlush = 1;
1674 msg.rxForward = 0;
1675 msg.returnStatus = 0;
1676 msg.resetDataToggle = 0xff;
1677 }
1678
1679 /* Closing port */
1680 else if (reset_port == 2) {
1681 msg._txOn = 0;
1682 msg._txOff = 1;
1683 msg.txFlush = 0;
1684 msg.txBreak = 0;
1685 msg.rxOn = 0;
1686 msg.rxOff = 1;
1687 msg.rxFlush = 1;
1688 msg.rxForward = 0;
1689 msg.returnStatus = 0;
1690 msg.resetDataToggle = 0;
1691 }
1692
1693 /* Sending intermediate configs */
1694 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001695 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 msg._txOff = 0;
1697 msg.txFlush = 0;
1698 msg.txBreak = (p_priv->break_on);
1699 msg.rxOn = 0;
1700 msg.rxOff = 0;
1701 msg.rxFlush = 0;
1702 msg.rxForward = 0;
1703 msg.returnStatus = 0;
1704 msg.resetDataToggle = 0x0;
1705 }
1706
Alan Coxdeb91682008-07-22 11:13:08 +01001707 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 msg.setTxTriState_setRts = 0xff;
1709 msg.txTriState_rts = p_priv->rts_state;
1710
1711 msg.setHskoa_setDtr = 0xff;
1712 msg.hskoa_dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01001713
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001715 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
1716
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 /* send the data out the device on control endpoint */
1718 this_urb->transfer_buffer_length = sizeof(msg);
1719
Alan Coxdeb91682008-07-22 11:13:08 +01001720 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1721 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001722 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723#if 0
1724 else {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001725 dev_dbg(&port->dev, "%s - usb_submit_urb(%d) OK %d bytes (end %d)\n", __func__
1726 outcont_urb, this_urb->transfer_buffer_length,
1727 usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 }
1729#endif
1730
Alan Coxa5b6f602008-04-08 17:16:06 +01001731 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732}
1733
1734static int keyspan_usa28_send_setup(struct usb_serial *serial,
1735 struct usb_serial_port *port,
1736 int reset_port)
1737{
Alan Coxdeb91682008-07-22 11:13:08 +01001738 struct keyspan_usa28_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 struct keyspan_serial_private *s_priv;
1740 struct keyspan_port_private *p_priv;
1741 const struct keyspan_device_details *d_details;
1742 struct urb *this_urb;
1743 int device_port, err;
1744
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745 s_priv = usb_get_serial_data(serial);
1746 p_priv = usb_get_serial_port_data(port);
1747 d_details = s_priv->device_details;
1748 device_port = port->number - port->serial->minor;
1749
1750 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01001751 this_urb = p_priv->outcont_urb;
1752 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001753 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 return -1;
1755 }
1756
1757 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001758 Don't overwrite resend for open/close condition. */
1759 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760 p_priv->resend_cont = reset_port + 1;
1761 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001762 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001764 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765 }
1766
Alan Coxdeb91682008-07-22 11:13:08 +01001767 memset(&msg, 0, sizeof(struct keyspan_usa28_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768
1769 msg.setBaudRate = 1;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001770 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1771 &msg.baudHi, &msg.baudLo, NULL,
1772 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1773 dev_dbg(&port->dev, "%s - Invalid baud rate requested %d.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001774 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775 msg.baudLo = 0xff;
1776 msg.baudHi = 0xb2; /* Values for 9600 baud */
1777 }
1778
1779 /* If parity is enabled, we must calculate it ourselves. */
1780 msg.parity = 0; /* XXX for now */
1781
1782 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1783 msg.xonFlowControl = 0;
1784
Alan Coxdeb91682008-07-22 11:13:08 +01001785 /* Do handshaking outputs, DTR is inverted relative to RTS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786 msg.rts = p_priv->rts_state;
1787 msg.dtr = p_priv->dtr_state;
1788
1789 msg.forwardingLength = 16;
1790 msg.forwardMs = 10;
1791 msg.breakThreshold = 45;
1792 msg.xonChar = 17;
1793 msg.xoffChar = 19;
1794
1795 /*msg.returnStatus = 1;
1796 msg.resetDataToggle = 0xff;*/
1797 /* Opening port */
1798 if (reset_port == 1) {
1799 msg._txOn = 1;
1800 msg._txOff = 0;
1801 msg.txFlush = 0;
1802 msg.txForceXoff = 0;
1803 msg.txBreak = 0;
1804 msg.rxOn = 1;
1805 msg.rxOff = 0;
1806 msg.rxFlush = 1;
1807 msg.rxForward = 0;
1808 msg.returnStatus = 0;
1809 msg.resetDataToggle = 0xff;
1810 }
1811 /* Closing port */
1812 else if (reset_port == 2) {
1813 msg._txOn = 0;
1814 msg._txOff = 1;
1815 msg.txFlush = 0;
1816 msg.txForceXoff = 0;
1817 msg.txBreak = 0;
1818 msg.rxOn = 0;
1819 msg.rxOff = 1;
1820 msg.rxFlush = 1;
1821 msg.rxForward = 0;
1822 msg.returnStatus = 0;
1823 msg.resetDataToggle = 0;
1824 }
1825 /* Sending intermediate configs */
1826 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001827 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828 msg._txOff = 0;
1829 msg.txFlush = 0;
1830 msg.txForceXoff = 0;
1831 msg.txBreak = (p_priv->break_on);
1832 msg.rxOn = 0;
1833 msg.rxOff = 0;
1834 msg.rxFlush = 0;
1835 msg.rxForward = 0;
1836 msg.returnStatus = 0;
1837 msg.resetDataToggle = 0x0;
1838 }
1839
1840 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001841 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842
1843 /* send the data out the device on control endpoint */
1844 this_urb->transfer_buffer_length = sizeof(msg);
1845
Alan Coxdeb91682008-07-22 11:13:08 +01001846 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1847 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001848 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849#if 0
1850 else {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001851 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) OK %d bytes\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 this_urb->transfer_buffer_length);
1853 }
1854#endif
1855
Alan Coxa5b6f602008-04-08 17:16:06 +01001856 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857}
1858
1859static int keyspan_usa49_send_setup(struct usb_serial *serial,
1860 struct usb_serial_port *port,
1861 int reset_port)
1862{
Lucy McCoy0ca12682007-05-18 12:10:41 -07001863 struct keyspan_usa49_portControlMessage msg;
1864 struct usb_ctrlrequest *dr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865 struct keyspan_serial_private *s_priv;
1866 struct keyspan_port_private *p_priv;
1867 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868 struct urb *this_urb;
1869 int err, device_port;
1870
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871 s_priv = usb_get_serial_data(serial);
1872 p_priv = usb_get_serial_port_data(port);
1873 d_details = s_priv->device_details;
1874
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875 this_urb = s_priv->glocont_urb;
1876
Lucy McCoy0ca12682007-05-18 12:10:41 -07001877 /* Work out which port within the device is being setup */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878 device_port = port->number - port->serial->minor;
1879
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05301880 /* Make sure we have an urb then send the message */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001882 dev_dbg(&port->dev, "%s - oops no urb for port %d.\n", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883 return -1;
1884 }
1885
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001886 dev_dbg(&port->dev, "%s - endpoint %d port %d (%d)\n",
1887 __func__, usb_pipeendpoint(this_urb->pipe),
1888 port->number, device_port);
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05301889
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001891 Don't overwrite resend for open/close condition. */
1892 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 p_priv->resend_cont = reset_port + 1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001894
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001896 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001898 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899 }
1900
Alan Coxdeb91682008-07-22 11:13:08 +01001901 memset(&msg, 0, sizeof(struct keyspan_usa49_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902
1903 /*msg.portNumber = port->number;*/
1904 msg.portNumber = device_port;
Alan Coxdeb91682008-07-22 11:13:08 +01001905
1906 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907 if (p_priv->old_baud != p_priv->baud) {
1908 p_priv->old_baud = p_priv->baud;
1909 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001910 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1911 &msg.baudHi, &msg.baudLo, &msg.prescaler,
1912 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1913 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
1914 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915 msg.baudLo = 0;
1916 msg.baudHi = 125; /* Values for 9600 baud */
1917 msg.prescaler = 10;
1918 }
Alan Coxdeb91682008-07-22 11:13:08 +01001919 /* msg.setPrescaler = 0xff; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920 }
1921
Ben Minerds2b982ab2012-07-12 00:10:16 +10001922 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 switch (p_priv->cflag & CSIZE) {
1924 case CS5:
1925 msg.lcr |= USA_DATABITS_5;
1926 break;
1927 case CS6:
1928 msg.lcr |= USA_DATABITS_6;
1929 break;
1930 case CS7:
1931 msg.lcr |= USA_DATABITS_7;
1932 break;
1933 case CS8:
1934 msg.lcr |= USA_DATABITS_8;
1935 break;
1936 }
1937 if (p_priv->cflag & PARENB) {
1938 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10001939 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01001940 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941 }
1942 msg.setLcr = 0xff;
1943
1944 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1945 msg.xonFlowControl = 0;
1946 msg.setFlowControl = 0xff;
Alan Coxdeb91682008-07-22 11:13:08 +01001947
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948 msg.forwardingLength = 16;
1949 msg.xonChar = 17;
1950 msg.xoffChar = 19;
1951
Alan Coxdeb91682008-07-22 11:13:08 +01001952 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953 if (reset_port == 1) {
1954 msg._txOn = 1;
1955 msg._txOff = 0;
1956 msg.txFlush = 0;
1957 msg.txBreak = 0;
1958 msg.rxOn = 1;
1959 msg.rxOff = 0;
1960 msg.rxFlush = 1;
1961 msg.rxForward = 0;
1962 msg.returnStatus = 0;
1963 msg.resetDataToggle = 0xff;
1964 msg.enablePort = 1;
1965 msg.disablePort = 0;
1966 }
1967 /* Closing port */
1968 else if (reset_port == 2) {
1969 msg._txOn = 0;
1970 msg._txOff = 1;
1971 msg.txFlush = 0;
1972 msg.txBreak = 0;
1973 msg.rxOn = 0;
1974 msg.rxOff = 1;
1975 msg.rxFlush = 1;
1976 msg.rxForward = 0;
1977 msg.returnStatus = 0;
1978 msg.resetDataToggle = 0;
1979 msg.enablePort = 0;
1980 msg.disablePort = 1;
1981 }
1982 /* Sending intermediate configs */
1983 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001984 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 msg._txOff = 0;
1986 msg.txFlush = 0;
1987 msg.txBreak = (p_priv->break_on);
1988 msg.rxOn = 0;
1989 msg.rxOff = 0;
1990 msg.rxFlush = 0;
1991 msg.rxForward = 0;
1992 msg.returnStatus = 0;
1993 msg.resetDataToggle = 0x0;
1994 msg.enablePort = 0;
1995 msg.disablePort = 0;
1996 }
1997
Alan Coxdeb91682008-07-22 11:13:08 +01001998 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999 msg.setRts = 0xff;
2000 msg.rts = p_priv->rts_state;
2001
2002 msg.setDtr = 0xff;
2003 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002004
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 p_priv->resend_cont = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006
Alan Coxdeb91682008-07-22 11:13:08 +01002007 /* if the device is a 49wg, we send control message on usb
2008 control EP 0 */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002009
2010 if (d_details->product_id == keyspan_usa49wg_product_id) {
2011 dr = (void *)(s_priv->ctrl_buf);
2012 dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT;
2013 dr->bRequest = 0xB0; /* 49wg control message */;
2014 dr->wValue = 0;
2015 dr->wIndex = 0;
2016 dr->wLength = cpu_to_le16(sizeof(msg));
2017
Alan Coxdeb91682008-07-22 11:13:08 +01002018 memcpy(s_priv->glocont_buf, &msg, sizeof(msg));
Lucy McCoy0ca12682007-05-18 12:10:41 -07002019
Alan Coxdeb91682008-07-22 11:13:08 +01002020 usb_fill_control_urb(this_urb, serial->dev,
2021 usb_sndctrlpipe(serial->dev, 0),
2022 (unsigned char *)dr, s_priv->glocont_buf,
2023 sizeof(msg), usa49_glocont_callback, serial);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002024
2025 } else {
2026 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Alan Coxdeb91682008-07-22 11:13:08 +01002027
Lucy McCoy0ca12682007-05-18 12:10:41 -07002028 /* send the data out the device on control endpoint */
2029 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002030 }
Alan Coxdeb91682008-07-22 11:13:08 +01002031 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2032 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002033 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034#if 0
2035 else {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002036 dev_dbg(&port->dev, "%s - usb_submit_urb(%d) OK %d bytes (end %d)\n", __func__,
2037 outcont_urb, this_urb->transfer_buffer_length,
2038 usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039 }
2040#endif
2041
Alan Coxa5b6f602008-04-08 17:16:06 +01002042 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043}
2044
2045static int keyspan_usa90_send_setup(struct usb_serial *serial,
2046 struct usb_serial_port *port,
2047 int reset_port)
2048{
Alan Coxdeb91682008-07-22 11:13:08 +01002049 struct keyspan_usa90_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050 struct keyspan_serial_private *s_priv;
2051 struct keyspan_port_private *p_priv;
2052 const struct keyspan_device_details *d_details;
2053 struct urb *this_urb;
2054 int err;
2055 u8 prescaler;
2056
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057 s_priv = usb_get_serial_data(serial);
2058 p_priv = usb_get_serial_port_data(port);
2059 d_details = s_priv->device_details;
2060
2061 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01002062 this_urb = p_priv->outcont_urb;
2063 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002064 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 return -1;
2066 }
2067
2068 /* Save reset port val for resend.
2069 Don't overwrite resend for open/close condition. */
2070 if ((reset_port + 1) > p_priv->resend_cont)
2071 p_priv->resend_cont = reset_port + 1;
2072 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002073 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002075 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076 }
2077
Alan Coxdeb91682008-07-22 11:13:08 +01002078 memset(&msg, 0, sizeof(struct keyspan_usa90_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079
Alan Coxdeb91682008-07-22 11:13:08 +01002080 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081 if (p_priv->old_baud != p_priv->baud) {
2082 p_priv->old_baud = p_priv->baud;
2083 msg.setClocking = 0x01;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002084 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2085 &msg.baudHi, &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) {
2086 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2087 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088 p_priv->baud = 9600;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002089 d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090 &msg.baudHi, &msg.baudLo, &prescaler, 0);
2091 }
2092 msg.setRxMode = 1;
2093 msg.setTxMode = 1;
2094 }
2095
2096 /* modes must always be correctly specified */
Alan Coxdeb91682008-07-22 11:13:08 +01002097 if (p_priv->baud > 57600) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098 msg.rxMode = RXMODE_DMA;
2099 msg.txMode = TXMODE_DMA;
Alan Coxdeb91682008-07-22 11:13:08 +01002100 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101 msg.rxMode = RXMODE_BYHAND;
2102 msg.txMode = TXMODE_BYHAND;
2103 }
2104
Ben Minerds2b982ab2012-07-12 00:10:16 +10002105 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106 switch (p_priv->cflag & CSIZE) {
2107 case CS5:
2108 msg.lcr |= USA_DATABITS_5;
2109 break;
2110 case CS6:
2111 msg.lcr |= USA_DATABITS_6;
2112 break;
2113 case CS7:
2114 msg.lcr |= USA_DATABITS_7;
2115 break;
2116 case CS8:
2117 msg.lcr |= USA_DATABITS_8;
2118 break;
2119 }
2120 if (p_priv->cflag & PARENB) {
2121 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002122 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002123 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 }
2125 if (p_priv->old_cflag != p_priv->cflag) {
2126 p_priv->old_cflag = p_priv->cflag;
2127 msg.setLcr = 0x01;
2128 }
2129
2130 if (p_priv->flow_control == flow_cts)
2131 msg.txFlowControl = TXFLOW_CTS;
2132 msg.setTxFlowControl = 0x01;
2133 msg.setRxFlowControl = 0x01;
Alan Coxdeb91682008-07-22 11:13:08 +01002134
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135 msg.rxForwardingLength = 16;
Alan Coxdeb91682008-07-22 11:13:08 +01002136 msg.rxForwardingTimeout = 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137 msg.txAckSetting = 0;
2138 msg.xonChar = 17;
2139 msg.xoffChar = 19;
2140
Alan Coxdeb91682008-07-22 11:13:08 +01002141 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142 if (reset_port == 1) {
2143 msg.portEnabled = 1;
2144 msg.rxFlush = 1;
2145 msg.txBreak = (p_priv->break_on);
2146 }
2147 /* Closing port */
Alan Coxdeb91682008-07-22 11:13:08 +01002148 else if (reset_port == 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 msg.portEnabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150 /* Sending intermediate configs */
2151 else {
Alan Stern1f871582010-02-17 10:05:47 -05002152 msg.portEnabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153 msg.txBreak = (p_priv->break_on);
2154 }
2155
Alan Coxdeb91682008-07-22 11:13:08 +01002156 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157 msg.setRts = 0x01;
2158 msg.rts = p_priv->rts_state;
2159
2160 msg.setDtr = 0x01;
2161 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002162
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01002164 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2165
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 /* send the data out the device on control endpoint */
2167 this_urb->transfer_buffer_length = sizeof(msg);
2168
Alan Coxdeb91682008-07-22 11:13:08 +01002169 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2170 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002171 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002172 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173}
2174
Lucy McCoy0ca12682007-05-18 12:10:41 -07002175static int keyspan_usa67_send_setup(struct usb_serial *serial,
2176 struct usb_serial_port *port,
2177 int reset_port)
2178{
2179 struct keyspan_usa67_portControlMessage msg;
2180 struct keyspan_serial_private *s_priv;
2181 struct keyspan_port_private *p_priv;
2182 const struct keyspan_device_details *d_details;
2183 struct urb *this_urb;
2184 int err, device_port;
2185
Lucy McCoy0ca12682007-05-18 12:10:41 -07002186 s_priv = usb_get_serial_data(serial);
2187 p_priv = usb_get_serial_port_data(port);
2188 d_details = s_priv->device_details;
2189
2190 this_urb = s_priv->glocont_urb;
2191
2192 /* Work out which port within the device is being setup */
2193 device_port = port->number - port->serial->minor;
2194
2195 /* Make sure we have an urb then send the message */
2196 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002197 dev_dbg(&port->dev, "%s - oops no urb for port %d.\n", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002198 port->number);
2199 return -1;
2200 }
2201
2202 /* Save reset port val for resend.
2203 Don't overwrite resend for open/close condition. */
2204 if ((reset_port + 1) > p_priv->resend_cont)
2205 p_priv->resend_cont = reset_port + 1;
2206 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002207 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002208 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002209 return -1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002210 }
2211
2212 memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
2213
2214 msg.port = device_port;
2215
2216 /* Only set baud rate if it's changed */
2217 if (p_priv->old_baud != p_priv->baud) {
2218 p_priv->old_baud = p_priv->baud;
2219 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002220 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2221 &msg.baudHi, &msg.baudLo, &msg.prescaler,
2222 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2223 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2224 __func__, p_priv->baud);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002225 msg.baudLo = 0;
2226 msg.baudHi = 125; /* Values for 9600 baud */
2227 msg.prescaler = 10;
2228 }
2229 msg.setPrescaler = 0xff;
2230 }
2231
2232 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
2233 switch (p_priv->cflag & CSIZE) {
2234 case CS5:
2235 msg.lcr |= USA_DATABITS_5;
2236 break;
2237 case CS6:
2238 msg.lcr |= USA_DATABITS_6;
2239 break;
2240 case CS7:
2241 msg.lcr |= USA_DATABITS_7;
2242 break;
2243 case CS8:
2244 msg.lcr |= USA_DATABITS_8;
2245 break;
2246 }
2247 if (p_priv->cflag & PARENB) {
2248 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002249 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002250 USA_PARITY_ODD : USA_PARITY_EVEN;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002251 }
2252 msg.setLcr = 0xff;
2253
2254 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2255 msg.xonFlowControl = 0;
2256 msg.setFlowControl = 0xff;
2257 msg.forwardingLength = 16;
2258 msg.xonChar = 17;
2259 msg.xoffChar = 19;
2260
2261 if (reset_port == 1) {
2262 /* Opening port */
2263 msg._txOn = 1;
2264 msg._txOff = 0;
2265 msg.txFlush = 0;
2266 msg.txBreak = 0;
2267 msg.rxOn = 1;
2268 msg.rxOff = 0;
2269 msg.rxFlush = 1;
2270 msg.rxForward = 0;
2271 msg.returnStatus = 0;
2272 msg.resetDataToggle = 0xff;
2273 } else if (reset_port == 2) {
2274 /* Closing port */
2275 msg._txOn = 0;
2276 msg._txOff = 1;
2277 msg.txFlush = 0;
2278 msg.txBreak = 0;
2279 msg.rxOn = 0;
2280 msg.rxOff = 1;
2281 msg.rxFlush = 1;
2282 msg.rxForward = 0;
2283 msg.returnStatus = 0;
2284 msg.resetDataToggle = 0;
2285 } else {
2286 /* Sending intermediate configs */
Alan Coxdeb91682008-07-22 11:13:08 +01002287 msg._txOn = (!p_priv->break_on);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002288 msg._txOff = 0;
2289 msg.txFlush = 0;
2290 msg.txBreak = (p_priv->break_on);
2291 msg.rxOn = 0;
2292 msg.rxOff = 0;
2293 msg.rxFlush = 0;
2294 msg.rxForward = 0;
2295 msg.returnStatus = 0;
2296 msg.resetDataToggle = 0x0;
2297 }
2298
2299 /* Do handshaking outputs */
2300 msg.setTxTriState_setRts = 0xff;
2301 msg.txTriState_rts = p_priv->rts_state;
2302
2303 msg.setHskoa_setDtr = 0xff;
2304 msg.hskoa_dtr = p_priv->dtr_state;
2305
2306 p_priv->resend_cont = 0;
2307
2308 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2309
2310 /* send the data out the device on control endpoint */
2311 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002312
2313 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2314 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002315 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002316 return 0;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002317}
2318
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
2320{
2321 struct usb_serial *serial = port->serial;
2322 struct keyspan_serial_private *s_priv;
2323 const struct keyspan_device_details *d_details;
2324
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325 s_priv = usb_get_serial_data(serial);
2326 d_details = s_priv->device_details;
2327
2328 switch (d_details->msg_format) {
2329 case msg_usa26:
2330 keyspan_usa26_send_setup(serial, port, reset_port);
2331 break;
2332 case msg_usa28:
2333 keyspan_usa28_send_setup(serial, port, reset_port);
2334 break;
2335 case msg_usa49:
2336 keyspan_usa49_send_setup(serial, port, reset_port);
2337 break;
2338 case msg_usa90:
2339 keyspan_usa90_send_setup(serial, port, reset_port);
2340 break;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002341 case msg_usa67:
2342 keyspan_usa67_send_setup(serial, port, reset_port);
2343 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344 }
2345}
2346
2347
2348/* Gets called by the "real" driver (ie once firmware is loaded
2349 and renumeration has taken place. */
Alan Coxdeb91682008-07-22 11:13:08 +01002350static int keyspan_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351{
2352 int i, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 const struct keyspan_device_details *d_details;
2355
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
Alan Coxdeb91682008-07-22 11:13:08 +01002357 if (d_details->product_id ==
2358 le16_to_cpu(serial->dev->descriptor.idProduct))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359 break;
2360 if (d_details == NULL) {
Alan Coxdeb91682008-07-22 11:13:08 +01002361 dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
2362 __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 return 1;
2364 }
2365
2366 /* Setup private data for serial driver */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01002367 s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368 if (!s_priv) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002369 dev_dbg(&serial->dev->dev, "%s - kmalloc for keyspan_serial_private failed.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370 return -ENOMEM;
2371 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372
2373 s_priv->device_details = d_details;
2374 usb_set_serial_data(serial, s_priv);
2375
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376 keyspan_setup_urbs(serial);
2377
Lucy McCoy0ca12682007-05-18 12:10:41 -07002378 if (s_priv->instat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002379 err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
2380 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002381 dev_dbg(&serial->dev->dev, "%s - submit instat urb failed %d\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002382 }
2383 if (s_priv->indat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002384 err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
2385 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002386 dev_dbg(&serial->dev->dev, "%s - submit indat urb failed %d\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 }
Alan Coxdeb91682008-07-22 11:13:08 +01002388
Alan Coxa5b6f602008-04-08 17:16:06 +01002389 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390}
2391
Alan Sternf9c99bb2009-06-02 11:53:55 -04002392static void keyspan_disconnect(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002394 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396 s_priv = usb_get_serial_data(serial);
2397
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 stop_urb(s_priv->instat_urb);
2399 stop_urb(s_priv->glocont_urb);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002400 stop_urb(s_priv->indat_urb);
Alan Sternf9c99bb2009-06-02 11:53:55 -04002401}
2402
2403static void keyspan_release(struct usb_serial *serial)
2404{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002405 struct keyspan_serial_private *s_priv;
Alan Sternf9c99bb2009-06-02 11:53:55 -04002406
Alan Sternf9c99bb2009-06-02 11:53:55 -04002407 s_priv = usb_get_serial_data(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002409 usb_free_urb(s_priv->instat_urb);
2410 usb_free_urb(s_priv->indat_urb);
2411 usb_free_urb(s_priv->glocont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002413 kfree(s_priv);
2414}
2415
2416static int keyspan_port_probe(struct usb_serial_port *port)
2417{
2418 struct usb_serial *serial = port->serial;
Bjørn Morkf0e3e352012-11-10 10:13:42 +01002419 struct keyspan_serial_private *s_priv;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002420 struct keyspan_port_private *p_priv;
2421 const struct keyspan_device_details *d_details;
2422 struct callbacks *cback;
2423 int endp;
2424 int port_num;
2425 int i;
2426
2427 s_priv = usb_get_serial_data(serial);
2428 d_details = s_priv->device_details;
2429
2430 p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL);
2431 if (!p_priv)
2432 return -ENOMEM;
2433
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002434 p_priv->device_details = d_details;
2435
2436 /* Setup values for the various callback routines */
2437 cback = &keyspan_callbacks[d_details->msg_format];
2438
2439 port_num = port->number - port->serial->minor;
2440
2441 /* Do indat endpoints first, once for each flip */
2442 endp = d_details->indat_endpoints[port_num];
2443 for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) {
2444 p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp,
2445 USB_DIR_IN, port,
2446 p_priv->in_buffer[i], 64,
2447 cback->indat_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448 }
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002449 /* outdat endpoints also have flip */
2450 endp = d_details->outdat_endpoints[port_num];
2451 for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) {
2452 p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp,
2453 USB_DIR_OUT, port,
2454 p_priv->out_buffer[i], 64,
2455 cback->outdat_callback);
2456 }
2457 /* inack endpoint */
2458 p_priv->inack_urb = keyspan_setup_urb(serial,
2459 d_details->inack_endpoints[port_num],
2460 USB_DIR_IN, port,
2461 p_priv->inack_buffer, 1,
2462 cback->inack_callback);
2463 /* outcont endpoint */
2464 p_priv->outcont_urb = keyspan_setup_urb(serial,
2465 d_details->outcont_endpoints[port_num],
2466 USB_DIR_OUT, port,
2467 p_priv->outcont_buffer, 64,
2468 cback->outcont_callback);
2469
2470 usb_set_serial_port_data(port, p_priv);
2471
2472 return 0;
2473}
2474
2475static int keyspan_port_remove(struct usb_serial_port *port)
2476{
2477 struct keyspan_port_private *p_priv;
2478 int i;
2479
2480 p_priv = usb_get_serial_port_data(port);
2481
2482 stop_urb(p_priv->inack_urb);
2483 stop_urb(p_priv->outcont_urb);
2484 for (i = 0; i < 2; i++) {
2485 stop_urb(p_priv->in_urbs[i]);
2486 stop_urb(p_priv->out_urbs[i]);
2487 }
2488
2489 usb_free_urb(p_priv->inack_urb);
2490 usb_free_urb(p_priv->outcont_urb);
2491 for (i = 0; i < 2; i++) {
2492 usb_free_urb(p_priv->in_urbs[i]);
2493 usb_free_urb(p_priv->out_urbs[i]);
2494 }
2495
2496 kfree(p_priv);
2497
2498 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499}
2500
Alan Coxdeb91682008-07-22 11:13:08 +01002501MODULE_AUTHOR(DRIVER_AUTHOR);
2502MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503MODULE_LICENSE("GPL");
2504
David Woodhouse2971c572008-05-30 14:04:03 +03002505MODULE_FIRMWARE("keyspan/usa28.fw");
2506MODULE_FIRMWARE("keyspan/usa28x.fw");
2507MODULE_FIRMWARE("keyspan/usa28xa.fw");
2508MODULE_FIRMWARE("keyspan/usa28xb.fw");
2509MODULE_FIRMWARE("keyspan/usa19.fw");
2510MODULE_FIRMWARE("keyspan/usa19qi.fw");
2511MODULE_FIRMWARE("keyspan/mpr.fw");
2512MODULE_FIRMWARE("keyspan/usa19qw.fw");
2513MODULE_FIRMWARE("keyspan/usa18x.fw");
2514MODULE_FIRMWARE("keyspan/usa19w.fw");
2515MODULE_FIRMWARE("keyspan/usa49w.fw");
2516MODULE_FIRMWARE("keyspan/usa49wlc.fw");