blob: 14a219ba4ee62578a3b264d738b845739d0fa124 [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) {
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100475 tty_insert_flip_string(&port->port, data,
476 urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 tty_flip_buffer_push(tty);
478 }
Alan Cox4a90f092008-10-13 10:39:46 +0100479 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480
481 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500482 err = usb_submit_urb(urb, GFP_ATOMIC);
483 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700484 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n",
Alan Stern1f871582010-02-17 10:05:47 -0500485 __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 p_priv->in_flip ^= 1;
487
488 urb = p_priv->in_urbs[p_priv->in_flip];
489 } while (urb->status != -EINPROGRESS);
490}
491
David Howells7d12e782006-10-05 14:55:46 +0100492static void usa28_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494}
495
David Howells7d12e782006-10-05 14:55:46 +0100496static void usa28_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497{
498 struct usb_serial_port *port;
499 struct keyspan_port_private *p_priv;
500
Ming Leicdc97792008-02-24 18:41:47 +0800501 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 p_priv = usb_get_serial_port_data(port);
503
504 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700505 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100506 keyspan_usa28_send_setup(port->serial, port,
507 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 }
509}
510
David Howells7d12e782006-10-05 14:55:46 +0100511static void usa28_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512{
513 int err;
514 unsigned char *data = urb->transfer_buffer;
515 struct keyspan_usa28_portStatusMessage *msg;
516 struct usb_serial *serial;
517 struct usb_serial_port *port;
518 struct keyspan_port_private *p_priv;
Alan Cox4a90f092008-10-13 10:39:46 +0100519 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700521 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522
Ming Leicdc97792008-02-24 18:41:47 +0800523 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700525 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700526 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 return;
528 }
529
530 if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700531 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 goto exit;
533 }
534
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700535 /*
536 dev_dbg(&urb->dev->dev,
537 "%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__,
538 data[0], data[1], data[2], data[3], data[4], data[5],
539 data[6], data[7], data[8], data[9], data[10], data[11]);
540 */
Alan Coxdeb91682008-07-22 11:13:08 +0100541
542 /* Now do something useful with the data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 msg = (struct keyspan_usa28_portStatusMessage *)data;
544
Alan Coxdeb91682008-07-22 11:13:08 +0100545 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700547 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 goto exit;
549 }
550 port = serial->port[msg->port];
551 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100552
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 /* Update handshaking pin state information */
554 old_dcd_state = p_priv->dcd_state;
555 p_priv->cts_state = ((msg->cts) ? 1 : 0);
556 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
557 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
558 p_priv->ri_state = ((msg->ri) ? 1 : 0);
559
Ben Minerdsddc04ae2012-07-12 00:10:18 +1000560 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
Alan Cox4a90f092008-10-13 10:39:46 +0100561 tty = tty_port_tty_get(&port->port);
Ben Minerds878b5fd2012-07-12 00:10:19 +1000562 if (tty && !C_CLOCAL(tty))
Alan Cox4a90f092008-10-13 10:39:46 +0100563 tty_hangup(tty);
564 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 }
566
567 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100568 err = usb_submit_urb(urb, GFP_ATOMIC);
569 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700570 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571exit: ;
572}
573
David Howells7d12e782006-10-05 14:55:46 +0100574static void usa28_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576}
577
578
David Howells7d12e782006-10-05 14:55:46 +0100579static void usa49_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580{
581 struct usb_serial *serial;
582 struct usb_serial_port *port;
583 struct keyspan_port_private *p_priv;
584 int i;
585
Ming Leicdc97792008-02-24 18:41:47 +0800586 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 for (i = 0; i < serial->num_ports; ++i) {
588 port = serial->port[i];
589 p_priv = usb_get_serial_port_data(port);
590
591 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700592 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100593 keyspan_usa49_send_setup(serial, port,
594 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 break;
596 }
597 }
598}
599
600 /* This is actually called glostat in the Keyspan
601 doco */
David Howells7d12e782006-10-05 14:55:46 +0100602static void usa49_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603{
604 int err;
605 unsigned char *data = urb->transfer_buffer;
606 struct keyspan_usa49_portStatusMessage *msg;
607 struct usb_serial *serial;
608 struct usb_serial_port *port;
609 struct keyspan_port_private *p_priv;
610 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700611 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612
Ming Leicdc97792008-02-24 18:41:47 +0800613 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700615 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700616 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 return;
618 }
619
Alan Coxdeb91682008-07-22 11:13:08 +0100620 if (urb->actual_length !=
621 sizeof(struct keyspan_usa49_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700622 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 goto exit;
624 }
625
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700626 /*
627 dev_dbg(&urb->dev->dev, "%s: %x %x %x %x %x %x %x %x %x %x %x",
628 __func__, data[0], data[1], data[2], data[3], data[4],
629 data[5], data[6], data[7], data[8], data[9], data[10]);
630 */
Alan Coxdeb91682008-07-22 11:13:08 +0100631
632 /* Now do something useful with the data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 msg = (struct keyspan_usa49_portStatusMessage *)data;
634
Alan Coxdeb91682008-07-22 11:13:08 +0100635 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 if (msg->portNumber >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700637 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
638 __func__, msg->portNumber);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 goto exit;
640 }
641 port = serial->port[msg->portNumber];
642 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100643
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 /* Update handshaking pin state information */
645 old_dcd_state = p_priv->dcd_state;
646 p_priv->cts_state = ((msg->cts) ? 1 : 0);
647 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
648 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
649 p_priv->ri_state = ((msg->ri) ? 1 : 0);
650
Alan Cox4a90f092008-10-13 10:39:46 +0100651 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
652 struct tty_struct *tty = tty_port_tty_get(&port->port);
653 if (tty && !C_CLOCAL(tty))
654 tty_hangup(tty);
655 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 }
657
Alan Coxdeb91682008-07-22 11:13:08 +0100658 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100659 err = usb_submit_urb(urb, GFP_ATOMIC);
660 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700661 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662exit: ;
663}
664
David Howells7d12e782006-10-05 14:55:46 +0100665static void usa49_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667}
668
David Howells7d12e782006-10-05 14:55:46 +0100669static void usa49_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670{
671 int i, err;
672 int endpoint;
673 struct usb_serial_port *port;
674 struct tty_struct *tty;
675 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700676 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 endpoint = usb_pipeendpoint(urb->pipe);
679
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700680 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700681 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
682 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683 return;
684 }
685
Ming Leicdc97792008-02-24 18:41:47 +0800686 port = urb->context;
Alan Cox4a90f092008-10-13 10:39:46 +0100687 tty = tty_port_tty_get(&port->port);
Alan Cox3004e532008-01-03 16:59:04 +0000688 if (tty && urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 /* 0x80 bit is error flag */
690 if ((data[0] & 0x80) == 0) {
691 /* no error on any byte */
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100692 tty_insert_flip_string(&port->port, data + 1,
Alan Coxf035a8a2008-07-22 11:13:32 +0100693 urb->actual_length - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 } else {
695 /* some bytes had errors, every byte has status */
696 for (i = 0; i + 1 < urb->actual_length; i += 2) {
697 int stat = data[i], flag = 0;
698 if (stat & RXERROR_OVERRUN)
699 flag |= TTY_OVERRUN;
700 if (stat & RXERROR_FRAMING)
701 flag |= TTY_FRAME;
702 if (stat & RXERROR_PARITY)
703 flag |= TTY_PARITY;
704 /* XXX should handle break (0x10) */
Jiri Slaby92a19f92013-01-03 15:53:03 +0100705 tty_insert_flip_char(&port->port, data[i+1],
706 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707 }
708 }
709 tty_flip_buffer_push(tty);
710 }
Alan Cox4a90f092008-10-13 10:39:46 +0100711 tty_kref_put(tty);
Alan Coxdeb91682008-07-22 11:13:08 +0100712
713 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500714 err = usb_submit_urb(urb, GFP_ATOMIC);
715 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700716 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717}
718
Lucy McCoy0ca12682007-05-18 12:10:41 -0700719static void usa49wg_indat_callback(struct urb *urb)
720{
721 int i, len, x, err;
722 struct usb_serial *serial;
723 struct usb_serial_port *port;
724 struct tty_struct *tty;
725 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700726 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700727
Lucy McCoy0ca12682007-05-18 12:10:41 -0700728 serial = urb->context;
729
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700730 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700731 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700732 return;
733 }
734
735 /* inbound data is in the form P#, len, status, data */
736 i = 0;
737 len = 0;
738
739 if (urb->actual_length) {
740 while (i < urb->actual_length) {
741
742 /* Check port number from message*/
743 if (data[i] >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700744 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800745 __func__, data[i]);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700746 return;
747 }
748 port = serial->port[data[i++]];
Alan Cox4a90f092008-10-13 10:39:46 +0100749 tty = tty_port_tty_get(&port->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700750 len = data[i++];
751
752 /* 0x80 bit is error flag */
753 if ((data[i] & 0x80) == 0) {
754 /* no error on any byte */
755 i++;
756 for (x = 1; x < len ; ++x)
Jiri Slaby92a19f92013-01-03 15:53:03 +0100757 tty_insert_flip_char(&port->port,
758 data[i++], 0);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700759 } else {
760 /*
761 * some bytes had errors, every byte has status
762 */
763 for (x = 0; x + 1 < len; x += 2) {
764 int stat = data[i], flag = 0;
765 if (stat & RXERROR_OVERRUN)
766 flag |= TTY_OVERRUN;
767 if (stat & RXERROR_FRAMING)
768 flag |= TTY_FRAME;
769 if (stat & RXERROR_PARITY)
770 flag |= TTY_PARITY;
771 /* XXX should handle break (0x10) */
Jiri Slaby92a19f92013-01-03 15:53:03 +0100772 tty_insert_flip_char(&port->port,
Lucy McCoy0ca12682007-05-18 12:10:41 -0700773 data[i+1], flag);
774 i += 2;
775 }
776 }
Alan Stern1f871582010-02-17 10:05:47 -0500777 tty_flip_buffer_push(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100778 tty_kref_put(tty);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700779 }
780 }
781
782 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700783 err = usb_submit_urb(urb, GFP_ATOMIC);
784 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700785 dev_dbg(&urb->dev->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700786}
787
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788/* not used, usa-49 doesn't have per-port control endpoints */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700789static void usa49_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791}
792
Lucy McCoy0ca12682007-05-18 12:10:41 -0700793static void usa90_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794{
795 int i, err;
796 int endpoint;
797 struct usb_serial_port *port;
798 struct keyspan_port_private *p_priv;
799 struct tty_struct *tty;
800 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700801 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 endpoint = usb_pipeendpoint(urb->pipe);
804
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700805 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700806 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800807 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 return;
809 }
810
Ming Leicdc97792008-02-24 18:41:47 +0800811 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 p_priv = usb_get_serial_port_data(port);
813
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 if (urb->actual_length) {
Alan Cox4a90f092008-10-13 10:39:46 +0100815 tty = tty_port_tty_get(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 /* if current mode is DMA, looks like usa28 format
Alan Coxdeb91682008-07-22 11:13:08 +0100817 otherwise looks like usa26 data format */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818
Alan Coxf035a8a2008-07-22 11:13:32 +0100819 if (p_priv->baud > 57600)
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100820 tty_insert_flip_string(&port->port, data,
821 urb->actual_length);
Alan Coxf035a8a2008-07-22 11:13:32 +0100822 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 /* 0x80 bit is error flag */
824 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100825 /* no errors on individual bytes, only
826 possible overrun err*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 if (data[0] & RXERROR_OVERRUN)
Alan Coxdeb91682008-07-22 11:13:08 +0100828 err = TTY_OVERRUN;
829 else
830 err = 0;
831 for (i = 1; i < urb->actual_length ; ++i)
Jiri Slaby92a19f92013-01-03 15:53:03 +0100832 tty_insert_flip_char(&port->port,
833 data[i], err);
Alan Coxdeb91682008-07-22 11:13:08 +0100834 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 /* some bytes had errors, every byte has status */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700836 dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 for (i = 0; i + 1 < urb->actual_length; i += 2) {
838 int stat = data[i], flag = 0;
839 if (stat & RXERROR_OVERRUN)
840 flag |= TTY_OVERRUN;
841 if (stat & RXERROR_FRAMING)
842 flag |= TTY_FRAME;
843 if (stat & RXERROR_PARITY)
844 flag |= TTY_PARITY;
845 /* XXX should handle break (0x10) */
Jiri Slaby92a19f92013-01-03 15:53:03 +0100846 tty_insert_flip_char(&port->port,
847 data[i+1], flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 }
849 }
850 }
851 tty_flip_buffer_push(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100852 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 }
Alan Coxdeb91682008-07-22 11:13:08 +0100854
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500856 err = usb_submit_urb(urb, GFP_ATOMIC);
857 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700858 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859}
860
861
David Howells7d12e782006-10-05 14:55:46 +0100862static void usa90_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863{
864 unsigned char *data = urb->transfer_buffer;
865 struct keyspan_usa90_portStatusMessage *msg;
866 struct usb_serial *serial;
867 struct usb_serial_port *port;
868 struct keyspan_port_private *p_priv;
Alan Cox4a90f092008-10-13 10:39:46 +0100869 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700871 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872
Ming Leicdc97792008-02-24 18:41:47 +0800873 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700875 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700876 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 return;
878 }
879 if (urb->actual_length < 14) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700880 dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 goto exit;
882 }
883
884 msg = (struct keyspan_usa90_portStatusMessage *)data;
885
886 /* Now do something useful with the data */
887
888 port = serial->port[0];
889 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100890
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 /* Update handshaking pin state information */
892 old_dcd_state = p_priv->dcd_state;
893 p_priv->cts_state = ((msg->cts) ? 1 : 0);
894 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
895 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
896 p_priv->ri_state = ((msg->ri) ? 1 : 0);
897
Alan Cox4a90f092008-10-13 10:39:46 +0100898 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
899 tty = tty_port_tty_get(&port->port);
900 if (tty && !C_CLOCAL(tty))
901 tty_hangup(tty);
902 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 }
Alan Coxdeb91682008-07-22 11:13:08 +0100904
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100906 err = usb_submit_urb(urb, GFP_ATOMIC);
907 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700908 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909exit:
910 ;
911}
912
David Howells7d12e782006-10-05 14:55:46 +0100913static void usa90_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914{
915 struct usb_serial_port *port;
916 struct keyspan_port_private *p_priv;
917
Ming Leicdc97792008-02-24 18:41:47 +0800918 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 p_priv = usb_get_serial_port_data(port);
920
921 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700922 dev_dbg(&urb->dev->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100923 keyspan_usa90_send_setup(port->serial, port,
924 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 }
926}
927
Lucy McCoy0ca12682007-05-18 12:10:41 -0700928/* Status messages from the 28xg */
929static void usa67_instat_callback(struct urb *urb)
930{
931 int err;
932 unsigned char *data = urb->transfer_buffer;
933 struct keyspan_usa67_portStatusMessage *msg;
934 struct usb_serial *serial;
935 struct usb_serial_port *port;
936 struct keyspan_port_private *p_priv;
937 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700938 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700939
Lucy McCoy0ca12682007-05-18 12:10:41 -0700940 serial = urb->context;
941
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700942 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700943 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700944 return;
945 }
946
Alan Coxdeb91682008-07-22 11:13:08 +0100947 if (urb->actual_length !=
948 sizeof(struct keyspan_usa67_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700949 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700950 return;
951 }
952
953
954 /* Now do something useful with the data */
955 msg = (struct keyspan_usa67_portStatusMessage *)data;
956
957 /* Check port number from message and retrieve private data */
958 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700959 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700960 return;
961 }
962
963 port = serial->port[msg->port];
964 p_priv = usb_get_serial_port_data(port);
965
966 /* Update handshaking pin state information */
967 old_dcd_state = p_priv->dcd_state;
968 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
969 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
970
Alan Cox4a90f092008-10-13 10:39:46 +0100971 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
972 struct tty_struct *tty = tty_port_tty_get(&port->port);
973 if (tty && !C_CLOCAL(tty))
974 tty_hangup(tty);
975 tty_kref_put(tty);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700976 }
977
978 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700979 err = usb_submit_urb(urb, GFP_ATOMIC);
980 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700981 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700982}
983
984static void usa67_glocont_callback(struct urb *urb)
985{
986 struct usb_serial *serial;
987 struct usb_serial_port *port;
988 struct keyspan_port_private *p_priv;
989 int i;
990
Lucy McCoy0ca12682007-05-18 12:10:41 -0700991 serial = urb->context;
992 for (i = 0; i < serial->num_ports; ++i) {
993 port = serial->port[i];
994 p_priv = usb_get_serial_port_data(port);
995
996 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700997 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700998 keyspan_usa67_send_setup(serial, port,
999 p_priv->resend_cont - 1);
1000 break;
1001 }
1002 }
1003}
1004
Alan Cox95da3102008-07-22 11:09:07 +01001005static int keyspan_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006{
Alan Cox95da3102008-07-22 11:09:07 +01001007 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 struct keyspan_port_private *p_priv;
1009 const struct keyspan_device_details *d_details;
1010 int flip;
1011 int data_len;
1012 struct urb *this_urb;
1013
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 p_priv = usb_get_serial_port_data(port);
1015 d_details = p_priv->device_details;
1016
Alan Coxa5b6f602008-04-08 17:16:06 +01001017 /* FIXME: locking */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 if (d_details->msg_format == msg_usa90)
Alan Coxdeb91682008-07-22 11:13:08 +01001019 data_len = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 else
1021 data_len = 63;
1022
1023 flip = p_priv->out_flip;
1024
1025 /* Check both endpoints to see if any are available. */
Alan Coxdeb91682008-07-22 11:13:08 +01001026 this_urb = p_priv->out_urbs[flip];
1027 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001029 return data_len;
1030 flip = (flip + 1) & d_details->outdat_endp_flip;
1031 this_urb = p_priv->out_urbs[flip];
1032 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001034 return data_len;
1035 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 }
Alan Coxa5b6f602008-04-08 17:16:06 +01001037 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038}
1039
1040
Alan Coxa509a7e2009-09-19 13:13:26 -07001041static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042{
Andrew Mortonf78ba152007-11-28 16:21:54 -08001043 struct keyspan_port_private *p_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 const struct keyspan_device_details *d_details;
1045 int i, err;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001046 int baud_rate, device_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 struct urb *urb;
Alan Cox95da3102008-07-22 11:09:07 +01001048 unsigned int cflag = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 p_priv = usb_get_serial_port_data(port);
1051 d_details = p_priv->device_details;
Borislav Petkov7eea4362007-11-14 17:00:39 -08001052
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 /* Set some sane defaults */
1054 p_priv->rts_state = 1;
1055 p_priv->dtr_state = 1;
1056 p_priv->baud = 9600;
1057
1058 /* force baud and lcr to be set on open */
1059 p_priv->old_baud = 0;
1060 p_priv->old_cflag = 0;
1061
1062 p_priv->out_flip = 0;
1063 p_priv->in_flip = 0;
1064
1065 /* Reset low level data toggle and start reading from endpoints */
1066 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001067 urb = p_priv->in_urbs[i];
1068 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070
Alan Coxdeb91682008-07-22 11:13:08 +01001071 /* make sure endpoint data toggle is synchronized
1072 with the device */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 usb_clear_halt(urb->dev, urb->pipe);
Alan Coxdeb91682008-07-22 11:13:08 +01001074 err = usb_submit_urb(urb, GFP_KERNEL);
1075 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001076 dev_dbg(&port->dev, "%s - submit urb %d failed (%d)\n", __func__, i, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 }
1078
1079 /* Reset low level data toggle on out endpoints */
1080 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001081 urb = p_priv->out_urbs[i];
1082 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 continue;
Alan Coxdeb91682008-07-22 11:13:08 +01001084 /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
1085 usb_pipeout(urb->pipe), 0); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 }
1087
Andrew Mortonf78ba152007-11-28 16:21:54 -08001088 /* get the terminal config for the setup message now so we don't
1089 * need to send 2 of them */
1090
Andrew Mortonf78ba152007-11-28 16:21:54 -08001091 device_port = port->number - port->serial->minor;
Alan Cox95da3102008-07-22 11:09:07 +01001092 if (tty) {
Alan Coxadc8d742012-07-14 15:31:47 +01001093 cflag = tty->termios.c_cflag;
Alan Cox95da3102008-07-22 11:09:07 +01001094 /* Baud rate calculation takes baud rate as an integer
1095 so other rates can be generated if desired. */
1096 baud_rate = tty_get_baud_rate(tty);
1097 /* If no match or invalid, leave as default */
1098 if (baud_rate >= 0
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001099 && d_details->calculate_baud_rate(port, baud_rate, d_details->baudclk,
Alan Cox95da3102008-07-22 11:09:07 +01001100 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
1101 p_priv->baud = baud_rate;
1102 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001103 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001104 /* set CTS/RTS handshake etc. */
1105 p_priv->cflag = cflag;
Ben Minerds2b982ab2012-07-12 00:10:16 +10001106 p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001107
1108 keyspan_send_setup(port, 1);
Alan Coxdeb91682008-07-22 11:13:08 +01001109 /* mdelay(100); */
1110 /* keyspan_set_termios(port, NULL); */
Andrew Mortonf78ba152007-11-28 16:21:54 -08001111
Alan Coxa5b6f602008-04-08 17:16:06 +01001112 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113}
1114
1115static inline void stop_urb(struct urb *urb)
1116{
Greg Kroah-Hartman242cf672005-07-29 16:11:07 -04001117 if (urb && urb->status == -EINPROGRESS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 usb_kill_urb(urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119}
1120
Alan Cox335f8512009-06-11 12:26:29 +01001121static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
1122{
1123 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
1124
1125 p_priv->rts_state = on;
1126 p_priv->dtr_state = on;
1127 keyspan_send_setup(port, 0);
1128}
1129
1130static void keyspan_close(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131{
1132 int i;
1133 struct usb_serial *serial = port->serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 struct keyspan_port_private *p_priv;
1135
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +01001137
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 p_priv->rts_state = 0;
1139 p_priv->dtr_state = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001140
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 if (serial->dev) {
1142 keyspan_send_setup(port, 2);
1143 /* pilot-xfer seems to work best with this delay */
1144 mdelay(100);
Alan Coxdeb91682008-07-22 11:13:08 +01001145 /* keyspan_set_termios(port, NULL); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 }
1147
1148 /*while (p_priv->outcont_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001149 dev_dbg(&port->dev, "%s - urb in progress\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 }*/
1151
1152 p_priv->out_flip = 0;
1153 p_priv->in_flip = 0;
1154
1155 if (serial->dev) {
1156 /* Stop reading/writing urbs */
1157 stop_urb(p_priv->inack_urb);
1158 /* stop_urb(p_priv->outcont_urb); */
1159 for (i = 0; i < 2; i++) {
1160 stop_urb(p_priv->in_urbs[i]);
1161 stop_urb(p_priv->out_urbs[i]);
1162 }
1163 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164}
1165
Alan Coxdeb91682008-07-22 11:13:08 +01001166/* download the firmware to a pre-renumeration device */
1167static int keyspan_fake_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168{
Rene Buergel8d733e22012-09-18 09:02:01 +02001169 char *fw_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001171 dev_dbg(&serial->dev->dev, "Keyspan startup version %04x product %04x\n",
1172 le16_to_cpu(serial->dev->descriptor.bcdDevice),
1173 le16_to_cpu(serial->dev->descriptor.idProduct));
Alan Coxdeb91682008-07-22 11:13:08 +01001174
1175 if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000)
1176 != 0x8000) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001177 dev_dbg(&serial->dev->dev, "Firmware already loaded. Quitting.\n");
Alan Coxdeb91682008-07-22 11:13:08 +01001178 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 }
1180
1181 /* Select firmware image on the basis of idProduct */
1182 switch (le16_to_cpu(serial->dev->descriptor.idProduct)) {
1183 case keyspan_usa28_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001184 fw_name = "keyspan/usa28.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 break;
1186
1187 case keyspan_usa28x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001188 fw_name = "keyspan/usa28x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 break;
1190
1191 case keyspan_usa28xa_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001192 fw_name = "keyspan/usa28xa.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193 break;
1194
1195 case keyspan_usa28xb_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001196 fw_name = "keyspan/usa28xb.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 break;
1198
1199 case keyspan_usa19_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001200 fw_name = "keyspan/usa19.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001202
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 case keyspan_usa19qi_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001204 fw_name = "keyspan/usa19qi.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001206
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 case keyspan_mpr_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001208 fw_name = "keyspan/mpr.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 break;
1210
1211 case keyspan_usa19qw_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001212 fw_name = "keyspan/usa19qw.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001214
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 case keyspan_usa18x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001216 fw_name = "keyspan/usa18x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001218
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 case keyspan_usa19w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001220 fw_name = "keyspan/usa19w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001222
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 case keyspan_usa49w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001224 fw_name = "keyspan/usa49w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 break;
1226
1227 case keyspan_usa49wlc_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001228 fw_name = "keyspan/usa49wlc.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 break;
1230
1231 default:
David Woodhouse2971c572008-05-30 14:04:03 +03001232 dev_err(&serial->dev->dev, "Unknown product ID (%04x)\n",
1233 le16_to_cpu(serial->dev->descriptor.idProduct));
1234 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 }
1236
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001237 dev_dbg(&serial->dev->dev, "Uploading Keyspan %s firmware.\n", fw_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238
Rene Buergel8d733e22012-09-18 09:02:01 +02001239 if (ezusb_fx1_ihex_firmware_download(serial->dev, fw_name) < 0) {
1240 dev_err(&serial->dev->dev, "failed to load firmware \"%s\"\n",
1241 fw_name);
1242 return -ENOENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 }
1244
Rene Buergel8d733e22012-09-18 09:02:01 +02001245 /* after downloading firmware Renumeration will occur in a
1246 moment and the new device will bind to the real driver */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247
1248 /* we don't want this device to have a driver assigned to it. */
Alan Coxdeb91682008-07-22 11:13:08 +01001249 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250}
1251
1252/* Helper functions used by keyspan_setup_urbs */
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001253static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *serial,
1254 int endpoint)
1255{
1256 struct usb_host_interface *iface_desc;
1257 struct usb_endpoint_descriptor *ep;
1258 int i;
1259
1260 iface_desc = serial->interface->cur_altsetting;
1261 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1262 ep = &iface_desc->endpoint[i].desc;
1263 if (ep->bEndpointAddress == endpoint)
1264 return ep;
1265 }
1266 dev_warn(&serial->interface->dev, "found no endpoint descriptor for "
1267 "endpoint %x\n", endpoint);
1268 return NULL;
1269}
1270
Alan Coxdeb91682008-07-22 11:13:08 +01001271static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272 int dir, void *ctx, char *buf, int len,
David Howells7d12e782006-10-05 14:55:46 +01001273 void (*callback)(struct urb *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274{
1275 struct urb *urb;
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001276 struct usb_endpoint_descriptor const *ep_desc;
1277 char const *ep_type_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278
1279 if (endpoint == -1)
1280 return NULL; /* endpoint not needed */
1281
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001282 dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %d.\n", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
1284 if (urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001285 dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %d failed.\n", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 return NULL;
1287 }
1288
Lucy McCoy0ca12682007-05-18 12:10:41 -07001289 if (endpoint == 0) {
1290 /* control EP filled in when used */
1291 return urb;
1292 }
1293
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001294 ep_desc = find_ep(serial, endpoint);
1295 if (!ep_desc) {
1296 /* leak the urb, something's wrong and the callers don't care */
1297 return urb;
1298 }
1299 if (usb_endpoint_xfer_int(ep_desc)) {
1300 ep_type_name = "INT";
1301 usb_fill_int_urb(urb, serial->dev,
1302 usb_sndintpipe(serial->dev, endpoint) | dir,
1303 buf, len, callback, ctx,
1304 ep_desc->bInterval);
1305 } else if (usb_endpoint_xfer_bulk(ep_desc)) {
1306 ep_type_name = "BULK";
1307 usb_fill_bulk_urb(urb, serial->dev,
1308 usb_sndbulkpipe(serial->dev, endpoint) | dir,
1309 buf, len, callback, ctx);
1310 } else {
1311 dev_warn(&serial->interface->dev,
1312 "unsupported endpoint type %x\n",
Julia Lawall2e0fe702008-12-29 11:22:14 +01001313 usb_endpoint_type(ep_desc));
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001314 usb_free_urb(urb);
1315 return NULL;
1316 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001318 dev_dbg(&serial->interface->dev, "%s - using urb %p for %s endpoint %x\n",
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001319 __func__, urb, ep_type_name, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 return urb;
1321}
1322
1323static struct callbacks {
David Howells7d12e782006-10-05 14:55:46 +01001324 void (*instat_callback)(struct urb *);
1325 void (*glocont_callback)(struct urb *);
1326 void (*indat_callback)(struct urb *);
1327 void (*outdat_callback)(struct urb *);
1328 void (*inack_callback)(struct urb *);
1329 void (*outcont_callback)(struct urb *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330} keyspan_callbacks[] = {
1331 {
1332 /* msg_usa26 callbacks */
1333 .instat_callback = usa26_instat_callback,
1334 .glocont_callback = usa26_glocont_callback,
1335 .indat_callback = usa26_indat_callback,
1336 .outdat_callback = usa2x_outdat_callback,
1337 .inack_callback = usa26_inack_callback,
1338 .outcont_callback = usa26_outcont_callback,
1339 }, {
1340 /* msg_usa28 callbacks */
1341 .instat_callback = usa28_instat_callback,
1342 .glocont_callback = usa28_glocont_callback,
1343 .indat_callback = usa28_indat_callback,
1344 .outdat_callback = usa2x_outdat_callback,
1345 .inack_callback = usa28_inack_callback,
1346 .outcont_callback = usa28_outcont_callback,
1347 }, {
1348 /* msg_usa49 callbacks */
1349 .instat_callback = usa49_instat_callback,
1350 .glocont_callback = usa49_glocont_callback,
1351 .indat_callback = usa49_indat_callback,
1352 .outdat_callback = usa2x_outdat_callback,
1353 .inack_callback = usa49_inack_callback,
1354 .outcont_callback = usa49_outcont_callback,
1355 }, {
1356 /* msg_usa90 callbacks */
1357 .instat_callback = usa90_instat_callback,
Alan Coxdeb91682008-07-22 11:13:08 +01001358 .glocont_callback = usa28_glocont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 .indat_callback = usa90_indat_callback,
1360 .outdat_callback = usa2x_outdat_callback,
1361 .inack_callback = usa28_inack_callback,
1362 .outcont_callback = usa90_outcont_callback,
Lucy McCoy0ca12682007-05-18 12:10:41 -07001363 }, {
1364 /* msg_usa67 callbacks */
1365 .instat_callback = usa67_instat_callback,
1366 .glocont_callback = usa67_glocont_callback,
1367 .indat_callback = usa26_indat_callback,
1368 .outdat_callback = usa2x_outdat_callback,
1369 .inack_callback = usa26_inack_callback,
1370 .outcont_callback = usa26_outcont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 }
1372};
1373
1374 /* Generic setup urbs function that uses
1375 data in device_details */
1376static void keyspan_setup_urbs(struct usb_serial *serial)
1377{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 struct keyspan_serial_private *s_priv;
1379 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 struct callbacks *cback;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382 s_priv = usb_get_serial_data(serial);
1383 d_details = s_priv->device_details;
1384
Alan Coxdeb91682008-07-22 11:13:08 +01001385 /* Setup values for the various callback routines */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 cback = &keyspan_callbacks[d_details->msg_format];
1387
Alan Coxdeb91682008-07-22 11:13:08 +01001388 /* Allocate and set up urbs for each one that is in use,
1389 starting with instat endpoints */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 s_priv->instat_urb = keyspan_setup_urb
1391 (serial, d_details->instat_endpoint, USB_DIR_IN,
1392 serial, s_priv->instat_buf, INSTAT_BUFLEN,
1393 cback->instat_callback);
1394
Lucy McCoy0ca12682007-05-18 12:10:41 -07001395 s_priv->indat_urb = keyspan_setup_urb
1396 (serial, d_details->indat_endpoint, USB_DIR_IN,
1397 serial, s_priv->indat_buf, INDAT49W_BUFLEN,
1398 usa49wg_indat_callback);
1399
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400 s_priv->glocont_urb = keyspan_setup_urb
1401 (serial, d_details->glocont_endpoint, USB_DIR_OUT,
1402 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
1403 cback->glocont_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404}
1405
1406/* usa19 function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001407static int keyspan_usa19_calc_baud(struct usb_serial_port *port,
1408 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 u8 *rate_low, u8 *prescaler, int portnum)
1410{
1411 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001412 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 cnt; /* inverse of divisor (programmed into 8051) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001415 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416
Alan Coxdeb91682008-07-22 11:13:08 +01001417 /* prevent divide by zero... */
1418 b16 = baud_rate * 16L;
1419 if (b16 == 0)
1420 return KEYSPAN_INVALID_BAUD_RATE;
1421 /* Any "standard" rate over 57k6 is marginal on the USA-19
1422 as we run out of divisor resolution. */
1423 if (baud_rate > 57600)
1424 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425
Alan Coxdeb91682008-07-22 11:13:08 +01001426 /* calculate the divisor and the counter (its inverse) */
1427 div = baudclk / b16;
1428 if (div == 0)
1429 return KEYSPAN_INVALID_BAUD_RATE;
1430 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432
Alan Coxdeb91682008-07-22 11:13:08 +01001433 if (div > 0xffff)
1434 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435
Alan Coxdeb91682008-07-22 11:13:08 +01001436 /* return the counter values if non-null */
1437 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001439 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001441 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001442 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001443 __func__, baud_rate, *rate_hi, *rate_low);
1444 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445}
1446
1447/* usa19hs function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001448static int keyspan_usa19hs_calc_baud(struct usb_serial_port *port,
1449 u32 baud_rate, u32 baudclk, u8 *rate_hi,
1450 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451{
1452 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001453 div; /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001455 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456
Alan Coxdeb91682008-07-22 11:13:08 +01001457 /* prevent divide by zero... */
1458 b16 = baud_rate * 16L;
1459 if (b16 == 0)
1460 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461
Alan Coxdeb91682008-07-22 11:13:08 +01001462 /* calculate the divisor */
1463 div = baudclk / b16;
1464 if (div == 0)
1465 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
Alan Coxdeb91682008-07-22 11:13:08 +01001467 if (div > 0xffff)
1468 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469
Alan Coxdeb91682008-07-22 11:13:08 +01001470 /* return the counter values if non-null */
1471 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001473
1474 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475 *rate_hi = (u8) ((div >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001476
1477 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001478 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001479 __func__, baud_rate, *rate_hi, *rate_low);
1480
1481 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482}
1483
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001484static int keyspan_usa19w_calc_baud(struct usb_serial_port *port,
1485 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486 u8 *rate_low, u8 *prescaler, int portnum)
1487{
1488 u32 b16, /* baud rate times 16 (actual rate used internally) */
1489 clk, /* clock with 13/8 prescaler */
Alan Coxdeb91682008-07-22 11:13:08 +01001490 div, /* divisor using 13/8 prescaler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 res, /* resulting baud rate using 13/8 prescaler */
1492 diff, /* error using 13/8 prescaler */
1493 smallest_diff;
1494 u8 best_prescaler;
1495 int i;
1496
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001497 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498
Alan Coxdeb91682008-07-22 11:13:08 +01001499 /* prevent divide by zero */
1500 b16 = baud_rate * 16L;
1501 if (b16 == 0)
1502 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503
Alan Coxdeb91682008-07-22 11:13:08 +01001504 /* Calculate prescaler by trying them all and looking
1505 for best fit */
1506
1507 /* start with largest possible difference */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508 smallest_diff = 0xffffffff;
1509
1510 /* 0 is an invalid prescaler, used as a flag */
1511 best_prescaler = 0;
1512
Alan Coxdeb91682008-07-22 11:13:08 +01001513 for (i = 8; i <= 0xff; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 clk = (baudclk * 8) / (u32) i;
Alan Coxdeb91682008-07-22 11:13:08 +01001515
1516 div = clk / b16;
1517 if (div == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519
1520 res = clk / div;
Alan Coxdeb91682008-07-22 11:13:08 +01001521 diff = (res > b16) ? (res-b16) : (b16-res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522
Alan Coxdeb91682008-07-22 11:13:08 +01001523 if (diff < smallest_diff) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 best_prescaler = i;
1525 smallest_diff = diff;
1526 }
1527 }
1528
Alan Coxdeb91682008-07-22 11:13:08 +01001529 if (best_prescaler == 0)
1530 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531
1532 clk = (baudclk * 8) / (u32) best_prescaler;
1533 div = clk / b16;
1534
Alan Coxdeb91682008-07-22 11:13:08 +01001535 /* return the divisor and prescaler if non-null */
1536 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001538 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 *rate_hi = (u8) ((div >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 if (prescaler) {
1541 *prescaler = best_prescaler;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001542 /* dev_dbg(&port->dev, "%s - %d %d\n", __func__, *prescaler, div); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 }
Alan Coxdeb91682008-07-22 11:13:08 +01001544 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545}
1546
1547 /* USA-28 supports different maximum baud rates on each port */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001548static int keyspan_usa28_calc_baud(struct usb_serial_port *port,
1549 u32 baud_rate, u32 baudclk, u8 *rate_hi,
1550 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551{
1552 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001553 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554 cnt; /* inverse of divisor (programmed into 8051) */
1555
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001556 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557
1558 /* prevent divide by zero */
Alan Coxdeb91682008-07-22 11:13:08 +01001559 b16 = baud_rate * 16L;
1560 if (b16 == 0)
1561 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562
Alan Coxdeb91682008-07-22 11:13:08 +01001563 /* calculate the divisor and the counter (its inverse) */
1564 div = KEYSPAN_USA28_BAUDCLK / b16;
1565 if (div == 0)
1566 return KEYSPAN_INVALID_BAUD_RATE;
1567 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569
Alan Coxdeb91682008-07-22 11:13:08 +01001570 /* check for out of range, based on portnum,
1571 and return result */
1572 if (portnum == 0) {
1573 if (div > 0xffff)
1574 return KEYSPAN_INVALID_BAUD_RATE;
1575 } else {
1576 if (portnum == 1) {
1577 if (div > 0xff)
1578 return KEYSPAN_INVALID_BAUD_RATE;
1579 } else
1580 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 }
1582
1583 /* return the counter values if not NULL
1584 (port 1 will ignore retHi) */
Alan Coxdeb91682008-07-22 11:13:08 +01001585 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001587 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001589 dev_dbg(&port->dev, "%s - %d OK.\n", __func__, baud_rate);
Alan Coxdeb91682008-07-22 11:13:08 +01001590 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591}
1592
1593static int keyspan_usa26_send_setup(struct usb_serial *serial,
1594 struct usb_serial_port *port,
1595 int reset_port)
1596{
Alan Coxdeb91682008-07-22 11:13:08 +01001597 struct keyspan_usa26_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598 struct keyspan_serial_private *s_priv;
1599 struct keyspan_port_private *p_priv;
1600 const struct keyspan_device_details *d_details;
1601 int outcont_urb;
1602 struct urb *this_urb;
1603 int device_port, err;
1604
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001605 dev_dbg(&port->dev, "%s reset=%d\n", __func__, reset_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606
1607 s_priv = usb_get_serial_data(serial);
1608 p_priv = usb_get_serial_port_data(port);
1609 d_details = s_priv->device_details;
1610 device_port = port->number - port->serial->minor;
1611
1612 outcont_urb = d_details->outcont_endpoints[port->number];
1613 this_urb = p_priv->outcont_urb;
1614
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001615 dev_dbg(&port->dev, "%s - endpoint %d\n", __func__, usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616
1617 /* Make sure we have an urb then send the message */
1618 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001619 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620 return -1;
1621 }
1622
1623 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001624 Don't overwrite resend for open/close condition. */
1625 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 p_priv->resend_cont = reset_port + 1;
1627 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001628 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001630 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 }
1632
Alan Coxdeb91682008-07-22 11:13:08 +01001633 memset(&msg, 0, sizeof(struct keyspan_usa26_portControlMessage));
1634
1635 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636 if (p_priv->old_baud != p_priv->baud) {
1637 p_priv->old_baud = p_priv->baud;
1638 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001639 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1640 &msg.baudHi, &msg.baudLo, &msg.prescaler,
1641 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1642 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
1643 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 msg.baudLo = 0;
1645 msg.baudHi = 125; /* Values for 9600 baud */
1646 msg.prescaler = 10;
1647 }
1648 msg.setPrescaler = 0xff;
1649 }
1650
Ben Minerds2b982ab2012-07-12 00:10:16 +10001651 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 switch (p_priv->cflag & CSIZE) {
1653 case CS5:
1654 msg.lcr |= USA_DATABITS_5;
1655 break;
1656 case CS6:
1657 msg.lcr |= USA_DATABITS_6;
1658 break;
1659 case CS7:
1660 msg.lcr |= USA_DATABITS_7;
1661 break;
1662 case CS8:
1663 msg.lcr |= USA_DATABITS_8;
1664 break;
1665 }
1666 if (p_priv->cflag & PARENB) {
1667 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10001668 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01001669 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670 }
1671 msg.setLcr = 0xff;
1672
1673 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1674 msg.xonFlowControl = 0;
1675 msg.setFlowControl = 0xff;
1676 msg.forwardingLength = 16;
1677 msg.xonChar = 17;
1678 msg.xoffChar = 19;
1679
1680 /* Opening port */
1681 if (reset_port == 1) {
1682 msg._txOn = 1;
1683 msg._txOff = 0;
1684 msg.txFlush = 0;
1685 msg.txBreak = 0;
1686 msg.rxOn = 1;
1687 msg.rxOff = 0;
1688 msg.rxFlush = 1;
1689 msg.rxForward = 0;
1690 msg.returnStatus = 0;
1691 msg.resetDataToggle = 0xff;
1692 }
1693
1694 /* Closing port */
1695 else if (reset_port == 2) {
1696 msg._txOn = 0;
1697 msg._txOff = 1;
1698 msg.txFlush = 0;
1699 msg.txBreak = 0;
1700 msg.rxOn = 0;
1701 msg.rxOff = 1;
1702 msg.rxFlush = 1;
1703 msg.rxForward = 0;
1704 msg.returnStatus = 0;
1705 msg.resetDataToggle = 0;
1706 }
1707
1708 /* Sending intermediate configs */
1709 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001710 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 msg._txOff = 0;
1712 msg.txFlush = 0;
1713 msg.txBreak = (p_priv->break_on);
1714 msg.rxOn = 0;
1715 msg.rxOff = 0;
1716 msg.rxFlush = 0;
1717 msg.rxForward = 0;
1718 msg.returnStatus = 0;
1719 msg.resetDataToggle = 0x0;
1720 }
1721
Alan Coxdeb91682008-07-22 11:13:08 +01001722 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723 msg.setTxTriState_setRts = 0xff;
1724 msg.txTriState_rts = p_priv->rts_state;
1725
1726 msg.setHskoa_setDtr = 0xff;
1727 msg.hskoa_dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01001728
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001730 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
1731
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 /* send the data out the device on control endpoint */
1733 this_urb->transfer_buffer_length = sizeof(msg);
1734
Alan Coxdeb91682008-07-22 11:13:08 +01001735 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1736 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001737 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738#if 0
1739 else {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001740 dev_dbg(&port->dev, "%s - usb_submit_urb(%d) OK %d bytes (end %d)\n", __func__
1741 outcont_urb, this_urb->transfer_buffer_length,
1742 usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743 }
1744#endif
1745
Alan Coxa5b6f602008-04-08 17:16:06 +01001746 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747}
1748
1749static int keyspan_usa28_send_setup(struct usb_serial *serial,
1750 struct usb_serial_port *port,
1751 int reset_port)
1752{
Alan Coxdeb91682008-07-22 11:13:08 +01001753 struct keyspan_usa28_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 struct keyspan_serial_private *s_priv;
1755 struct keyspan_port_private *p_priv;
1756 const struct keyspan_device_details *d_details;
1757 struct urb *this_urb;
1758 int device_port, err;
1759
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760 s_priv = usb_get_serial_data(serial);
1761 p_priv = usb_get_serial_port_data(port);
1762 d_details = s_priv->device_details;
1763 device_port = port->number - port->serial->minor;
1764
1765 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01001766 this_urb = p_priv->outcont_urb;
1767 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001768 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 return -1;
1770 }
1771
1772 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001773 Don't overwrite resend for open/close condition. */
1774 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775 p_priv->resend_cont = reset_port + 1;
1776 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001777 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001779 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780 }
1781
Alan Coxdeb91682008-07-22 11:13:08 +01001782 memset(&msg, 0, sizeof(struct keyspan_usa28_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783
1784 msg.setBaudRate = 1;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001785 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1786 &msg.baudHi, &msg.baudLo, NULL,
1787 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1788 dev_dbg(&port->dev, "%s - Invalid baud rate requested %d.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001789 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790 msg.baudLo = 0xff;
1791 msg.baudHi = 0xb2; /* Values for 9600 baud */
1792 }
1793
1794 /* If parity is enabled, we must calculate it ourselves. */
1795 msg.parity = 0; /* XXX for now */
1796
1797 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1798 msg.xonFlowControl = 0;
1799
Alan Coxdeb91682008-07-22 11:13:08 +01001800 /* Do handshaking outputs, DTR is inverted relative to RTS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801 msg.rts = p_priv->rts_state;
1802 msg.dtr = p_priv->dtr_state;
1803
1804 msg.forwardingLength = 16;
1805 msg.forwardMs = 10;
1806 msg.breakThreshold = 45;
1807 msg.xonChar = 17;
1808 msg.xoffChar = 19;
1809
1810 /*msg.returnStatus = 1;
1811 msg.resetDataToggle = 0xff;*/
1812 /* Opening port */
1813 if (reset_port == 1) {
1814 msg._txOn = 1;
1815 msg._txOff = 0;
1816 msg.txFlush = 0;
1817 msg.txForceXoff = 0;
1818 msg.txBreak = 0;
1819 msg.rxOn = 1;
1820 msg.rxOff = 0;
1821 msg.rxFlush = 1;
1822 msg.rxForward = 0;
1823 msg.returnStatus = 0;
1824 msg.resetDataToggle = 0xff;
1825 }
1826 /* Closing port */
1827 else if (reset_port == 2) {
1828 msg._txOn = 0;
1829 msg._txOff = 1;
1830 msg.txFlush = 0;
1831 msg.txForceXoff = 0;
1832 msg.txBreak = 0;
1833 msg.rxOn = 0;
1834 msg.rxOff = 1;
1835 msg.rxFlush = 1;
1836 msg.rxForward = 0;
1837 msg.returnStatus = 0;
1838 msg.resetDataToggle = 0;
1839 }
1840 /* Sending intermediate configs */
1841 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001842 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 msg._txOff = 0;
1844 msg.txFlush = 0;
1845 msg.txForceXoff = 0;
1846 msg.txBreak = (p_priv->break_on);
1847 msg.rxOn = 0;
1848 msg.rxOff = 0;
1849 msg.rxFlush = 0;
1850 msg.rxForward = 0;
1851 msg.returnStatus = 0;
1852 msg.resetDataToggle = 0x0;
1853 }
1854
1855 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001856 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857
1858 /* send the data out the device on control endpoint */
1859 this_urb->transfer_buffer_length = sizeof(msg);
1860
Alan Coxdeb91682008-07-22 11:13:08 +01001861 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1862 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001863 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864#if 0
1865 else {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001866 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) OK %d bytes\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867 this_urb->transfer_buffer_length);
1868 }
1869#endif
1870
Alan Coxa5b6f602008-04-08 17:16:06 +01001871 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872}
1873
1874static int keyspan_usa49_send_setup(struct usb_serial *serial,
1875 struct usb_serial_port *port,
1876 int reset_port)
1877{
Lucy McCoy0ca12682007-05-18 12:10:41 -07001878 struct keyspan_usa49_portControlMessage msg;
1879 struct usb_ctrlrequest *dr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880 struct keyspan_serial_private *s_priv;
1881 struct keyspan_port_private *p_priv;
1882 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883 struct urb *this_urb;
1884 int err, device_port;
1885
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 s_priv = usb_get_serial_data(serial);
1887 p_priv = usb_get_serial_port_data(port);
1888 d_details = s_priv->device_details;
1889
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 this_urb = s_priv->glocont_urb;
1891
Lucy McCoy0ca12682007-05-18 12:10:41 -07001892 /* Work out which port within the device is being setup */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 device_port = port->number - port->serial->minor;
1894
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05301895 /* Make sure we have an urb then send the message */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001897 dev_dbg(&port->dev, "%s - oops no urb for port %d.\n", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 return -1;
1899 }
1900
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001901 dev_dbg(&port->dev, "%s - endpoint %d port %d (%d)\n",
1902 __func__, usb_pipeendpoint(this_urb->pipe),
1903 port->number, device_port);
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05301904
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001906 Don't overwrite resend for open/close condition. */
1907 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908 p_priv->resend_cont = reset_port + 1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001909
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001911 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001913 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914 }
1915
Alan Coxdeb91682008-07-22 11:13:08 +01001916 memset(&msg, 0, sizeof(struct keyspan_usa49_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917
1918 /*msg.portNumber = port->number;*/
1919 msg.portNumber = device_port;
Alan Coxdeb91682008-07-22 11:13:08 +01001920
1921 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922 if (p_priv->old_baud != p_priv->baud) {
1923 p_priv->old_baud = p_priv->baud;
1924 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001925 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1926 &msg.baudHi, &msg.baudLo, &msg.prescaler,
1927 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1928 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
1929 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 msg.baudLo = 0;
1931 msg.baudHi = 125; /* Values for 9600 baud */
1932 msg.prescaler = 10;
1933 }
Alan Coxdeb91682008-07-22 11:13:08 +01001934 /* msg.setPrescaler = 0xff; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935 }
1936
Ben Minerds2b982ab2012-07-12 00:10:16 +10001937 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 switch (p_priv->cflag & CSIZE) {
1939 case CS5:
1940 msg.lcr |= USA_DATABITS_5;
1941 break;
1942 case CS6:
1943 msg.lcr |= USA_DATABITS_6;
1944 break;
1945 case CS7:
1946 msg.lcr |= USA_DATABITS_7;
1947 break;
1948 case CS8:
1949 msg.lcr |= USA_DATABITS_8;
1950 break;
1951 }
1952 if (p_priv->cflag & PARENB) {
1953 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10001954 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01001955 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 }
1957 msg.setLcr = 0xff;
1958
1959 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1960 msg.xonFlowControl = 0;
1961 msg.setFlowControl = 0xff;
Alan Coxdeb91682008-07-22 11:13:08 +01001962
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 msg.forwardingLength = 16;
1964 msg.xonChar = 17;
1965 msg.xoffChar = 19;
1966
Alan Coxdeb91682008-07-22 11:13:08 +01001967 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968 if (reset_port == 1) {
1969 msg._txOn = 1;
1970 msg._txOff = 0;
1971 msg.txFlush = 0;
1972 msg.txBreak = 0;
1973 msg.rxOn = 1;
1974 msg.rxOff = 0;
1975 msg.rxFlush = 1;
1976 msg.rxForward = 0;
1977 msg.returnStatus = 0;
1978 msg.resetDataToggle = 0xff;
1979 msg.enablePort = 1;
1980 msg.disablePort = 0;
1981 }
1982 /* Closing port */
1983 else if (reset_port == 2) {
1984 msg._txOn = 0;
1985 msg._txOff = 1;
1986 msg.txFlush = 0;
1987 msg.txBreak = 0;
1988 msg.rxOn = 0;
1989 msg.rxOff = 1;
1990 msg.rxFlush = 1;
1991 msg.rxForward = 0;
1992 msg.returnStatus = 0;
1993 msg.resetDataToggle = 0;
1994 msg.enablePort = 0;
1995 msg.disablePort = 1;
1996 }
1997 /* Sending intermediate configs */
1998 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001999 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000 msg._txOff = 0;
2001 msg.txFlush = 0;
2002 msg.txBreak = (p_priv->break_on);
2003 msg.rxOn = 0;
2004 msg.rxOff = 0;
2005 msg.rxFlush = 0;
2006 msg.rxForward = 0;
2007 msg.returnStatus = 0;
2008 msg.resetDataToggle = 0x0;
2009 msg.enablePort = 0;
2010 msg.disablePort = 0;
2011 }
2012
Alan Coxdeb91682008-07-22 11:13:08 +01002013 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 msg.setRts = 0xff;
2015 msg.rts = p_priv->rts_state;
2016
2017 msg.setDtr = 0xff;
2018 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002019
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 p_priv->resend_cont = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021
Alan Coxdeb91682008-07-22 11:13:08 +01002022 /* if the device is a 49wg, we send control message on usb
2023 control EP 0 */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002024
2025 if (d_details->product_id == keyspan_usa49wg_product_id) {
2026 dr = (void *)(s_priv->ctrl_buf);
2027 dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT;
2028 dr->bRequest = 0xB0; /* 49wg control message */;
2029 dr->wValue = 0;
2030 dr->wIndex = 0;
2031 dr->wLength = cpu_to_le16(sizeof(msg));
2032
Alan Coxdeb91682008-07-22 11:13:08 +01002033 memcpy(s_priv->glocont_buf, &msg, sizeof(msg));
Lucy McCoy0ca12682007-05-18 12:10:41 -07002034
Alan Coxdeb91682008-07-22 11:13:08 +01002035 usb_fill_control_urb(this_urb, serial->dev,
2036 usb_sndctrlpipe(serial->dev, 0),
2037 (unsigned char *)dr, s_priv->glocont_buf,
2038 sizeof(msg), usa49_glocont_callback, serial);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002039
2040 } else {
2041 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Alan Coxdeb91682008-07-22 11:13:08 +01002042
Lucy McCoy0ca12682007-05-18 12:10:41 -07002043 /* send the data out the device on control endpoint */
2044 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002045 }
Alan Coxdeb91682008-07-22 11:13:08 +01002046 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2047 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002048 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049#if 0
2050 else {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002051 dev_dbg(&port->dev, "%s - usb_submit_urb(%d) OK %d bytes (end %d)\n", __func__,
2052 outcont_urb, this_urb->transfer_buffer_length,
2053 usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054 }
2055#endif
2056
Alan Coxa5b6f602008-04-08 17:16:06 +01002057 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058}
2059
2060static int keyspan_usa90_send_setup(struct usb_serial *serial,
2061 struct usb_serial_port *port,
2062 int reset_port)
2063{
Alan Coxdeb91682008-07-22 11:13:08 +01002064 struct keyspan_usa90_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 struct keyspan_serial_private *s_priv;
2066 struct keyspan_port_private *p_priv;
2067 const struct keyspan_device_details *d_details;
2068 struct urb *this_urb;
2069 int err;
2070 u8 prescaler;
2071
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072 s_priv = usb_get_serial_data(serial);
2073 p_priv = usb_get_serial_port_data(port);
2074 d_details = s_priv->device_details;
2075
2076 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01002077 this_urb = p_priv->outcont_urb;
2078 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002079 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 return -1;
2081 }
2082
2083 /* Save reset port val for resend.
2084 Don't overwrite resend for open/close condition. */
2085 if ((reset_port + 1) > p_priv->resend_cont)
2086 p_priv->resend_cont = reset_port + 1;
2087 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002088 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002090 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091 }
2092
Alan Coxdeb91682008-07-22 11:13:08 +01002093 memset(&msg, 0, sizeof(struct keyspan_usa90_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094
Alan Coxdeb91682008-07-22 11:13:08 +01002095 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096 if (p_priv->old_baud != p_priv->baud) {
2097 p_priv->old_baud = p_priv->baud;
2098 msg.setClocking = 0x01;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002099 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2100 &msg.baudHi, &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) {
2101 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2102 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 p_priv->baud = 9600;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002104 d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 &msg.baudHi, &msg.baudLo, &prescaler, 0);
2106 }
2107 msg.setRxMode = 1;
2108 msg.setTxMode = 1;
2109 }
2110
2111 /* modes must always be correctly specified */
Alan Coxdeb91682008-07-22 11:13:08 +01002112 if (p_priv->baud > 57600) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113 msg.rxMode = RXMODE_DMA;
2114 msg.txMode = TXMODE_DMA;
Alan Coxdeb91682008-07-22 11:13:08 +01002115 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 msg.rxMode = RXMODE_BYHAND;
2117 msg.txMode = TXMODE_BYHAND;
2118 }
2119
Ben Minerds2b982ab2012-07-12 00:10:16 +10002120 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 switch (p_priv->cflag & CSIZE) {
2122 case CS5:
2123 msg.lcr |= USA_DATABITS_5;
2124 break;
2125 case CS6:
2126 msg.lcr |= USA_DATABITS_6;
2127 break;
2128 case CS7:
2129 msg.lcr |= USA_DATABITS_7;
2130 break;
2131 case CS8:
2132 msg.lcr |= USA_DATABITS_8;
2133 break;
2134 }
2135 if (p_priv->cflag & PARENB) {
2136 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002137 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002138 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 }
2140 if (p_priv->old_cflag != p_priv->cflag) {
2141 p_priv->old_cflag = p_priv->cflag;
2142 msg.setLcr = 0x01;
2143 }
2144
2145 if (p_priv->flow_control == flow_cts)
2146 msg.txFlowControl = TXFLOW_CTS;
2147 msg.setTxFlowControl = 0x01;
2148 msg.setRxFlowControl = 0x01;
Alan Coxdeb91682008-07-22 11:13:08 +01002149
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150 msg.rxForwardingLength = 16;
Alan Coxdeb91682008-07-22 11:13:08 +01002151 msg.rxForwardingTimeout = 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 msg.txAckSetting = 0;
2153 msg.xonChar = 17;
2154 msg.xoffChar = 19;
2155
Alan Coxdeb91682008-07-22 11:13:08 +01002156 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157 if (reset_port == 1) {
2158 msg.portEnabled = 1;
2159 msg.rxFlush = 1;
2160 msg.txBreak = (p_priv->break_on);
2161 }
2162 /* Closing port */
Alan Coxdeb91682008-07-22 11:13:08 +01002163 else if (reset_port == 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 msg.portEnabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165 /* Sending intermediate configs */
2166 else {
Alan Stern1f871582010-02-17 10:05:47 -05002167 msg.portEnabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168 msg.txBreak = (p_priv->break_on);
2169 }
2170
Alan Coxdeb91682008-07-22 11:13:08 +01002171 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172 msg.setRts = 0x01;
2173 msg.rts = p_priv->rts_state;
2174
2175 msg.setDtr = 0x01;
2176 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002177
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01002179 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2180
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181 /* send the data out the device on control endpoint */
2182 this_urb->transfer_buffer_length = sizeof(msg);
2183
Alan Coxdeb91682008-07-22 11:13:08 +01002184 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2185 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002186 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002187 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188}
2189
Lucy McCoy0ca12682007-05-18 12:10:41 -07002190static int keyspan_usa67_send_setup(struct usb_serial *serial,
2191 struct usb_serial_port *port,
2192 int reset_port)
2193{
2194 struct keyspan_usa67_portControlMessage msg;
2195 struct keyspan_serial_private *s_priv;
2196 struct keyspan_port_private *p_priv;
2197 const struct keyspan_device_details *d_details;
2198 struct urb *this_urb;
2199 int err, device_port;
2200
Lucy McCoy0ca12682007-05-18 12:10:41 -07002201 s_priv = usb_get_serial_data(serial);
2202 p_priv = usb_get_serial_port_data(port);
2203 d_details = s_priv->device_details;
2204
2205 this_urb = s_priv->glocont_urb;
2206
2207 /* Work out which port within the device is being setup */
2208 device_port = port->number - port->serial->minor;
2209
2210 /* Make sure we have an urb then send the message */
2211 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002212 dev_dbg(&port->dev, "%s - oops no urb for port %d.\n", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002213 port->number);
2214 return -1;
2215 }
2216
2217 /* Save reset port val for resend.
2218 Don't overwrite resend for open/close condition. */
2219 if ((reset_port + 1) > p_priv->resend_cont)
2220 p_priv->resend_cont = reset_port + 1;
2221 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002222 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002223 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002224 return -1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002225 }
2226
2227 memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
2228
2229 msg.port = device_port;
2230
2231 /* Only set baud rate if it's changed */
2232 if (p_priv->old_baud != p_priv->baud) {
2233 p_priv->old_baud = p_priv->baud;
2234 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002235 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2236 &msg.baudHi, &msg.baudLo, &msg.prescaler,
2237 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2238 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2239 __func__, p_priv->baud);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002240 msg.baudLo = 0;
2241 msg.baudHi = 125; /* Values for 9600 baud */
2242 msg.prescaler = 10;
2243 }
2244 msg.setPrescaler = 0xff;
2245 }
2246
2247 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
2248 switch (p_priv->cflag & CSIZE) {
2249 case CS5:
2250 msg.lcr |= USA_DATABITS_5;
2251 break;
2252 case CS6:
2253 msg.lcr |= USA_DATABITS_6;
2254 break;
2255 case CS7:
2256 msg.lcr |= USA_DATABITS_7;
2257 break;
2258 case CS8:
2259 msg.lcr |= USA_DATABITS_8;
2260 break;
2261 }
2262 if (p_priv->cflag & PARENB) {
2263 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002264 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002265 USA_PARITY_ODD : USA_PARITY_EVEN;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002266 }
2267 msg.setLcr = 0xff;
2268
2269 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2270 msg.xonFlowControl = 0;
2271 msg.setFlowControl = 0xff;
2272 msg.forwardingLength = 16;
2273 msg.xonChar = 17;
2274 msg.xoffChar = 19;
2275
2276 if (reset_port == 1) {
2277 /* Opening port */
2278 msg._txOn = 1;
2279 msg._txOff = 0;
2280 msg.txFlush = 0;
2281 msg.txBreak = 0;
2282 msg.rxOn = 1;
2283 msg.rxOff = 0;
2284 msg.rxFlush = 1;
2285 msg.rxForward = 0;
2286 msg.returnStatus = 0;
2287 msg.resetDataToggle = 0xff;
2288 } else if (reset_port == 2) {
2289 /* Closing port */
2290 msg._txOn = 0;
2291 msg._txOff = 1;
2292 msg.txFlush = 0;
2293 msg.txBreak = 0;
2294 msg.rxOn = 0;
2295 msg.rxOff = 1;
2296 msg.rxFlush = 1;
2297 msg.rxForward = 0;
2298 msg.returnStatus = 0;
2299 msg.resetDataToggle = 0;
2300 } else {
2301 /* Sending intermediate configs */
Alan Coxdeb91682008-07-22 11:13:08 +01002302 msg._txOn = (!p_priv->break_on);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002303 msg._txOff = 0;
2304 msg.txFlush = 0;
2305 msg.txBreak = (p_priv->break_on);
2306 msg.rxOn = 0;
2307 msg.rxOff = 0;
2308 msg.rxFlush = 0;
2309 msg.rxForward = 0;
2310 msg.returnStatus = 0;
2311 msg.resetDataToggle = 0x0;
2312 }
2313
2314 /* Do handshaking outputs */
2315 msg.setTxTriState_setRts = 0xff;
2316 msg.txTriState_rts = p_priv->rts_state;
2317
2318 msg.setHskoa_setDtr = 0xff;
2319 msg.hskoa_dtr = p_priv->dtr_state;
2320
2321 p_priv->resend_cont = 0;
2322
2323 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2324
2325 /* send the data out the device on control endpoint */
2326 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002327
2328 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2329 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002330 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002331 return 0;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002332}
2333
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
2335{
2336 struct usb_serial *serial = port->serial;
2337 struct keyspan_serial_private *s_priv;
2338 const struct keyspan_device_details *d_details;
2339
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340 s_priv = usb_get_serial_data(serial);
2341 d_details = s_priv->device_details;
2342
2343 switch (d_details->msg_format) {
2344 case msg_usa26:
2345 keyspan_usa26_send_setup(serial, port, reset_port);
2346 break;
2347 case msg_usa28:
2348 keyspan_usa28_send_setup(serial, port, reset_port);
2349 break;
2350 case msg_usa49:
2351 keyspan_usa49_send_setup(serial, port, reset_port);
2352 break;
2353 case msg_usa90:
2354 keyspan_usa90_send_setup(serial, port, reset_port);
2355 break;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002356 case msg_usa67:
2357 keyspan_usa67_send_setup(serial, port, reset_port);
2358 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359 }
2360}
2361
2362
2363/* Gets called by the "real" driver (ie once firmware is loaded
2364 and renumeration has taken place. */
Alan Coxdeb91682008-07-22 11:13:08 +01002365static int keyspan_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366{
2367 int i, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369 const struct keyspan_device_details *d_details;
2370
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371 for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
Alan Coxdeb91682008-07-22 11:13:08 +01002372 if (d_details->product_id ==
2373 le16_to_cpu(serial->dev->descriptor.idProduct))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374 break;
2375 if (d_details == NULL) {
Alan Coxdeb91682008-07-22 11:13:08 +01002376 dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
2377 __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378 return 1;
2379 }
2380
2381 /* Setup private data for serial driver */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01002382 s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383 if (!s_priv) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002384 dev_dbg(&serial->dev->dev, "%s - kmalloc for keyspan_serial_private failed.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385 return -ENOMEM;
2386 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387
2388 s_priv->device_details = d_details;
2389 usb_set_serial_data(serial, s_priv);
2390
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 keyspan_setup_urbs(serial);
2392
Lucy McCoy0ca12682007-05-18 12:10:41 -07002393 if (s_priv->instat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002394 err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
2395 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002396 dev_dbg(&serial->dev->dev, "%s - submit instat urb failed %d\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002397 }
2398 if (s_priv->indat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002399 err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
2400 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002401 dev_dbg(&serial->dev->dev, "%s - submit indat urb failed %d\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 }
Alan Coxdeb91682008-07-22 11:13:08 +01002403
Alan Coxa5b6f602008-04-08 17:16:06 +01002404 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405}
2406
Alan Sternf9c99bb2009-06-02 11:53:55 -04002407static void keyspan_disconnect(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002409 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411 s_priv = usb_get_serial_data(serial);
2412
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413 stop_urb(s_priv->instat_urb);
2414 stop_urb(s_priv->glocont_urb);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002415 stop_urb(s_priv->indat_urb);
Alan Sternf9c99bb2009-06-02 11:53:55 -04002416}
2417
2418static void keyspan_release(struct usb_serial *serial)
2419{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002420 struct keyspan_serial_private *s_priv;
Alan Sternf9c99bb2009-06-02 11:53:55 -04002421
Alan Sternf9c99bb2009-06-02 11:53:55 -04002422 s_priv = usb_get_serial_data(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002424 usb_free_urb(s_priv->instat_urb);
2425 usb_free_urb(s_priv->indat_urb);
2426 usb_free_urb(s_priv->glocont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002428 kfree(s_priv);
2429}
2430
2431static int keyspan_port_probe(struct usb_serial_port *port)
2432{
2433 struct usb_serial *serial = port->serial;
Bjørn Morkf0e3e352012-11-10 10:13:42 +01002434 struct keyspan_serial_private *s_priv;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002435 struct keyspan_port_private *p_priv;
2436 const struct keyspan_device_details *d_details;
2437 struct callbacks *cback;
2438 int endp;
2439 int port_num;
2440 int i;
2441
2442 s_priv = usb_get_serial_data(serial);
2443 d_details = s_priv->device_details;
2444
2445 p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL);
2446 if (!p_priv)
2447 return -ENOMEM;
2448
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002449 p_priv->device_details = d_details;
2450
2451 /* Setup values for the various callback routines */
2452 cback = &keyspan_callbacks[d_details->msg_format];
2453
2454 port_num = port->number - port->serial->minor;
2455
2456 /* Do indat endpoints first, once for each flip */
2457 endp = d_details->indat_endpoints[port_num];
2458 for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) {
2459 p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp,
2460 USB_DIR_IN, port,
2461 p_priv->in_buffer[i], 64,
2462 cback->indat_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463 }
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002464 /* outdat endpoints also have flip */
2465 endp = d_details->outdat_endpoints[port_num];
2466 for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) {
2467 p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp,
2468 USB_DIR_OUT, port,
2469 p_priv->out_buffer[i], 64,
2470 cback->outdat_callback);
2471 }
2472 /* inack endpoint */
2473 p_priv->inack_urb = keyspan_setup_urb(serial,
2474 d_details->inack_endpoints[port_num],
2475 USB_DIR_IN, port,
2476 p_priv->inack_buffer, 1,
2477 cback->inack_callback);
2478 /* outcont endpoint */
2479 p_priv->outcont_urb = keyspan_setup_urb(serial,
2480 d_details->outcont_endpoints[port_num],
2481 USB_DIR_OUT, port,
2482 p_priv->outcont_buffer, 64,
2483 cback->outcont_callback);
2484
2485 usb_set_serial_port_data(port, p_priv);
2486
2487 return 0;
2488}
2489
2490static int keyspan_port_remove(struct usb_serial_port *port)
2491{
2492 struct keyspan_port_private *p_priv;
2493 int i;
2494
2495 p_priv = usb_get_serial_port_data(port);
2496
2497 stop_urb(p_priv->inack_urb);
2498 stop_urb(p_priv->outcont_urb);
2499 for (i = 0; i < 2; i++) {
2500 stop_urb(p_priv->in_urbs[i]);
2501 stop_urb(p_priv->out_urbs[i]);
2502 }
2503
2504 usb_free_urb(p_priv->inack_urb);
2505 usb_free_urb(p_priv->outcont_urb);
2506 for (i = 0; i < 2; i++) {
2507 usb_free_urb(p_priv->in_urbs[i]);
2508 usb_free_urb(p_priv->out_urbs[i]);
2509 }
2510
2511 kfree(p_priv);
2512
2513 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514}
2515
Alan Coxdeb91682008-07-22 11:13:08 +01002516MODULE_AUTHOR(DRIVER_AUTHOR);
2517MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002518MODULE_LICENSE("GPL");
2519
David Woodhouse2971c572008-05-30 14:04:03 +03002520MODULE_FIRMWARE("keyspan/usa28.fw");
2521MODULE_FIRMWARE("keyspan/usa28x.fw");
2522MODULE_FIRMWARE("keyspan/usa28xa.fw");
2523MODULE_FIRMWARE("keyspan/usa28xb.fw");
2524MODULE_FIRMWARE("keyspan/usa19.fw");
2525MODULE_FIRMWARE("keyspan/usa19qi.fw");
2526MODULE_FIRMWARE("keyspan/mpr.fw");
2527MODULE_FIRMWARE("keyspan/usa19qw.fw");
2528MODULE_FIRMWARE("keyspan/usa18x.fw");
2529MODULE_FIRMWARE("keyspan/usa19w.fw");
2530MODULE_FIRMWARE("keyspan/usa49w.fw");
2531MODULE_FIRMWARE("keyspan/usa49wlc.fw");