blob: e08755e9b6129e42761a9a28b8fb672319f9e8cf [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
Johan Hovold0cd782b2016-05-08 20:08:00 +0200258 dev_dbg(&port->dev, "%s - endpoint %x 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) {
Johan Hovold0cd782b2016-05-08 20:08:00 +0200303 dev_dbg(&urb->dev->dev, "%s - nonzero status %d on endpoint %x\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 */
Johan Hovold855515a2014-11-18 11:25:20 +0100314 if (data[0] & RXERROR_OVERRUN) {
315 tty_insert_flip_char(&port->port, 0,
316 TTY_OVERRUN);
317 }
Alan Coxdeb91682008-07-22 11:13:08 +0100318 for (i = 1; i < urb->actual_length ; ++i)
Johan Hovold855515a2014-11-18 11:25:20 +0100319 tty_insert_flip_char(&port->port, data[i],
320 TTY_NORMAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 } else {
322 /* some bytes had errors, every byte has status */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700323 dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 for (i = 0; i + 1 < urb->actual_length; i += 2) {
Johan Hovold5d1678a2014-11-18 11:25:19 +0100325 int stat = data[i];
326 int flag = TTY_NORMAL;
327
328 if (stat & RXERROR_OVERRUN) {
329 tty_insert_flip_char(&port->port, 0,
330 TTY_OVERRUN);
331 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 /* XXX should handle break (0x10) */
Johan Hovold5d1678a2014-11-18 11:25:19 +0100333 if (stat & RXERROR_PARITY)
334 flag = TTY_PARITY;
335 else if (stat & RXERROR_FRAMING)
336 flag = TTY_FRAME;
337
Jiri Slaby92a19f92013-01-03 15:53:03 +0100338 tty_insert_flip_char(&port->port, data[i+1],
339 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 }
341 }
Jiri Slaby2e124b42013-01-03 15:53:06 +0100342 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 }
Alan Coxdeb91682008-07-22 11:13:08 +0100344
345 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500346 err = usb_submit_urb(urb, GFP_ATOMIC);
347 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700348 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349}
350
Alan Coxdeb91682008-07-22 11:13:08 +0100351/* Outdat handling is common for all devices */
David Howells7d12e782006-10-05 14:55:46 +0100352static void usa2x_outdat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353{
354 struct usb_serial_port *port;
355 struct keyspan_port_private *p_priv;
356
Ming Leicdc97792008-02-24 18:41:47 +0800357 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 p_priv = usb_get_serial_port_data(port);
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700359 dev_dbg(&port->dev, "%s - urb %d\n", __func__, urb == p_priv->out_urbs[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360
Alan Stern1f871582010-02-17 10:05:47 -0500361 usb_serial_port_softint(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362}
363
David Howells7d12e782006-10-05 14:55:46 +0100364static void usa26_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366}
367
David Howells7d12e782006-10-05 14:55:46 +0100368static void usa26_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369{
370 struct usb_serial_port *port;
371 struct keyspan_port_private *p_priv;
372
Ming Leicdc97792008-02-24 18:41:47 +0800373 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 p_priv = usb_get_serial_port_data(port);
375
376 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700377 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100378 keyspan_usa26_send_setup(port->serial, port,
379 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 }
381}
382
David Howells7d12e782006-10-05 14:55:46 +0100383static void usa26_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384{
385 unsigned char *data = urb->transfer_buffer;
386 struct keyspan_usa26_portStatusMessage *msg;
387 struct usb_serial *serial;
388 struct usb_serial_port *port;
389 struct keyspan_port_private *p_priv;
390 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700391 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392
Ming Leicdc97792008-02-24 18:41:47 +0800393 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700395 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +0200396 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
397 __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 return;
399 }
400 if (urb->actual_length != 9) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700401 dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 goto exit;
403 }
404
405 msg = (struct keyspan_usa26_portStatusMessage *)data;
406
Alan Coxdeb91682008-07-22 11:13:08 +0100407 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700409 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 goto exit;
411 }
412 port = serial->port[msg->port];
413 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb5122232014-12-22 18:39:39 +0100414 if (!p_priv)
415 goto resubmit;
Alan Coxdeb91682008-07-22 11:13:08 +0100416
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 /* Update handshaking pin state information */
418 old_dcd_state = p_priv->dcd_state;
419 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
420 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
421 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
422 p_priv->ri_state = ((msg->ri) ? 1 : 0);
423
Jiri Slabyaa27a092013-03-07 13:12:30 +0100424 if (old_dcd_state != p_priv->dcd_state)
425 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb5122232014-12-22 18:39:39 +0100426resubmit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100428 err = usb_submit_urb(urb, GFP_ATOMIC);
429 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700430 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431exit: ;
432}
433
David Howells7d12e782006-10-05 14:55:46 +0100434static void usa26_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436}
437
438
David Howells7d12e782006-10-05 14:55:46 +0100439static void usa28_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440{
Alan Coxf035a8a2008-07-22 11:13:32 +0100441 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 unsigned char *data;
444 struct keyspan_port_private *p_priv;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700445 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446
Ming Leicdc97792008-02-24 18:41:47 +0800447 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 p_priv = usb_get_serial_port_data(port);
449 data = urb->transfer_buffer;
450
451 if (urb != p_priv->in_urbs[p_priv->in_flip])
452 return;
453
454 do {
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700455 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +0200456 dev_dbg(&urb->dev->dev, "%s - nonzero status %d on endpoint %x\n",
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700457 __func__, status, usb_pipeendpoint(urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 return;
459 }
460
Ming Leicdc97792008-02-24 18:41:47 +0800461 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 p_priv = usb_get_serial_port_data(port);
463 data = urb->transfer_buffer;
464
Jiri Slaby2e124b42013-01-03 15:53:06 +0100465 if (urb->actual_length) {
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100466 tty_insert_flip_string(&port->port, data,
467 urb->actual_length);
Jiri Slaby2e124b42013-01-03 15:53:06 +0100468 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 }
470
471 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500472 err = usb_submit_urb(urb, GFP_ATOMIC);
473 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700474 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n",
Alan Stern1f871582010-02-17 10:05:47 -0500475 __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 p_priv->in_flip ^= 1;
477
478 urb = p_priv->in_urbs[p_priv->in_flip];
479 } while (urb->status != -EINPROGRESS);
480}
481
David Howells7d12e782006-10-05 14:55:46 +0100482static void usa28_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484}
485
David Howells7d12e782006-10-05 14:55:46 +0100486static void usa28_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487{
488 struct usb_serial_port *port;
489 struct keyspan_port_private *p_priv;
490
Ming Leicdc97792008-02-24 18:41:47 +0800491 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 p_priv = usb_get_serial_port_data(port);
493
494 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700495 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100496 keyspan_usa28_send_setup(port->serial, port,
497 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 }
499}
500
David Howells7d12e782006-10-05 14:55:46 +0100501static void usa28_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502{
503 int err;
504 unsigned char *data = urb->transfer_buffer;
505 struct keyspan_usa28_portStatusMessage *msg;
506 struct usb_serial *serial;
507 struct usb_serial_port *port;
508 struct keyspan_port_private *p_priv;
509 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700510 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511
Ming Leicdc97792008-02-24 18:41:47 +0800512 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700514 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +0200515 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
516 __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 return;
518 }
519
520 if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700521 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 goto exit;
523 }
524
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 msg = (struct keyspan_usa28_portStatusMessage *)data;
526
Alan Coxdeb91682008-07-22 11:13:08 +0100527 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700529 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 goto exit;
531 }
532 port = serial->port[msg->port];
533 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb5122232014-12-22 18:39:39 +0100534 if (!p_priv)
535 goto resubmit;
Alan Coxdeb91682008-07-22 11:13:08 +0100536
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 /* Update handshaking pin state information */
538 old_dcd_state = p_priv->dcd_state;
539 p_priv->cts_state = ((msg->cts) ? 1 : 0);
540 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
541 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
542 p_priv->ri_state = ((msg->ri) ? 1 : 0);
543
Jiri Slabyaa27a092013-03-07 13:12:30 +0100544 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
545 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb5122232014-12-22 18:39:39 +0100546resubmit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100548 err = usb_submit_urb(urb, GFP_ATOMIC);
549 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700550 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551exit: ;
552}
553
David Howells7d12e782006-10-05 14:55:46 +0100554static void usa28_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556}
557
558
David Howells7d12e782006-10-05 14:55:46 +0100559static void usa49_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560{
561 struct usb_serial *serial;
562 struct usb_serial_port *port;
563 struct keyspan_port_private *p_priv;
564 int i;
565
Ming Leicdc97792008-02-24 18:41:47 +0800566 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 for (i = 0; i < serial->num_ports; ++i) {
568 port = serial->port[i];
569 p_priv = usb_get_serial_port_data(port);
Johan Hovold79ed6ec2020-01-17 10:50:25 +0100570 if (!p_priv)
571 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572
573 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700574 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100575 keyspan_usa49_send_setup(serial, port,
576 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 break;
578 }
579 }
580}
581
582 /* This is actually called glostat in the Keyspan
583 doco */
David Howells7d12e782006-10-05 14:55:46 +0100584static void usa49_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585{
586 int err;
587 unsigned char *data = urb->transfer_buffer;
588 struct keyspan_usa49_portStatusMessage *msg;
589 struct usb_serial *serial;
590 struct usb_serial_port *port;
591 struct keyspan_port_private *p_priv;
592 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700593 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594
Ming Leicdc97792008-02-24 18:41:47 +0800595 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700597 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +0200598 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
599 __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 return;
601 }
602
Alan Coxdeb91682008-07-22 11:13:08 +0100603 if (urb->actual_length !=
604 sizeof(struct keyspan_usa49_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700605 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 goto exit;
607 }
608
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 msg = (struct keyspan_usa49_portStatusMessage *)data;
610
Alan Coxdeb91682008-07-22 11:13:08 +0100611 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 if (msg->portNumber >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700613 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
614 __func__, msg->portNumber);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 goto exit;
616 }
617 port = serial->port[msg->portNumber];
618 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb5122232014-12-22 18:39:39 +0100619 if (!p_priv)
620 goto resubmit;
Alan Coxdeb91682008-07-22 11:13:08 +0100621
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 /* Update handshaking pin state information */
623 old_dcd_state = p_priv->dcd_state;
624 p_priv->cts_state = ((msg->cts) ? 1 : 0);
625 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
626 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
627 p_priv->ri_state = ((msg->ri) ? 1 : 0);
628
Jiri Slabyaa27a092013-03-07 13:12:30 +0100629 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
630 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb5122232014-12-22 18:39:39 +0100631resubmit:
Alan Coxdeb91682008-07-22 11:13:08 +0100632 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100633 err = usb_submit_urb(urb, GFP_ATOMIC);
634 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700635 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636exit: ;
637}
638
David Howells7d12e782006-10-05 14:55:46 +0100639static void usa49_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641}
642
David Howells7d12e782006-10-05 14:55:46 +0100643static void usa49_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644{
645 int i, err;
646 int endpoint;
647 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700649 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 endpoint = usb_pipeendpoint(urb->pipe);
652
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700653 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +0200654 dev_dbg(&urb->dev->dev, "%s - nonzero status %d on endpoint %x\n",
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700655 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 return;
657 }
658
Ming Leicdc97792008-02-24 18:41:47 +0800659 port = urb->context;
Jiri Slaby2e124b42013-01-03 15:53:06 +0100660 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 /* 0x80 bit is error flag */
662 if ((data[0] & 0x80) == 0) {
663 /* no error on any byte */
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100664 tty_insert_flip_string(&port->port, data + 1,
Alan Coxf035a8a2008-07-22 11:13:32 +0100665 urb->actual_length - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 } else {
667 /* some bytes had errors, every byte has status */
668 for (i = 0; i + 1 < urb->actual_length; i += 2) {
Johan Hovold5d1678a2014-11-18 11:25:19 +0100669 int stat = data[i];
670 int flag = TTY_NORMAL;
671
672 if (stat & RXERROR_OVERRUN) {
673 tty_insert_flip_char(&port->port, 0,
674 TTY_OVERRUN);
675 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 /* XXX should handle break (0x10) */
Johan Hovold5d1678a2014-11-18 11:25:19 +0100677 if (stat & RXERROR_PARITY)
678 flag = TTY_PARITY;
679 else if (stat & RXERROR_FRAMING)
680 flag = TTY_FRAME;
681
Jiri Slaby92a19f92013-01-03 15:53:03 +0100682 tty_insert_flip_char(&port->port, data[i+1],
683 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 }
685 }
Jiri Slaby2e124b42013-01-03 15:53:06 +0100686 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 }
Alan Coxdeb91682008-07-22 11:13:08 +0100688
689 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500690 err = usb_submit_urb(urb, GFP_ATOMIC);
691 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700692 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693}
694
Lucy McCoy0ca12682007-05-18 12:10:41 -0700695static void usa49wg_indat_callback(struct urb *urb)
696{
697 int i, len, x, err;
698 struct usb_serial *serial;
699 struct usb_serial_port *port;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700700 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700701 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700702
Lucy McCoy0ca12682007-05-18 12:10:41 -0700703 serial = urb->context;
704
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700705 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +0200706 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
707 __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700708 return;
709 }
710
711 /* inbound data is in the form P#, len, status, data */
712 i = 0;
713 len = 0;
714
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300715 while (i < urb->actual_length) {
Lucy McCoy0ca12682007-05-18 12:10:41 -0700716
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300717 /* Check port number from message */
718 if (data[i] >= serial->num_ports) {
719 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
720 __func__, data[i]);
721 return;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700722 }
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300723 port = serial->port[data[i++]];
724 len = data[i++];
725
726 /* 0x80 bit is error flag */
727 if ((data[i] & 0x80) == 0) {
728 /* no error on any byte */
729 i++;
Dan Carpenter01a60e72013-04-05 08:43:20 +0300730 for (x = 1; x < len && i < urb->actual_length; ++x)
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300731 tty_insert_flip_char(&port->port,
732 data[i++], 0);
733 } else {
734 /*
735 * some bytes had errors, every byte has status
736 */
Dan Carpenter01a60e72013-04-05 08:43:20 +0300737 for (x = 0; x + 1 < len &&
738 i + 1 < urb->actual_length; x += 2) {
Johan Hovold5d1678a2014-11-18 11:25:19 +0100739 int stat = data[i];
740 int flag = TTY_NORMAL;
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300741
Johan Hovold5d1678a2014-11-18 11:25:19 +0100742 if (stat & RXERROR_OVERRUN) {
743 tty_insert_flip_char(&port->port, 0,
744 TTY_OVERRUN);
745 }
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300746 /* XXX should handle break (0x10) */
Johan Hovold5d1678a2014-11-18 11:25:19 +0100747 if (stat & RXERROR_PARITY)
748 flag = TTY_PARITY;
749 else if (stat & RXERROR_FRAMING)
750 flag = TTY_FRAME;
751
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300752 tty_insert_flip_char(&port->port, data[i+1],
753 flag);
754 i += 2;
755 }
756 }
757 tty_flip_buffer_push(&port->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700758 }
759
760 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700761 err = usb_submit_urb(urb, GFP_ATOMIC);
762 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700763 dev_dbg(&urb->dev->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700764}
765
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766/* not used, usa-49 doesn't have per-port control endpoints */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700767static void usa49_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769}
770
Lucy McCoy0ca12682007-05-18 12:10:41 -0700771static void usa90_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772{
773 int i, err;
774 int endpoint;
775 struct usb_serial_port *port;
776 struct keyspan_port_private *p_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700778 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 endpoint = usb_pipeendpoint(urb->pipe);
781
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700782 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +0200783 dev_dbg(&urb->dev->dev, "%s - nonzero status %d on endpoint %x\n",
784 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 return;
786 }
787
Ming Leicdc97792008-02-24 18:41:47 +0800788 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 p_priv = usb_get_serial_port_data(port);
790
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 /* if current mode is DMA, looks like usa28 format
Alan Coxdeb91682008-07-22 11:13:08 +0100793 otherwise looks like usa26 data format */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794
Alan Coxf035a8a2008-07-22 11:13:32 +0100795 if (p_priv->baud > 57600)
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100796 tty_insert_flip_string(&port->port, data,
797 urb->actual_length);
Alan Coxf035a8a2008-07-22 11:13:32 +0100798 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 /* 0x80 bit is error flag */
800 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100801 /* no errors on individual bytes, only
802 possible overrun err*/
Johan Hovold855515a2014-11-18 11:25:20 +0100803 if (data[0] & RXERROR_OVERRUN) {
804 tty_insert_flip_char(&port->port, 0,
805 TTY_OVERRUN);
806 }
Alan Coxdeb91682008-07-22 11:13:08 +0100807 for (i = 1; i < urb->actual_length ; ++i)
Jiri Slaby92a19f92013-01-03 15:53:03 +0100808 tty_insert_flip_char(&port->port,
Johan Hovold855515a2014-11-18 11:25:20 +0100809 data[i], TTY_NORMAL);
Alan Coxdeb91682008-07-22 11:13:08 +0100810 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 /* some bytes had errors, every byte has status */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700812 dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 for (i = 0; i + 1 < urb->actual_length; i += 2) {
Johan Hovold5d1678a2014-11-18 11:25:19 +0100814 int stat = data[i];
815 int flag = TTY_NORMAL;
816
817 if (stat & RXERROR_OVERRUN) {
818 tty_insert_flip_char(
819 &port->port, 0,
820 TTY_OVERRUN);
821 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 /* XXX should handle break (0x10) */
Johan Hovold5d1678a2014-11-18 11:25:19 +0100823 if (stat & RXERROR_PARITY)
824 flag = TTY_PARITY;
825 else if (stat & RXERROR_FRAMING)
826 flag = TTY_FRAME;
827
Jiri Slaby92a19f92013-01-03 15:53:03 +0100828 tty_insert_flip_char(&port->port,
829 data[i+1], flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 }
831 }
832 }
Jiri Slaby2e124b42013-01-03 15:53:06 +0100833 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 }
Alan Coxdeb91682008-07-22 11:13:08 +0100835
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500837 err = usb_submit_urb(urb, GFP_ATOMIC);
838 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700839 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840}
841
842
David Howells7d12e782006-10-05 14:55:46 +0100843static void usa90_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844{
845 unsigned char *data = urb->transfer_buffer;
846 struct keyspan_usa90_portStatusMessage *msg;
847 struct usb_serial *serial;
848 struct usb_serial_port *port;
849 struct keyspan_port_private *p_priv;
850 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700851 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852
Ming Leicdc97792008-02-24 18:41:47 +0800853 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700855 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +0200856 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
857 __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 return;
859 }
860 if (urb->actual_length < 14) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700861 dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 goto exit;
863 }
864
865 msg = (struct keyspan_usa90_portStatusMessage *)data;
866
867 /* Now do something useful with the data */
868
869 port = serial->port[0];
870 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb5122232014-12-22 18:39:39 +0100871 if (!p_priv)
872 goto resubmit;
Alan Coxdeb91682008-07-22 11:13:08 +0100873
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 /* Update handshaking pin state information */
875 old_dcd_state = p_priv->dcd_state;
876 p_priv->cts_state = ((msg->cts) ? 1 : 0);
877 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
878 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
879 p_priv->ri_state = ((msg->ri) ? 1 : 0);
880
Jiri Slabyaa27a092013-03-07 13:12:30 +0100881 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
882 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb5122232014-12-22 18:39:39 +0100883resubmit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100885 err = usb_submit_urb(urb, GFP_ATOMIC);
886 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700887 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888exit:
889 ;
890}
891
David Howells7d12e782006-10-05 14:55:46 +0100892static void usa90_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893{
894 struct usb_serial_port *port;
895 struct keyspan_port_private *p_priv;
896
Ming Leicdc97792008-02-24 18:41:47 +0800897 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 p_priv = usb_get_serial_port_data(port);
899
900 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700901 dev_dbg(&urb->dev->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100902 keyspan_usa90_send_setup(port->serial, port,
903 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 }
905}
906
Lucy McCoy0ca12682007-05-18 12:10:41 -0700907/* Status messages from the 28xg */
908static void usa67_instat_callback(struct urb *urb)
909{
910 int err;
911 unsigned char *data = urb->transfer_buffer;
912 struct keyspan_usa67_portStatusMessage *msg;
913 struct usb_serial *serial;
914 struct usb_serial_port *port;
915 struct keyspan_port_private *p_priv;
916 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700917 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700918
Lucy McCoy0ca12682007-05-18 12:10:41 -0700919 serial = urb->context;
920
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700921 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +0200922 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
923 __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700924 return;
925 }
926
Alan Coxdeb91682008-07-22 11:13:08 +0100927 if (urb->actual_length !=
928 sizeof(struct keyspan_usa67_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700929 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700930 return;
931 }
932
933
934 /* Now do something useful with the data */
935 msg = (struct keyspan_usa67_portStatusMessage *)data;
936
937 /* Check port number from message and retrieve private data */
938 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700939 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700940 return;
941 }
942
943 port = serial->port[msg->port];
944 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb5122232014-12-22 18:39:39 +0100945 if (!p_priv)
946 goto resubmit;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700947
948 /* Update handshaking pin state information */
949 old_dcd_state = p_priv->dcd_state;
950 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
951 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
952
Jiri Slabyaa27a092013-03-07 13:12:30 +0100953 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
954 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb5122232014-12-22 18:39:39 +0100955resubmit:
Lucy McCoy0ca12682007-05-18 12:10:41 -0700956 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700957 err = usb_submit_urb(urb, GFP_ATOMIC);
958 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700959 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700960}
961
962static void usa67_glocont_callback(struct urb *urb)
963{
964 struct usb_serial *serial;
965 struct usb_serial_port *port;
966 struct keyspan_port_private *p_priv;
967 int i;
968
Lucy McCoy0ca12682007-05-18 12:10:41 -0700969 serial = urb->context;
970 for (i = 0; i < serial->num_ports; ++i) {
971 port = serial->port[i];
972 p_priv = usb_get_serial_port_data(port);
Johan Hovold79ed6ec2020-01-17 10:50:25 +0100973 if (!p_priv)
974 continue;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700975
976 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700977 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700978 keyspan_usa67_send_setup(serial, port,
979 p_priv->resend_cont - 1);
980 break;
981 }
982 }
983}
984
Alan Cox95da3102008-07-22 11:09:07 +0100985static int keyspan_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986{
Alan Cox95da3102008-07-22 11:09:07 +0100987 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 struct keyspan_port_private *p_priv;
989 const struct keyspan_device_details *d_details;
990 int flip;
991 int data_len;
992 struct urb *this_urb;
993
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 p_priv = usb_get_serial_port_data(port);
995 d_details = p_priv->device_details;
996
Alan Coxa5b6f602008-04-08 17:16:06 +0100997 /* FIXME: locking */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 if (d_details->msg_format == msg_usa90)
Alan Coxdeb91682008-07-22 11:13:08 +0100999 data_len = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 else
1001 data_len = 63;
1002
1003 flip = p_priv->out_flip;
1004
1005 /* Check both endpoints to see if any are available. */
Alan Coxdeb91682008-07-22 11:13:08 +01001006 this_urb = p_priv->out_urbs[flip];
1007 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001009 return data_len;
1010 flip = (flip + 1) & d_details->outdat_endp_flip;
1011 this_urb = p_priv->out_urbs[flip];
1012 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001014 return data_len;
1015 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 }
Alan Coxa5b6f602008-04-08 17:16:06 +01001017 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018}
1019
1020
Alan Coxa509a7e2009-09-19 13:13:26 -07001021static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022{
Andrew Mortonf78ba152007-11-28 16:21:54 -08001023 struct keyspan_port_private *p_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 const struct keyspan_device_details *d_details;
1025 int i, err;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001026 int baud_rate, device_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 struct urb *urb;
Alan Cox95da3102008-07-22 11:09:07 +01001028 unsigned int cflag = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 p_priv = usb_get_serial_port_data(port);
1031 d_details = p_priv->device_details;
Borislav Petkov7eea4362007-11-14 17:00:39 -08001032
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 /* Set some sane defaults */
1034 p_priv->rts_state = 1;
1035 p_priv->dtr_state = 1;
1036 p_priv->baud = 9600;
1037
1038 /* force baud and lcr to be set on open */
1039 p_priv->old_baud = 0;
1040 p_priv->old_cflag = 0;
1041
1042 p_priv->out_flip = 0;
1043 p_priv->in_flip = 0;
1044
1045 /* Reset low level data toggle and start reading from endpoints */
1046 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001047 urb = p_priv->in_urbs[i];
1048 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050
Alan Coxdeb91682008-07-22 11:13:08 +01001051 /* make sure endpoint data toggle is synchronized
1052 with the device */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 usb_clear_halt(urb->dev, urb->pipe);
Alan Coxdeb91682008-07-22 11:13:08 +01001054 err = usb_submit_urb(urb, GFP_KERNEL);
1055 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001056 dev_dbg(&port->dev, "%s - submit urb %d failed (%d)\n", __func__, i, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 }
1058
1059 /* Reset low level data toggle on out endpoints */
1060 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001061 urb = p_priv->out_urbs[i];
1062 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 continue;
Alan Coxdeb91682008-07-22 11:13:08 +01001064 /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
1065 usb_pipeout(urb->pipe), 0); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 }
1067
Andrew Mortonf78ba152007-11-28 16:21:54 -08001068 /* get the terminal config for the setup message now so we don't
1069 * need to send 2 of them */
1070
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001071 device_port = port->port_number;
Alan Cox95da3102008-07-22 11:09:07 +01001072 if (tty) {
Alan Coxadc8d742012-07-14 15:31:47 +01001073 cflag = tty->termios.c_cflag;
Alan Cox95da3102008-07-22 11:09:07 +01001074 /* Baud rate calculation takes baud rate as an integer
1075 so other rates can be generated if desired. */
1076 baud_rate = tty_get_baud_rate(tty);
1077 /* If no match or invalid, leave as default */
1078 if (baud_rate >= 0
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001079 && d_details->calculate_baud_rate(port, baud_rate, d_details->baudclk,
Alan Cox95da3102008-07-22 11:09:07 +01001080 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
1081 p_priv->baud = baud_rate;
1082 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001083 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001084 /* set CTS/RTS handshake etc. */
1085 p_priv->cflag = cflag;
Ben Minerds2b982ab2012-07-12 00:10:16 +10001086 p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001087
1088 keyspan_send_setup(port, 1);
Alan Coxdeb91682008-07-22 11:13:08 +01001089 /* mdelay(100); */
1090 /* keyspan_set_termios(port, NULL); */
Andrew Mortonf78ba152007-11-28 16:21:54 -08001091
Alan Coxa5b6f602008-04-08 17:16:06 +01001092 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093}
1094
Alan Cox335f8512009-06-11 12:26:29 +01001095static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
1096{
1097 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
1098
1099 p_priv->rts_state = on;
1100 p_priv->dtr_state = on;
1101 keyspan_send_setup(port, 0);
1102}
1103
1104static void keyspan_close(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105{
1106 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 struct keyspan_port_private *p_priv;
1108
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +01001110
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 p_priv->rts_state = 0;
1112 p_priv->dtr_state = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001113
Johan Hovold80dfe0c2013-03-21 12:36:32 +01001114 keyspan_send_setup(port, 2);
1115 /* pilot-xfer seems to work best with this delay */
1116 mdelay(100);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117
1118 p_priv->out_flip = 0;
1119 p_priv->in_flip = 0;
1120
Johan Hovold61924502016-05-08 20:07:59 +02001121 usb_kill_urb(p_priv->inack_urb);
Johan Hovold80dfe0c2013-03-21 12:36:32 +01001122 for (i = 0; i < 2; i++) {
Johan Hovold61924502016-05-08 20:07:59 +02001123 usb_kill_urb(p_priv->in_urbs[i]);
1124 usb_kill_urb(p_priv->out_urbs[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126}
1127
Alan Coxdeb91682008-07-22 11:13:08 +01001128/* download the firmware to a pre-renumeration device */
1129static int keyspan_fake_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130{
Rene Buergel8d733e22012-09-18 09:02:01 +02001131 char *fw_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001133 dev_dbg(&serial->dev->dev, "Keyspan startup version %04x product %04x\n",
1134 le16_to_cpu(serial->dev->descriptor.bcdDevice),
1135 le16_to_cpu(serial->dev->descriptor.idProduct));
Alan Coxdeb91682008-07-22 11:13:08 +01001136
1137 if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000)
1138 != 0x8000) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001139 dev_dbg(&serial->dev->dev, "Firmware already loaded. Quitting.\n");
Alan Coxdeb91682008-07-22 11:13:08 +01001140 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 }
1142
1143 /* Select firmware image on the basis of idProduct */
1144 switch (le16_to_cpu(serial->dev->descriptor.idProduct)) {
1145 case keyspan_usa28_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001146 fw_name = "keyspan/usa28.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 break;
1148
1149 case keyspan_usa28x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001150 fw_name = "keyspan/usa28x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 break;
1152
1153 case keyspan_usa28xa_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001154 fw_name = "keyspan/usa28xa.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 break;
1156
1157 case keyspan_usa28xb_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001158 fw_name = "keyspan/usa28xb.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 break;
1160
1161 case keyspan_usa19_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001162 fw_name = "keyspan/usa19.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001164
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 case keyspan_usa19qi_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001166 fw_name = "keyspan/usa19qi.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001168
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 case keyspan_mpr_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001170 fw_name = "keyspan/mpr.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 break;
1172
1173 case keyspan_usa19qw_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001174 fw_name = "keyspan/usa19qw.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001176
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 case keyspan_usa18x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001178 fw_name = "keyspan/usa18x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001180
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 case keyspan_usa19w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001182 fw_name = "keyspan/usa19w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001184
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 case keyspan_usa49w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001186 fw_name = "keyspan/usa49w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 break;
1188
1189 case keyspan_usa49wlc_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001190 fw_name = "keyspan/usa49wlc.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 break;
1192
1193 default:
David Woodhouse2971c572008-05-30 14:04:03 +03001194 dev_err(&serial->dev->dev, "Unknown product ID (%04x)\n",
1195 le16_to_cpu(serial->dev->descriptor.idProduct));
1196 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 }
1198
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001199 dev_dbg(&serial->dev->dev, "Uploading Keyspan %s firmware.\n", fw_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200
Rene Buergel8d733e22012-09-18 09:02:01 +02001201 if (ezusb_fx1_ihex_firmware_download(serial->dev, fw_name) < 0) {
1202 dev_err(&serial->dev->dev, "failed to load firmware \"%s\"\n",
1203 fw_name);
1204 return -ENOENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 }
1206
Rene Buergel8d733e22012-09-18 09:02:01 +02001207 /* after downloading firmware Renumeration will occur in a
1208 moment and the new device will bind to the real driver */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209
1210 /* we don't want this device to have a driver assigned to it. */
Alan Coxdeb91682008-07-22 11:13:08 +01001211 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212}
1213
1214/* Helper functions used by keyspan_setup_urbs */
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001215static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *serial,
1216 int endpoint)
1217{
1218 struct usb_host_interface *iface_desc;
1219 struct usb_endpoint_descriptor *ep;
1220 int i;
1221
1222 iface_desc = serial->interface->cur_altsetting;
1223 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1224 ep = &iface_desc->endpoint[i].desc;
1225 if (ep->bEndpointAddress == endpoint)
1226 return ep;
1227 }
Johan Hovold0cd782b2016-05-08 20:08:00 +02001228 dev_warn(&serial->interface->dev, "found no endpoint descriptor for endpoint %x\n",
1229 endpoint);
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001230 return NULL;
1231}
1232
Alan Coxdeb91682008-07-22 11:13:08 +01001233static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 int dir, void *ctx, char *buf, int len,
David Howells7d12e782006-10-05 14:55:46 +01001235 void (*callback)(struct urb *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236{
1237 struct urb *urb;
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001238 struct usb_endpoint_descriptor const *ep_desc;
1239 char const *ep_type_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240
1241 if (endpoint == -1)
1242 return NULL; /* endpoint not needed */
1243
Johan Hovold0cd782b2016-05-08 20:08:00 +02001244 dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %x\n",
1245 __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
Johan Hovold10c642d2013-12-29 19:22:56 +01001247 if (!urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249
Lucy McCoy0ca12682007-05-18 12:10:41 -07001250 if (endpoint == 0) {
1251 /* control EP filled in when used */
1252 return urb;
1253 }
1254
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001255 ep_desc = find_ep(serial, endpoint);
1256 if (!ep_desc) {
Johan Hovoldc45a69c2019-10-03 15:49:58 +02001257 usb_free_urb(urb);
1258 return NULL;
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001259 }
1260 if (usb_endpoint_xfer_int(ep_desc)) {
1261 ep_type_name = "INT";
1262 usb_fill_int_urb(urb, serial->dev,
1263 usb_sndintpipe(serial->dev, endpoint) | dir,
1264 buf, len, callback, ctx,
1265 ep_desc->bInterval);
1266 } else if (usb_endpoint_xfer_bulk(ep_desc)) {
1267 ep_type_name = "BULK";
1268 usb_fill_bulk_urb(urb, serial->dev,
1269 usb_sndbulkpipe(serial->dev, endpoint) | dir,
1270 buf, len, callback, ctx);
1271 } else {
1272 dev_warn(&serial->interface->dev,
1273 "unsupported endpoint type %x\n",
Julia Lawall2e0fe702008-12-29 11:22:14 +01001274 usb_endpoint_type(ep_desc));
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001275 usb_free_urb(urb);
1276 return NULL;
1277 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001279 dev_dbg(&serial->interface->dev, "%s - using urb %p for %s endpoint %x\n",
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001280 __func__, urb, ep_type_name, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 return urb;
1282}
1283
1284static struct callbacks {
David Howells7d12e782006-10-05 14:55:46 +01001285 void (*instat_callback)(struct urb *);
1286 void (*glocont_callback)(struct urb *);
1287 void (*indat_callback)(struct urb *);
1288 void (*outdat_callback)(struct urb *);
1289 void (*inack_callback)(struct urb *);
1290 void (*outcont_callback)(struct urb *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291} keyspan_callbacks[] = {
1292 {
1293 /* msg_usa26 callbacks */
1294 .instat_callback = usa26_instat_callback,
1295 .glocont_callback = usa26_glocont_callback,
1296 .indat_callback = usa26_indat_callback,
1297 .outdat_callback = usa2x_outdat_callback,
1298 .inack_callback = usa26_inack_callback,
1299 .outcont_callback = usa26_outcont_callback,
1300 }, {
1301 /* msg_usa28 callbacks */
1302 .instat_callback = usa28_instat_callback,
1303 .glocont_callback = usa28_glocont_callback,
1304 .indat_callback = usa28_indat_callback,
1305 .outdat_callback = usa2x_outdat_callback,
1306 .inack_callback = usa28_inack_callback,
1307 .outcont_callback = usa28_outcont_callback,
1308 }, {
1309 /* msg_usa49 callbacks */
1310 .instat_callback = usa49_instat_callback,
1311 .glocont_callback = usa49_glocont_callback,
1312 .indat_callback = usa49_indat_callback,
1313 .outdat_callback = usa2x_outdat_callback,
1314 .inack_callback = usa49_inack_callback,
1315 .outcont_callback = usa49_outcont_callback,
1316 }, {
1317 /* msg_usa90 callbacks */
1318 .instat_callback = usa90_instat_callback,
Alan Coxdeb91682008-07-22 11:13:08 +01001319 .glocont_callback = usa28_glocont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 .indat_callback = usa90_indat_callback,
1321 .outdat_callback = usa2x_outdat_callback,
1322 .inack_callback = usa28_inack_callback,
1323 .outcont_callback = usa90_outcont_callback,
Lucy McCoy0ca12682007-05-18 12:10:41 -07001324 }, {
1325 /* msg_usa67 callbacks */
1326 .instat_callback = usa67_instat_callback,
1327 .glocont_callback = usa67_glocont_callback,
1328 .indat_callback = usa26_indat_callback,
1329 .outdat_callback = usa2x_outdat_callback,
1330 .inack_callback = usa26_inack_callback,
1331 .outcont_callback = usa26_outcont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 }
1333};
1334
1335 /* Generic setup urbs function that uses
1336 data in device_details */
1337static void keyspan_setup_urbs(struct usb_serial *serial)
1338{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 struct keyspan_serial_private *s_priv;
1340 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 struct callbacks *cback;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 s_priv = usb_get_serial_data(serial);
1344 d_details = s_priv->device_details;
1345
Alan Coxdeb91682008-07-22 11:13:08 +01001346 /* Setup values for the various callback routines */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 cback = &keyspan_callbacks[d_details->msg_format];
1348
Alan Coxdeb91682008-07-22 11:13:08 +01001349 /* Allocate and set up urbs for each one that is in use,
1350 starting with instat endpoints */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 s_priv->instat_urb = keyspan_setup_urb
1352 (serial, d_details->instat_endpoint, USB_DIR_IN,
1353 serial, s_priv->instat_buf, INSTAT_BUFLEN,
1354 cback->instat_callback);
1355
Lucy McCoy0ca12682007-05-18 12:10:41 -07001356 s_priv->indat_urb = keyspan_setup_urb
1357 (serial, d_details->indat_endpoint, USB_DIR_IN,
1358 serial, s_priv->indat_buf, INDAT49W_BUFLEN,
1359 usa49wg_indat_callback);
1360
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 s_priv->glocont_urb = keyspan_setup_urb
1362 (serial, d_details->glocont_endpoint, USB_DIR_OUT,
1363 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
1364 cback->glocont_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365}
1366
1367/* usa19 function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001368static int keyspan_usa19_calc_baud(struct usb_serial_port *port,
1369 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370 u8 *rate_low, u8 *prescaler, int portnum)
1371{
1372 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001373 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 cnt; /* inverse of divisor (programmed into 8051) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001376 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377
Alan Coxdeb91682008-07-22 11:13:08 +01001378 /* prevent divide by zero... */
1379 b16 = baud_rate * 16L;
1380 if (b16 == 0)
1381 return KEYSPAN_INVALID_BAUD_RATE;
1382 /* Any "standard" rate over 57k6 is marginal on the USA-19
1383 as we run out of divisor resolution. */
1384 if (baud_rate > 57600)
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 and the counter (its inverse) */
1388 div = baudclk / b16;
1389 if (div == 0)
1390 return KEYSPAN_INVALID_BAUD_RATE;
1391 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393
Alan Coxdeb91682008-07-22 11:13:08 +01001394 if (div > 0xffff)
1395 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396
Alan Coxdeb91682008-07-22 11:13:08 +01001397 /* return the counter values if non-null */
1398 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001400 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001402 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 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406}
1407
1408/* usa19hs function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001409static int keyspan_usa19hs_calc_baud(struct usb_serial_port *port,
1410 u32 baud_rate, u32 baudclk, u8 *rate_hi,
1411 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412{
1413 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001414 div; /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001416 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417
Alan Coxdeb91682008-07-22 11:13:08 +01001418 /* prevent divide by zero... */
1419 b16 = baud_rate * 16L;
1420 if (b16 == 0)
1421 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422
Alan Coxdeb91682008-07-22 11:13:08 +01001423 /* calculate the divisor */
1424 div = baudclk / b16;
1425 if (div == 0)
1426 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427
Alan Coxdeb91682008-07-22 11:13:08 +01001428 if (div > 0xffff)
1429 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430
Alan Coxdeb91682008-07-22 11:13:08 +01001431 /* return the counter values if non-null */
1432 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001434
1435 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 *rate_hi = (u8) ((div >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001437
1438 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001439 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001440 __func__, baud_rate, *rate_hi, *rate_low);
1441
1442 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443}
1444
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001445static int keyspan_usa19w_calc_baud(struct usb_serial_port *port,
1446 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 u8 *rate_low, u8 *prescaler, int portnum)
1448{
1449 u32 b16, /* baud rate times 16 (actual rate used internally) */
1450 clk, /* clock with 13/8 prescaler */
Alan Coxdeb91682008-07-22 11:13:08 +01001451 div, /* divisor using 13/8 prescaler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 res, /* resulting baud rate using 13/8 prescaler */
1453 diff, /* error using 13/8 prescaler */
1454 smallest_diff;
1455 u8 best_prescaler;
1456 int i;
1457
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001458 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459
Alan Coxdeb91682008-07-22 11:13:08 +01001460 /* prevent divide by zero */
1461 b16 = baud_rate * 16L;
1462 if (b16 == 0)
1463 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
Alan Coxdeb91682008-07-22 11:13:08 +01001465 /* Calculate prescaler by trying them all and looking
1466 for best fit */
1467
1468 /* start with largest possible difference */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 smallest_diff = 0xffffffff;
1470
1471 /* 0 is an invalid prescaler, used as a flag */
1472 best_prescaler = 0;
1473
Alan Coxdeb91682008-07-22 11:13:08 +01001474 for (i = 8; i <= 0xff; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475 clk = (baudclk * 8) / (u32) i;
Alan Coxdeb91682008-07-22 11:13:08 +01001476
1477 div = clk / b16;
1478 if (div == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480
1481 res = clk / div;
Alan Coxdeb91682008-07-22 11:13:08 +01001482 diff = (res > b16) ? (res-b16) : (b16-res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483
Alan Coxdeb91682008-07-22 11:13:08 +01001484 if (diff < smallest_diff) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485 best_prescaler = i;
1486 smallest_diff = diff;
1487 }
1488 }
1489
Alan Coxdeb91682008-07-22 11:13:08 +01001490 if (best_prescaler == 0)
1491 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492
1493 clk = (baudclk * 8) / (u32) best_prescaler;
1494 div = clk / b16;
1495
Alan Coxdeb91682008-07-22 11:13:08 +01001496 /* return the divisor and prescaler if non-null */
1497 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001499 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 *rate_hi = (u8) ((div >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 if (prescaler) {
1502 *prescaler = best_prescaler;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001503 /* dev_dbg(&port->dev, "%s - %d %d\n", __func__, *prescaler, div); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 }
Alan Coxdeb91682008-07-22 11:13:08 +01001505 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506}
1507
1508 /* USA-28 supports different maximum baud rates on each port */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001509static int keyspan_usa28_calc_baud(struct usb_serial_port *port,
1510 u32 baud_rate, u32 baudclk, u8 *rate_hi,
1511 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512{
1513 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001514 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 cnt; /* inverse of divisor (programmed into 8051) */
1516
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001517 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518
1519 /* prevent divide by zero */
Alan Coxdeb91682008-07-22 11:13:08 +01001520 b16 = baud_rate * 16L;
1521 if (b16 == 0)
1522 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523
Alan Coxdeb91682008-07-22 11:13:08 +01001524 /* calculate the divisor and the counter (its inverse) */
1525 div = KEYSPAN_USA28_BAUDCLK / b16;
1526 if (div == 0)
1527 return KEYSPAN_INVALID_BAUD_RATE;
1528 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530
Alan Coxdeb91682008-07-22 11:13:08 +01001531 /* check for out of range, based on portnum,
1532 and return result */
1533 if (portnum == 0) {
1534 if (div > 0xffff)
1535 return KEYSPAN_INVALID_BAUD_RATE;
1536 } else {
1537 if (portnum == 1) {
1538 if (div > 0xff)
1539 return KEYSPAN_INVALID_BAUD_RATE;
1540 } else
1541 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 }
1543
1544 /* return the counter values if not NULL
1545 (port 1 will ignore retHi) */
Alan Coxdeb91682008-07-22 11:13:08 +01001546 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001548 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001550 dev_dbg(&port->dev, "%s - %d OK.\n", __func__, baud_rate);
Alan Coxdeb91682008-07-22 11:13:08 +01001551 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552}
1553
1554static int keyspan_usa26_send_setup(struct usb_serial *serial,
1555 struct usb_serial_port *port,
1556 int reset_port)
1557{
Alan Coxdeb91682008-07-22 11:13:08 +01001558 struct keyspan_usa26_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 struct keyspan_serial_private *s_priv;
1560 struct keyspan_port_private *p_priv;
1561 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562 struct urb *this_urb;
1563 int device_port, err;
1564
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001565 dev_dbg(&port->dev, "%s reset=%d\n", __func__, reset_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566
1567 s_priv = usb_get_serial_data(serial);
1568 p_priv = usb_get_serial_port_data(port);
1569 d_details = s_priv->device_details;
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001570 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572 this_urb = p_priv->outcont_urb;
1573
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 /* Make sure we have an urb then send the message */
1575 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001576 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577 return -1;
1578 }
1579
Johan Hovold0cd782b2016-05-08 20:08:00 +02001580 dev_dbg(&port->dev, "%s - endpoint %x\n",
1581 __func__, usb_pipeendpoint(this_urb->pipe));
Rickard Strandqvistd5afce82014-05-16 17:39:13 +02001582
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001584 Don't overwrite resend for open/close condition. */
1585 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586 p_priv->resend_cont = reset_port + 1;
1587 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001588 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001590 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 }
1592
Alan Coxdeb91682008-07-22 11:13:08 +01001593 memset(&msg, 0, sizeof(struct keyspan_usa26_portControlMessage));
1594
1595 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 if (p_priv->old_baud != p_priv->baud) {
1597 p_priv->old_baud = p_priv->baud;
1598 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001599 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1600 &msg.baudHi, &msg.baudLo, &msg.prescaler,
1601 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1602 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
1603 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 msg.baudLo = 0;
1605 msg.baudHi = 125; /* Values for 9600 baud */
1606 msg.prescaler = 10;
1607 }
1608 msg.setPrescaler = 0xff;
1609 }
1610
Ben Minerds2b982ab2012-07-12 00:10:16 +10001611 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 switch (p_priv->cflag & CSIZE) {
1613 case CS5:
1614 msg.lcr |= USA_DATABITS_5;
1615 break;
1616 case CS6:
1617 msg.lcr |= USA_DATABITS_6;
1618 break;
1619 case CS7:
1620 msg.lcr |= USA_DATABITS_7;
1621 break;
1622 case CS8:
1623 msg.lcr |= USA_DATABITS_8;
1624 break;
1625 }
1626 if (p_priv->cflag & PARENB) {
1627 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10001628 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01001629 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 }
1631 msg.setLcr = 0xff;
1632
1633 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1634 msg.xonFlowControl = 0;
1635 msg.setFlowControl = 0xff;
1636 msg.forwardingLength = 16;
1637 msg.xonChar = 17;
1638 msg.xoffChar = 19;
1639
1640 /* Opening port */
1641 if (reset_port == 1) {
1642 msg._txOn = 1;
1643 msg._txOff = 0;
1644 msg.txFlush = 0;
1645 msg.txBreak = 0;
1646 msg.rxOn = 1;
1647 msg.rxOff = 0;
1648 msg.rxFlush = 1;
1649 msg.rxForward = 0;
1650 msg.returnStatus = 0;
1651 msg.resetDataToggle = 0xff;
1652 }
1653
1654 /* Closing port */
1655 else if (reset_port == 2) {
1656 msg._txOn = 0;
1657 msg._txOff = 1;
1658 msg.txFlush = 0;
1659 msg.txBreak = 0;
1660 msg.rxOn = 0;
1661 msg.rxOff = 1;
1662 msg.rxFlush = 1;
1663 msg.rxForward = 0;
1664 msg.returnStatus = 0;
1665 msg.resetDataToggle = 0;
1666 }
1667
1668 /* Sending intermediate configs */
1669 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001670 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 msg._txOff = 0;
1672 msg.txFlush = 0;
1673 msg.txBreak = (p_priv->break_on);
1674 msg.rxOn = 0;
1675 msg.rxOff = 0;
1676 msg.rxFlush = 0;
1677 msg.rxForward = 0;
1678 msg.returnStatus = 0;
1679 msg.resetDataToggle = 0x0;
1680 }
1681
Alan Coxdeb91682008-07-22 11:13:08 +01001682 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683 msg.setTxTriState_setRts = 0xff;
1684 msg.txTriState_rts = p_priv->rts_state;
1685
1686 msg.setHskoa_setDtr = 0xff;
1687 msg.hskoa_dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01001688
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001690 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
1691
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692 /* send the data out the device on control endpoint */
1693 this_urb->transfer_buffer_length = sizeof(msg);
1694
Alan Coxdeb91682008-07-22 11:13:08 +01001695 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1696 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001697 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01001698 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699}
1700
1701static int keyspan_usa28_send_setup(struct usb_serial *serial,
1702 struct usb_serial_port *port,
1703 int reset_port)
1704{
Alan Coxdeb91682008-07-22 11:13:08 +01001705 struct keyspan_usa28_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 struct keyspan_serial_private *s_priv;
1707 struct keyspan_port_private *p_priv;
1708 const struct keyspan_device_details *d_details;
1709 struct urb *this_urb;
1710 int device_port, err;
1711
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 s_priv = usb_get_serial_data(serial);
1713 p_priv = usb_get_serial_port_data(port);
1714 d_details = s_priv->device_details;
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001715 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716
1717 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01001718 this_urb = p_priv->outcont_urb;
1719 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001720 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721 return -1;
1722 }
1723
1724 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001725 Don't overwrite resend for open/close condition. */
1726 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727 p_priv->resend_cont = reset_port + 1;
1728 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001729 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001731 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 }
1733
Alan Coxdeb91682008-07-22 11:13:08 +01001734 memset(&msg, 0, sizeof(struct keyspan_usa28_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735
1736 msg.setBaudRate = 1;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001737 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1738 &msg.baudHi, &msg.baudLo, NULL,
1739 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1740 dev_dbg(&port->dev, "%s - Invalid baud rate requested %d.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001741 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 msg.baudLo = 0xff;
1743 msg.baudHi = 0xb2; /* Values for 9600 baud */
1744 }
1745
1746 /* If parity is enabled, we must calculate it ourselves. */
1747 msg.parity = 0; /* XXX for now */
1748
1749 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1750 msg.xonFlowControl = 0;
1751
Alan Coxdeb91682008-07-22 11:13:08 +01001752 /* Do handshaking outputs, DTR is inverted relative to RTS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 msg.rts = p_priv->rts_state;
1754 msg.dtr = p_priv->dtr_state;
1755
1756 msg.forwardingLength = 16;
1757 msg.forwardMs = 10;
1758 msg.breakThreshold = 45;
1759 msg.xonChar = 17;
1760 msg.xoffChar = 19;
1761
1762 /*msg.returnStatus = 1;
1763 msg.resetDataToggle = 0xff;*/
1764 /* Opening port */
1765 if (reset_port == 1) {
1766 msg._txOn = 1;
1767 msg._txOff = 0;
1768 msg.txFlush = 0;
1769 msg.txForceXoff = 0;
1770 msg.txBreak = 0;
1771 msg.rxOn = 1;
1772 msg.rxOff = 0;
1773 msg.rxFlush = 1;
1774 msg.rxForward = 0;
1775 msg.returnStatus = 0;
1776 msg.resetDataToggle = 0xff;
1777 }
1778 /* Closing port */
1779 else if (reset_port == 2) {
1780 msg._txOn = 0;
1781 msg._txOff = 1;
1782 msg.txFlush = 0;
1783 msg.txForceXoff = 0;
1784 msg.txBreak = 0;
1785 msg.rxOn = 0;
1786 msg.rxOff = 1;
1787 msg.rxFlush = 1;
1788 msg.rxForward = 0;
1789 msg.returnStatus = 0;
1790 msg.resetDataToggle = 0;
1791 }
1792 /* Sending intermediate configs */
1793 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001794 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795 msg._txOff = 0;
1796 msg.txFlush = 0;
1797 msg.txForceXoff = 0;
1798 msg.txBreak = (p_priv->break_on);
1799 msg.rxOn = 0;
1800 msg.rxOff = 0;
1801 msg.rxFlush = 0;
1802 msg.rxForward = 0;
1803 msg.returnStatus = 0;
1804 msg.resetDataToggle = 0x0;
1805 }
1806
1807 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001808 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809
1810 /* send the data out the device on control endpoint */
1811 this_urb->transfer_buffer_length = sizeof(msg);
1812
Alan Coxdeb91682008-07-22 11:13:08 +01001813 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1814 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001815 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816
Alan Coxa5b6f602008-04-08 17:16:06 +01001817 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818}
1819
1820static int keyspan_usa49_send_setup(struct usb_serial *serial,
1821 struct usb_serial_port *port,
1822 int reset_port)
1823{
Lucy McCoy0ca12682007-05-18 12:10:41 -07001824 struct keyspan_usa49_portControlMessage msg;
1825 struct usb_ctrlrequest *dr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826 struct keyspan_serial_private *s_priv;
1827 struct keyspan_port_private *p_priv;
1828 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829 struct urb *this_urb;
1830 int err, device_port;
1831
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 s_priv = usb_get_serial_data(serial);
1833 p_priv = usb_get_serial_port_data(port);
1834 d_details = s_priv->device_details;
1835
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 this_urb = s_priv->glocont_urb;
1837
Lucy McCoy0ca12682007-05-18 12:10:41 -07001838 /* Work out which port within the device is being setup */
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001839 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05301841 /* Make sure we have an urb then send the message */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 if (this_urb == NULL) {
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001843 dev_dbg(&port->dev, "%s - oops no urb for port.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844 return -1;
1845 }
1846
Johan Hovold0cd782b2016-05-08 20:08:00 +02001847 dev_dbg(&port->dev, "%s - endpoint %x (%d)\n",
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001848 __func__, usb_pipeendpoint(this_urb->pipe), device_port);
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05301849
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001851 Don't overwrite resend for open/close condition. */
1852 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853 p_priv->resend_cont = reset_port + 1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001854
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001856 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001858 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 }
1860
Alan Coxdeb91682008-07-22 11:13:08 +01001861 memset(&msg, 0, sizeof(struct keyspan_usa49_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863 msg.portNumber = device_port;
Alan Coxdeb91682008-07-22 11:13:08 +01001864
1865 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866 if (p_priv->old_baud != p_priv->baud) {
1867 p_priv->old_baud = p_priv->baud;
1868 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001869 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1870 &msg.baudHi, &msg.baudLo, &msg.prescaler,
1871 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1872 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
1873 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874 msg.baudLo = 0;
1875 msg.baudHi = 125; /* Values for 9600 baud */
1876 msg.prescaler = 10;
1877 }
Alan Coxdeb91682008-07-22 11:13:08 +01001878 /* msg.setPrescaler = 0xff; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879 }
1880
Ben Minerds2b982ab2012-07-12 00:10:16 +10001881 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882 switch (p_priv->cflag & CSIZE) {
1883 case CS5:
1884 msg.lcr |= USA_DATABITS_5;
1885 break;
1886 case CS6:
1887 msg.lcr |= USA_DATABITS_6;
1888 break;
1889 case CS7:
1890 msg.lcr |= USA_DATABITS_7;
1891 break;
1892 case CS8:
1893 msg.lcr |= USA_DATABITS_8;
1894 break;
1895 }
1896 if (p_priv->cflag & PARENB) {
1897 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10001898 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01001899 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 }
1901 msg.setLcr = 0xff;
1902
1903 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1904 msg.xonFlowControl = 0;
1905 msg.setFlowControl = 0xff;
Alan Coxdeb91682008-07-22 11:13:08 +01001906
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907 msg.forwardingLength = 16;
1908 msg.xonChar = 17;
1909 msg.xoffChar = 19;
1910
Alan Coxdeb91682008-07-22 11:13:08 +01001911 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912 if (reset_port == 1) {
1913 msg._txOn = 1;
1914 msg._txOff = 0;
1915 msg.txFlush = 0;
1916 msg.txBreak = 0;
1917 msg.rxOn = 1;
1918 msg.rxOff = 0;
1919 msg.rxFlush = 1;
1920 msg.rxForward = 0;
1921 msg.returnStatus = 0;
1922 msg.resetDataToggle = 0xff;
1923 msg.enablePort = 1;
1924 msg.disablePort = 0;
1925 }
1926 /* Closing port */
1927 else if (reset_port == 2) {
1928 msg._txOn = 0;
1929 msg._txOff = 1;
1930 msg.txFlush = 0;
1931 msg.txBreak = 0;
1932 msg.rxOn = 0;
1933 msg.rxOff = 1;
1934 msg.rxFlush = 1;
1935 msg.rxForward = 0;
1936 msg.returnStatus = 0;
1937 msg.resetDataToggle = 0;
1938 msg.enablePort = 0;
1939 msg.disablePort = 1;
1940 }
1941 /* Sending intermediate configs */
1942 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001943 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944 msg._txOff = 0;
1945 msg.txFlush = 0;
1946 msg.txBreak = (p_priv->break_on);
1947 msg.rxOn = 0;
1948 msg.rxOff = 0;
1949 msg.rxFlush = 0;
1950 msg.rxForward = 0;
1951 msg.returnStatus = 0;
1952 msg.resetDataToggle = 0x0;
1953 msg.enablePort = 0;
1954 msg.disablePort = 0;
1955 }
1956
Alan Coxdeb91682008-07-22 11:13:08 +01001957 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 msg.setRts = 0xff;
1959 msg.rts = p_priv->rts_state;
1960
1961 msg.setDtr = 0xff;
1962 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01001963
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964 p_priv->resend_cont = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965
Alan Coxdeb91682008-07-22 11:13:08 +01001966 /* if the device is a 49wg, we send control message on usb
1967 control EP 0 */
Lucy McCoy0ca12682007-05-18 12:10:41 -07001968
1969 if (d_details->product_id == keyspan_usa49wg_product_id) {
1970 dr = (void *)(s_priv->ctrl_buf);
1971 dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT;
Mathieu OTHACEHE64248392016-02-04 19:01:30 +01001972 dr->bRequest = 0xB0; /* 49wg control message */
Lucy McCoy0ca12682007-05-18 12:10:41 -07001973 dr->wValue = 0;
1974 dr->wIndex = 0;
1975 dr->wLength = cpu_to_le16(sizeof(msg));
1976
Alan Coxdeb91682008-07-22 11:13:08 +01001977 memcpy(s_priv->glocont_buf, &msg, sizeof(msg));
Lucy McCoy0ca12682007-05-18 12:10:41 -07001978
Alan Coxdeb91682008-07-22 11:13:08 +01001979 usb_fill_control_urb(this_urb, serial->dev,
1980 usb_sndctrlpipe(serial->dev, 0),
1981 (unsigned char *)dr, s_priv->glocont_buf,
1982 sizeof(msg), usa49_glocont_callback, serial);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001983
1984 } else {
1985 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Alan Coxdeb91682008-07-22 11:13:08 +01001986
Lucy McCoy0ca12682007-05-18 12:10:41 -07001987 /* send the data out the device on control endpoint */
1988 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001989 }
Alan Coxdeb91682008-07-22 11:13:08 +01001990 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1991 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001992 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993
Alan Coxa5b6f602008-04-08 17:16:06 +01001994 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995}
1996
1997static int keyspan_usa90_send_setup(struct usb_serial *serial,
1998 struct usb_serial_port *port,
1999 int reset_port)
2000{
Alan Coxdeb91682008-07-22 11:13:08 +01002001 struct keyspan_usa90_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002 struct keyspan_serial_private *s_priv;
2003 struct keyspan_port_private *p_priv;
2004 const struct keyspan_device_details *d_details;
2005 struct urb *this_urb;
2006 int err;
2007 u8 prescaler;
2008
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 s_priv = usb_get_serial_data(serial);
2010 p_priv = usb_get_serial_port_data(port);
2011 d_details = s_priv->device_details;
2012
2013 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01002014 this_urb = p_priv->outcont_urb;
2015 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002016 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017 return -1;
2018 }
2019
2020 /* Save reset port val for resend.
2021 Don't overwrite resend for open/close condition. */
2022 if ((reset_port + 1) > p_priv->resend_cont)
2023 p_priv->resend_cont = reset_port + 1;
2024 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002025 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002027 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028 }
2029
Alan Coxdeb91682008-07-22 11:13:08 +01002030 memset(&msg, 0, sizeof(struct keyspan_usa90_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031
Alan Coxdeb91682008-07-22 11:13:08 +01002032 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 if (p_priv->old_baud != p_priv->baud) {
2034 p_priv->old_baud = p_priv->baud;
2035 msg.setClocking = 0x01;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002036 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2037 &msg.baudHi, &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) {
2038 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2039 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 p_priv->baud = 9600;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002041 d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042 &msg.baudHi, &msg.baudLo, &prescaler, 0);
2043 }
2044 msg.setRxMode = 1;
2045 msg.setTxMode = 1;
2046 }
2047
2048 /* modes must always be correctly specified */
Alan Coxdeb91682008-07-22 11:13:08 +01002049 if (p_priv->baud > 57600) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050 msg.rxMode = RXMODE_DMA;
2051 msg.txMode = TXMODE_DMA;
Alan Coxdeb91682008-07-22 11:13:08 +01002052 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 msg.rxMode = RXMODE_BYHAND;
2054 msg.txMode = TXMODE_BYHAND;
2055 }
2056
Ben Minerds2b982ab2012-07-12 00:10:16 +10002057 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058 switch (p_priv->cflag & CSIZE) {
2059 case CS5:
2060 msg.lcr |= USA_DATABITS_5;
2061 break;
2062 case CS6:
2063 msg.lcr |= USA_DATABITS_6;
2064 break;
2065 case CS7:
2066 msg.lcr |= USA_DATABITS_7;
2067 break;
2068 case CS8:
2069 msg.lcr |= USA_DATABITS_8;
2070 break;
2071 }
2072 if (p_priv->cflag & PARENB) {
2073 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002074 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002075 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076 }
2077 if (p_priv->old_cflag != p_priv->cflag) {
2078 p_priv->old_cflag = p_priv->cflag;
2079 msg.setLcr = 0x01;
2080 }
2081
2082 if (p_priv->flow_control == flow_cts)
2083 msg.txFlowControl = TXFLOW_CTS;
2084 msg.setTxFlowControl = 0x01;
2085 msg.setRxFlowControl = 0x01;
Alan Coxdeb91682008-07-22 11:13:08 +01002086
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 msg.rxForwardingLength = 16;
Alan Coxdeb91682008-07-22 11:13:08 +01002088 msg.rxForwardingTimeout = 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089 msg.txAckSetting = 0;
2090 msg.xonChar = 17;
2091 msg.xoffChar = 19;
2092
Alan Coxdeb91682008-07-22 11:13:08 +01002093 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094 if (reset_port == 1) {
2095 msg.portEnabled = 1;
2096 msg.rxFlush = 1;
2097 msg.txBreak = (p_priv->break_on);
2098 }
2099 /* Closing port */
Alan Coxdeb91682008-07-22 11:13:08 +01002100 else if (reset_port == 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101 msg.portEnabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102 /* Sending intermediate configs */
2103 else {
Alan Stern1f871582010-02-17 10:05:47 -05002104 msg.portEnabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 msg.txBreak = (p_priv->break_on);
2106 }
2107
Alan Coxdeb91682008-07-22 11:13:08 +01002108 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109 msg.setRts = 0x01;
2110 msg.rts = p_priv->rts_state;
2111
2112 msg.setDtr = 0x01;
2113 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002114
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01002116 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2117
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 /* send the data out the device on control endpoint */
2119 this_urb->transfer_buffer_length = sizeof(msg);
2120
Alan Coxdeb91682008-07-22 11:13:08 +01002121 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2122 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002123 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002124 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125}
2126
Lucy McCoy0ca12682007-05-18 12:10:41 -07002127static int keyspan_usa67_send_setup(struct usb_serial *serial,
2128 struct usb_serial_port *port,
2129 int reset_port)
2130{
2131 struct keyspan_usa67_portControlMessage msg;
2132 struct keyspan_serial_private *s_priv;
2133 struct keyspan_port_private *p_priv;
2134 const struct keyspan_device_details *d_details;
2135 struct urb *this_urb;
2136 int err, device_port;
2137
Lucy McCoy0ca12682007-05-18 12:10:41 -07002138 s_priv = usb_get_serial_data(serial);
2139 p_priv = usb_get_serial_port_data(port);
2140 d_details = s_priv->device_details;
2141
2142 this_urb = s_priv->glocont_urb;
2143
2144 /* Work out which port within the device is being setup */
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002145 device_port = port->port_number;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002146
2147 /* Make sure we have an urb then send the message */
2148 if (this_urb == NULL) {
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002149 dev_dbg(&port->dev, "%s - oops no urb for port.\n", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002150 return -1;
2151 }
2152
2153 /* Save reset port val for resend.
2154 Don't overwrite resend for open/close condition. */
2155 if ((reset_port + 1) > p_priv->resend_cont)
2156 p_priv->resend_cont = reset_port + 1;
2157 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002158 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002159 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002160 return -1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002161 }
2162
2163 memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
2164
2165 msg.port = device_port;
2166
2167 /* Only set baud rate if it's changed */
2168 if (p_priv->old_baud != p_priv->baud) {
2169 p_priv->old_baud = p_priv->baud;
2170 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002171 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2172 &msg.baudHi, &msg.baudLo, &msg.prescaler,
2173 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2174 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2175 __func__, p_priv->baud);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002176 msg.baudLo = 0;
2177 msg.baudHi = 125; /* Values for 9600 baud */
2178 msg.prescaler = 10;
2179 }
2180 msg.setPrescaler = 0xff;
2181 }
2182
2183 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
2184 switch (p_priv->cflag & CSIZE) {
2185 case CS5:
2186 msg.lcr |= USA_DATABITS_5;
2187 break;
2188 case CS6:
2189 msg.lcr |= USA_DATABITS_6;
2190 break;
2191 case CS7:
2192 msg.lcr |= USA_DATABITS_7;
2193 break;
2194 case CS8:
2195 msg.lcr |= USA_DATABITS_8;
2196 break;
2197 }
2198 if (p_priv->cflag & PARENB) {
2199 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002200 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002201 USA_PARITY_ODD : USA_PARITY_EVEN;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002202 }
2203 msg.setLcr = 0xff;
2204
2205 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2206 msg.xonFlowControl = 0;
2207 msg.setFlowControl = 0xff;
2208 msg.forwardingLength = 16;
2209 msg.xonChar = 17;
2210 msg.xoffChar = 19;
2211
2212 if (reset_port == 1) {
2213 /* Opening port */
2214 msg._txOn = 1;
2215 msg._txOff = 0;
2216 msg.txFlush = 0;
2217 msg.txBreak = 0;
2218 msg.rxOn = 1;
2219 msg.rxOff = 0;
2220 msg.rxFlush = 1;
2221 msg.rxForward = 0;
2222 msg.returnStatus = 0;
2223 msg.resetDataToggle = 0xff;
2224 } else if (reset_port == 2) {
2225 /* Closing port */
2226 msg._txOn = 0;
2227 msg._txOff = 1;
2228 msg.txFlush = 0;
2229 msg.txBreak = 0;
2230 msg.rxOn = 0;
2231 msg.rxOff = 1;
2232 msg.rxFlush = 1;
2233 msg.rxForward = 0;
2234 msg.returnStatus = 0;
2235 msg.resetDataToggle = 0;
2236 } else {
2237 /* Sending intermediate configs */
Alan Coxdeb91682008-07-22 11:13:08 +01002238 msg._txOn = (!p_priv->break_on);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002239 msg._txOff = 0;
2240 msg.txFlush = 0;
2241 msg.txBreak = (p_priv->break_on);
2242 msg.rxOn = 0;
2243 msg.rxOff = 0;
2244 msg.rxFlush = 0;
2245 msg.rxForward = 0;
2246 msg.returnStatus = 0;
2247 msg.resetDataToggle = 0x0;
2248 }
2249
2250 /* Do handshaking outputs */
2251 msg.setTxTriState_setRts = 0xff;
2252 msg.txTriState_rts = p_priv->rts_state;
2253
2254 msg.setHskoa_setDtr = 0xff;
2255 msg.hskoa_dtr = p_priv->dtr_state;
2256
2257 p_priv->resend_cont = 0;
2258
2259 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2260
2261 /* send the data out the device on control endpoint */
2262 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002263
2264 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2265 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002266 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002267 return 0;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002268}
2269
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
2271{
2272 struct usb_serial *serial = port->serial;
2273 struct keyspan_serial_private *s_priv;
2274 const struct keyspan_device_details *d_details;
2275
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276 s_priv = usb_get_serial_data(serial);
2277 d_details = s_priv->device_details;
2278
2279 switch (d_details->msg_format) {
2280 case msg_usa26:
2281 keyspan_usa26_send_setup(serial, port, reset_port);
2282 break;
2283 case msg_usa28:
2284 keyspan_usa28_send_setup(serial, port, reset_port);
2285 break;
2286 case msg_usa49:
2287 keyspan_usa49_send_setup(serial, port, reset_port);
2288 break;
2289 case msg_usa90:
2290 keyspan_usa90_send_setup(serial, port, reset_port);
2291 break;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002292 case msg_usa67:
2293 keyspan_usa67_send_setup(serial, port, reset_port);
2294 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295 }
2296}
2297
2298
2299/* Gets called by the "real" driver (ie once firmware is loaded
2300 and renumeration has taken place. */
Alan Coxdeb91682008-07-22 11:13:08 +01002301static int keyspan_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302{
2303 int i, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305 const struct keyspan_device_details *d_details;
2306
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307 for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
Alan Coxdeb91682008-07-22 11:13:08 +01002308 if (d_details->product_id ==
2309 le16_to_cpu(serial->dev->descriptor.idProduct))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 break;
2311 if (d_details == NULL) {
Alan Coxdeb91682008-07-22 11:13:08 +01002312 dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
2313 __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
Johan Hovoldff8a43c2013-08-13 13:27:35 +02002314 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315 }
2316
2317 /* Setup private data for serial driver */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01002318 s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
Johan Hovold10c642d2013-12-29 19:22:56 +01002319 if (!s_priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321
Johan Hovold2fcd1c92013-08-13 13:27:36 +02002322 s_priv->instat_buf = kzalloc(INSTAT_BUFLEN, GFP_KERNEL);
2323 if (!s_priv->instat_buf)
2324 goto err_instat_buf;
2325
2326 s_priv->indat_buf = kzalloc(INDAT49W_BUFLEN, GFP_KERNEL);
2327 if (!s_priv->indat_buf)
2328 goto err_indat_buf;
2329
2330 s_priv->glocont_buf = kzalloc(GLOCONT_BUFLEN, GFP_KERNEL);
2331 if (!s_priv->glocont_buf)
2332 goto err_glocont_buf;
2333
2334 s_priv->ctrl_buf = kzalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
2335 if (!s_priv->ctrl_buf)
2336 goto err_ctrl_buf;
2337
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338 s_priv->device_details = d_details;
2339 usb_set_serial_data(serial, s_priv);
2340
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341 keyspan_setup_urbs(serial);
2342
Lucy McCoy0ca12682007-05-18 12:10:41 -07002343 if (s_priv->instat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002344 err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
2345 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002346 dev_dbg(&serial->dev->dev, "%s - submit instat urb failed %d\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002347 }
2348 if (s_priv->indat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002349 err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
2350 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002351 dev_dbg(&serial->dev->dev, "%s - submit indat urb failed %d\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 }
Alan Coxdeb91682008-07-22 11:13:08 +01002353
Alan Coxa5b6f602008-04-08 17:16:06 +01002354 return 0;
Johan Hovold2fcd1c92013-08-13 13:27:36 +02002355
2356err_ctrl_buf:
2357 kfree(s_priv->glocont_buf);
2358err_glocont_buf:
2359 kfree(s_priv->indat_buf);
2360err_indat_buf:
2361 kfree(s_priv->instat_buf);
2362err_instat_buf:
2363 kfree(s_priv);
2364
2365 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366}
2367
Alan Sternf9c99bb2009-06-02 11:53:55 -04002368static void keyspan_disconnect(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002370 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 s_priv = usb_get_serial_data(serial);
2373
Johan Hovold61924502016-05-08 20:07:59 +02002374 usb_kill_urb(s_priv->instat_urb);
2375 usb_kill_urb(s_priv->glocont_urb);
2376 usb_kill_urb(s_priv->indat_urb);
Alan Sternf9c99bb2009-06-02 11:53:55 -04002377}
2378
2379static void keyspan_release(struct usb_serial *serial)
2380{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002381 struct keyspan_serial_private *s_priv;
Alan Sternf9c99bb2009-06-02 11:53:55 -04002382
Alan Sternf9c99bb2009-06-02 11:53:55 -04002383 s_priv = usb_get_serial_data(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384
Johan Hovold35be1a72016-05-08 20:07:58 +02002385 /* Make sure to unlink the URBs submitted in attach. */
2386 usb_kill_urb(s_priv->instat_urb);
2387 usb_kill_urb(s_priv->indat_urb);
2388
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002389 usb_free_urb(s_priv->instat_urb);
2390 usb_free_urb(s_priv->indat_urb);
2391 usb_free_urb(s_priv->glocont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392
Johan Hovold2fcd1c92013-08-13 13:27:36 +02002393 kfree(s_priv->ctrl_buf);
2394 kfree(s_priv->glocont_buf);
2395 kfree(s_priv->indat_buf);
2396 kfree(s_priv->instat_buf);
2397
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002398 kfree(s_priv);
2399}
2400
2401static int keyspan_port_probe(struct usb_serial_port *port)
2402{
2403 struct usb_serial *serial = port->serial;
Bjørn Morkf0e3e352012-11-10 10:13:42 +01002404 struct keyspan_serial_private *s_priv;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002405 struct keyspan_port_private *p_priv;
2406 const struct keyspan_device_details *d_details;
2407 struct callbacks *cback;
2408 int endp;
2409 int port_num;
2410 int i;
2411
2412 s_priv = usb_get_serial_data(serial);
2413 d_details = s_priv->device_details;
2414
2415 p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL);
2416 if (!p_priv)
2417 return -ENOMEM;
2418
Johan Hovoldbad41a52013-08-13 13:27:37 +02002419 for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i) {
2420 p_priv->in_buffer[i] = kzalloc(IN_BUFLEN, GFP_KERNEL);
2421 if (!p_priv->in_buffer[i])
2422 goto err_in_buffer;
2423 }
2424
2425 for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i) {
2426 p_priv->out_buffer[i] = kzalloc(OUT_BUFLEN, GFP_KERNEL);
2427 if (!p_priv->out_buffer[i])
2428 goto err_out_buffer;
2429 }
2430
2431 p_priv->inack_buffer = kzalloc(INACK_BUFLEN, GFP_KERNEL);
2432 if (!p_priv->inack_buffer)
2433 goto err_inack_buffer;
2434
2435 p_priv->outcont_buffer = kzalloc(OUTCONT_BUFLEN, GFP_KERNEL);
2436 if (!p_priv->outcont_buffer)
2437 goto err_outcont_buffer;
2438
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002439 p_priv->device_details = d_details;
2440
2441 /* Setup values for the various callback routines */
2442 cback = &keyspan_callbacks[d_details->msg_format];
2443
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002444 port_num = port->port_number;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002445
2446 /* Do indat endpoints first, once for each flip */
2447 endp = d_details->indat_endpoints[port_num];
2448 for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) {
2449 p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp,
2450 USB_DIR_IN, port,
Johan Hovoldbad41a52013-08-13 13:27:37 +02002451 p_priv->in_buffer[i],
2452 IN_BUFLEN,
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002453 cback->indat_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454 }
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002455 /* outdat endpoints also have flip */
2456 endp = d_details->outdat_endpoints[port_num];
2457 for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) {
2458 p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp,
2459 USB_DIR_OUT, port,
Johan Hovoldbad41a52013-08-13 13:27:37 +02002460 p_priv->out_buffer[i],
2461 OUT_BUFLEN,
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002462 cback->outdat_callback);
2463 }
2464 /* inack endpoint */
2465 p_priv->inack_urb = keyspan_setup_urb(serial,
2466 d_details->inack_endpoints[port_num],
2467 USB_DIR_IN, port,
Johan Hovoldbad41a52013-08-13 13:27:37 +02002468 p_priv->inack_buffer,
2469 INACK_BUFLEN,
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002470 cback->inack_callback);
2471 /* outcont endpoint */
2472 p_priv->outcont_urb = keyspan_setup_urb(serial,
2473 d_details->outcont_endpoints[port_num],
2474 USB_DIR_OUT, port,
Johan Hovoldbad41a52013-08-13 13:27:37 +02002475 p_priv->outcont_buffer,
2476 OUTCONT_BUFLEN,
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002477 cback->outcont_callback);
2478
2479 usb_set_serial_port_data(port, p_priv);
2480
2481 return 0;
Johan Hovoldbad41a52013-08-13 13:27:37 +02002482
2483err_outcont_buffer:
2484 kfree(p_priv->inack_buffer);
2485err_inack_buffer:
2486 for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i)
2487 kfree(p_priv->out_buffer[i]);
2488err_out_buffer:
2489 for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i)
2490 kfree(p_priv->in_buffer[i]);
2491err_in_buffer:
2492 kfree(p_priv);
2493
2494 return -ENOMEM;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002495}
2496
2497static int keyspan_port_remove(struct usb_serial_port *port)
2498{
2499 struct keyspan_port_private *p_priv;
2500 int i;
2501
2502 p_priv = usb_get_serial_port_data(port);
2503
Johan Hovold61924502016-05-08 20:07:59 +02002504 usb_kill_urb(p_priv->inack_urb);
2505 usb_kill_urb(p_priv->outcont_urb);
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002506 for (i = 0; i < 2; i++) {
Johan Hovold61924502016-05-08 20:07:59 +02002507 usb_kill_urb(p_priv->in_urbs[i]);
2508 usb_kill_urb(p_priv->out_urbs[i]);
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002509 }
2510
2511 usb_free_urb(p_priv->inack_urb);
2512 usb_free_urb(p_priv->outcont_urb);
2513 for (i = 0; i < 2; i++) {
2514 usb_free_urb(p_priv->in_urbs[i]);
2515 usb_free_urb(p_priv->out_urbs[i]);
2516 }
2517
Johan Hovoldbad41a52013-08-13 13:27:37 +02002518 kfree(p_priv->outcont_buffer);
2519 kfree(p_priv->inack_buffer);
2520 for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i)
2521 kfree(p_priv->out_buffer[i]);
2522 for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i)
2523 kfree(p_priv->in_buffer[i]);
2524
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002525 kfree(p_priv);
2526
2527 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528}
2529
Alan Coxdeb91682008-07-22 11:13:08 +01002530MODULE_AUTHOR(DRIVER_AUTHOR);
2531MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002532MODULE_LICENSE("GPL");
2533
David Woodhouse2971c572008-05-30 14:04:03 +03002534MODULE_FIRMWARE("keyspan/usa28.fw");
2535MODULE_FIRMWARE("keyspan/usa28x.fw");
2536MODULE_FIRMWARE("keyspan/usa28xa.fw");
2537MODULE_FIRMWARE("keyspan/usa28xb.fw");
2538MODULE_FIRMWARE("keyspan/usa19.fw");
2539MODULE_FIRMWARE("keyspan/usa19qi.fw");
2540MODULE_FIRMWARE("keyspan/mpr.fw");
2541MODULE_FIRMWARE("keyspan/usa19qw.fw");
2542MODULE_FIRMWARE("keyspan/usa18x.fw");
2543MODULE_FIRMWARE("keyspan/usa19w.fw");
2544MODULE_FIRMWARE("keyspan/usa49w.fw");
2545MODULE_FIRMWARE("keyspan/usa49wlc.fw");