blob: 93cb7cebda62760bcaae46f3710e7477ff59a507 [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/slab.h>
35#include <linux/tty.h>
36#include <linux/tty_driver.h>
37#include <linux/tty_flip.h>
38#include <linux/module.h>
39#include <linux/spinlock.h>
Alan Coxdeb91682008-07-22 11:13:08 +010040#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/usb.h>
Greg Kroah-Hartmana9698882006-07-11 21:22:58 -070042#include <linux/usb/serial.h>
Rene Buergelcc183e22012-09-18 09:00:41 +020043#include <linux/usb/ezusb.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include "keyspan.h"
45
Linus Torvalds1da177e2005-04-16 15:20:36 -070046#define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu"
47#define DRIVER_DESC "Keyspan USB to Serial Converter Driver"
48
49#define INSTAT_BUFLEN 32
50#define GLOCONT_BUFLEN 64
Lucy McCoy0ca12682007-05-18 12:10:41 -070051#define INDAT49W_BUFLEN 512
Johan Hovoldbad41a52013-08-13 13:27:37 +020052#define IN_BUFLEN 64
53#define OUT_BUFLEN 64
54#define INACK_BUFLEN 1
55#define OUTCONT_BUFLEN 64
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
57 /* Per device and per port private data */
58struct keyspan_serial_private {
59 const struct keyspan_device_details *device_details;
60
61 struct urb *instat_urb;
Johan Hovold2fcd1c92013-08-13 13:27:36 +020062 char *instat_buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
Alan Coxdeb91682008-07-22 11:13:08 +010064 /* added to support 49wg, where data from all 4 ports comes in
65 on 1 EP and high-speed supported */
Lucy McCoy0ca12682007-05-18 12:10:41 -070066 struct urb *indat_urb;
Johan Hovold2fcd1c92013-08-13 13:27:36 +020067 char *indat_buf;
Lucy McCoy0ca12682007-05-18 12:10:41 -070068
Linus Torvalds1da177e2005-04-16 15:20:36 -070069 /* XXX this one probably will need a lock */
70 struct urb *glocont_urb;
Johan Hovold2fcd1c92013-08-13 13:27:36 +020071 char *glocont_buf;
72 char *ctrl_buf; /* for EP0 control message */
Linus Torvalds1da177e2005-04-16 15:20:36 -070073};
74
75struct keyspan_port_private {
76 /* Keep track of which input & output endpoints to use */
77 int in_flip;
78 int out_flip;
79
80 /* Keep duplicate of device details in each port
81 structure as well - simplifies some of the
82 callback functions etc. */
83 const struct keyspan_device_details *device_details;
84
85 /* Input endpoints and buffer for this port */
86 struct urb *in_urbs[2];
Johan Hovoldbad41a52013-08-13 13:27:37 +020087 char *in_buffer[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 /* Output endpoints and buffer for this port */
89 struct urb *out_urbs[2];
Johan Hovoldbad41a52013-08-13 13:27:37 +020090 char *out_buffer[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -070091
92 /* Input ack endpoint */
93 struct urb *inack_urb;
Johan Hovoldbad41a52013-08-13 13:27:37 +020094 char *inack_buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -070095
96 /* Output control endpoint */
97 struct urb *outcont_urb;
Johan Hovoldbad41a52013-08-13 13:27:37 +020098 char *outcont_buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
100 /* Settings for the port */
101 int baud;
102 int old_baud;
103 unsigned int cflag;
104 unsigned int old_cflag;
105 enum {flow_none, flow_cts, flow_xon} flow_control;
106 int rts_state; /* Handshaking pins (outputs) */
107 int dtr_state;
108 int cts_state; /* Handshaking pins (inputs) */
109 int dsr_state;
110 int dcd_state;
111 int ri_state;
112 int break_on;
113
114 unsigned long tx_start_time[2];
115 int resend_cont; /* need to resend control packet */
116};
117
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118/* Include Keyspan message headers. All current Keyspan Adapters
Lucy McCoy0ca12682007-05-18 12:10:41 -0700119 make use of one of five message formats which are referred
Alan Coxdeb91682008-07-22 11:13:08 +0100120 to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and
121 within this driver. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122#include "keyspan_usa26msg.h"
123#include "keyspan_usa28msg.h"
124#include "keyspan_usa49msg.h"
125#include "keyspan_usa90msg.h"
Lucy McCoy0ca12682007-05-18 12:10:41 -0700126#include "keyspan_usa67msg.h"
Alan Coxdeb91682008-07-22 11:13:08 +0100127
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -0700129module_usb_serial_driver(serial_drivers, keyspan_ids_combined);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130
Alan Cox95da3102008-07-22 11:09:07 +0100131static void keyspan_break_ctl(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132{
Alan Cox95da3102008-07-22 11:09:07 +0100133 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134 struct keyspan_port_private *p_priv;
135
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136 p_priv = usb_get_serial_port_data(port);
137
138 if (break_state == -1)
139 p_priv->break_on = 1;
140 else
141 p_priv->break_on = 0;
142
143 keyspan_send_setup(port, 0);
144}
145
146
Alan Coxdeb91682008-07-22 11:13:08 +0100147static void keyspan_set_termios(struct tty_struct *tty,
Alan Cox95da3102008-07-22 11:09:07 +0100148 struct usb_serial_port *port, struct ktermios *old_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149{
150 int baud_rate, device_port;
151 struct keyspan_port_private *p_priv;
152 const struct keyspan_device_details *d_details;
153 unsigned int cflag;
154
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 p_priv = usb_get_serial_port_data(port);
156 d_details = p_priv->device_details;
Alan Coxadc8d742012-07-14 15:31:47 +0100157 cflag = tty->termios.c_cflag;
Greg Kroah-Hartman11438322013-06-06 10:32:00 -0700158 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159
160 /* Baud rate calculation takes baud rate as an integer
161 so other rates can be generated if desired. */
Alan Cox74240b02007-10-18 01:24:20 -0700162 baud_rate = tty_get_baud_rate(tty);
Alan Coxdeb91682008-07-22 11:13:08 +0100163 /* If no match or invalid, don't change */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700164 if (d_details->calculate_baud_rate(port, baud_rate, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
166 /* FIXME - more to do here to ensure rate changes cleanly */
Rahul Bedarkarcd8c5052014-01-02 19:29:24 +0530167 /* FIXME - calculate exact rate from divisor ? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 p_priv->baud = baud_rate;
Alan Cox74240b02007-10-18 01:24:20 -0700169 } else
170 baud_rate = tty_termios_baud_rate(old_termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171
Alan Cox74240b02007-10-18 01:24:20 -0700172 tty_encode_baud_rate(tty, baud_rate, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173 /* set CTS/RTS handshake etc. */
174 p_priv->cflag = cflag;
Ben Minerds2b982ab2012-07-12 00:10:16 +1000175 p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176
Alan Cox74240b02007-10-18 01:24:20 -0700177 /* Mark/Space not supported */
Alan Coxadc8d742012-07-14 15:31:47 +0100178 tty->termios.c_cflag &= ~CMSPAR;
Alan Cox74240b02007-10-18 01:24:20 -0700179
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 keyspan_send_setup(port, 0);
181}
182
Alan Cox60b33c12011-02-14 16:26:14 +0000183static int keyspan_tiocmget(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184{
Alan Cox95da3102008-07-22 11:09:07 +0100185 struct usb_serial_port *port = tty->driver_data;
186 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 unsigned int value;
Alan Coxdeb91682008-07-22 11:13:08 +0100188
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 value = ((p_priv->rts_state) ? TIOCM_RTS : 0) |
190 ((p_priv->dtr_state) ? TIOCM_DTR : 0) |
191 ((p_priv->cts_state) ? TIOCM_CTS : 0) |
192 ((p_priv->dsr_state) ? TIOCM_DSR : 0) |
193 ((p_priv->dcd_state) ? TIOCM_CAR : 0) |
Alan Coxdeb91682008-07-22 11:13:08 +0100194 ((p_priv->ri_state) ? TIOCM_RNG : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195
196 return value;
197}
198
Alan Cox20b9d172011-02-14 16:26:50 +0000199static int keyspan_tiocmset(struct tty_struct *tty,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 unsigned int set, unsigned int clear)
201{
Alan Cox95da3102008-07-22 11:09:07 +0100202 struct usb_serial_port *port = tty->driver_data;
203 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100204
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205 if (set & TIOCM_RTS)
206 p_priv->rts_state = 1;
207 if (set & TIOCM_DTR)
208 p_priv->dtr_state = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 if (clear & TIOCM_RTS)
210 p_priv->rts_state = 0;
211 if (clear & TIOCM_DTR)
212 p_priv->dtr_state = 0;
213 keyspan_send_setup(port, 0);
214 return 0;
215}
216
Alan Cox95da3102008-07-22 11:09:07 +0100217/* Write function is similar for the four protocols used
218 with only a minor change for usa90 (usa19hs) required */
219static int keyspan_write(struct tty_struct *tty,
220 struct usb_serial_port *port, const unsigned char *buf, int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221{
222 struct keyspan_port_private *p_priv;
223 const struct keyspan_device_details *d_details;
224 int flip;
225 int left, todo;
226 struct urb *this_urb;
Alan Coxdeb91682008-07-22 11:13:08 +0100227 int err, maxDataLen, dataOffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228
229 p_priv = usb_get_serial_port_data(port);
230 d_details = p_priv->device_details;
231
232 if (d_details->msg_format == msg_usa90) {
Alan Coxdeb91682008-07-22 11:13:08 +0100233 maxDataLen = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 dataOffset = 0;
235 } else {
236 maxDataLen = 63;
237 dataOffset = 1;
238 }
Alan Coxdeb91682008-07-22 11:13:08 +0100239
Greg Kroah-Hartman11438322013-06-06 10:32:00 -0700240 dev_dbg(&port->dev, "%s - %d chars, flip=%d\n", __func__, count,
241 p_priv->out_flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242
243 for (left = count; left > 0; left -= todo) {
244 todo = left;
245 if (todo > maxDataLen)
246 todo = maxDataLen;
247
248 flip = p_priv->out_flip;
Alan Coxdeb91682008-07-22 11:13:08 +0100249
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 /* Check we have a valid urb/endpoint before we use it... */
Alan Coxdeb91682008-07-22 11:13:08 +0100251 this_urb = p_priv->out_urbs[flip];
252 if (this_urb == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 /* no bulk out, so return 0 bytes written */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700254 dev_dbg(&port->dev, "%s - no output urb :(\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 return count;
256 }
257
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700258 dev_dbg(&port->dev, "%s - endpoint %d flip %d\n",
Alan Coxdeb91682008-07-22 11:13:08 +0100259 __func__, usb_pipeendpoint(this_urb->pipe), flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260
261 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +0100262 if (time_before(jiffies,
263 p_priv->tx_start_time[flip] + 10 * HZ))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 usb_unlink_urb(this_urb);
266 break;
267 }
268
Alan Coxdeb91682008-07-22 11:13:08 +0100269 /* First byte in buffer is "last flag" (except for usa19hx)
270 - unused so for now so set to zero */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 ((char *)this_urb->transfer_buffer)[0] = 0;
272
Alan Coxdeb91682008-07-22 11:13:08 +0100273 memcpy(this_urb->transfer_buffer + dataOffset, buf, todo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 buf += todo;
275
276 /* send the data out the bulk port */
277 this_urb->transfer_buffer_length = todo + dataOffset;
278
Alan Coxdeb91682008-07-22 11:13:08 +0100279 err = usb_submit_urb(this_urb, GFP_ATOMIC);
280 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700281 dev_dbg(&port->dev, "usb_submit_urb(write bulk) failed (%d)\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 p_priv->tx_start_time[flip] = jiffies;
283
284 /* Flip for next time if usa26 or usa28 interface
285 (not used on usa49) */
286 p_priv->out_flip = (flip + 1) & d_details->outdat_endp_flip;
287 }
288
289 return count - left;
290}
291
David Howells7d12e782006-10-05 14:55:46 +0100292static void usa26_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293{
294 int i, err;
295 int endpoint;
296 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700298 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 endpoint = usb_pipeendpoint(urb->pipe);
301
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700302 if (status) {
Stefan Hubnera8ffa0b2012-12-13 22:45:00 +0100303 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700304 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 return;
306 }
307
Ming Leicdc97792008-02-24 18:41:47 +0800308 port = urb->context;
Jiri Slaby2e124b42013-01-03 15:53:06 +0100309 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 /* 0x80 bit is error flag */
311 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100312 /* no errors on individual bytes, only
313 possible overrun err */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 if (data[0] & RXERROR_OVERRUN)
Alan Coxdeb91682008-07-22 11:13:08 +0100315 err = TTY_OVERRUN;
316 else
317 err = 0;
318 for (i = 1; i < urb->actual_length ; ++i)
Jiri Slaby92a19f92013-01-03 15:53:03 +0100319 tty_insert_flip_char(&port->port, data[i], err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 } else {
321 /* some bytes had errors, every byte has status */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700322 dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 for (i = 0; i + 1 < urb->actual_length; i += 2) {
324 int stat = data[i], flag = 0;
325 if (stat & RXERROR_OVERRUN)
326 flag |= TTY_OVERRUN;
327 if (stat & RXERROR_FRAMING)
328 flag |= TTY_FRAME;
329 if (stat & RXERROR_PARITY)
330 flag |= TTY_PARITY;
331 /* XXX should handle break (0x10) */
Jiri Slaby92a19f92013-01-03 15:53:03 +0100332 tty_insert_flip_char(&port->port, data[i+1],
333 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 }
335 }
Jiri Slaby2e124b42013-01-03 15:53:06 +0100336 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 }
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;
384 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700385 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386
Ming Leicdc97792008-02-24 18:41:47 +0800387 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700389 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700390 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 return;
392 }
393 if (urb->actual_length != 9) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700394 dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 goto exit;
396 }
397
398 msg = (struct keyspan_usa26_portStatusMessage *)data;
399
Alan Coxdeb91682008-07-22 11:13:08 +0100400 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700402 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 goto exit;
404 }
405 port = serial->port[msg->port];
406 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100407
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 /* Update handshaking pin state information */
409 old_dcd_state = p_priv->dcd_state;
410 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
411 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
412 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
413 p_priv->ri_state = ((msg->ri) ? 1 : 0);
414
Jiri Slabyaa27a092013-03-07 13:12:30 +0100415 if (old_dcd_state != p_priv->dcd_state)
416 tty_port_tty_hangup(&port->port, true);
Alan Coxdeb91682008-07-22 11:13:08 +0100417
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100419 err = usb_submit_urb(urb, GFP_ATOMIC);
420 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700421 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422exit: ;
423}
424
David Howells7d12e782006-10-05 14:55:46 +0100425static void usa26_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427}
428
429
David Howells7d12e782006-10-05 14:55:46 +0100430static void usa28_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431{
Alan Coxf035a8a2008-07-22 11:13:32 +0100432 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 unsigned char *data;
435 struct keyspan_port_private *p_priv;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700436 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437
Ming Leicdc97792008-02-24 18:41:47 +0800438 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 p_priv = usb_get_serial_port_data(port);
440 data = urb->transfer_buffer;
441
442 if (urb != p_priv->in_urbs[p_priv->in_flip])
443 return;
444
445 do {
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700446 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700447 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
448 __func__, status, usb_pipeendpoint(urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 return;
450 }
451
Ming Leicdc97792008-02-24 18:41:47 +0800452 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 p_priv = usb_get_serial_port_data(port);
454 data = urb->transfer_buffer;
455
Jiri Slaby2e124b42013-01-03 15:53:06 +0100456 if (urb->actual_length) {
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100457 tty_insert_flip_string(&port->port, data,
458 urb->actual_length);
Jiri Slaby2e124b42013-01-03 15:53:06 +0100459 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 }
461
462 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500463 err = usb_submit_urb(urb, GFP_ATOMIC);
464 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700465 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n",
Alan Stern1f871582010-02-17 10:05:47 -0500466 __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 p_priv->in_flip ^= 1;
468
469 urb = p_priv->in_urbs[p_priv->in_flip];
470 } while (urb->status != -EINPROGRESS);
471}
472
David Howells7d12e782006-10-05 14:55:46 +0100473static void usa28_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475}
476
David Howells7d12e782006-10-05 14:55:46 +0100477static void usa28_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478{
479 struct usb_serial_port *port;
480 struct keyspan_port_private *p_priv;
481
Ming Leicdc97792008-02-24 18:41:47 +0800482 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 p_priv = usb_get_serial_port_data(port);
484
485 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700486 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100487 keyspan_usa28_send_setup(port->serial, port,
488 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 }
490}
491
David Howells7d12e782006-10-05 14:55:46 +0100492static void usa28_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493{
494 int err;
495 unsigned char *data = urb->transfer_buffer;
496 struct keyspan_usa28_portStatusMessage *msg;
497 struct usb_serial *serial;
498 struct usb_serial_port *port;
499 struct keyspan_port_private *p_priv;
500 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700501 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502
Ming Leicdc97792008-02-24 18:41:47 +0800503 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700505 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700506 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 return;
508 }
509
510 if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700511 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 goto exit;
513 }
514
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 msg = (struct keyspan_usa28_portStatusMessage *)data;
516
Alan Coxdeb91682008-07-22 11:13:08 +0100517 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700519 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 goto exit;
521 }
522 port = serial->port[msg->port];
523 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100524
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 /* Update handshaking pin state information */
526 old_dcd_state = p_priv->dcd_state;
527 p_priv->cts_state = ((msg->cts) ? 1 : 0);
528 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
529 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
530 p_priv->ri_state = ((msg->ri) ? 1 : 0);
531
Jiri Slabyaa27a092013-03-07 13:12:30 +0100532 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
533 tty_port_tty_hangup(&port->port, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534
535 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100536 err = usb_submit_urb(urb, GFP_ATOMIC);
537 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700538 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539exit: ;
540}
541
David Howells7d12e782006-10-05 14:55:46 +0100542static void usa28_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544}
545
546
David Howells7d12e782006-10-05 14:55:46 +0100547static void usa49_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548{
549 struct usb_serial *serial;
550 struct usb_serial_port *port;
551 struct keyspan_port_private *p_priv;
552 int i;
553
Ming Leicdc97792008-02-24 18:41:47 +0800554 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 for (i = 0; i < serial->num_ports; ++i) {
556 port = serial->port[i];
557 p_priv = usb_get_serial_port_data(port);
558
559 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700560 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100561 keyspan_usa49_send_setup(serial, port,
562 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 break;
564 }
565 }
566}
567
568 /* This is actually called glostat in the Keyspan
569 doco */
David Howells7d12e782006-10-05 14:55:46 +0100570static void usa49_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571{
572 int err;
573 unsigned char *data = urb->transfer_buffer;
574 struct keyspan_usa49_portStatusMessage *msg;
575 struct usb_serial *serial;
576 struct usb_serial_port *port;
577 struct keyspan_port_private *p_priv;
578 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700579 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580
Ming Leicdc97792008-02-24 18:41:47 +0800581 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700583 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700584 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 return;
586 }
587
Alan Coxdeb91682008-07-22 11:13:08 +0100588 if (urb->actual_length !=
589 sizeof(struct keyspan_usa49_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700590 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 goto exit;
592 }
593
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 msg = (struct keyspan_usa49_portStatusMessage *)data;
595
Alan Coxdeb91682008-07-22 11:13:08 +0100596 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 if (msg->portNumber >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700598 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
599 __func__, msg->portNumber);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 goto exit;
601 }
602 port = serial->port[msg->portNumber];
603 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100604
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 /* Update handshaking pin state information */
606 old_dcd_state = p_priv->dcd_state;
607 p_priv->cts_state = ((msg->cts) ? 1 : 0);
608 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
609 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
610 p_priv->ri_state = ((msg->ri) ? 1 : 0);
611
Jiri Slabyaa27a092013-03-07 13:12:30 +0100612 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
613 tty_port_tty_hangup(&port->port, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614
Alan Coxdeb91682008-07-22 11:13:08 +0100615 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100616 err = usb_submit_urb(urb, GFP_ATOMIC);
617 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700618 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619exit: ;
620}
621
David Howells7d12e782006-10-05 14:55:46 +0100622static void usa49_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624}
625
David Howells7d12e782006-10-05 14:55:46 +0100626static void usa49_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627{
628 int i, err;
629 int endpoint;
630 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700632 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 endpoint = usb_pipeendpoint(urb->pipe);
635
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700636 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700637 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
638 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 return;
640 }
641
Ming Leicdc97792008-02-24 18:41:47 +0800642 port = urb->context;
Jiri Slaby2e124b42013-01-03 15:53:06 +0100643 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 /* 0x80 bit is error flag */
645 if ((data[0] & 0x80) == 0) {
646 /* no error on any byte */
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100647 tty_insert_flip_string(&port->port, data + 1,
Alan Coxf035a8a2008-07-22 11:13:32 +0100648 urb->actual_length - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 } else {
650 /* some bytes had errors, every byte has status */
651 for (i = 0; i + 1 < urb->actual_length; i += 2) {
652 int stat = data[i], flag = 0;
653 if (stat & RXERROR_OVERRUN)
654 flag |= TTY_OVERRUN;
655 if (stat & RXERROR_FRAMING)
656 flag |= TTY_FRAME;
657 if (stat & RXERROR_PARITY)
658 flag |= TTY_PARITY;
659 /* XXX should handle break (0x10) */
Jiri Slaby92a19f92013-01-03 15:53:03 +0100660 tty_insert_flip_char(&port->port, data[i+1],
661 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 }
663 }
Jiri Slaby2e124b42013-01-03 15:53:06 +0100664 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 }
Alan Coxdeb91682008-07-22 11:13:08 +0100666
667 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500668 err = usb_submit_urb(urb, GFP_ATOMIC);
669 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700670 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671}
672
Lucy McCoy0ca12682007-05-18 12:10:41 -0700673static void usa49wg_indat_callback(struct urb *urb)
674{
675 int i, len, x, err;
676 struct usb_serial *serial;
677 struct usb_serial_port *port;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700678 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700679 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700680
Lucy McCoy0ca12682007-05-18 12:10:41 -0700681 serial = urb->context;
682
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700683 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700684 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700685 return;
686 }
687
688 /* inbound data is in the form P#, len, status, data */
689 i = 0;
690 len = 0;
691
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300692 while (i < urb->actual_length) {
Lucy McCoy0ca12682007-05-18 12:10:41 -0700693
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300694 /* Check port number from message */
695 if (data[i] >= serial->num_ports) {
696 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
697 __func__, data[i]);
698 return;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700699 }
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300700 port = serial->port[data[i++]];
701 len = data[i++];
702
703 /* 0x80 bit is error flag */
704 if ((data[i] & 0x80) == 0) {
705 /* no error on any byte */
706 i++;
Dan Carpenter01a60e72013-04-05 08:43:20 +0300707 for (x = 1; x < len && i < urb->actual_length; ++x)
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300708 tty_insert_flip_char(&port->port,
709 data[i++], 0);
710 } else {
711 /*
712 * some bytes had errors, every byte has status
713 */
Dan Carpenter01a60e72013-04-05 08:43:20 +0300714 for (x = 0; x + 1 < len &&
715 i + 1 < urb->actual_length; x += 2) {
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300716 int stat = data[i], flag = 0;
717
718 if (stat & RXERROR_OVERRUN)
719 flag |= TTY_OVERRUN;
720 if (stat & RXERROR_FRAMING)
721 flag |= TTY_FRAME;
722 if (stat & RXERROR_PARITY)
723 flag |= TTY_PARITY;
724 /* XXX should handle break (0x10) */
725 tty_insert_flip_char(&port->port, data[i+1],
726 flag);
727 i += 2;
728 }
729 }
730 tty_flip_buffer_push(&port->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700731 }
732
733 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700734 err = usb_submit_urb(urb, GFP_ATOMIC);
735 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700736 dev_dbg(&urb->dev->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700737}
738
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739/* not used, usa-49 doesn't have per-port control endpoints */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700740static void usa49_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742}
743
Lucy McCoy0ca12682007-05-18 12:10:41 -0700744static void usa90_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745{
746 int i, err;
747 int endpoint;
748 struct usb_serial_port *port;
749 struct keyspan_port_private *p_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700751 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 endpoint = usb_pipeendpoint(urb->pipe);
754
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700755 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700756 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800757 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 return;
759 }
760
Ming Leicdc97792008-02-24 18:41:47 +0800761 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 p_priv = usb_get_serial_port_data(port);
763
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 /* if current mode is DMA, looks like usa28 format
Alan Coxdeb91682008-07-22 11:13:08 +0100766 otherwise looks like usa26 data format */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767
Alan Coxf035a8a2008-07-22 11:13:32 +0100768 if (p_priv->baud > 57600)
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100769 tty_insert_flip_string(&port->port, data,
770 urb->actual_length);
Alan Coxf035a8a2008-07-22 11:13:32 +0100771 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 /* 0x80 bit is error flag */
773 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100774 /* no errors on individual bytes, only
775 possible overrun err*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 if (data[0] & RXERROR_OVERRUN)
Alan Coxdeb91682008-07-22 11:13:08 +0100777 err = TTY_OVERRUN;
778 else
779 err = 0;
780 for (i = 1; i < urb->actual_length ; ++i)
Jiri Slaby92a19f92013-01-03 15:53:03 +0100781 tty_insert_flip_char(&port->port,
782 data[i], err);
Alan Coxdeb91682008-07-22 11:13:08 +0100783 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 /* some bytes had errors, every byte has status */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700785 dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 for (i = 0; i + 1 < urb->actual_length; i += 2) {
787 int stat = data[i], flag = 0;
788 if (stat & RXERROR_OVERRUN)
789 flag |= TTY_OVERRUN;
790 if (stat & RXERROR_FRAMING)
791 flag |= TTY_FRAME;
792 if (stat & RXERROR_PARITY)
793 flag |= TTY_PARITY;
794 /* XXX should handle break (0x10) */
Jiri Slaby92a19f92013-01-03 15:53:03 +0100795 tty_insert_flip_char(&port->port,
796 data[i+1], flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 }
798 }
799 }
Jiri Slaby2e124b42013-01-03 15:53:06 +0100800 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 }
Alan Coxdeb91682008-07-22 11:13:08 +0100802
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500804 err = usb_submit_urb(urb, GFP_ATOMIC);
805 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700806 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807}
808
809
David Howells7d12e782006-10-05 14:55:46 +0100810static void usa90_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811{
812 unsigned char *data = urb->transfer_buffer;
813 struct keyspan_usa90_portStatusMessage *msg;
814 struct usb_serial *serial;
815 struct usb_serial_port *port;
816 struct keyspan_port_private *p_priv;
817 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700818 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819
Ming Leicdc97792008-02-24 18:41:47 +0800820 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700822 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700823 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 return;
825 }
826 if (urb->actual_length < 14) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700827 dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 goto exit;
829 }
830
831 msg = (struct keyspan_usa90_portStatusMessage *)data;
832
833 /* Now do something useful with the data */
834
835 port = serial->port[0];
836 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100837
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 /* Update handshaking pin state information */
839 old_dcd_state = p_priv->dcd_state;
840 p_priv->cts_state = ((msg->cts) ? 1 : 0);
841 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
842 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
843 p_priv->ri_state = ((msg->ri) ? 1 : 0);
844
Jiri Slabyaa27a092013-03-07 13:12:30 +0100845 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
846 tty_port_tty_hangup(&port->port, true);
Alan Coxdeb91682008-07-22 11:13:08 +0100847
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100849 err = usb_submit_urb(urb, GFP_ATOMIC);
850 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700851 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852exit:
853 ;
854}
855
David Howells7d12e782006-10-05 14:55:46 +0100856static void usa90_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857{
858 struct usb_serial_port *port;
859 struct keyspan_port_private *p_priv;
860
Ming Leicdc97792008-02-24 18:41:47 +0800861 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 p_priv = usb_get_serial_port_data(port);
863
864 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700865 dev_dbg(&urb->dev->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100866 keyspan_usa90_send_setup(port->serial, port,
867 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 }
869}
870
Lucy McCoy0ca12682007-05-18 12:10:41 -0700871/* Status messages from the 28xg */
872static void usa67_instat_callback(struct urb *urb)
873{
874 int err;
875 unsigned char *data = urb->transfer_buffer;
876 struct keyspan_usa67_portStatusMessage *msg;
877 struct usb_serial *serial;
878 struct usb_serial_port *port;
879 struct keyspan_port_private *p_priv;
880 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700881 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700882
Lucy McCoy0ca12682007-05-18 12:10:41 -0700883 serial = urb->context;
884
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700885 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700886 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700887 return;
888 }
889
Alan Coxdeb91682008-07-22 11:13:08 +0100890 if (urb->actual_length !=
891 sizeof(struct keyspan_usa67_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700892 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700893 return;
894 }
895
896
897 /* Now do something useful with the data */
898 msg = (struct keyspan_usa67_portStatusMessage *)data;
899
900 /* Check port number from message and retrieve private data */
901 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700902 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700903 return;
904 }
905
906 port = serial->port[msg->port];
907 p_priv = usb_get_serial_port_data(port);
908
909 /* Update handshaking pin state information */
910 old_dcd_state = p_priv->dcd_state;
911 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
912 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
913
Jiri Slabyaa27a092013-03-07 13:12:30 +0100914 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
915 tty_port_tty_hangup(&port->port, true);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700916
917 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700918 err = usb_submit_urb(urb, GFP_ATOMIC);
919 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700920 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700921}
922
923static void usa67_glocont_callback(struct urb *urb)
924{
925 struct usb_serial *serial;
926 struct usb_serial_port *port;
927 struct keyspan_port_private *p_priv;
928 int i;
929
Lucy McCoy0ca12682007-05-18 12:10:41 -0700930 serial = urb->context;
931 for (i = 0; i < serial->num_ports; ++i) {
932 port = serial->port[i];
933 p_priv = usb_get_serial_port_data(port);
934
935 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700936 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700937 keyspan_usa67_send_setup(serial, port,
938 p_priv->resend_cont - 1);
939 break;
940 }
941 }
942}
943
Alan Cox95da3102008-07-22 11:09:07 +0100944static int keyspan_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945{
Alan Cox95da3102008-07-22 11:09:07 +0100946 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 struct keyspan_port_private *p_priv;
948 const struct keyspan_device_details *d_details;
949 int flip;
950 int data_len;
951 struct urb *this_urb;
952
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 p_priv = usb_get_serial_port_data(port);
954 d_details = p_priv->device_details;
955
Alan Coxa5b6f602008-04-08 17:16:06 +0100956 /* FIXME: locking */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 if (d_details->msg_format == msg_usa90)
Alan Coxdeb91682008-07-22 11:13:08 +0100958 data_len = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959 else
960 data_len = 63;
961
962 flip = p_priv->out_flip;
963
964 /* Check both endpoints to see if any are available. */
Alan Coxdeb91682008-07-22 11:13:08 +0100965 this_urb = p_priv->out_urbs[flip];
966 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +0100968 return data_len;
969 flip = (flip + 1) & d_details->outdat_endp_flip;
970 this_urb = p_priv->out_urbs[flip];
971 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +0100973 return data_len;
974 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 }
Alan Coxa5b6f602008-04-08 17:16:06 +0100976 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977}
978
979
Alan Coxa509a7e2009-09-19 13:13:26 -0700980static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981{
Andrew Mortonf78ba152007-11-28 16:21:54 -0800982 struct keyspan_port_private *p_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 const struct keyspan_device_details *d_details;
984 int i, err;
Andrew Mortonf78ba152007-11-28 16:21:54 -0800985 int baud_rate, device_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 struct urb *urb;
Alan Cox95da3102008-07-22 11:09:07 +0100987 unsigned int cflag = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 p_priv = usb_get_serial_port_data(port);
990 d_details = p_priv->device_details;
Borislav Petkov7eea4362007-11-14 17:00:39 -0800991
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 /* Set some sane defaults */
993 p_priv->rts_state = 1;
994 p_priv->dtr_state = 1;
995 p_priv->baud = 9600;
996
997 /* force baud and lcr to be set on open */
998 p_priv->old_baud = 0;
999 p_priv->old_cflag = 0;
1000
1001 p_priv->out_flip = 0;
1002 p_priv->in_flip = 0;
1003
1004 /* Reset low level data toggle and start reading from endpoints */
1005 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001006 urb = p_priv->in_urbs[i];
1007 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009
Alan Coxdeb91682008-07-22 11:13:08 +01001010 /* make sure endpoint data toggle is synchronized
1011 with the device */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 usb_clear_halt(urb->dev, urb->pipe);
Alan Coxdeb91682008-07-22 11:13:08 +01001013 err = usb_submit_urb(urb, GFP_KERNEL);
1014 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001015 dev_dbg(&port->dev, "%s - submit urb %d failed (%d)\n", __func__, i, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 }
1017
1018 /* Reset low level data toggle on out endpoints */
1019 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001020 urb = p_priv->out_urbs[i];
1021 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 continue;
Alan Coxdeb91682008-07-22 11:13:08 +01001023 /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
1024 usb_pipeout(urb->pipe), 0); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 }
1026
Andrew Mortonf78ba152007-11-28 16:21:54 -08001027 /* get the terminal config for the setup message now so we don't
1028 * need to send 2 of them */
1029
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001030 device_port = port->port_number;
Alan Cox95da3102008-07-22 11:09:07 +01001031 if (tty) {
Alan Coxadc8d742012-07-14 15:31:47 +01001032 cflag = tty->termios.c_cflag;
Alan Cox95da3102008-07-22 11:09:07 +01001033 /* Baud rate calculation takes baud rate as an integer
1034 so other rates can be generated if desired. */
1035 baud_rate = tty_get_baud_rate(tty);
1036 /* If no match or invalid, leave as default */
1037 if (baud_rate >= 0
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001038 && d_details->calculate_baud_rate(port, baud_rate, d_details->baudclk,
Alan Cox95da3102008-07-22 11:09:07 +01001039 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
1040 p_priv->baud = baud_rate;
1041 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001042 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001043 /* set CTS/RTS handshake etc. */
1044 p_priv->cflag = cflag;
Ben Minerds2b982ab2012-07-12 00:10:16 +10001045 p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001046
1047 keyspan_send_setup(port, 1);
Alan Coxdeb91682008-07-22 11:13:08 +01001048 /* mdelay(100); */
1049 /* keyspan_set_termios(port, NULL); */
Andrew Mortonf78ba152007-11-28 16:21:54 -08001050
Alan Coxa5b6f602008-04-08 17:16:06 +01001051 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052}
1053
1054static inline void stop_urb(struct urb *urb)
1055{
Greg Kroah-Hartman242cf672005-07-29 16:11:07 -04001056 if (urb && urb->status == -EINPROGRESS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 usb_kill_urb(urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058}
1059
Alan Cox335f8512009-06-11 12:26:29 +01001060static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
1061{
1062 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
1063
1064 p_priv->rts_state = on;
1065 p_priv->dtr_state = on;
1066 keyspan_send_setup(port, 0);
1067}
1068
1069static void keyspan_close(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070{
1071 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 struct keyspan_port_private *p_priv;
1073
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +01001075
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 p_priv->rts_state = 0;
1077 p_priv->dtr_state = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001078
Johan Hovold80dfe0c2013-03-21 12:36:32 +01001079 keyspan_send_setup(port, 2);
1080 /* pilot-xfer seems to work best with this delay */
1081 mdelay(100);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082
1083 p_priv->out_flip = 0;
1084 p_priv->in_flip = 0;
1085
Johan Hovold80dfe0c2013-03-21 12:36:32 +01001086 stop_urb(p_priv->inack_urb);
1087 for (i = 0; i < 2; i++) {
1088 stop_urb(p_priv->in_urbs[i]);
1089 stop_urb(p_priv->out_urbs[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091}
1092
Alan Coxdeb91682008-07-22 11:13:08 +01001093/* download the firmware to a pre-renumeration device */
1094static int keyspan_fake_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095{
Rene Buergel8d733e22012-09-18 09:02:01 +02001096 char *fw_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001098 dev_dbg(&serial->dev->dev, "Keyspan startup version %04x product %04x\n",
1099 le16_to_cpu(serial->dev->descriptor.bcdDevice),
1100 le16_to_cpu(serial->dev->descriptor.idProduct));
Alan Coxdeb91682008-07-22 11:13:08 +01001101
1102 if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000)
1103 != 0x8000) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001104 dev_dbg(&serial->dev->dev, "Firmware already loaded. Quitting.\n");
Alan Coxdeb91682008-07-22 11:13:08 +01001105 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 }
1107
1108 /* Select firmware image on the basis of idProduct */
1109 switch (le16_to_cpu(serial->dev->descriptor.idProduct)) {
1110 case keyspan_usa28_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001111 fw_name = "keyspan/usa28.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 break;
1113
1114 case keyspan_usa28x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001115 fw_name = "keyspan/usa28x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 break;
1117
1118 case keyspan_usa28xa_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001119 fw_name = "keyspan/usa28xa.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 break;
1121
1122 case keyspan_usa28xb_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001123 fw_name = "keyspan/usa28xb.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 break;
1125
1126 case keyspan_usa19_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001127 fw_name = "keyspan/usa19.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001129
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 case keyspan_usa19qi_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001131 fw_name = "keyspan/usa19qi.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001133
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 case keyspan_mpr_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001135 fw_name = "keyspan/mpr.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 break;
1137
1138 case keyspan_usa19qw_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001139 fw_name = "keyspan/usa19qw.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001141
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142 case keyspan_usa18x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001143 fw_name = "keyspan/usa18x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001145
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 case keyspan_usa19w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001147 fw_name = "keyspan/usa19w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001149
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 case keyspan_usa49w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001151 fw_name = "keyspan/usa49w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 break;
1153
1154 case keyspan_usa49wlc_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001155 fw_name = "keyspan/usa49wlc.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 break;
1157
1158 default:
David Woodhouse2971c572008-05-30 14:04:03 +03001159 dev_err(&serial->dev->dev, "Unknown product ID (%04x)\n",
1160 le16_to_cpu(serial->dev->descriptor.idProduct));
1161 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 }
1163
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001164 dev_dbg(&serial->dev->dev, "Uploading Keyspan %s firmware.\n", fw_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165
Rene Buergel8d733e22012-09-18 09:02:01 +02001166 if (ezusb_fx1_ihex_firmware_download(serial->dev, fw_name) < 0) {
1167 dev_err(&serial->dev->dev, "failed to load firmware \"%s\"\n",
1168 fw_name);
1169 return -ENOENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 }
1171
Rene Buergel8d733e22012-09-18 09:02:01 +02001172 /* after downloading firmware Renumeration will occur in a
1173 moment and the new device will bind to the real driver */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174
1175 /* we don't want this device to have a driver assigned to it. */
Alan Coxdeb91682008-07-22 11:13:08 +01001176 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177}
1178
1179/* Helper functions used by keyspan_setup_urbs */
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001180static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *serial,
1181 int endpoint)
1182{
1183 struct usb_host_interface *iface_desc;
1184 struct usb_endpoint_descriptor *ep;
1185 int i;
1186
1187 iface_desc = serial->interface->cur_altsetting;
1188 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1189 ep = &iface_desc->endpoint[i].desc;
1190 if (ep->bEndpointAddress == endpoint)
1191 return ep;
1192 }
1193 dev_warn(&serial->interface->dev, "found no endpoint descriptor for "
1194 "endpoint %x\n", endpoint);
1195 return NULL;
1196}
1197
Alan Coxdeb91682008-07-22 11:13:08 +01001198static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 int dir, void *ctx, char *buf, int len,
David Howells7d12e782006-10-05 14:55:46 +01001200 void (*callback)(struct urb *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201{
1202 struct urb *urb;
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001203 struct usb_endpoint_descriptor const *ep_desc;
1204 char const *ep_type_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205
1206 if (endpoint == -1)
1207 return NULL; /* endpoint not needed */
1208
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001209 dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %d.\n", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
Johan Hovold10c642d2013-12-29 19:22:56 +01001211 if (!urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213
Lucy McCoy0ca12682007-05-18 12:10:41 -07001214 if (endpoint == 0) {
1215 /* control EP filled in when used */
1216 return urb;
1217 }
1218
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001219 ep_desc = find_ep(serial, endpoint);
1220 if (!ep_desc) {
1221 /* leak the urb, something's wrong and the callers don't care */
1222 return urb;
1223 }
1224 if (usb_endpoint_xfer_int(ep_desc)) {
1225 ep_type_name = "INT";
1226 usb_fill_int_urb(urb, serial->dev,
1227 usb_sndintpipe(serial->dev, endpoint) | dir,
1228 buf, len, callback, ctx,
1229 ep_desc->bInterval);
1230 } else if (usb_endpoint_xfer_bulk(ep_desc)) {
1231 ep_type_name = "BULK";
1232 usb_fill_bulk_urb(urb, serial->dev,
1233 usb_sndbulkpipe(serial->dev, endpoint) | dir,
1234 buf, len, callback, ctx);
1235 } else {
1236 dev_warn(&serial->interface->dev,
1237 "unsupported endpoint type %x\n",
Julia Lawall2e0fe702008-12-29 11:22:14 +01001238 usb_endpoint_type(ep_desc));
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001239 usb_free_urb(urb);
1240 return NULL;
1241 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001243 dev_dbg(&serial->interface->dev, "%s - using urb %p for %s endpoint %x\n",
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001244 __func__, urb, ep_type_name, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245 return urb;
1246}
1247
1248static struct callbacks {
David Howells7d12e782006-10-05 14:55:46 +01001249 void (*instat_callback)(struct urb *);
1250 void (*glocont_callback)(struct urb *);
1251 void (*indat_callback)(struct urb *);
1252 void (*outdat_callback)(struct urb *);
1253 void (*inack_callback)(struct urb *);
1254 void (*outcont_callback)(struct urb *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255} keyspan_callbacks[] = {
1256 {
1257 /* msg_usa26 callbacks */
1258 .instat_callback = usa26_instat_callback,
1259 .glocont_callback = usa26_glocont_callback,
1260 .indat_callback = usa26_indat_callback,
1261 .outdat_callback = usa2x_outdat_callback,
1262 .inack_callback = usa26_inack_callback,
1263 .outcont_callback = usa26_outcont_callback,
1264 }, {
1265 /* msg_usa28 callbacks */
1266 .instat_callback = usa28_instat_callback,
1267 .glocont_callback = usa28_glocont_callback,
1268 .indat_callback = usa28_indat_callback,
1269 .outdat_callback = usa2x_outdat_callback,
1270 .inack_callback = usa28_inack_callback,
1271 .outcont_callback = usa28_outcont_callback,
1272 }, {
1273 /* msg_usa49 callbacks */
1274 .instat_callback = usa49_instat_callback,
1275 .glocont_callback = usa49_glocont_callback,
1276 .indat_callback = usa49_indat_callback,
1277 .outdat_callback = usa2x_outdat_callback,
1278 .inack_callback = usa49_inack_callback,
1279 .outcont_callback = usa49_outcont_callback,
1280 }, {
1281 /* msg_usa90 callbacks */
1282 .instat_callback = usa90_instat_callback,
Alan Coxdeb91682008-07-22 11:13:08 +01001283 .glocont_callback = usa28_glocont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 .indat_callback = usa90_indat_callback,
1285 .outdat_callback = usa2x_outdat_callback,
1286 .inack_callback = usa28_inack_callback,
1287 .outcont_callback = usa90_outcont_callback,
Lucy McCoy0ca12682007-05-18 12:10:41 -07001288 }, {
1289 /* msg_usa67 callbacks */
1290 .instat_callback = usa67_instat_callback,
1291 .glocont_callback = usa67_glocont_callback,
1292 .indat_callback = usa26_indat_callback,
1293 .outdat_callback = usa2x_outdat_callback,
1294 .inack_callback = usa26_inack_callback,
1295 .outcont_callback = usa26_outcont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 }
1297};
1298
1299 /* Generic setup urbs function that uses
1300 data in device_details */
1301static void keyspan_setup_urbs(struct usb_serial *serial)
1302{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 struct keyspan_serial_private *s_priv;
1304 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305 struct callbacks *cback;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 s_priv = usb_get_serial_data(serial);
1308 d_details = s_priv->device_details;
1309
Alan Coxdeb91682008-07-22 11:13:08 +01001310 /* Setup values for the various callback routines */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 cback = &keyspan_callbacks[d_details->msg_format];
1312
Alan Coxdeb91682008-07-22 11:13:08 +01001313 /* Allocate and set up urbs for each one that is in use,
1314 starting with instat endpoints */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315 s_priv->instat_urb = keyspan_setup_urb
1316 (serial, d_details->instat_endpoint, USB_DIR_IN,
1317 serial, s_priv->instat_buf, INSTAT_BUFLEN,
1318 cback->instat_callback);
1319
Lucy McCoy0ca12682007-05-18 12:10:41 -07001320 s_priv->indat_urb = keyspan_setup_urb
1321 (serial, d_details->indat_endpoint, USB_DIR_IN,
1322 serial, s_priv->indat_buf, INDAT49W_BUFLEN,
1323 usa49wg_indat_callback);
1324
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 s_priv->glocont_urb = keyspan_setup_urb
1326 (serial, d_details->glocont_endpoint, USB_DIR_OUT,
1327 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
1328 cback->glocont_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329}
1330
1331/* usa19 function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001332static int keyspan_usa19_calc_baud(struct usb_serial_port *port,
1333 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 u8 *rate_low, u8 *prescaler, int portnum)
1335{
1336 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001337 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 cnt; /* inverse of divisor (programmed into 8051) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001340 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341
Alan Coxdeb91682008-07-22 11:13:08 +01001342 /* prevent divide by zero... */
1343 b16 = baud_rate * 16L;
1344 if (b16 == 0)
1345 return KEYSPAN_INVALID_BAUD_RATE;
1346 /* Any "standard" rate over 57k6 is marginal on the USA-19
1347 as we run out of divisor resolution. */
1348 if (baud_rate > 57600)
1349 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350
Alan Coxdeb91682008-07-22 11:13:08 +01001351 /* calculate the divisor and the counter (its inverse) */
1352 div = baudclk / b16;
1353 if (div == 0)
1354 return KEYSPAN_INVALID_BAUD_RATE;
1355 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357
Alan Coxdeb91682008-07-22 11:13:08 +01001358 if (div > 0xffff)
1359 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
Alan Coxdeb91682008-07-22 11:13:08 +01001361 /* return the counter values if non-null */
1362 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001364 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001366 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001367 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001368 __func__, baud_rate, *rate_hi, *rate_low);
1369 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370}
1371
1372/* usa19hs function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001373static int keyspan_usa19hs_calc_baud(struct usb_serial_port *port,
1374 u32 baud_rate, u32 baudclk, u8 *rate_hi,
1375 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376{
1377 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001378 div; /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001380 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381
Alan Coxdeb91682008-07-22 11:13:08 +01001382 /* prevent divide by zero... */
1383 b16 = baud_rate * 16L;
1384 if (b16 == 0)
1385 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
Alan Coxdeb91682008-07-22 11:13:08 +01001387 /* calculate the divisor */
1388 div = baudclk / b16;
1389 if (div == 0)
1390 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391
Alan Coxdeb91682008-07-22 11:13:08 +01001392 if (div > 0xffff)
1393 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394
Alan Coxdeb91682008-07-22 11:13:08 +01001395 /* return the counter values if non-null */
1396 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001398
1399 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400 *rate_hi = (u8) ((div >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001401
1402 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001403 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001404 __func__, baud_rate, *rate_hi, *rate_low);
1405
1406 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407}
1408
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001409static int keyspan_usa19w_calc_baud(struct usb_serial_port *port,
1410 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 u8 *rate_low, u8 *prescaler, int portnum)
1412{
1413 u32 b16, /* baud rate times 16 (actual rate used internally) */
1414 clk, /* clock with 13/8 prescaler */
Alan Coxdeb91682008-07-22 11:13:08 +01001415 div, /* divisor using 13/8 prescaler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 res, /* resulting baud rate using 13/8 prescaler */
1417 diff, /* error using 13/8 prescaler */
1418 smallest_diff;
1419 u8 best_prescaler;
1420 int i;
1421
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001422 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423
Alan Coxdeb91682008-07-22 11:13:08 +01001424 /* prevent divide by zero */
1425 b16 = baud_rate * 16L;
1426 if (b16 == 0)
1427 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428
Alan Coxdeb91682008-07-22 11:13:08 +01001429 /* Calculate prescaler by trying them all and looking
1430 for best fit */
1431
1432 /* start with largest possible difference */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 smallest_diff = 0xffffffff;
1434
1435 /* 0 is an invalid prescaler, used as a flag */
1436 best_prescaler = 0;
1437
Alan Coxdeb91682008-07-22 11:13:08 +01001438 for (i = 8; i <= 0xff; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 clk = (baudclk * 8) / (u32) i;
Alan Coxdeb91682008-07-22 11:13:08 +01001440
1441 div = clk / b16;
1442 if (div == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
1445 res = clk / div;
Alan Coxdeb91682008-07-22 11:13:08 +01001446 diff = (res > b16) ? (res-b16) : (b16-res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447
Alan Coxdeb91682008-07-22 11:13:08 +01001448 if (diff < smallest_diff) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 best_prescaler = i;
1450 smallest_diff = diff;
1451 }
1452 }
1453
Alan Coxdeb91682008-07-22 11:13:08 +01001454 if (best_prescaler == 0)
1455 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456
1457 clk = (baudclk * 8) / (u32) best_prescaler;
1458 div = clk / b16;
1459
Alan Coxdeb91682008-07-22 11:13:08 +01001460 /* return the divisor and prescaler if non-null */
1461 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001463 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 *rate_hi = (u8) ((div >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 if (prescaler) {
1466 *prescaler = best_prescaler;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001467 /* dev_dbg(&port->dev, "%s - %d %d\n", __func__, *prescaler, div); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 }
Alan Coxdeb91682008-07-22 11:13:08 +01001469 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470}
1471
1472 /* USA-28 supports different maximum baud rates on each port */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001473static int keyspan_usa28_calc_baud(struct usb_serial_port *port,
1474 u32 baud_rate, u32 baudclk, u8 *rate_hi,
1475 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476{
1477 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001478 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 cnt; /* inverse of divisor (programmed into 8051) */
1480
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001481 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482
1483 /* prevent divide by zero */
Alan Coxdeb91682008-07-22 11:13:08 +01001484 b16 = baud_rate * 16L;
1485 if (b16 == 0)
1486 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487
Alan Coxdeb91682008-07-22 11:13:08 +01001488 /* calculate the divisor and the counter (its inverse) */
1489 div = KEYSPAN_USA28_BAUDCLK / b16;
1490 if (div == 0)
1491 return KEYSPAN_INVALID_BAUD_RATE;
1492 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494
Alan Coxdeb91682008-07-22 11:13:08 +01001495 /* check for out of range, based on portnum,
1496 and return result */
1497 if (portnum == 0) {
1498 if (div > 0xffff)
1499 return KEYSPAN_INVALID_BAUD_RATE;
1500 } else {
1501 if (portnum == 1) {
1502 if (div > 0xff)
1503 return KEYSPAN_INVALID_BAUD_RATE;
1504 } else
1505 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506 }
1507
1508 /* return the counter values if not NULL
1509 (port 1 will ignore retHi) */
Alan Coxdeb91682008-07-22 11:13:08 +01001510 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001512 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001514 dev_dbg(&port->dev, "%s - %d OK.\n", __func__, baud_rate);
Alan Coxdeb91682008-07-22 11:13:08 +01001515 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516}
1517
1518static int keyspan_usa26_send_setup(struct usb_serial *serial,
1519 struct usb_serial_port *port,
1520 int reset_port)
1521{
Alan Coxdeb91682008-07-22 11:13:08 +01001522 struct keyspan_usa26_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 struct keyspan_serial_private *s_priv;
1524 struct keyspan_port_private *p_priv;
1525 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 struct urb *this_urb;
1527 int device_port, err;
1528
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001529 dev_dbg(&port->dev, "%s reset=%d\n", __func__, reset_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530
1531 s_priv = usb_get_serial_data(serial);
1532 p_priv = usb_get_serial_port_data(port);
1533 d_details = s_priv->device_details;
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001534 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 this_urb = p_priv->outcont_urb;
1537
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 /* Make sure we have an urb then send the message */
1539 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001540 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 return -1;
1542 }
1543
Rickard Strandqvistd5afce82014-05-16 17:39:13 +02001544 dev_dbg(&port->dev, "%s - endpoint %d\n", __func__, usb_pipeendpoint(this_urb->pipe));
1545
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001547 Don't overwrite resend for open/close condition. */
1548 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 p_priv->resend_cont = reset_port + 1;
1550 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001551 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001553 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554 }
1555
Alan Coxdeb91682008-07-22 11:13:08 +01001556 memset(&msg, 0, sizeof(struct keyspan_usa26_portControlMessage));
1557
1558 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 if (p_priv->old_baud != p_priv->baud) {
1560 p_priv->old_baud = p_priv->baud;
1561 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001562 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1563 &msg.baudHi, &msg.baudLo, &msg.prescaler,
1564 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1565 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
1566 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567 msg.baudLo = 0;
1568 msg.baudHi = 125; /* Values for 9600 baud */
1569 msg.prescaler = 10;
1570 }
1571 msg.setPrescaler = 0xff;
1572 }
1573
Ben Minerds2b982ab2012-07-12 00:10:16 +10001574 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575 switch (p_priv->cflag & CSIZE) {
1576 case CS5:
1577 msg.lcr |= USA_DATABITS_5;
1578 break;
1579 case CS6:
1580 msg.lcr |= USA_DATABITS_6;
1581 break;
1582 case CS7:
1583 msg.lcr |= USA_DATABITS_7;
1584 break;
1585 case CS8:
1586 msg.lcr |= USA_DATABITS_8;
1587 break;
1588 }
1589 if (p_priv->cflag & PARENB) {
1590 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10001591 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01001592 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593 }
1594 msg.setLcr = 0xff;
1595
1596 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1597 msg.xonFlowControl = 0;
1598 msg.setFlowControl = 0xff;
1599 msg.forwardingLength = 16;
1600 msg.xonChar = 17;
1601 msg.xoffChar = 19;
1602
1603 /* Opening port */
1604 if (reset_port == 1) {
1605 msg._txOn = 1;
1606 msg._txOff = 0;
1607 msg.txFlush = 0;
1608 msg.txBreak = 0;
1609 msg.rxOn = 1;
1610 msg.rxOff = 0;
1611 msg.rxFlush = 1;
1612 msg.rxForward = 0;
1613 msg.returnStatus = 0;
1614 msg.resetDataToggle = 0xff;
1615 }
1616
1617 /* Closing port */
1618 else if (reset_port == 2) {
1619 msg._txOn = 0;
1620 msg._txOff = 1;
1621 msg.txFlush = 0;
1622 msg.txBreak = 0;
1623 msg.rxOn = 0;
1624 msg.rxOff = 1;
1625 msg.rxFlush = 1;
1626 msg.rxForward = 0;
1627 msg.returnStatus = 0;
1628 msg.resetDataToggle = 0;
1629 }
1630
1631 /* Sending intermediate configs */
1632 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001633 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 msg._txOff = 0;
1635 msg.txFlush = 0;
1636 msg.txBreak = (p_priv->break_on);
1637 msg.rxOn = 0;
1638 msg.rxOff = 0;
1639 msg.rxFlush = 0;
1640 msg.rxForward = 0;
1641 msg.returnStatus = 0;
1642 msg.resetDataToggle = 0x0;
1643 }
1644
Alan Coxdeb91682008-07-22 11:13:08 +01001645 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 msg.setTxTriState_setRts = 0xff;
1647 msg.txTriState_rts = p_priv->rts_state;
1648
1649 msg.setHskoa_setDtr = 0xff;
1650 msg.hskoa_dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01001651
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001653 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
1654
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 /* send the data out the device on control endpoint */
1656 this_urb->transfer_buffer_length = sizeof(msg);
1657
Alan Coxdeb91682008-07-22 11:13:08 +01001658 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1659 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001660 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01001661 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662}
1663
1664static int keyspan_usa28_send_setup(struct usb_serial *serial,
1665 struct usb_serial_port *port,
1666 int reset_port)
1667{
Alan Coxdeb91682008-07-22 11:13:08 +01001668 struct keyspan_usa28_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669 struct keyspan_serial_private *s_priv;
1670 struct keyspan_port_private *p_priv;
1671 const struct keyspan_device_details *d_details;
1672 struct urb *this_urb;
1673 int device_port, err;
1674
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675 s_priv = usb_get_serial_data(serial);
1676 p_priv = usb_get_serial_port_data(port);
1677 d_details = s_priv->device_details;
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001678 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679
1680 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01001681 this_urb = p_priv->outcont_urb;
1682 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001683 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 return -1;
1685 }
1686
1687 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001688 Don't overwrite resend for open/close condition. */
1689 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 p_priv->resend_cont = reset_port + 1;
1691 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001692 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001694 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695 }
1696
Alan Coxdeb91682008-07-22 11:13:08 +01001697 memset(&msg, 0, sizeof(struct keyspan_usa28_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698
1699 msg.setBaudRate = 1;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001700 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1701 &msg.baudHi, &msg.baudLo, NULL,
1702 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1703 dev_dbg(&port->dev, "%s - Invalid baud rate requested %d.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001704 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705 msg.baudLo = 0xff;
1706 msg.baudHi = 0xb2; /* Values for 9600 baud */
1707 }
1708
1709 /* If parity is enabled, we must calculate it ourselves. */
1710 msg.parity = 0; /* XXX for now */
1711
1712 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1713 msg.xonFlowControl = 0;
1714
Alan Coxdeb91682008-07-22 11:13:08 +01001715 /* Do handshaking outputs, DTR is inverted relative to RTS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 msg.rts = p_priv->rts_state;
1717 msg.dtr = p_priv->dtr_state;
1718
1719 msg.forwardingLength = 16;
1720 msg.forwardMs = 10;
1721 msg.breakThreshold = 45;
1722 msg.xonChar = 17;
1723 msg.xoffChar = 19;
1724
1725 /*msg.returnStatus = 1;
1726 msg.resetDataToggle = 0xff;*/
1727 /* Opening port */
1728 if (reset_port == 1) {
1729 msg._txOn = 1;
1730 msg._txOff = 0;
1731 msg.txFlush = 0;
1732 msg.txForceXoff = 0;
1733 msg.txBreak = 0;
1734 msg.rxOn = 1;
1735 msg.rxOff = 0;
1736 msg.rxFlush = 1;
1737 msg.rxForward = 0;
1738 msg.returnStatus = 0;
1739 msg.resetDataToggle = 0xff;
1740 }
1741 /* Closing port */
1742 else if (reset_port == 2) {
1743 msg._txOn = 0;
1744 msg._txOff = 1;
1745 msg.txFlush = 0;
1746 msg.txForceXoff = 0;
1747 msg.txBreak = 0;
1748 msg.rxOn = 0;
1749 msg.rxOff = 1;
1750 msg.rxFlush = 1;
1751 msg.rxForward = 0;
1752 msg.returnStatus = 0;
1753 msg.resetDataToggle = 0;
1754 }
1755 /* Sending intermediate configs */
1756 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001757 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758 msg._txOff = 0;
1759 msg.txFlush = 0;
1760 msg.txForceXoff = 0;
1761 msg.txBreak = (p_priv->break_on);
1762 msg.rxOn = 0;
1763 msg.rxOff = 0;
1764 msg.rxFlush = 0;
1765 msg.rxForward = 0;
1766 msg.returnStatus = 0;
1767 msg.resetDataToggle = 0x0;
1768 }
1769
1770 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001771 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772
1773 /* send the data out the device on control endpoint */
1774 this_urb->transfer_buffer_length = sizeof(msg);
1775
Alan Coxdeb91682008-07-22 11:13:08 +01001776 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1777 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001778 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779
Alan Coxa5b6f602008-04-08 17:16:06 +01001780 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781}
1782
1783static int keyspan_usa49_send_setup(struct usb_serial *serial,
1784 struct usb_serial_port *port,
1785 int reset_port)
1786{
Lucy McCoy0ca12682007-05-18 12:10:41 -07001787 struct keyspan_usa49_portControlMessage msg;
1788 struct usb_ctrlrequest *dr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789 struct keyspan_serial_private *s_priv;
1790 struct keyspan_port_private *p_priv;
1791 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792 struct urb *this_urb;
1793 int err, device_port;
1794
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795 s_priv = usb_get_serial_data(serial);
1796 p_priv = usb_get_serial_port_data(port);
1797 d_details = s_priv->device_details;
1798
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799 this_urb = s_priv->glocont_urb;
1800
Lucy McCoy0ca12682007-05-18 12:10:41 -07001801 /* Work out which port within the device is being setup */
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001802 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05301804 /* Make sure we have an urb then send the message */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 if (this_urb == NULL) {
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001806 dev_dbg(&port->dev, "%s - oops no urb for port.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807 return -1;
1808 }
1809
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001810 dev_dbg(&port->dev, "%s - endpoint %d (%d)\n",
1811 __func__, usb_pipeendpoint(this_urb->pipe), device_port);
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05301812
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001814 Don't overwrite resend for open/close condition. */
1815 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816 p_priv->resend_cont = reset_port + 1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001817
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001819 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001821 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822 }
1823
Alan Coxdeb91682008-07-22 11:13:08 +01001824 memset(&msg, 0, sizeof(struct keyspan_usa49_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826 msg.portNumber = device_port;
Alan Coxdeb91682008-07-22 11:13:08 +01001827
1828 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829 if (p_priv->old_baud != p_priv->baud) {
1830 p_priv->old_baud = p_priv->baud;
1831 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001832 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1833 &msg.baudHi, &msg.baudLo, &msg.prescaler,
1834 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1835 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
1836 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837 msg.baudLo = 0;
1838 msg.baudHi = 125; /* Values for 9600 baud */
1839 msg.prescaler = 10;
1840 }
Alan Coxdeb91682008-07-22 11:13:08 +01001841 /* msg.setPrescaler = 0xff; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 }
1843
Ben Minerds2b982ab2012-07-12 00:10:16 +10001844 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845 switch (p_priv->cflag & CSIZE) {
1846 case CS5:
1847 msg.lcr |= USA_DATABITS_5;
1848 break;
1849 case CS6:
1850 msg.lcr |= USA_DATABITS_6;
1851 break;
1852 case CS7:
1853 msg.lcr |= USA_DATABITS_7;
1854 break;
1855 case CS8:
1856 msg.lcr |= USA_DATABITS_8;
1857 break;
1858 }
1859 if (p_priv->cflag & PARENB) {
1860 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10001861 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01001862 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863 }
1864 msg.setLcr = 0xff;
1865
1866 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1867 msg.xonFlowControl = 0;
1868 msg.setFlowControl = 0xff;
Alan Coxdeb91682008-07-22 11:13:08 +01001869
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 msg.forwardingLength = 16;
1871 msg.xonChar = 17;
1872 msg.xoffChar = 19;
1873
Alan Coxdeb91682008-07-22 11:13:08 +01001874 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875 if (reset_port == 1) {
1876 msg._txOn = 1;
1877 msg._txOff = 0;
1878 msg.txFlush = 0;
1879 msg.txBreak = 0;
1880 msg.rxOn = 1;
1881 msg.rxOff = 0;
1882 msg.rxFlush = 1;
1883 msg.rxForward = 0;
1884 msg.returnStatus = 0;
1885 msg.resetDataToggle = 0xff;
1886 msg.enablePort = 1;
1887 msg.disablePort = 0;
1888 }
1889 /* Closing port */
1890 else if (reset_port == 2) {
1891 msg._txOn = 0;
1892 msg._txOff = 1;
1893 msg.txFlush = 0;
1894 msg.txBreak = 0;
1895 msg.rxOn = 0;
1896 msg.rxOff = 1;
1897 msg.rxFlush = 1;
1898 msg.rxForward = 0;
1899 msg.returnStatus = 0;
1900 msg.resetDataToggle = 0;
1901 msg.enablePort = 0;
1902 msg.disablePort = 1;
1903 }
1904 /* Sending intermediate configs */
1905 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001906 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907 msg._txOff = 0;
1908 msg.txFlush = 0;
1909 msg.txBreak = (p_priv->break_on);
1910 msg.rxOn = 0;
1911 msg.rxOff = 0;
1912 msg.rxFlush = 0;
1913 msg.rxForward = 0;
1914 msg.returnStatus = 0;
1915 msg.resetDataToggle = 0x0;
1916 msg.enablePort = 0;
1917 msg.disablePort = 0;
1918 }
1919
Alan Coxdeb91682008-07-22 11:13:08 +01001920 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921 msg.setRts = 0xff;
1922 msg.rts = p_priv->rts_state;
1923
1924 msg.setDtr = 0xff;
1925 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01001926
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927 p_priv->resend_cont = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928
Alan Coxdeb91682008-07-22 11:13:08 +01001929 /* if the device is a 49wg, we send control message on usb
1930 control EP 0 */
Lucy McCoy0ca12682007-05-18 12:10:41 -07001931
1932 if (d_details->product_id == keyspan_usa49wg_product_id) {
1933 dr = (void *)(s_priv->ctrl_buf);
1934 dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT;
1935 dr->bRequest = 0xB0; /* 49wg control message */;
1936 dr->wValue = 0;
1937 dr->wIndex = 0;
1938 dr->wLength = cpu_to_le16(sizeof(msg));
1939
Alan Coxdeb91682008-07-22 11:13:08 +01001940 memcpy(s_priv->glocont_buf, &msg, sizeof(msg));
Lucy McCoy0ca12682007-05-18 12:10:41 -07001941
Alan Coxdeb91682008-07-22 11:13:08 +01001942 usb_fill_control_urb(this_urb, serial->dev,
1943 usb_sndctrlpipe(serial->dev, 0),
1944 (unsigned char *)dr, s_priv->glocont_buf,
1945 sizeof(msg), usa49_glocont_callback, serial);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001946
1947 } else {
1948 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Alan Coxdeb91682008-07-22 11:13:08 +01001949
Lucy McCoy0ca12682007-05-18 12:10:41 -07001950 /* send the data out the device on control endpoint */
1951 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001952 }
Alan Coxdeb91682008-07-22 11:13:08 +01001953 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1954 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001955 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956
Alan Coxa5b6f602008-04-08 17:16:06 +01001957 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958}
1959
1960static int keyspan_usa90_send_setup(struct usb_serial *serial,
1961 struct usb_serial_port *port,
1962 int reset_port)
1963{
Alan Coxdeb91682008-07-22 11:13:08 +01001964 struct keyspan_usa90_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965 struct keyspan_serial_private *s_priv;
1966 struct keyspan_port_private *p_priv;
1967 const struct keyspan_device_details *d_details;
1968 struct urb *this_urb;
1969 int err;
1970 u8 prescaler;
1971
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972 s_priv = usb_get_serial_data(serial);
1973 p_priv = usb_get_serial_port_data(port);
1974 d_details = s_priv->device_details;
1975
1976 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01001977 this_urb = p_priv->outcont_urb;
1978 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001979 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980 return -1;
1981 }
1982
1983 /* Save reset port val for resend.
1984 Don't overwrite resend for open/close condition. */
1985 if ((reset_port + 1) > p_priv->resend_cont)
1986 p_priv->resend_cont = reset_port + 1;
1987 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001988 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001990 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991 }
1992
Alan Coxdeb91682008-07-22 11:13:08 +01001993 memset(&msg, 0, sizeof(struct keyspan_usa90_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994
Alan Coxdeb91682008-07-22 11:13:08 +01001995 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996 if (p_priv->old_baud != p_priv->baud) {
1997 p_priv->old_baud = p_priv->baud;
1998 msg.setClocking = 0x01;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001999 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2000 &msg.baudHi, &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) {
2001 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2002 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003 p_priv->baud = 9600;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002004 d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 &msg.baudHi, &msg.baudLo, &prescaler, 0);
2006 }
2007 msg.setRxMode = 1;
2008 msg.setTxMode = 1;
2009 }
2010
2011 /* modes must always be correctly specified */
Alan Coxdeb91682008-07-22 11:13:08 +01002012 if (p_priv->baud > 57600) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013 msg.rxMode = RXMODE_DMA;
2014 msg.txMode = TXMODE_DMA;
Alan Coxdeb91682008-07-22 11:13:08 +01002015 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016 msg.rxMode = RXMODE_BYHAND;
2017 msg.txMode = TXMODE_BYHAND;
2018 }
2019
Ben Minerds2b982ab2012-07-12 00:10:16 +10002020 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021 switch (p_priv->cflag & CSIZE) {
2022 case CS5:
2023 msg.lcr |= USA_DATABITS_5;
2024 break;
2025 case CS6:
2026 msg.lcr |= USA_DATABITS_6;
2027 break;
2028 case CS7:
2029 msg.lcr |= USA_DATABITS_7;
2030 break;
2031 case CS8:
2032 msg.lcr |= USA_DATABITS_8;
2033 break;
2034 }
2035 if (p_priv->cflag & PARENB) {
2036 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002037 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002038 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039 }
2040 if (p_priv->old_cflag != p_priv->cflag) {
2041 p_priv->old_cflag = p_priv->cflag;
2042 msg.setLcr = 0x01;
2043 }
2044
2045 if (p_priv->flow_control == flow_cts)
2046 msg.txFlowControl = TXFLOW_CTS;
2047 msg.setTxFlowControl = 0x01;
2048 msg.setRxFlowControl = 0x01;
Alan Coxdeb91682008-07-22 11:13:08 +01002049
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050 msg.rxForwardingLength = 16;
Alan Coxdeb91682008-07-22 11:13:08 +01002051 msg.rxForwardingTimeout = 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052 msg.txAckSetting = 0;
2053 msg.xonChar = 17;
2054 msg.xoffChar = 19;
2055
Alan Coxdeb91682008-07-22 11:13:08 +01002056 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057 if (reset_port == 1) {
2058 msg.portEnabled = 1;
2059 msg.rxFlush = 1;
2060 msg.txBreak = (p_priv->break_on);
2061 }
2062 /* Closing port */
Alan Coxdeb91682008-07-22 11:13:08 +01002063 else if (reset_port == 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 msg.portEnabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 /* Sending intermediate configs */
2066 else {
Alan Stern1f871582010-02-17 10:05:47 -05002067 msg.portEnabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068 msg.txBreak = (p_priv->break_on);
2069 }
2070
Alan Coxdeb91682008-07-22 11:13:08 +01002071 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072 msg.setRts = 0x01;
2073 msg.rts = p_priv->rts_state;
2074
2075 msg.setDtr = 0x01;
2076 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002077
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01002079 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2080
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081 /* send the data out the device on control endpoint */
2082 this_urb->transfer_buffer_length = sizeof(msg);
2083
Alan Coxdeb91682008-07-22 11:13:08 +01002084 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2085 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002086 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002087 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088}
2089
Lucy McCoy0ca12682007-05-18 12:10:41 -07002090static int keyspan_usa67_send_setup(struct usb_serial *serial,
2091 struct usb_serial_port *port,
2092 int reset_port)
2093{
2094 struct keyspan_usa67_portControlMessage msg;
2095 struct keyspan_serial_private *s_priv;
2096 struct keyspan_port_private *p_priv;
2097 const struct keyspan_device_details *d_details;
2098 struct urb *this_urb;
2099 int err, device_port;
2100
Lucy McCoy0ca12682007-05-18 12:10:41 -07002101 s_priv = usb_get_serial_data(serial);
2102 p_priv = usb_get_serial_port_data(port);
2103 d_details = s_priv->device_details;
2104
2105 this_urb = s_priv->glocont_urb;
2106
2107 /* Work out which port within the device is being setup */
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002108 device_port = port->port_number;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002109
2110 /* Make sure we have an urb then send the message */
2111 if (this_urb == NULL) {
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002112 dev_dbg(&port->dev, "%s - oops no urb for port.\n", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002113 return -1;
2114 }
2115
2116 /* Save reset port val for resend.
2117 Don't overwrite resend for open/close condition. */
2118 if ((reset_port + 1) > p_priv->resend_cont)
2119 p_priv->resend_cont = reset_port + 1;
2120 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002121 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002122 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002123 return -1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002124 }
2125
2126 memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
2127
2128 msg.port = device_port;
2129
2130 /* Only set baud rate if it's changed */
2131 if (p_priv->old_baud != p_priv->baud) {
2132 p_priv->old_baud = p_priv->baud;
2133 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002134 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2135 &msg.baudHi, &msg.baudLo, &msg.prescaler,
2136 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2137 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2138 __func__, p_priv->baud);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002139 msg.baudLo = 0;
2140 msg.baudHi = 125; /* Values for 9600 baud */
2141 msg.prescaler = 10;
2142 }
2143 msg.setPrescaler = 0xff;
2144 }
2145
2146 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
2147 switch (p_priv->cflag & CSIZE) {
2148 case CS5:
2149 msg.lcr |= USA_DATABITS_5;
2150 break;
2151 case CS6:
2152 msg.lcr |= USA_DATABITS_6;
2153 break;
2154 case CS7:
2155 msg.lcr |= USA_DATABITS_7;
2156 break;
2157 case CS8:
2158 msg.lcr |= USA_DATABITS_8;
2159 break;
2160 }
2161 if (p_priv->cflag & PARENB) {
2162 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002163 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002164 USA_PARITY_ODD : USA_PARITY_EVEN;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002165 }
2166 msg.setLcr = 0xff;
2167
2168 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2169 msg.xonFlowControl = 0;
2170 msg.setFlowControl = 0xff;
2171 msg.forwardingLength = 16;
2172 msg.xonChar = 17;
2173 msg.xoffChar = 19;
2174
2175 if (reset_port == 1) {
2176 /* Opening port */
2177 msg._txOn = 1;
2178 msg._txOff = 0;
2179 msg.txFlush = 0;
2180 msg.txBreak = 0;
2181 msg.rxOn = 1;
2182 msg.rxOff = 0;
2183 msg.rxFlush = 1;
2184 msg.rxForward = 0;
2185 msg.returnStatus = 0;
2186 msg.resetDataToggle = 0xff;
2187 } else if (reset_port == 2) {
2188 /* Closing port */
2189 msg._txOn = 0;
2190 msg._txOff = 1;
2191 msg.txFlush = 0;
2192 msg.txBreak = 0;
2193 msg.rxOn = 0;
2194 msg.rxOff = 1;
2195 msg.rxFlush = 1;
2196 msg.rxForward = 0;
2197 msg.returnStatus = 0;
2198 msg.resetDataToggle = 0;
2199 } else {
2200 /* Sending intermediate configs */
Alan Coxdeb91682008-07-22 11:13:08 +01002201 msg._txOn = (!p_priv->break_on);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002202 msg._txOff = 0;
2203 msg.txFlush = 0;
2204 msg.txBreak = (p_priv->break_on);
2205 msg.rxOn = 0;
2206 msg.rxOff = 0;
2207 msg.rxFlush = 0;
2208 msg.rxForward = 0;
2209 msg.returnStatus = 0;
2210 msg.resetDataToggle = 0x0;
2211 }
2212
2213 /* Do handshaking outputs */
2214 msg.setTxTriState_setRts = 0xff;
2215 msg.txTriState_rts = p_priv->rts_state;
2216
2217 msg.setHskoa_setDtr = 0xff;
2218 msg.hskoa_dtr = p_priv->dtr_state;
2219
2220 p_priv->resend_cont = 0;
2221
2222 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2223
2224 /* send the data out the device on control endpoint */
2225 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002226
2227 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2228 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002229 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002230 return 0;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002231}
2232
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
2234{
2235 struct usb_serial *serial = port->serial;
2236 struct keyspan_serial_private *s_priv;
2237 const struct keyspan_device_details *d_details;
2238
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239 s_priv = usb_get_serial_data(serial);
2240 d_details = s_priv->device_details;
2241
2242 switch (d_details->msg_format) {
2243 case msg_usa26:
2244 keyspan_usa26_send_setup(serial, port, reset_port);
2245 break;
2246 case msg_usa28:
2247 keyspan_usa28_send_setup(serial, port, reset_port);
2248 break;
2249 case msg_usa49:
2250 keyspan_usa49_send_setup(serial, port, reset_port);
2251 break;
2252 case msg_usa90:
2253 keyspan_usa90_send_setup(serial, port, reset_port);
2254 break;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002255 case msg_usa67:
2256 keyspan_usa67_send_setup(serial, port, reset_port);
2257 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258 }
2259}
2260
2261
2262/* Gets called by the "real" driver (ie once firmware is loaded
2263 and renumeration has taken place. */
Alan Coxdeb91682008-07-22 11:13:08 +01002264static int keyspan_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265{
2266 int i, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002268 const struct keyspan_device_details *d_details;
2269
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270 for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
Alan Coxdeb91682008-07-22 11:13:08 +01002271 if (d_details->product_id ==
2272 le16_to_cpu(serial->dev->descriptor.idProduct))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273 break;
2274 if (d_details == NULL) {
Alan Coxdeb91682008-07-22 11:13:08 +01002275 dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
2276 __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
Johan Hovoldff8a43c2013-08-13 13:27:35 +02002277 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278 }
2279
2280 /* Setup private data for serial driver */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01002281 s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
Johan Hovold10c642d2013-12-29 19:22:56 +01002282 if (!s_priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284
Johan Hovold2fcd1c92013-08-13 13:27:36 +02002285 s_priv->instat_buf = kzalloc(INSTAT_BUFLEN, GFP_KERNEL);
2286 if (!s_priv->instat_buf)
2287 goto err_instat_buf;
2288
2289 s_priv->indat_buf = kzalloc(INDAT49W_BUFLEN, GFP_KERNEL);
2290 if (!s_priv->indat_buf)
2291 goto err_indat_buf;
2292
2293 s_priv->glocont_buf = kzalloc(GLOCONT_BUFLEN, GFP_KERNEL);
2294 if (!s_priv->glocont_buf)
2295 goto err_glocont_buf;
2296
2297 s_priv->ctrl_buf = kzalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
2298 if (!s_priv->ctrl_buf)
2299 goto err_ctrl_buf;
2300
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301 s_priv->device_details = d_details;
2302 usb_set_serial_data(serial, s_priv);
2303
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 keyspan_setup_urbs(serial);
2305
Lucy McCoy0ca12682007-05-18 12:10:41 -07002306 if (s_priv->instat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002307 err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
2308 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002309 dev_dbg(&serial->dev->dev, "%s - submit instat urb failed %d\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002310 }
2311 if (s_priv->indat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002312 err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
2313 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002314 dev_dbg(&serial->dev->dev, "%s - submit indat urb failed %d\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315 }
Alan Coxdeb91682008-07-22 11:13:08 +01002316
Alan Coxa5b6f602008-04-08 17:16:06 +01002317 return 0;
Johan Hovold2fcd1c92013-08-13 13:27:36 +02002318
2319err_ctrl_buf:
2320 kfree(s_priv->glocont_buf);
2321err_glocont_buf:
2322 kfree(s_priv->indat_buf);
2323err_indat_buf:
2324 kfree(s_priv->instat_buf);
2325err_instat_buf:
2326 kfree(s_priv);
2327
2328 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329}
2330
Alan Sternf9c99bb2009-06-02 11:53:55 -04002331static void keyspan_disconnect(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002333 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 s_priv = usb_get_serial_data(serial);
2336
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 stop_urb(s_priv->instat_urb);
2338 stop_urb(s_priv->glocont_urb);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002339 stop_urb(s_priv->indat_urb);
Alan Sternf9c99bb2009-06-02 11:53:55 -04002340}
2341
2342static void keyspan_release(struct usb_serial *serial)
2343{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002344 struct keyspan_serial_private *s_priv;
Alan Sternf9c99bb2009-06-02 11:53:55 -04002345
Alan Sternf9c99bb2009-06-02 11:53:55 -04002346 s_priv = usb_get_serial_data(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002348 usb_free_urb(s_priv->instat_urb);
2349 usb_free_urb(s_priv->indat_urb);
2350 usb_free_urb(s_priv->glocont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351
Johan Hovold2fcd1c92013-08-13 13:27:36 +02002352 kfree(s_priv->ctrl_buf);
2353 kfree(s_priv->glocont_buf);
2354 kfree(s_priv->indat_buf);
2355 kfree(s_priv->instat_buf);
2356
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002357 kfree(s_priv);
2358}
2359
2360static int keyspan_port_probe(struct usb_serial_port *port)
2361{
2362 struct usb_serial *serial = port->serial;
Bjørn Morkf0e3e352012-11-10 10:13:42 +01002363 struct keyspan_serial_private *s_priv;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002364 struct keyspan_port_private *p_priv;
2365 const struct keyspan_device_details *d_details;
2366 struct callbacks *cback;
2367 int endp;
2368 int port_num;
2369 int i;
2370
2371 s_priv = usb_get_serial_data(serial);
2372 d_details = s_priv->device_details;
2373
2374 p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL);
2375 if (!p_priv)
2376 return -ENOMEM;
2377
Johan Hovoldbad41a52013-08-13 13:27:37 +02002378 for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i) {
2379 p_priv->in_buffer[i] = kzalloc(IN_BUFLEN, GFP_KERNEL);
2380 if (!p_priv->in_buffer[i])
2381 goto err_in_buffer;
2382 }
2383
2384 for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i) {
2385 p_priv->out_buffer[i] = kzalloc(OUT_BUFLEN, GFP_KERNEL);
2386 if (!p_priv->out_buffer[i])
2387 goto err_out_buffer;
2388 }
2389
2390 p_priv->inack_buffer = kzalloc(INACK_BUFLEN, GFP_KERNEL);
2391 if (!p_priv->inack_buffer)
2392 goto err_inack_buffer;
2393
2394 p_priv->outcont_buffer = kzalloc(OUTCONT_BUFLEN, GFP_KERNEL);
2395 if (!p_priv->outcont_buffer)
2396 goto err_outcont_buffer;
2397
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002398 p_priv->device_details = d_details;
2399
2400 /* Setup values for the various callback routines */
2401 cback = &keyspan_callbacks[d_details->msg_format];
2402
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002403 port_num = port->port_number;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002404
2405 /* Do indat endpoints first, once for each flip */
2406 endp = d_details->indat_endpoints[port_num];
2407 for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) {
2408 p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp,
2409 USB_DIR_IN, port,
Johan Hovoldbad41a52013-08-13 13:27:37 +02002410 p_priv->in_buffer[i],
2411 IN_BUFLEN,
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002412 cback->indat_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413 }
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002414 /* outdat endpoints also have flip */
2415 endp = d_details->outdat_endpoints[port_num];
2416 for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) {
2417 p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp,
2418 USB_DIR_OUT, port,
Johan Hovoldbad41a52013-08-13 13:27:37 +02002419 p_priv->out_buffer[i],
2420 OUT_BUFLEN,
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002421 cback->outdat_callback);
2422 }
2423 /* inack endpoint */
2424 p_priv->inack_urb = keyspan_setup_urb(serial,
2425 d_details->inack_endpoints[port_num],
2426 USB_DIR_IN, port,
Johan Hovoldbad41a52013-08-13 13:27:37 +02002427 p_priv->inack_buffer,
2428 INACK_BUFLEN,
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002429 cback->inack_callback);
2430 /* outcont endpoint */
2431 p_priv->outcont_urb = keyspan_setup_urb(serial,
2432 d_details->outcont_endpoints[port_num],
2433 USB_DIR_OUT, port,
Johan Hovoldbad41a52013-08-13 13:27:37 +02002434 p_priv->outcont_buffer,
2435 OUTCONT_BUFLEN,
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002436 cback->outcont_callback);
2437
2438 usb_set_serial_port_data(port, p_priv);
2439
2440 return 0;
Johan Hovoldbad41a52013-08-13 13:27:37 +02002441
2442err_outcont_buffer:
2443 kfree(p_priv->inack_buffer);
2444err_inack_buffer:
2445 for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i)
2446 kfree(p_priv->out_buffer[i]);
2447err_out_buffer:
2448 for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i)
2449 kfree(p_priv->in_buffer[i]);
2450err_in_buffer:
2451 kfree(p_priv);
2452
2453 return -ENOMEM;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002454}
2455
2456static int keyspan_port_remove(struct usb_serial_port *port)
2457{
2458 struct keyspan_port_private *p_priv;
2459 int i;
2460
2461 p_priv = usb_get_serial_port_data(port);
2462
2463 stop_urb(p_priv->inack_urb);
2464 stop_urb(p_priv->outcont_urb);
2465 for (i = 0; i < 2; i++) {
2466 stop_urb(p_priv->in_urbs[i]);
2467 stop_urb(p_priv->out_urbs[i]);
2468 }
2469
2470 usb_free_urb(p_priv->inack_urb);
2471 usb_free_urb(p_priv->outcont_urb);
2472 for (i = 0; i < 2; i++) {
2473 usb_free_urb(p_priv->in_urbs[i]);
2474 usb_free_urb(p_priv->out_urbs[i]);
2475 }
2476
Johan Hovoldbad41a52013-08-13 13:27:37 +02002477 kfree(p_priv->outcont_buffer);
2478 kfree(p_priv->inack_buffer);
2479 for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i)
2480 kfree(p_priv->out_buffer[i]);
2481 for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i)
2482 kfree(p_priv->in_buffer[i]);
2483
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002484 kfree(p_priv);
2485
2486 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487}
2488
Alan Coxdeb91682008-07-22 11:13:08 +01002489MODULE_AUTHOR(DRIVER_AUTHOR);
2490MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491MODULE_LICENSE("GPL");
2492
David Woodhouse2971c572008-05-30 14:04:03 +03002493MODULE_FIRMWARE("keyspan/usa28.fw");
2494MODULE_FIRMWARE("keyspan/usa28x.fw");
2495MODULE_FIRMWARE("keyspan/usa28xa.fw");
2496MODULE_FIRMWARE("keyspan/usa28xb.fw");
2497MODULE_FIRMWARE("keyspan/usa19.fw");
2498MODULE_FIRMWARE("keyspan/usa19qi.fw");
2499MODULE_FIRMWARE("keyspan/mpr.fw");
2500MODULE_FIRMWARE("keyspan/usa19qw.fw");
2501MODULE_FIRMWARE("keyspan/usa18x.fw");
2502MODULE_FIRMWARE("keyspan/usa19w.fw");
2503MODULE_FIRMWARE("keyspan/usa49w.fw");
2504MODULE_FIRMWARE("keyspan/usa49wlc.fw");