blob: a4f5caebda437861db8fd014b08f2527622eb16a [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;
294 struct tty_struct *tty;
295 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700296 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 endpoint = usb_pipeendpoint(urb->pipe);
299
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700300 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700301 dev_dbg(&urb->dev->dev,"%s - nonzero status: %x on endpoint %d.\n",
302 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 return;
304 }
305
Ming Leicdc97792008-02-24 18:41:47 +0800306 port = urb->context;
Alan Cox4a90f092008-10-13 10:39:46 +0100307 tty = tty_port_tty_get(&port->port);
Alan Coxa5569a52008-01-21 17:18:24 -0800308 if (tty && urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 /* 0x80 bit is error flag */
310 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100311 /* no errors on individual bytes, only
312 possible overrun err */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313 if (data[0] & RXERROR_OVERRUN)
Alan Coxdeb91682008-07-22 11:13:08 +0100314 err = TTY_OVERRUN;
315 else
316 err = 0;
317 for (i = 1; i < urb->actual_length ; ++i)
Jiri Slaby92a19f92013-01-03 15:53:03 +0100318 tty_insert_flip_char(&port->port, data[i], err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 } else {
320 /* some bytes had errors, every byte has status */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700321 dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 for (i = 0; i + 1 < urb->actual_length; i += 2) {
323 int stat = data[i], flag = 0;
324 if (stat & RXERROR_OVERRUN)
325 flag |= TTY_OVERRUN;
326 if (stat & RXERROR_FRAMING)
327 flag |= TTY_FRAME;
328 if (stat & RXERROR_PARITY)
329 flag |= TTY_PARITY;
330 /* XXX should handle break (0x10) */
Jiri Slaby92a19f92013-01-03 15:53:03 +0100331 tty_insert_flip_char(&port->port, data[i+1],
332 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 }
334 }
335 tty_flip_buffer_push(tty);
336 }
Alan Cox4a90f092008-10-13 10:39:46 +0100337 tty_kref_put(tty);
Alan Coxdeb91682008-07-22 11:13:08 +0100338
339 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500340 err = usb_submit_urb(urb, GFP_ATOMIC);
341 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700342 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343}
344
Alan Coxdeb91682008-07-22 11:13:08 +0100345/* Outdat handling is common for all devices */
David Howells7d12e782006-10-05 14:55:46 +0100346static void usa2x_outdat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347{
348 struct usb_serial_port *port;
349 struct keyspan_port_private *p_priv;
350
Ming Leicdc97792008-02-24 18:41:47 +0800351 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 p_priv = usb_get_serial_port_data(port);
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700353 dev_dbg(&port->dev, "%s - urb %d\n", __func__, urb == p_priv->out_urbs[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354
Alan Stern1f871582010-02-17 10:05:47 -0500355 usb_serial_port_softint(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356}
357
David Howells7d12e782006-10-05 14:55:46 +0100358static void usa26_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360}
361
David Howells7d12e782006-10-05 14:55:46 +0100362static void usa26_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363{
364 struct usb_serial_port *port;
365 struct keyspan_port_private *p_priv;
366
Ming Leicdc97792008-02-24 18:41:47 +0800367 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 p_priv = usb_get_serial_port_data(port);
369
370 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700371 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100372 keyspan_usa26_send_setup(port->serial, port,
373 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 }
375}
376
David Howells7d12e782006-10-05 14:55:46 +0100377static void usa26_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378{
379 unsigned char *data = urb->transfer_buffer;
380 struct keyspan_usa26_portStatusMessage *msg;
381 struct usb_serial *serial;
382 struct usb_serial_port *port;
383 struct keyspan_port_private *p_priv;
Alan Cox4a90f092008-10-13 10:39:46 +0100384 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700386 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387
Ming Leicdc97792008-02-24 18:41:47 +0800388 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700390 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700391 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 return;
393 }
394 if (urb->actual_length != 9) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700395 dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 goto exit;
397 }
398
399 msg = (struct keyspan_usa26_portStatusMessage *)data;
400
401#if 0
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700402 dev_dbg(&urb->dev->dev,
403 "%s - port status: port %d cts %d dcd %d dsr %d ri %d toff %d txoff %d rxen %d cr %d",
404 __func__, msg->port, msg->hskia_cts, msg->gpia_dcd, msg->dsr,
405 msg->ri, msg->_txOff, msg->_txXoff, msg->rxEnabled,
406 msg->controlResponse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407#endif
408
409 /* Now do something useful with the data */
410
411
Alan Coxdeb91682008-07-22 11:13:08 +0100412 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700414 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 goto exit;
416 }
417 port = serial->port[msg->port];
418 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100419
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 /* Update handshaking pin state information */
421 old_dcd_state = p_priv->dcd_state;
422 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
423 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
424 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
425 p_priv->ri_state = ((msg->ri) ? 1 : 0);
426
Alan Cox4a90f092008-10-13 10:39:46 +0100427 if (old_dcd_state != p_priv->dcd_state) {
428 tty = tty_port_tty_get(&port->port);
429 if (tty && !C_CLOCAL(tty))
430 tty_hangup(tty);
431 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 }
Alan Coxdeb91682008-07-22 11:13:08 +0100433
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100435 err = usb_submit_urb(urb, GFP_ATOMIC);
436 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700437 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438exit: ;
439}
440
David Howells7d12e782006-10-05 14:55:46 +0100441static void usa26_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443}
444
445
David Howells7d12e782006-10-05 14:55:46 +0100446static void usa28_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447{
Alan Coxf035a8a2008-07-22 11:13:32 +0100448 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 struct usb_serial_port *port;
450 struct tty_struct *tty;
451 unsigned char *data;
452 struct keyspan_port_private *p_priv;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700453 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454
Ming Leicdc97792008-02-24 18:41:47 +0800455 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 p_priv = usb_get_serial_port_data(port);
457 data = urb->transfer_buffer;
458
459 if (urb != p_priv->in_urbs[p_priv->in_flip])
460 return;
461
462 do {
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700463 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700464 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
465 __func__, status, usb_pipeendpoint(urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 return;
467 }
468
Ming Leicdc97792008-02-24 18:41:47 +0800469 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 p_priv = usb_get_serial_port_data(port);
471 data = urb->transfer_buffer;
472
Ben Minerds40adac82012-07-12 00:10:17 +1000473 tty = tty_port_tty_get(&port->port);
Alan Cox4a90f092008-10-13 10:39:46 +0100474 if (tty && urb->actual_length) {
Alan Coxf035a8a2008-07-22 11:13:32 +0100475 tty_insert_flip_string(tty, data, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 tty_flip_buffer_push(tty);
477 }
Alan Cox4a90f092008-10-13 10:39:46 +0100478 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479
480 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500481 err = usb_submit_urb(urb, GFP_ATOMIC);
482 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700483 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n",
Alan Stern1f871582010-02-17 10:05:47 -0500484 __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 p_priv->in_flip ^= 1;
486
487 urb = p_priv->in_urbs[p_priv->in_flip];
488 } while (urb->status != -EINPROGRESS);
489}
490
David Howells7d12e782006-10-05 14:55:46 +0100491static void usa28_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493}
494
David Howells7d12e782006-10-05 14:55:46 +0100495static void usa28_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496{
497 struct usb_serial_port *port;
498 struct keyspan_port_private *p_priv;
499
Ming Leicdc97792008-02-24 18:41:47 +0800500 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 p_priv = usb_get_serial_port_data(port);
502
503 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700504 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100505 keyspan_usa28_send_setup(port->serial, port,
506 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 }
508}
509
David Howells7d12e782006-10-05 14:55:46 +0100510static void usa28_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511{
512 int err;
513 unsigned char *data = urb->transfer_buffer;
514 struct keyspan_usa28_portStatusMessage *msg;
515 struct usb_serial *serial;
516 struct usb_serial_port *port;
517 struct keyspan_port_private *p_priv;
Alan Cox4a90f092008-10-13 10:39:46 +0100518 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700520 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521
Ming Leicdc97792008-02-24 18:41:47 +0800522 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700524 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700525 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 return;
527 }
528
529 if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700530 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 goto exit;
532 }
533
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700534 /*
535 dev_dbg(&urb->dev->dev,
536 "%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__,
537 data[0], data[1], data[2], data[3], data[4], data[5],
538 data[6], data[7], data[8], data[9], data[10], data[11]);
539 */
Alan Coxdeb91682008-07-22 11:13:08 +0100540
541 /* Now do something useful with the data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 msg = (struct keyspan_usa28_portStatusMessage *)data;
543
Alan Coxdeb91682008-07-22 11:13:08 +0100544 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700546 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 goto exit;
548 }
549 port = serial->port[msg->port];
550 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100551
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 /* Update handshaking pin state information */
553 old_dcd_state = p_priv->dcd_state;
554 p_priv->cts_state = ((msg->cts) ? 1 : 0);
555 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
556 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
557 p_priv->ri_state = ((msg->ri) ? 1 : 0);
558
Ben Minerdsddc04ae2012-07-12 00:10:18 +1000559 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
Alan Cox4a90f092008-10-13 10:39:46 +0100560 tty = tty_port_tty_get(&port->port);
Ben Minerds878b5fd2012-07-12 00:10:19 +1000561 if (tty && !C_CLOCAL(tty))
Alan Cox4a90f092008-10-13 10:39:46 +0100562 tty_hangup(tty);
563 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 }
565
566 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100567 err = usb_submit_urb(urb, GFP_ATOMIC);
568 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700569 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570exit: ;
571}
572
David Howells7d12e782006-10-05 14:55:46 +0100573static void usa28_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575}
576
577
David Howells7d12e782006-10-05 14:55:46 +0100578static void usa49_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579{
580 struct usb_serial *serial;
581 struct usb_serial_port *port;
582 struct keyspan_port_private *p_priv;
583 int i;
584
Ming Leicdc97792008-02-24 18:41:47 +0800585 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 for (i = 0; i < serial->num_ports; ++i) {
587 port = serial->port[i];
588 p_priv = usb_get_serial_port_data(port);
589
590 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700591 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100592 keyspan_usa49_send_setup(serial, port,
593 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 break;
595 }
596 }
597}
598
599 /* This is actually called glostat in the Keyspan
600 doco */
David Howells7d12e782006-10-05 14:55:46 +0100601static void usa49_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602{
603 int err;
604 unsigned char *data = urb->transfer_buffer;
605 struct keyspan_usa49_portStatusMessage *msg;
606 struct usb_serial *serial;
607 struct usb_serial_port *port;
608 struct keyspan_port_private *p_priv;
609 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700610 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611
Ming Leicdc97792008-02-24 18:41:47 +0800612 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700614 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700615 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 return;
617 }
618
Alan Coxdeb91682008-07-22 11:13:08 +0100619 if (urb->actual_length !=
620 sizeof(struct keyspan_usa49_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700621 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 goto exit;
623 }
624
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700625 /*
626 dev_dbg(&urb->dev->dev, "%s: %x %x %x %x %x %x %x %x %x %x %x",
627 __func__, data[0], data[1], data[2], data[3], data[4],
628 data[5], data[6], data[7], data[8], data[9], data[10]);
629 */
Alan Coxdeb91682008-07-22 11:13:08 +0100630
631 /* Now do something useful with the data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 msg = (struct keyspan_usa49_portStatusMessage *)data;
633
Alan Coxdeb91682008-07-22 11:13:08 +0100634 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 if (msg->portNumber >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700636 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
637 __func__, msg->portNumber);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 goto exit;
639 }
640 port = serial->port[msg->portNumber];
641 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100642
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 /* Update handshaking pin state information */
644 old_dcd_state = p_priv->dcd_state;
645 p_priv->cts_state = ((msg->cts) ? 1 : 0);
646 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
647 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
648 p_priv->ri_state = ((msg->ri) ? 1 : 0);
649
Alan Cox4a90f092008-10-13 10:39:46 +0100650 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
651 struct tty_struct *tty = tty_port_tty_get(&port->port);
652 if (tty && !C_CLOCAL(tty))
653 tty_hangup(tty);
654 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 }
656
Alan Coxdeb91682008-07-22 11:13:08 +0100657 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100658 err = usb_submit_urb(urb, GFP_ATOMIC);
659 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700660 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661exit: ;
662}
663
David Howells7d12e782006-10-05 14:55:46 +0100664static void usa49_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666}
667
David Howells7d12e782006-10-05 14:55:46 +0100668static void usa49_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669{
670 int i, err;
671 int endpoint;
672 struct usb_serial_port *port;
673 struct tty_struct *tty;
674 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700675 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 endpoint = usb_pipeendpoint(urb->pipe);
678
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700679 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700680 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
681 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 return;
683 }
684
Ming Leicdc97792008-02-24 18:41:47 +0800685 port = urb->context;
Alan Cox4a90f092008-10-13 10:39:46 +0100686 tty = tty_port_tty_get(&port->port);
Alan Cox3004e532008-01-03 16:59:04 +0000687 if (tty && urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 /* 0x80 bit is error flag */
689 if ((data[0] & 0x80) == 0) {
690 /* no error on any byte */
Alan Coxf035a8a2008-07-22 11:13:32 +0100691 tty_insert_flip_string(tty, data + 1,
692 urb->actual_length - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 } else {
694 /* some bytes had errors, every byte has status */
695 for (i = 0; i + 1 < urb->actual_length; i += 2) {
696 int stat = data[i], flag = 0;
697 if (stat & RXERROR_OVERRUN)
698 flag |= TTY_OVERRUN;
699 if (stat & RXERROR_FRAMING)
700 flag |= TTY_FRAME;
701 if (stat & RXERROR_PARITY)
702 flag |= TTY_PARITY;
703 /* XXX should handle break (0x10) */
Jiri Slaby92a19f92013-01-03 15:53:03 +0100704 tty_insert_flip_char(&port->port, data[i+1],
705 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 }
707 }
708 tty_flip_buffer_push(tty);
709 }
Alan Cox4a90f092008-10-13 10:39:46 +0100710 tty_kref_put(tty);
Alan Coxdeb91682008-07-22 11:13:08 +0100711
712 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500713 err = usb_submit_urb(urb, GFP_ATOMIC);
714 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700715 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716}
717
Lucy McCoy0ca12682007-05-18 12:10:41 -0700718static void usa49wg_indat_callback(struct urb *urb)
719{
720 int i, len, x, err;
721 struct usb_serial *serial;
722 struct usb_serial_port *port;
723 struct tty_struct *tty;
724 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700725 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700726
Lucy McCoy0ca12682007-05-18 12:10:41 -0700727 serial = urb->context;
728
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700729 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700730 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700731 return;
732 }
733
734 /* inbound data is in the form P#, len, status, data */
735 i = 0;
736 len = 0;
737
738 if (urb->actual_length) {
739 while (i < urb->actual_length) {
740
741 /* Check port number from message*/
742 if (data[i] >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700743 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800744 __func__, data[i]);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700745 return;
746 }
747 port = serial->port[data[i++]];
Alan Cox4a90f092008-10-13 10:39:46 +0100748 tty = tty_port_tty_get(&port->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700749 len = data[i++];
750
751 /* 0x80 bit is error flag */
752 if ((data[i] & 0x80) == 0) {
753 /* no error on any byte */
754 i++;
755 for (x = 1; x < len ; ++x)
Jiri Slaby92a19f92013-01-03 15:53:03 +0100756 tty_insert_flip_char(&port->port,
757 data[i++], 0);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700758 } else {
759 /*
760 * some bytes had errors, every byte has status
761 */
762 for (x = 0; x + 1 < len; x += 2) {
763 int stat = data[i], flag = 0;
764 if (stat & RXERROR_OVERRUN)
765 flag |= TTY_OVERRUN;
766 if (stat & RXERROR_FRAMING)
767 flag |= TTY_FRAME;
768 if (stat & RXERROR_PARITY)
769 flag |= TTY_PARITY;
770 /* XXX should handle break (0x10) */
Jiri Slaby92a19f92013-01-03 15:53:03 +0100771 tty_insert_flip_char(&port->port,
Lucy McCoy0ca12682007-05-18 12:10:41 -0700772 data[i+1], flag);
773 i += 2;
774 }
775 }
Alan Stern1f871582010-02-17 10:05:47 -0500776 tty_flip_buffer_push(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100777 tty_kref_put(tty);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700778 }
779 }
780
781 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700782 err = usb_submit_urb(urb, GFP_ATOMIC);
783 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700784 dev_dbg(&urb->dev->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700785}
786
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787/* not used, usa-49 doesn't have per-port control endpoints */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700788static void usa49_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790}
791
Lucy McCoy0ca12682007-05-18 12:10:41 -0700792static void usa90_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793{
794 int i, err;
795 int endpoint;
796 struct usb_serial_port *port;
797 struct keyspan_port_private *p_priv;
798 struct tty_struct *tty;
799 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700800 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 endpoint = usb_pipeendpoint(urb->pipe);
803
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700804 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700805 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800806 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 return;
808 }
809
Ming Leicdc97792008-02-24 18:41:47 +0800810 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 p_priv = usb_get_serial_port_data(port);
812
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 if (urb->actual_length) {
Alan Cox4a90f092008-10-13 10:39:46 +0100814 tty = tty_port_tty_get(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 /* if current mode is DMA, looks like usa28 format
Alan Coxdeb91682008-07-22 11:13:08 +0100816 otherwise looks like usa26 data format */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817
Alan Coxf035a8a2008-07-22 11:13:32 +0100818 if (p_priv->baud > 57600)
819 tty_insert_flip_string(tty, data, urb->actual_length);
820 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 /* 0x80 bit is error flag */
822 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100823 /* no errors on individual bytes, only
824 possible overrun err*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 if (data[0] & RXERROR_OVERRUN)
Alan Coxdeb91682008-07-22 11:13:08 +0100826 err = TTY_OVERRUN;
827 else
828 err = 0;
829 for (i = 1; i < urb->actual_length ; ++i)
Jiri Slaby92a19f92013-01-03 15:53:03 +0100830 tty_insert_flip_char(&port->port,
831 data[i], err);
Alan Coxdeb91682008-07-22 11:13:08 +0100832 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 /* some bytes had errors, every byte has status */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700834 dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 for (i = 0; i + 1 < urb->actual_length; i += 2) {
836 int stat = data[i], flag = 0;
837 if (stat & RXERROR_OVERRUN)
838 flag |= TTY_OVERRUN;
839 if (stat & RXERROR_FRAMING)
840 flag |= TTY_FRAME;
841 if (stat & RXERROR_PARITY)
842 flag |= TTY_PARITY;
843 /* XXX should handle break (0x10) */
Jiri Slaby92a19f92013-01-03 15:53:03 +0100844 tty_insert_flip_char(&port->port,
845 data[i+1], flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 }
847 }
848 }
849 tty_flip_buffer_push(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100850 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 }
Alan Coxdeb91682008-07-22 11:13:08 +0100852
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500854 err = usb_submit_urb(urb, GFP_ATOMIC);
855 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700856 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857}
858
859
David Howells7d12e782006-10-05 14:55:46 +0100860static void usa90_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861{
862 unsigned char *data = urb->transfer_buffer;
863 struct keyspan_usa90_portStatusMessage *msg;
864 struct usb_serial *serial;
865 struct usb_serial_port *port;
866 struct keyspan_port_private *p_priv;
Alan Cox4a90f092008-10-13 10:39:46 +0100867 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700869 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870
Ming Leicdc97792008-02-24 18:41:47 +0800871 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700873 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700874 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 return;
876 }
877 if (urb->actual_length < 14) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700878 dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 goto exit;
880 }
881
882 msg = (struct keyspan_usa90_portStatusMessage *)data;
883
884 /* Now do something useful with the data */
885
886 port = serial->port[0];
887 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100888
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 /* Update handshaking pin state information */
890 old_dcd_state = p_priv->dcd_state;
891 p_priv->cts_state = ((msg->cts) ? 1 : 0);
892 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
893 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
894 p_priv->ri_state = ((msg->ri) ? 1 : 0);
895
Alan Cox4a90f092008-10-13 10:39:46 +0100896 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
897 tty = tty_port_tty_get(&port->port);
898 if (tty && !C_CLOCAL(tty))
899 tty_hangup(tty);
900 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 }
Alan Coxdeb91682008-07-22 11:13:08 +0100902
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100904 err = usb_submit_urb(urb, GFP_ATOMIC);
905 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700906 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907exit:
908 ;
909}
910
David Howells7d12e782006-10-05 14:55:46 +0100911static void usa90_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912{
913 struct usb_serial_port *port;
914 struct keyspan_port_private *p_priv;
915
Ming Leicdc97792008-02-24 18:41:47 +0800916 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 p_priv = usb_get_serial_port_data(port);
918
919 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700920 dev_dbg(&urb->dev->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100921 keyspan_usa90_send_setup(port->serial, port,
922 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 }
924}
925
Lucy McCoy0ca12682007-05-18 12:10:41 -0700926/* Status messages from the 28xg */
927static void usa67_instat_callback(struct urb *urb)
928{
929 int err;
930 unsigned char *data = urb->transfer_buffer;
931 struct keyspan_usa67_portStatusMessage *msg;
932 struct usb_serial *serial;
933 struct usb_serial_port *port;
934 struct keyspan_port_private *p_priv;
935 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700936 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700937
Lucy McCoy0ca12682007-05-18 12:10:41 -0700938 serial = urb->context;
939
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700940 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700941 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700942 return;
943 }
944
Alan Coxdeb91682008-07-22 11:13:08 +0100945 if (urb->actual_length !=
946 sizeof(struct keyspan_usa67_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700947 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700948 return;
949 }
950
951
952 /* Now do something useful with the data */
953 msg = (struct keyspan_usa67_portStatusMessage *)data;
954
955 /* Check port number from message and retrieve private data */
956 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700957 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700958 return;
959 }
960
961 port = serial->port[msg->port];
962 p_priv = usb_get_serial_port_data(port);
963
964 /* Update handshaking pin state information */
965 old_dcd_state = p_priv->dcd_state;
966 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
967 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
968
Alan Cox4a90f092008-10-13 10:39:46 +0100969 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
970 struct tty_struct *tty = tty_port_tty_get(&port->port);
971 if (tty && !C_CLOCAL(tty))
972 tty_hangup(tty);
973 tty_kref_put(tty);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700974 }
975
976 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700977 err = usb_submit_urb(urb, GFP_ATOMIC);
978 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700979 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700980}
981
982static void usa67_glocont_callback(struct urb *urb)
983{
984 struct usb_serial *serial;
985 struct usb_serial_port *port;
986 struct keyspan_port_private *p_priv;
987 int i;
988
Lucy McCoy0ca12682007-05-18 12:10:41 -0700989 serial = urb->context;
990 for (i = 0; i < serial->num_ports; ++i) {
991 port = serial->port[i];
992 p_priv = usb_get_serial_port_data(port);
993
994 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700995 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700996 keyspan_usa67_send_setup(serial, port,
997 p_priv->resend_cont - 1);
998 break;
999 }
1000 }
1001}
1002
Alan Cox95da3102008-07-22 11:09:07 +01001003static int keyspan_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004{
Alan Cox95da3102008-07-22 11:09:07 +01001005 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 struct keyspan_port_private *p_priv;
1007 const struct keyspan_device_details *d_details;
1008 int flip;
1009 int data_len;
1010 struct urb *this_urb;
1011
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 p_priv = usb_get_serial_port_data(port);
1013 d_details = p_priv->device_details;
1014
Alan Coxa5b6f602008-04-08 17:16:06 +01001015 /* FIXME: locking */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 if (d_details->msg_format == msg_usa90)
Alan Coxdeb91682008-07-22 11:13:08 +01001017 data_len = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 else
1019 data_len = 63;
1020
1021 flip = p_priv->out_flip;
1022
1023 /* Check both endpoints to see if any are available. */
Alan Coxdeb91682008-07-22 11:13:08 +01001024 this_urb = p_priv->out_urbs[flip];
1025 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001027 return data_len;
1028 flip = (flip + 1) & d_details->outdat_endp_flip;
1029 this_urb = p_priv->out_urbs[flip];
1030 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001032 return data_len;
1033 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 }
Alan Coxa5b6f602008-04-08 17:16:06 +01001035 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036}
1037
1038
Alan Coxa509a7e2009-09-19 13:13:26 -07001039static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040{
Andrew Mortonf78ba152007-11-28 16:21:54 -08001041 struct keyspan_port_private *p_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 const struct keyspan_device_details *d_details;
1043 int i, err;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001044 int baud_rate, device_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 struct urb *urb;
Alan Cox95da3102008-07-22 11:09:07 +01001046 unsigned int cflag = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 p_priv = usb_get_serial_port_data(port);
1049 d_details = p_priv->device_details;
Borislav Petkov7eea4362007-11-14 17:00:39 -08001050
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 /* Set some sane defaults */
1052 p_priv->rts_state = 1;
1053 p_priv->dtr_state = 1;
1054 p_priv->baud = 9600;
1055
1056 /* force baud and lcr to be set on open */
1057 p_priv->old_baud = 0;
1058 p_priv->old_cflag = 0;
1059
1060 p_priv->out_flip = 0;
1061 p_priv->in_flip = 0;
1062
1063 /* Reset low level data toggle and start reading from endpoints */
1064 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001065 urb = p_priv->in_urbs[i];
1066 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068
Alan Coxdeb91682008-07-22 11:13:08 +01001069 /* make sure endpoint data toggle is synchronized
1070 with the device */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 usb_clear_halt(urb->dev, urb->pipe);
Alan Coxdeb91682008-07-22 11:13:08 +01001072 err = usb_submit_urb(urb, GFP_KERNEL);
1073 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001074 dev_dbg(&port->dev, "%s - submit urb %d failed (%d)\n", __func__, i, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 }
1076
1077 /* Reset low level data toggle on out endpoints */
1078 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001079 urb = p_priv->out_urbs[i];
1080 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 continue;
Alan Coxdeb91682008-07-22 11:13:08 +01001082 /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
1083 usb_pipeout(urb->pipe), 0); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 }
1085
Andrew Mortonf78ba152007-11-28 16:21:54 -08001086 /* get the terminal config for the setup message now so we don't
1087 * need to send 2 of them */
1088
Andrew Mortonf78ba152007-11-28 16:21:54 -08001089 device_port = port->number - port->serial->minor;
Alan Cox95da3102008-07-22 11:09:07 +01001090 if (tty) {
Alan Coxadc8d742012-07-14 15:31:47 +01001091 cflag = tty->termios.c_cflag;
Alan Cox95da3102008-07-22 11:09:07 +01001092 /* Baud rate calculation takes baud rate as an integer
1093 so other rates can be generated if desired. */
1094 baud_rate = tty_get_baud_rate(tty);
1095 /* If no match or invalid, leave as default */
1096 if (baud_rate >= 0
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001097 && d_details->calculate_baud_rate(port, baud_rate, d_details->baudclk,
Alan Cox95da3102008-07-22 11:09:07 +01001098 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
1099 p_priv->baud = baud_rate;
1100 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001101 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001102 /* set CTS/RTS handshake etc. */
1103 p_priv->cflag = cflag;
Ben Minerds2b982ab2012-07-12 00:10:16 +10001104 p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001105
1106 keyspan_send_setup(port, 1);
Alan Coxdeb91682008-07-22 11:13:08 +01001107 /* mdelay(100); */
1108 /* keyspan_set_termios(port, NULL); */
Andrew Mortonf78ba152007-11-28 16:21:54 -08001109
Alan Coxa5b6f602008-04-08 17:16:06 +01001110 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111}
1112
1113static inline void stop_urb(struct urb *urb)
1114{
Greg Kroah-Hartman242cf672005-07-29 16:11:07 -04001115 if (urb && urb->status == -EINPROGRESS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 usb_kill_urb(urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117}
1118
Alan Cox335f8512009-06-11 12:26:29 +01001119static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
1120{
1121 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
1122
1123 p_priv->rts_state = on;
1124 p_priv->dtr_state = on;
1125 keyspan_send_setup(port, 0);
1126}
1127
1128static void keyspan_close(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129{
1130 int i;
1131 struct usb_serial *serial = port->serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 struct keyspan_port_private *p_priv;
1133
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +01001135
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 p_priv->rts_state = 0;
1137 p_priv->dtr_state = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001138
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139 if (serial->dev) {
1140 keyspan_send_setup(port, 2);
1141 /* pilot-xfer seems to work best with this delay */
1142 mdelay(100);
Alan Coxdeb91682008-07-22 11:13:08 +01001143 /* keyspan_set_termios(port, NULL); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 }
1145
1146 /*while (p_priv->outcont_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001147 dev_dbg(&port->dev, "%s - urb in progress\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 }*/
1149
1150 p_priv->out_flip = 0;
1151 p_priv->in_flip = 0;
1152
1153 if (serial->dev) {
1154 /* Stop reading/writing urbs */
1155 stop_urb(p_priv->inack_urb);
1156 /* stop_urb(p_priv->outcont_urb); */
1157 for (i = 0; i < 2; i++) {
1158 stop_urb(p_priv->in_urbs[i]);
1159 stop_urb(p_priv->out_urbs[i]);
1160 }
1161 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162}
1163
Alan Coxdeb91682008-07-22 11:13:08 +01001164/* download the firmware to a pre-renumeration device */
1165static int keyspan_fake_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166{
Rene Buergel8d733e22012-09-18 09:02:01 +02001167 char *fw_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001169 dev_dbg(&serial->dev->dev, "Keyspan startup version %04x product %04x\n",
1170 le16_to_cpu(serial->dev->descriptor.bcdDevice),
1171 le16_to_cpu(serial->dev->descriptor.idProduct));
Alan Coxdeb91682008-07-22 11:13:08 +01001172
1173 if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000)
1174 != 0x8000) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001175 dev_dbg(&serial->dev->dev, "Firmware already loaded. Quitting.\n");
Alan Coxdeb91682008-07-22 11:13:08 +01001176 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 }
1178
1179 /* Select firmware image on the basis of idProduct */
1180 switch (le16_to_cpu(serial->dev->descriptor.idProduct)) {
1181 case keyspan_usa28_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001182 fw_name = "keyspan/usa28.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 break;
1184
1185 case keyspan_usa28x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001186 fw_name = "keyspan/usa28x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 break;
1188
1189 case keyspan_usa28xa_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001190 fw_name = "keyspan/usa28xa.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 break;
1192
1193 case keyspan_usa28xb_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001194 fw_name = "keyspan/usa28xb.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 break;
1196
1197 case keyspan_usa19_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001198 fw_name = "keyspan/usa19.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001200
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 case keyspan_usa19qi_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001202 fw_name = "keyspan/usa19qi.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001204
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 case keyspan_mpr_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001206 fw_name = "keyspan/mpr.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 break;
1208
1209 case keyspan_usa19qw_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001210 fw_name = "keyspan/usa19qw.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001212
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 case keyspan_usa18x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001214 fw_name = "keyspan/usa18x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001216
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 case keyspan_usa19w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001218 fw_name = "keyspan/usa19w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001220
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 case keyspan_usa49w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001222 fw_name = "keyspan/usa49w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 break;
1224
1225 case keyspan_usa49wlc_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001226 fw_name = "keyspan/usa49wlc.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 break;
1228
1229 default:
David Woodhouse2971c572008-05-30 14:04:03 +03001230 dev_err(&serial->dev->dev, "Unknown product ID (%04x)\n",
1231 le16_to_cpu(serial->dev->descriptor.idProduct));
1232 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 }
1234
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001235 dev_dbg(&serial->dev->dev, "Uploading Keyspan %s firmware.\n", fw_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236
Rene Buergel8d733e22012-09-18 09:02:01 +02001237 if (ezusb_fx1_ihex_firmware_download(serial->dev, fw_name) < 0) {
1238 dev_err(&serial->dev->dev, "failed to load firmware \"%s\"\n",
1239 fw_name);
1240 return -ENOENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241 }
1242
Rene Buergel8d733e22012-09-18 09:02:01 +02001243 /* after downloading firmware Renumeration will occur in a
1244 moment and the new device will bind to the real driver */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245
1246 /* we don't want this device to have a driver assigned to it. */
Alan Coxdeb91682008-07-22 11:13:08 +01001247 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248}
1249
1250/* Helper functions used by keyspan_setup_urbs */
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001251static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *serial,
1252 int endpoint)
1253{
1254 struct usb_host_interface *iface_desc;
1255 struct usb_endpoint_descriptor *ep;
1256 int i;
1257
1258 iface_desc = serial->interface->cur_altsetting;
1259 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1260 ep = &iface_desc->endpoint[i].desc;
1261 if (ep->bEndpointAddress == endpoint)
1262 return ep;
1263 }
1264 dev_warn(&serial->interface->dev, "found no endpoint descriptor for "
1265 "endpoint %x\n", endpoint);
1266 return NULL;
1267}
1268
Alan Coxdeb91682008-07-22 11:13:08 +01001269static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 int dir, void *ctx, char *buf, int len,
David Howells7d12e782006-10-05 14:55:46 +01001271 void (*callback)(struct urb *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272{
1273 struct urb *urb;
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001274 struct usb_endpoint_descriptor const *ep_desc;
1275 char const *ep_type_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276
1277 if (endpoint == -1)
1278 return NULL; /* endpoint not needed */
1279
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001280 dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %d.\n", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
1282 if (urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001283 dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %d failed.\n", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 return NULL;
1285 }
1286
Lucy McCoy0ca12682007-05-18 12:10:41 -07001287 if (endpoint == 0) {
1288 /* control EP filled in when used */
1289 return urb;
1290 }
1291
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001292 ep_desc = find_ep(serial, endpoint);
1293 if (!ep_desc) {
1294 /* leak the urb, something's wrong and the callers don't care */
1295 return urb;
1296 }
1297 if (usb_endpoint_xfer_int(ep_desc)) {
1298 ep_type_name = "INT";
1299 usb_fill_int_urb(urb, serial->dev,
1300 usb_sndintpipe(serial->dev, endpoint) | dir,
1301 buf, len, callback, ctx,
1302 ep_desc->bInterval);
1303 } else if (usb_endpoint_xfer_bulk(ep_desc)) {
1304 ep_type_name = "BULK";
1305 usb_fill_bulk_urb(urb, serial->dev,
1306 usb_sndbulkpipe(serial->dev, endpoint) | dir,
1307 buf, len, callback, ctx);
1308 } else {
1309 dev_warn(&serial->interface->dev,
1310 "unsupported endpoint type %x\n",
Julia Lawall2e0fe702008-12-29 11:22:14 +01001311 usb_endpoint_type(ep_desc));
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001312 usb_free_urb(urb);
1313 return NULL;
1314 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001316 dev_dbg(&serial->interface->dev, "%s - using urb %p for %s endpoint %x\n",
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001317 __func__, urb, ep_type_name, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 return urb;
1319}
1320
1321static struct callbacks {
David Howells7d12e782006-10-05 14:55:46 +01001322 void (*instat_callback)(struct urb *);
1323 void (*glocont_callback)(struct urb *);
1324 void (*indat_callback)(struct urb *);
1325 void (*outdat_callback)(struct urb *);
1326 void (*inack_callback)(struct urb *);
1327 void (*outcont_callback)(struct urb *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328} keyspan_callbacks[] = {
1329 {
1330 /* msg_usa26 callbacks */
1331 .instat_callback = usa26_instat_callback,
1332 .glocont_callback = usa26_glocont_callback,
1333 .indat_callback = usa26_indat_callback,
1334 .outdat_callback = usa2x_outdat_callback,
1335 .inack_callback = usa26_inack_callback,
1336 .outcont_callback = usa26_outcont_callback,
1337 }, {
1338 /* msg_usa28 callbacks */
1339 .instat_callback = usa28_instat_callback,
1340 .glocont_callback = usa28_glocont_callback,
1341 .indat_callback = usa28_indat_callback,
1342 .outdat_callback = usa2x_outdat_callback,
1343 .inack_callback = usa28_inack_callback,
1344 .outcont_callback = usa28_outcont_callback,
1345 }, {
1346 /* msg_usa49 callbacks */
1347 .instat_callback = usa49_instat_callback,
1348 .glocont_callback = usa49_glocont_callback,
1349 .indat_callback = usa49_indat_callback,
1350 .outdat_callback = usa2x_outdat_callback,
1351 .inack_callback = usa49_inack_callback,
1352 .outcont_callback = usa49_outcont_callback,
1353 }, {
1354 /* msg_usa90 callbacks */
1355 .instat_callback = usa90_instat_callback,
Alan Coxdeb91682008-07-22 11:13:08 +01001356 .glocont_callback = usa28_glocont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 .indat_callback = usa90_indat_callback,
1358 .outdat_callback = usa2x_outdat_callback,
1359 .inack_callback = usa28_inack_callback,
1360 .outcont_callback = usa90_outcont_callback,
Lucy McCoy0ca12682007-05-18 12:10:41 -07001361 }, {
1362 /* msg_usa67 callbacks */
1363 .instat_callback = usa67_instat_callback,
1364 .glocont_callback = usa67_glocont_callback,
1365 .indat_callback = usa26_indat_callback,
1366 .outdat_callback = usa2x_outdat_callback,
1367 .inack_callback = usa26_inack_callback,
1368 .outcont_callback = usa26_outcont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 }
1370};
1371
1372 /* Generic setup urbs function that uses
1373 data in device_details */
1374static void keyspan_setup_urbs(struct usb_serial *serial)
1375{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 struct keyspan_serial_private *s_priv;
1377 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 struct callbacks *cback;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 s_priv = usb_get_serial_data(serial);
1381 d_details = s_priv->device_details;
1382
Alan Coxdeb91682008-07-22 11:13:08 +01001383 /* Setup values for the various callback routines */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384 cback = &keyspan_callbacks[d_details->msg_format];
1385
Alan Coxdeb91682008-07-22 11:13:08 +01001386 /* Allocate and set up urbs for each one that is in use,
1387 starting with instat endpoints */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388 s_priv->instat_urb = keyspan_setup_urb
1389 (serial, d_details->instat_endpoint, USB_DIR_IN,
1390 serial, s_priv->instat_buf, INSTAT_BUFLEN,
1391 cback->instat_callback);
1392
Lucy McCoy0ca12682007-05-18 12:10:41 -07001393 s_priv->indat_urb = keyspan_setup_urb
1394 (serial, d_details->indat_endpoint, USB_DIR_IN,
1395 serial, s_priv->indat_buf, INDAT49W_BUFLEN,
1396 usa49wg_indat_callback);
1397
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398 s_priv->glocont_urb = keyspan_setup_urb
1399 (serial, d_details->glocont_endpoint, USB_DIR_OUT,
1400 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
1401 cback->glocont_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402}
1403
1404/* usa19 function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001405static int keyspan_usa19_calc_baud(struct usb_serial_port *port,
1406 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 u8 *rate_low, u8 *prescaler, int portnum)
1408{
1409 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001410 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 cnt; /* inverse of divisor (programmed into 8051) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001413 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414
Alan Coxdeb91682008-07-22 11:13:08 +01001415 /* prevent divide by zero... */
1416 b16 = baud_rate * 16L;
1417 if (b16 == 0)
1418 return KEYSPAN_INVALID_BAUD_RATE;
1419 /* Any "standard" rate over 57k6 is marginal on the USA-19
1420 as we run out of divisor resolution. */
1421 if (baud_rate > 57600)
1422 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423
Alan Coxdeb91682008-07-22 11:13:08 +01001424 /* calculate the divisor and the counter (its inverse) */
1425 div = baudclk / b16;
1426 if (div == 0)
1427 return KEYSPAN_INVALID_BAUD_RATE;
1428 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430
Alan Coxdeb91682008-07-22 11:13:08 +01001431 if (div > 0xffff)
1432 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433
Alan Coxdeb91682008-07-22 11:13:08 +01001434 /* return the counter values if non-null */
1435 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001437 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001439 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001440 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001441 __func__, baud_rate, *rate_hi, *rate_low);
1442 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443}
1444
1445/* usa19hs function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001446static int keyspan_usa19hs_calc_baud(struct usb_serial_port *port,
1447 u32 baud_rate, u32 baudclk, u8 *rate_hi,
1448 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449{
1450 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001451 div; /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001453 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454
Alan Coxdeb91682008-07-22 11:13:08 +01001455 /* prevent divide by zero... */
1456 b16 = baud_rate * 16L;
1457 if (b16 == 0)
1458 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459
Alan Coxdeb91682008-07-22 11:13:08 +01001460 /* calculate the divisor */
1461 div = baudclk / b16;
1462 if (div == 0)
1463 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
Alan Coxdeb91682008-07-22 11:13:08 +01001465 if (div > 0xffff)
1466 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467
Alan Coxdeb91682008-07-22 11:13:08 +01001468 /* return the counter values if non-null */
1469 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001471
1472 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 *rate_hi = (u8) ((div >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001474
1475 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001476 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001477 __func__, baud_rate, *rate_hi, *rate_low);
1478
1479 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480}
1481
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001482static int keyspan_usa19w_calc_baud(struct usb_serial_port *port,
1483 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 u8 *rate_low, u8 *prescaler, int portnum)
1485{
1486 u32 b16, /* baud rate times 16 (actual rate used internally) */
1487 clk, /* clock with 13/8 prescaler */
Alan Coxdeb91682008-07-22 11:13:08 +01001488 div, /* divisor using 13/8 prescaler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 res, /* resulting baud rate using 13/8 prescaler */
1490 diff, /* error using 13/8 prescaler */
1491 smallest_diff;
1492 u8 best_prescaler;
1493 int i;
1494
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001495 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496
Alan Coxdeb91682008-07-22 11:13:08 +01001497 /* prevent divide by zero */
1498 b16 = baud_rate * 16L;
1499 if (b16 == 0)
1500 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501
Alan Coxdeb91682008-07-22 11:13:08 +01001502 /* Calculate prescaler by trying them all and looking
1503 for best fit */
1504
1505 /* start with largest possible difference */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506 smallest_diff = 0xffffffff;
1507
1508 /* 0 is an invalid prescaler, used as a flag */
1509 best_prescaler = 0;
1510
Alan Coxdeb91682008-07-22 11:13:08 +01001511 for (i = 8; i <= 0xff; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512 clk = (baudclk * 8) / (u32) i;
Alan Coxdeb91682008-07-22 11:13:08 +01001513
1514 div = clk / b16;
1515 if (div == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517
1518 res = clk / div;
Alan Coxdeb91682008-07-22 11:13:08 +01001519 diff = (res > b16) ? (res-b16) : (b16-res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520
Alan Coxdeb91682008-07-22 11:13:08 +01001521 if (diff < smallest_diff) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 best_prescaler = i;
1523 smallest_diff = diff;
1524 }
1525 }
1526
Alan Coxdeb91682008-07-22 11:13:08 +01001527 if (best_prescaler == 0)
1528 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529
1530 clk = (baudclk * 8) / (u32) best_prescaler;
1531 div = clk / b16;
1532
Alan Coxdeb91682008-07-22 11:13:08 +01001533 /* return the divisor and prescaler if non-null */
1534 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001536 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537 *rate_hi = (u8) ((div >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 if (prescaler) {
1539 *prescaler = best_prescaler;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001540 /* dev_dbg(&port->dev, "%s - %d %d\n", __func__, *prescaler, div); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 }
Alan Coxdeb91682008-07-22 11:13:08 +01001542 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543}
1544
1545 /* USA-28 supports different maximum baud rates on each port */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001546static int keyspan_usa28_calc_baud(struct usb_serial_port *port,
1547 u32 baud_rate, u32 baudclk, u8 *rate_hi,
1548 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549{
1550 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001551 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 cnt; /* inverse of divisor (programmed into 8051) */
1553
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001554 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555
1556 /* prevent divide by zero */
Alan Coxdeb91682008-07-22 11:13:08 +01001557 b16 = baud_rate * 16L;
1558 if (b16 == 0)
1559 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560
Alan Coxdeb91682008-07-22 11:13:08 +01001561 /* calculate the divisor and the counter (its inverse) */
1562 div = KEYSPAN_USA28_BAUDCLK / b16;
1563 if (div == 0)
1564 return KEYSPAN_INVALID_BAUD_RATE;
1565 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567
Alan Coxdeb91682008-07-22 11:13:08 +01001568 /* check for out of range, based on portnum,
1569 and return result */
1570 if (portnum == 0) {
1571 if (div > 0xffff)
1572 return KEYSPAN_INVALID_BAUD_RATE;
1573 } else {
1574 if (portnum == 1) {
1575 if (div > 0xff)
1576 return KEYSPAN_INVALID_BAUD_RATE;
1577 } else
1578 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 }
1580
1581 /* return the counter values if not NULL
1582 (port 1 will ignore retHi) */
Alan Coxdeb91682008-07-22 11:13:08 +01001583 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001585 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001587 dev_dbg(&port->dev, "%s - %d OK.\n", __func__, baud_rate);
Alan Coxdeb91682008-07-22 11:13:08 +01001588 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589}
1590
1591static int keyspan_usa26_send_setup(struct usb_serial *serial,
1592 struct usb_serial_port *port,
1593 int reset_port)
1594{
Alan Coxdeb91682008-07-22 11:13:08 +01001595 struct keyspan_usa26_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 struct keyspan_serial_private *s_priv;
1597 struct keyspan_port_private *p_priv;
1598 const struct keyspan_device_details *d_details;
1599 int outcont_urb;
1600 struct urb *this_urb;
1601 int device_port, err;
1602
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001603 dev_dbg(&port->dev, "%s reset=%d\n", __func__, reset_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604
1605 s_priv = usb_get_serial_data(serial);
1606 p_priv = usb_get_serial_port_data(port);
1607 d_details = s_priv->device_details;
1608 device_port = port->number - port->serial->minor;
1609
1610 outcont_urb = d_details->outcont_endpoints[port->number];
1611 this_urb = p_priv->outcont_urb;
1612
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001613 dev_dbg(&port->dev, "%s - endpoint %d\n", __func__, usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614
1615 /* Make sure we have an urb then send the message */
1616 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001617 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618 return -1;
1619 }
1620
1621 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001622 Don't overwrite resend for open/close condition. */
1623 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624 p_priv->resend_cont = reset_port + 1;
1625 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001626 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001628 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 }
1630
Alan Coxdeb91682008-07-22 11:13:08 +01001631 memset(&msg, 0, sizeof(struct keyspan_usa26_portControlMessage));
1632
1633 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 if (p_priv->old_baud != p_priv->baud) {
1635 p_priv->old_baud = p_priv->baud;
1636 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001637 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1638 &msg.baudHi, &msg.baudLo, &msg.prescaler,
1639 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1640 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
1641 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642 msg.baudLo = 0;
1643 msg.baudHi = 125; /* Values for 9600 baud */
1644 msg.prescaler = 10;
1645 }
1646 msg.setPrescaler = 0xff;
1647 }
1648
Ben Minerds2b982ab2012-07-12 00:10:16 +10001649 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650 switch (p_priv->cflag & CSIZE) {
1651 case CS5:
1652 msg.lcr |= USA_DATABITS_5;
1653 break;
1654 case CS6:
1655 msg.lcr |= USA_DATABITS_6;
1656 break;
1657 case CS7:
1658 msg.lcr |= USA_DATABITS_7;
1659 break;
1660 case CS8:
1661 msg.lcr |= USA_DATABITS_8;
1662 break;
1663 }
1664 if (p_priv->cflag & PARENB) {
1665 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10001666 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01001667 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 }
1669 msg.setLcr = 0xff;
1670
1671 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1672 msg.xonFlowControl = 0;
1673 msg.setFlowControl = 0xff;
1674 msg.forwardingLength = 16;
1675 msg.xonChar = 17;
1676 msg.xoffChar = 19;
1677
1678 /* Opening port */
1679 if (reset_port == 1) {
1680 msg._txOn = 1;
1681 msg._txOff = 0;
1682 msg.txFlush = 0;
1683 msg.txBreak = 0;
1684 msg.rxOn = 1;
1685 msg.rxOff = 0;
1686 msg.rxFlush = 1;
1687 msg.rxForward = 0;
1688 msg.returnStatus = 0;
1689 msg.resetDataToggle = 0xff;
1690 }
1691
1692 /* Closing port */
1693 else if (reset_port == 2) {
1694 msg._txOn = 0;
1695 msg._txOff = 1;
1696 msg.txFlush = 0;
1697 msg.txBreak = 0;
1698 msg.rxOn = 0;
1699 msg.rxOff = 1;
1700 msg.rxFlush = 1;
1701 msg.rxForward = 0;
1702 msg.returnStatus = 0;
1703 msg.resetDataToggle = 0;
1704 }
1705
1706 /* Sending intermediate configs */
1707 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001708 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 msg._txOff = 0;
1710 msg.txFlush = 0;
1711 msg.txBreak = (p_priv->break_on);
1712 msg.rxOn = 0;
1713 msg.rxOff = 0;
1714 msg.rxFlush = 0;
1715 msg.rxForward = 0;
1716 msg.returnStatus = 0;
1717 msg.resetDataToggle = 0x0;
1718 }
1719
Alan Coxdeb91682008-07-22 11:13:08 +01001720 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721 msg.setTxTriState_setRts = 0xff;
1722 msg.txTriState_rts = p_priv->rts_state;
1723
1724 msg.setHskoa_setDtr = 0xff;
1725 msg.hskoa_dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01001726
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001728 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
1729
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730 /* send the data out the device on control endpoint */
1731 this_urb->transfer_buffer_length = sizeof(msg);
1732
Alan Coxdeb91682008-07-22 11:13:08 +01001733 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1734 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001735 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736#if 0
1737 else {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001738 dev_dbg(&port->dev, "%s - usb_submit_urb(%d) OK %d bytes (end %d)\n", __func__
1739 outcont_urb, this_urb->transfer_buffer_length,
1740 usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741 }
1742#endif
1743
Alan Coxa5b6f602008-04-08 17:16:06 +01001744 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745}
1746
1747static int keyspan_usa28_send_setup(struct usb_serial *serial,
1748 struct usb_serial_port *port,
1749 int reset_port)
1750{
Alan Coxdeb91682008-07-22 11:13:08 +01001751 struct keyspan_usa28_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752 struct keyspan_serial_private *s_priv;
1753 struct keyspan_port_private *p_priv;
1754 const struct keyspan_device_details *d_details;
1755 struct urb *this_urb;
1756 int device_port, err;
1757
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758 s_priv = usb_get_serial_data(serial);
1759 p_priv = usb_get_serial_port_data(port);
1760 d_details = s_priv->device_details;
1761 device_port = port->number - port->serial->minor;
1762
1763 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01001764 this_urb = p_priv->outcont_urb;
1765 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001766 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767 return -1;
1768 }
1769
1770 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001771 Don't overwrite resend for open/close condition. */
1772 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773 p_priv->resend_cont = reset_port + 1;
1774 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001775 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001777 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 }
1779
Alan Coxdeb91682008-07-22 11:13:08 +01001780 memset(&msg, 0, sizeof(struct keyspan_usa28_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781
1782 msg.setBaudRate = 1;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001783 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1784 &msg.baudHi, &msg.baudLo, NULL,
1785 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1786 dev_dbg(&port->dev, "%s - Invalid baud rate requested %d.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001787 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788 msg.baudLo = 0xff;
1789 msg.baudHi = 0xb2; /* Values for 9600 baud */
1790 }
1791
1792 /* If parity is enabled, we must calculate it ourselves. */
1793 msg.parity = 0; /* XXX for now */
1794
1795 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1796 msg.xonFlowControl = 0;
1797
Alan Coxdeb91682008-07-22 11:13:08 +01001798 /* Do handshaking outputs, DTR is inverted relative to RTS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799 msg.rts = p_priv->rts_state;
1800 msg.dtr = p_priv->dtr_state;
1801
1802 msg.forwardingLength = 16;
1803 msg.forwardMs = 10;
1804 msg.breakThreshold = 45;
1805 msg.xonChar = 17;
1806 msg.xoffChar = 19;
1807
1808 /*msg.returnStatus = 1;
1809 msg.resetDataToggle = 0xff;*/
1810 /* Opening port */
1811 if (reset_port == 1) {
1812 msg._txOn = 1;
1813 msg._txOff = 0;
1814 msg.txFlush = 0;
1815 msg.txForceXoff = 0;
1816 msg.txBreak = 0;
1817 msg.rxOn = 1;
1818 msg.rxOff = 0;
1819 msg.rxFlush = 1;
1820 msg.rxForward = 0;
1821 msg.returnStatus = 0;
1822 msg.resetDataToggle = 0xff;
1823 }
1824 /* Closing port */
1825 else if (reset_port == 2) {
1826 msg._txOn = 0;
1827 msg._txOff = 1;
1828 msg.txFlush = 0;
1829 msg.txForceXoff = 0;
1830 msg.txBreak = 0;
1831 msg.rxOn = 0;
1832 msg.rxOff = 1;
1833 msg.rxFlush = 1;
1834 msg.rxForward = 0;
1835 msg.returnStatus = 0;
1836 msg.resetDataToggle = 0;
1837 }
1838 /* Sending intermediate configs */
1839 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001840 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 msg._txOff = 0;
1842 msg.txFlush = 0;
1843 msg.txForceXoff = 0;
1844 msg.txBreak = (p_priv->break_on);
1845 msg.rxOn = 0;
1846 msg.rxOff = 0;
1847 msg.rxFlush = 0;
1848 msg.rxForward = 0;
1849 msg.returnStatus = 0;
1850 msg.resetDataToggle = 0x0;
1851 }
1852
1853 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001854 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855
1856 /* send the data out the device on control endpoint */
1857 this_urb->transfer_buffer_length = sizeof(msg);
1858
Alan Coxdeb91682008-07-22 11:13:08 +01001859 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1860 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001861 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862#if 0
1863 else {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001864 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) OK %d bytes\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865 this_urb->transfer_buffer_length);
1866 }
1867#endif
1868
Alan Coxa5b6f602008-04-08 17:16:06 +01001869 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870}
1871
1872static int keyspan_usa49_send_setup(struct usb_serial *serial,
1873 struct usb_serial_port *port,
1874 int reset_port)
1875{
Lucy McCoy0ca12682007-05-18 12:10:41 -07001876 struct keyspan_usa49_portControlMessage msg;
1877 struct usb_ctrlrequest *dr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878 struct keyspan_serial_private *s_priv;
1879 struct keyspan_port_private *p_priv;
1880 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881 struct urb *this_urb;
1882 int err, device_port;
1883
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884 s_priv = usb_get_serial_data(serial);
1885 p_priv = usb_get_serial_port_data(port);
1886 d_details = s_priv->device_details;
1887
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888 this_urb = s_priv->glocont_urb;
1889
Lucy McCoy0ca12682007-05-18 12:10:41 -07001890 /* Work out which port within the device is being setup */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891 device_port = port->number - port->serial->minor;
1892
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05301893 /* Make sure we have an urb then send the message */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001895 dev_dbg(&port->dev, "%s - oops no urb for port %d.\n", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 return -1;
1897 }
1898
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001899 dev_dbg(&port->dev, "%s - endpoint %d port %d (%d)\n",
1900 __func__, usb_pipeendpoint(this_urb->pipe),
1901 port->number, device_port);
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05301902
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001904 Don't overwrite resend for open/close condition. */
1905 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906 p_priv->resend_cont = reset_port + 1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001907
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001909 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001911 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912 }
1913
Alan Coxdeb91682008-07-22 11:13:08 +01001914 memset(&msg, 0, sizeof(struct keyspan_usa49_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915
1916 /*msg.portNumber = port->number;*/
1917 msg.portNumber = device_port;
Alan Coxdeb91682008-07-22 11:13:08 +01001918
1919 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920 if (p_priv->old_baud != p_priv->baud) {
1921 p_priv->old_baud = p_priv->baud;
1922 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001923 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1924 &msg.baudHi, &msg.baudLo, &msg.prescaler,
1925 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1926 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
1927 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928 msg.baudLo = 0;
1929 msg.baudHi = 125; /* Values for 9600 baud */
1930 msg.prescaler = 10;
1931 }
Alan Coxdeb91682008-07-22 11:13:08 +01001932 /* msg.setPrescaler = 0xff; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 }
1934
Ben Minerds2b982ab2012-07-12 00:10:16 +10001935 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936 switch (p_priv->cflag & CSIZE) {
1937 case CS5:
1938 msg.lcr |= USA_DATABITS_5;
1939 break;
1940 case CS6:
1941 msg.lcr |= USA_DATABITS_6;
1942 break;
1943 case CS7:
1944 msg.lcr |= USA_DATABITS_7;
1945 break;
1946 case CS8:
1947 msg.lcr |= USA_DATABITS_8;
1948 break;
1949 }
1950 if (p_priv->cflag & PARENB) {
1951 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10001952 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01001953 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954 }
1955 msg.setLcr = 0xff;
1956
1957 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1958 msg.xonFlowControl = 0;
1959 msg.setFlowControl = 0xff;
Alan Coxdeb91682008-07-22 11:13:08 +01001960
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 msg.forwardingLength = 16;
1962 msg.xonChar = 17;
1963 msg.xoffChar = 19;
1964
Alan Coxdeb91682008-07-22 11:13:08 +01001965 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966 if (reset_port == 1) {
1967 msg._txOn = 1;
1968 msg._txOff = 0;
1969 msg.txFlush = 0;
1970 msg.txBreak = 0;
1971 msg.rxOn = 1;
1972 msg.rxOff = 0;
1973 msg.rxFlush = 1;
1974 msg.rxForward = 0;
1975 msg.returnStatus = 0;
1976 msg.resetDataToggle = 0xff;
1977 msg.enablePort = 1;
1978 msg.disablePort = 0;
1979 }
1980 /* Closing port */
1981 else if (reset_port == 2) {
1982 msg._txOn = 0;
1983 msg._txOff = 1;
1984 msg.txFlush = 0;
1985 msg.txBreak = 0;
1986 msg.rxOn = 0;
1987 msg.rxOff = 1;
1988 msg.rxFlush = 1;
1989 msg.rxForward = 0;
1990 msg.returnStatus = 0;
1991 msg.resetDataToggle = 0;
1992 msg.enablePort = 0;
1993 msg.disablePort = 1;
1994 }
1995 /* Sending intermediate configs */
1996 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001997 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 msg._txOff = 0;
1999 msg.txFlush = 0;
2000 msg.txBreak = (p_priv->break_on);
2001 msg.rxOn = 0;
2002 msg.rxOff = 0;
2003 msg.rxFlush = 0;
2004 msg.rxForward = 0;
2005 msg.returnStatus = 0;
2006 msg.resetDataToggle = 0x0;
2007 msg.enablePort = 0;
2008 msg.disablePort = 0;
2009 }
2010
Alan Coxdeb91682008-07-22 11:13:08 +01002011 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012 msg.setRts = 0xff;
2013 msg.rts = p_priv->rts_state;
2014
2015 msg.setDtr = 0xff;
2016 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002017
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018 p_priv->resend_cont = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019
Alan Coxdeb91682008-07-22 11:13:08 +01002020 /* if the device is a 49wg, we send control message on usb
2021 control EP 0 */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002022
2023 if (d_details->product_id == keyspan_usa49wg_product_id) {
2024 dr = (void *)(s_priv->ctrl_buf);
2025 dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT;
2026 dr->bRequest = 0xB0; /* 49wg control message */;
2027 dr->wValue = 0;
2028 dr->wIndex = 0;
2029 dr->wLength = cpu_to_le16(sizeof(msg));
2030
Alan Coxdeb91682008-07-22 11:13:08 +01002031 memcpy(s_priv->glocont_buf, &msg, sizeof(msg));
Lucy McCoy0ca12682007-05-18 12:10:41 -07002032
Alan Coxdeb91682008-07-22 11:13:08 +01002033 usb_fill_control_urb(this_urb, serial->dev,
2034 usb_sndctrlpipe(serial->dev, 0),
2035 (unsigned char *)dr, s_priv->glocont_buf,
2036 sizeof(msg), usa49_glocont_callback, serial);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002037
2038 } else {
2039 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Alan Coxdeb91682008-07-22 11:13:08 +01002040
Lucy McCoy0ca12682007-05-18 12:10:41 -07002041 /* send the data out the device on control endpoint */
2042 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002043 }
Alan Coxdeb91682008-07-22 11:13:08 +01002044 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2045 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002046 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047#if 0
2048 else {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002049 dev_dbg(&port->dev, "%s - usb_submit_urb(%d) OK %d bytes (end %d)\n", __func__,
2050 outcont_urb, this_urb->transfer_buffer_length,
2051 usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052 }
2053#endif
2054
Alan Coxa5b6f602008-04-08 17:16:06 +01002055 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056}
2057
2058static int keyspan_usa90_send_setup(struct usb_serial *serial,
2059 struct usb_serial_port *port,
2060 int reset_port)
2061{
Alan Coxdeb91682008-07-22 11:13:08 +01002062 struct keyspan_usa90_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 struct keyspan_serial_private *s_priv;
2064 struct keyspan_port_private *p_priv;
2065 const struct keyspan_device_details *d_details;
2066 struct urb *this_urb;
2067 int err;
2068 u8 prescaler;
2069
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070 s_priv = usb_get_serial_data(serial);
2071 p_priv = usb_get_serial_port_data(port);
2072 d_details = s_priv->device_details;
2073
2074 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01002075 this_urb = p_priv->outcont_urb;
2076 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002077 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078 return -1;
2079 }
2080
2081 /* Save reset port val for resend.
2082 Don't overwrite resend for open/close condition. */
2083 if ((reset_port + 1) > p_priv->resend_cont)
2084 p_priv->resend_cont = reset_port + 1;
2085 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002086 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002088 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089 }
2090
Alan Coxdeb91682008-07-22 11:13:08 +01002091 memset(&msg, 0, sizeof(struct keyspan_usa90_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092
Alan Coxdeb91682008-07-22 11:13:08 +01002093 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094 if (p_priv->old_baud != p_priv->baud) {
2095 p_priv->old_baud = p_priv->baud;
2096 msg.setClocking = 0x01;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002097 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2098 &msg.baudHi, &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) {
2099 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2100 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101 p_priv->baud = 9600;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002102 d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 &msg.baudHi, &msg.baudLo, &prescaler, 0);
2104 }
2105 msg.setRxMode = 1;
2106 msg.setTxMode = 1;
2107 }
2108
2109 /* modes must always be correctly specified */
Alan Coxdeb91682008-07-22 11:13:08 +01002110 if (p_priv->baud > 57600) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111 msg.rxMode = RXMODE_DMA;
2112 msg.txMode = TXMODE_DMA;
Alan Coxdeb91682008-07-22 11:13:08 +01002113 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 msg.rxMode = RXMODE_BYHAND;
2115 msg.txMode = TXMODE_BYHAND;
2116 }
2117
Ben Minerds2b982ab2012-07-12 00:10:16 +10002118 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119 switch (p_priv->cflag & CSIZE) {
2120 case CS5:
2121 msg.lcr |= USA_DATABITS_5;
2122 break;
2123 case CS6:
2124 msg.lcr |= USA_DATABITS_6;
2125 break;
2126 case CS7:
2127 msg.lcr |= USA_DATABITS_7;
2128 break;
2129 case CS8:
2130 msg.lcr |= USA_DATABITS_8;
2131 break;
2132 }
2133 if (p_priv->cflag & PARENB) {
2134 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002135 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002136 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137 }
2138 if (p_priv->old_cflag != p_priv->cflag) {
2139 p_priv->old_cflag = p_priv->cflag;
2140 msg.setLcr = 0x01;
2141 }
2142
2143 if (p_priv->flow_control == flow_cts)
2144 msg.txFlowControl = TXFLOW_CTS;
2145 msg.setTxFlowControl = 0x01;
2146 msg.setRxFlowControl = 0x01;
Alan Coxdeb91682008-07-22 11:13:08 +01002147
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148 msg.rxForwardingLength = 16;
Alan Coxdeb91682008-07-22 11:13:08 +01002149 msg.rxForwardingTimeout = 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150 msg.txAckSetting = 0;
2151 msg.xonChar = 17;
2152 msg.xoffChar = 19;
2153
Alan Coxdeb91682008-07-22 11:13:08 +01002154 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155 if (reset_port == 1) {
2156 msg.portEnabled = 1;
2157 msg.rxFlush = 1;
2158 msg.txBreak = (p_priv->break_on);
2159 }
2160 /* Closing port */
Alan Coxdeb91682008-07-22 11:13:08 +01002161 else if (reset_port == 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 msg.portEnabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 /* Sending intermediate configs */
2164 else {
Alan Stern1f871582010-02-17 10:05:47 -05002165 msg.portEnabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 msg.txBreak = (p_priv->break_on);
2167 }
2168
Alan Coxdeb91682008-07-22 11:13:08 +01002169 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170 msg.setRts = 0x01;
2171 msg.rts = p_priv->rts_state;
2172
2173 msg.setDtr = 0x01;
2174 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002175
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01002177 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2178
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 /* send the data out the device on control endpoint */
2180 this_urb->transfer_buffer_length = sizeof(msg);
2181
Alan Coxdeb91682008-07-22 11:13:08 +01002182 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2183 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002184 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002185 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186}
2187
Lucy McCoy0ca12682007-05-18 12:10:41 -07002188static int keyspan_usa67_send_setup(struct usb_serial *serial,
2189 struct usb_serial_port *port,
2190 int reset_port)
2191{
2192 struct keyspan_usa67_portControlMessage msg;
2193 struct keyspan_serial_private *s_priv;
2194 struct keyspan_port_private *p_priv;
2195 const struct keyspan_device_details *d_details;
2196 struct urb *this_urb;
2197 int err, device_port;
2198
Lucy McCoy0ca12682007-05-18 12:10:41 -07002199 s_priv = usb_get_serial_data(serial);
2200 p_priv = usb_get_serial_port_data(port);
2201 d_details = s_priv->device_details;
2202
2203 this_urb = s_priv->glocont_urb;
2204
2205 /* Work out which port within the device is being setup */
2206 device_port = port->number - port->serial->minor;
2207
2208 /* Make sure we have an urb then send the message */
2209 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002210 dev_dbg(&port->dev, "%s - oops no urb for port %d.\n", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002211 port->number);
2212 return -1;
2213 }
2214
2215 /* Save reset port val for resend.
2216 Don't overwrite resend for open/close condition. */
2217 if ((reset_port + 1) > p_priv->resend_cont)
2218 p_priv->resend_cont = reset_port + 1;
2219 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002220 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002221 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002222 return -1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002223 }
2224
2225 memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
2226
2227 msg.port = device_port;
2228
2229 /* Only set baud rate if it's changed */
2230 if (p_priv->old_baud != p_priv->baud) {
2231 p_priv->old_baud = p_priv->baud;
2232 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002233 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2234 &msg.baudHi, &msg.baudLo, &msg.prescaler,
2235 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2236 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2237 __func__, p_priv->baud);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002238 msg.baudLo = 0;
2239 msg.baudHi = 125; /* Values for 9600 baud */
2240 msg.prescaler = 10;
2241 }
2242 msg.setPrescaler = 0xff;
2243 }
2244
2245 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
2246 switch (p_priv->cflag & CSIZE) {
2247 case CS5:
2248 msg.lcr |= USA_DATABITS_5;
2249 break;
2250 case CS6:
2251 msg.lcr |= USA_DATABITS_6;
2252 break;
2253 case CS7:
2254 msg.lcr |= USA_DATABITS_7;
2255 break;
2256 case CS8:
2257 msg.lcr |= USA_DATABITS_8;
2258 break;
2259 }
2260 if (p_priv->cflag & PARENB) {
2261 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002262 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002263 USA_PARITY_ODD : USA_PARITY_EVEN;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002264 }
2265 msg.setLcr = 0xff;
2266
2267 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2268 msg.xonFlowControl = 0;
2269 msg.setFlowControl = 0xff;
2270 msg.forwardingLength = 16;
2271 msg.xonChar = 17;
2272 msg.xoffChar = 19;
2273
2274 if (reset_port == 1) {
2275 /* Opening port */
2276 msg._txOn = 1;
2277 msg._txOff = 0;
2278 msg.txFlush = 0;
2279 msg.txBreak = 0;
2280 msg.rxOn = 1;
2281 msg.rxOff = 0;
2282 msg.rxFlush = 1;
2283 msg.rxForward = 0;
2284 msg.returnStatus = 0;
2285 msg.resetDataToggle = 0xff;
2286 } else if (reset_port == 2) {
2287 /* Closing port */
2288 msg._txOn = 0;
2289 msg._txOff = 1;
2290 msg.txFlush = 0;
2291 msg.txBreak = 0;
2292 msg.rxOn = 0;
2293 msg.rxOff = 1;
2294 msg.rxFlush = 1;
2295 msg.rxForward = 0;
2296 msg.returnStatus = 0;
2297 msg.resetDataToggle = 0;
2298 } else {
2299 /* Sending intermediate configs */
Alan Coxdeb91682008-07-22 11:13:08 +01002300 msg._txOn = (!p_priv->break_on);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002301 msg._txOff = 0;
2302 msg.txFlush = 0;
2303 msg.txBreak = (p_priv->break_on);
2304 msg.rxOn = 0;
2305 msg.rxOff = 0;
2306 msg.rxFlush = 0;
2307 msg.rxForward = 0;
2308 msg.returnStatus = 0;
2309 msg.resetDataToggle = 0x0;
2310 }
2311
2312 /* Do handshaking outputs */
2313 msg.setTxTriState_setRts = 0xff;
2314 msg.txTriState_rts = p_priv->rts_state;
2315
2316 msg.setHskoa_setDtr = 0xff;
2317 msg.hskoa_dtr = p_priv->dtr_state;
2318
2319 p_priv->resend_cont = 0;
2320
2321 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2322
2323 /* send the data out the device on control endpoint */
2324 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002325
2326 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2327 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002328 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002329 return 0;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002330}
2331
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
2333{
2334 struct usb_serial *serial = port->serial;
2335 struct keyspan_serial_private *s_priv;
2336 const struct keyspan_device_details *d_details;
2337
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338 s_priv = usb_get_serial_data(serial);
2339 d_details = s_priv->device_details;
2340
2341 switch (d_details->msg_format) {
2342 case msg_usa26:
2343 keyspan_usa26_send_setup(serial, port, reset_port);
2344 break;
2345 case msg_usa28:
2346 keyspan_usa28_send_setup(serial, port, reset_port);
2347 break;
2348 case msg_usa49:
2349 keyspan_usa49_send_setup(serial, port, reset_port);
2350 break;
2351 case msg_usa90:
2352 keyspan_usa90_send_setup(serial, port, reset_port);
2353 break;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002354 case msg_usa67:
2355 keyspan_usa67_send_setup(serial, port, reset_port);
2356 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 }
2358}
2359
2360
2361/* Gets called by the "real" driver (ie once firmware is loaded
2362 and renumeration has taken place. */
Alan Coxdeb91682008-07-22 11:13:08 +01002363static int keyspan_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364{
2365 int i, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367 const struct keyspan_device_details *d_details;
2368
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369 for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
Alan Coxdeb91682008-07-22 11:13:08 +01002370 if (d_details->product_id ==
2371 le16_to_cpu(serial->dev->descriptor.idProduct))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 break;
2373 if (d_details == NULL) {
Alan Coxdeb91682008-07-22 11:13:08 +01002374 dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
2375 __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376 return 1;
2377 }
2378
2379 /* Setup private data for serial driver */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01002380 s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381 if (!s_priv) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002382 dev_dbg(&serial->dev->dev, "%s - kmalloc for keyspan_serial_private failed.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383 return -ENOMEM;
2384 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385
2386 s_priv->device_details = d_details;
2387 usb_set_serial_data(serial, s_priv);
2388
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389 keyspan_setup_urbs(serial);
2390
Lucy McCoy0ca12682007-05-18 12:10:41 -07002391 if (s_priv->instat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002392 err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
2393 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002394 dev_dbg(&serial->dev->dev, "%s - submit instat urb failed %d\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002395 }
2396 if (s_priv->indat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002397 err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
2398 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002399 dev_dbg(&serial->dev->dev, "%s - submit indat urb failed %d\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400 }
Alan Coxdeb91682008-07-22 11:13:08 +01002401
Alan Coxa5b6f602008-04-08 17:16:06 +01002402 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403}
2404
Alan Sternf9c99bb2009-06-02 11:53:55 -04002405static void keyspan_disconnect(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002407 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409 s_priv = usb_get_serial_data(serial);
2410
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411 stop_urb(s_priv->instat_urb);
2412 stop_urb(s_priv->glocont_urb);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002413 stop_urb(s_priv->indat_urb);
Alan Sternf9c99bb2009-06-02 11:53:55 -04002414}
2415
2416static void keyspan_release(struct usb_serial *serial)
2417{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002418 struct keyspan_serial_private *s_priv;
Alan Sternf9c99bb2009-06-02 11:53:55 -04002419
Alan Sternf9c99bb2009-06-02 11:53:55 -04002420 s_priv = usb_get_serial_data(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002422 usb_free_urb(s_priv->instat_urb);
2423 usb_free_urb(s_priv->indat_urb);
2424 usb_free_urb(s_priv->glocont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002426 kfree(s_priv);
2427}
2428
2429static int keyspan_port_probe(struct usb_serial_port *port)
2430{
2431 struct usb_serial *serial = port->serial;
Bjørn Morkf0e3e352012-11-10 10:13:42 +01002432 struct keyspan_serial_private *s_priv;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002433 struct keyspan_port_private *p_priv;
2434 const struct keyspan_device_details *d_details;
2435 struct callbacks *cback;
2436 int endp;
2437 int port_num;
2438 int i;
2439
2440 s_priv = usb_get_serial_data(serial);
2441 d_details = s_priv->device_details;
2442
2443 p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL);
2444 if (!p_priv)
2445 return -ENOMEM;
2446
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002447 p_priv->device_details = d_details;
2448
2449 /* Setup values for the various callback routines */
2450 cback = &keyspan_callbacks[d_details->msg_format];
2451
2452 port_num = port->number - port->serial->minor;
2453
2454 /* Do indat endpoints first, once for each flip */
2455 endp = d_details->indat_endpoints[port_num];
2456 for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) {
2457 p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp,
2458 USB_DIR_IN, port,
2459 p_priv->in_buffer[i], 64,
2460 cback->indat_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461 }
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002462 /* outdat endpoints also have flip */
2463 endp = d_details->outdat_endpoints[port_num];
2464 for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) {
2465 p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp,
2466 USB_DIR_OUT, port,
2467 p_priv->out_buffer[i], 64,
2468 cback->outdat_callback);
2469 }
2470 /* inack endpoint */
2471 p_priv->inack_urb = keyspan_setup_urb(serial,
2472 d_details->inack_endpoints[port_num],
2473 USB_DIR_IN, port,
2474 p_priv->inack_buffer, 1,
2475 cback->inack_callback);
2476 /* outcont endpoint */
2477 p_priv->outcont_urb = keyspan_setup_urb(serial,
2478 d_details->outcont_endpoints[port_num],
2479 USB_DIR_OUT, port,
2480 p_priv->outcont_buffer, 64,
2481 cback->outcont_callback);
2482
2483 usb_set_serial_port_data(port, p_priv);
2484
2485 return 0;
2486}
2487
2488static int keyspan_port_remove(struct usb_serial_port *port)
2489{
2490 struct keyspan_port_private *p_priv;
2491 int i;
2492
2493 p_priv = usb_get_serial_port_data(port);
2494
2495 stop_urb(p_priv->inack_urb);
2496 stop_urb(p_priv->outcont_urb);
2497 for (i = 0; i < 2; i++) {
2498 stop_urb(p_priv->in_urbs[i]);
2499 stop_urb(p_priv->out_urbs[i]);
2500 }
2501
2502 usb_free_urb(p_priv->inack_urb);
2503 usb_free_urb(p_priv->outcont_urb);
2504 for (i = 0; i < 2; i++) {
2505 usb_free_urb(p_priv->in_urbs[i]);
2506 usb_free_urb(p_priv->out_urbs[i]);
2507 }
2508
2509 kfree(p_priv);
2510
2511 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512}
2513
Alan Coxdeb91682008-07-22 11:13:08 +01002514MODULE_AUTHOR(DRIVER_AUTHOR);
2515MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516MODULE_LICENSE("GPL");
2517
David Woodhouse2971c572008-05-30 14:04:03 +03002518MODULE_FIRMWARE("keyspan/usa28.fw");
2519MODULE_FIRMWARE("keyspan/usa28x.fw");
2520MODULE_FIRMWARE("keyspan/usa28xa.fw");
2521MODULE_FIRMWARE("keyspan/usa28xb.fw");
2522MODULE_FIRMWARE("keyspan/usa19.fw");
2523MODULE_FIRMWARE("keyspan/usa19qi.fw");
2524MODULE_FIRMWARE("keyspan/mpr.fw");
2525MODULE_FIRMWARE("keyspan/usa19qw.fw");
2526MODULE_FIRMWARE("keyspan/usa18x.fw");
2527MODULE_FIRMWARE("keyspan/usa19w.fw");
2528MODULE_FIRMWARE("keyspan/usa49w.fw");
2529MODULE_FIRMWARE("keyspan/usa49wlc.fw");