blob: 1f9414bdd64989c65f3c9eff22190bbb8d73b9fe [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);
570
571 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700572 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100573 keyspan_usa49_send_setup(serial, port,
574 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 break;
576 }
577 }
578}
579
580 /* This is actually called glostat in the Keyspan
581 doco */
David Howells7d12e782006-10-05 14:55:46 +0100582static void usa49_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583{
584 int err;
585 unsigned char *data = urb->transfer_buffer;
586 struct keyspan_usa49_portStatusMessage *msg;
587 struct usb_serial *serial;
588 struct usb_serial_port *port;
589 struct keyspan_port_private *p_priv;
590 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700591 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592
Ming Leicdc97792008-02-24 18:41:47 +0800593 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700595 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +0200596 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
597 __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 return;
599 }
600
Alan Coxdeb91682008-07-22 11:13:08 +0100601 if (urb->actual_length !=
602 sizeof(struct keyspan_usa49_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700603 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 goto exit;
605 }
606
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 msg = (struct keyspan_usa49_portStatusMessage *)data;
608
Alan Coxdeb91682008-07-22 11:13:08 +0100609 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 if (msg->portNumber >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700611 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
612 __func__, msg->portNumber);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 goto exit;
614 }
615 port = serial->port[msg->portNumber];
616 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb5122232014-12-22 18:39:39 +0100617 if (!p_priv)
618 goto resubmit;
Alan Coxdeb91682008-07-22 11:13:08 +0100619
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 /* Update handshaking pin state information */
621 old_dcd_state = p_priv->dcd_state;
622 p_priv->cts_state = ((msg->cts) ? 1 : 0);
623 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
624 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
625 p_priv->ri_state = ((msg->ri) ? 1 : 0);
626
Jiri Slabyaa27a092013-03-07 13:12:30 +0100627 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
628 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb5122232014-12-22 18:39:39 +0100629resubmit:
Alan Coxdeb91682008-07-22 11:13:08 +0100630 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100631 err = usb_submit_urb(urb, GFP_ATOMIC);
632 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700633 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634exit: ;
635}
636
David Howells7d12e782006-10-05 14:55:46 +0100637static void usa49_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639}
640
David Howells7d12e782006-10-05 14:55:46 +0100641static void usa49_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642{
643 int i, err;
644 int endpoint;
645 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700647 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 endpoint = usb_pipeendpoint(urb->pipe);
650
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700651 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +0200652 dev_dbg(&urb->dev->dev, "%s - nonzero status %d on endpoint %x\n",
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700653 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 return;
655 }
656
Ming Leicdc97792008-02-24 18:41:47 +0800657 port = urb->context;
Jiri Slaby2e124b42013-01-03 15:53:06 +0100658 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 /* 0x80 bit is error flag */
660 if ((data[0] & 0x80) == 0) {
661 /* no error on any byte */
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100662 tty_insert_flip_string(&port->port, data + 1,
Alan Coxf035a8a2008-07-22 11:13:32 +0100663 urb->actual_length - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 } else {
665 /* some bytes had errors, every byte has status */
666 for (i = 0; i + 1 < urb->actual_length; i += 2) {
Johan Hovold5d1678a2014-11-18 11:25:19 +0100667 int stat = data[i];
668 int flag = TTY_NORMAL;
669
670 if (stat & RXERROR_OVERRUN) {
671 tty_insert_flip_char(&port->port, 0,
672 TTY_OVERRUN);
673 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 /* XXX should handle break (0x10) */
Johan Hovold5d1678a2014-11-18 11:25:19 +0100675 if (stat & RXERROR_PARITY)
676 flag = TTY_PARITY;
677 else if (stat & RXERROR_FRAMING)
678 flag = TTY_FRAME;
679
Jiri Slaby92a19f92013-01-03 15:53:03 +0100680 tty_insert_flip_char(&port->port, data[i+1],
681 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 }
683 }
Jiri Slaby2e124b42013-01-03 15:53:06 +0100684 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 }
Alan Coxdeb91682008-07-22 11:13:08 +0100686
687 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500688 err = usb_submit_urb(urb, GFP_ATOMIC);
689 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700690 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691}
692
Lucy McCoy0ca12682007-05-18 12:10:41 -0700693static void usa49wg_indat_callback(struct urb *urb)
694{
695 int i, len, x, err;
696 struct usb_serial *serial;
697 struct usb_serial_port *port;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700698 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700699 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700700
Lucy McCoy0ca12682007-05-18 12:10:41 -0700701 serial = urb->context;
702
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700703 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +0200704 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
705 __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700706 return;
707 }
708
709 /* inbound data is in the form P#, len, status, data */
710 i = 0;
711 len = 0;
712
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300713 while (i < urb->actual_length) {
Lucy McCoy0ca12682007-05-18 12:10:41 -0700714
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300715 /* Check port number from message */
716 if (data[i] >= serial->num_ports) {
717 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
718 __func__, data[i]);
719 return;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700720 }
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300721 port = serial->port[data[i++]];
722 len = data[i++];
723
724 /* 0x80 bit is error flag */
725 if ((data[i] & 0x80) == 0) {
726 /* no error on any byte */
727 i++;
Dan Carpenter01a60e72013-04-05 08:43:20 +0300728 for (x = 1; x < len && i < urb->actual_length; ++x)
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300729 tty_insert_flip_char(&port->port,
730 data[i++], 0);
731 } else {
732 /*
733 * some bytes had errors, every byte has status
734 */
Dan Carpenter01a60e72013-04-05 08:43:20 +0300735 for (x = 0; x + 1 < len &&
736 i + 1 < urb->actual_length; x += 2) {
Johan Hovold5d1678a2014-11-18 11:25:19 +0100737 int stat = data[i];
738 int flag = TTY_NORMAL;
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300739
Johan Hovold5d1678a2014-11-18 11:25:19 +0100740 if (stat & RXERROR_OVERRUN) {
741 tty_insert_flip_char(&port->port, 0,
742 TTY_OVERRUN);
743 }
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300744 /* XXX should handle break (0x10) */
Johan Hovold5d1678a2014-11-18 11:25:19 +0100745 if (stat & RXERROR_PARITY)
746 flag = TTY_PARITY;
747 else if (stat & RXERROR_FRAMING)
748 flag = TTY_FRAME;
749
Dan Carpenter6a3ae842013-04-05 08:42:41 +0300750 tty_insert_flip_char(&port->port, data[i+1],
751 flag);
752 i += 2;
753 }
754 }
755 tty_flip_buffer_push(&port->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700756 }
757
758 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700759 err = usb_submit_urb(urb, GFP_ATOMIC);
760 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700761 dev_dbg(&urb->dev->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700762}
763
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764/* not used, usa-49 doesn't have per-port control endpoints */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700765static void usa49_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767}
768
Lucy McCoy0ca12682007-05-18 12:10:41 -0700769static void usa90_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770{
771 int i, err;
772 int endpoint;
773 struct usb_serial_port *port;
774 struct keyspan_port_private *p_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700776 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 endpoint = usb_pipeendpoint(urb->pipe);
779
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700780 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +0200781 dev_dbg(&urb->dev->dev, "%s - nonzero status %d on endpoint %x\n",
782 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 return;
784 }
785
Ming Leicdc97792008-02-24 18:41:47 +0800786 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 p_priv = usb_get_serial_port_data(port);
788
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 /* if current mode is DMA, looks like usa28 format
Alan Coxdeb91682008-07-22 11:13:08 +0100791 otherwise looks like usa26 data format */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792
Alan Coxf035a8a2008-07-22 11:13:32 +0100793 if (p_priv->baud > 57600)
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100794 tty_insert_flip_string(&port->port, data,
795 urb->actual_length);
Alan Coxf035a8a2008-07-22 11:13:32 +0100796 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 /* 0x80 bit is error flag */
798 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100799 /* no errors on individual bytes, only
800 possible overrun err*/
Johan Hovold855515a2014-11-18 11:25:20 +0100801 if (data[0] & RXERROR_OVERRUN) {
802 tty_insert_flip_char(&port->port, 0,
803 TTY_OVERRUN);
804 }
Alan Coxdeb91682008-07-22 11:13:08 +0100805 for (i = 1; i < urb->actual_length ; ++i)
Jiri Slaby92a19f92013-01-03 15:53:03 +0100806 tty_insert_flip_char(&port->port,
Johan Hovold855515a2014-11-18 11:25:20 +0100807 data[i], TTY_NORMAL);
Alan Coxdeb91682008-07-22 11:13:08 +0100808 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 /* some bytes had errors, every byte has status */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700810 dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 for (i = 0; i + 1 < urb->actual_length; i += 2) {
Johan Hovold5d1678a2014-11-18 11:25:19 +0100812 int stat = data[i];
813 int flag = TTY_NORMAL;
814
815 if (stat & RXERROR_OVERRUN) {
816 tty_insert_flip_char(
817 &port->port, 0,
818 TTY_OVERRUN);
819 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 /* XXX should handle break (0x10) */
Johan Hovold5d1678a2014-11-18 11:25:19 +0100821 if (stat & RXERROR_PARITY)
822 flag = TTY_PARITY;
823 else if (stat & RXERROR_FRAMING)
824 flag = TTY_FRAME;
825
Jiri Slaby92a19f92013-01-03 15:53:03 +0100826 tty_insert_flip_char(&port->port,
827 data[i+1], flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 }
829 }
830 }
Jiri Slaby2e124b42013-01-03 15:53:06 +0100831 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 }
Alan Coxdeb91682008-07-22 11:13:08 +0100833
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500835 err = usb_submit_urb(urb, GFP_ATOMIC);
836 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700837 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838}
839
840
David Howells7d12e782006-10-05 14:55:46 +0100841static void usa90_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842{
843 unsigned char *data = urb->transfer_buffer;
844 struct keyspan_usa90_portStatusMessage *msg;
845 struct usb_serial *serial;
846 struct usb_serial_port *port;
847 struct keyspan_port_private *p_priv;
848 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700849 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850
Ming Leicdc97792008-02-24 18:41:47 +0800851 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700853 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +0200854 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
855 __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 return;
857 }
858 if (urb->actual_length < 14) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700859 dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 goto exit;
861 }
862
863 msg = (struct keyspan_usa90_portStatusMessage *)data;
864
865 /* Now do something useful with the data */
866
867 port = serial->port[0];
868 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb5122232014-12-22 18:39:39 +0100869 if (!p_priv)
870 goto resubmit;
Alan Coxdeb91682008-07-22 11:13:08 +0100871
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 /* Update handshaking pin state information */
873 old_dcd_state = p_priv->dcd_state;
874 p_priv->cts_state = ((msg->cts) ? 1 : 0);
875 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
876 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
877 p_priv->ri_state = ((msg->ri) ? 1 : 0);
878
Jiri Slabyaa27a092013-03-07 13:12:30 +0100879 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
880 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb5122232014-12-22 18:39:39 +0100881resubmit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100883 err = usb_submit_urb(urb, GFP_ATOMIC);
884 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700885 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886exit:
887 ;
888}
889
David Howells7d12e782006-10-05 14:55:46 +0100890static void usa90_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891{
892 struct usb_serial_port *port;
893 struct keyspan_port_private *p_priv;
894
Ming Leicdc97792008-02-24 18:41:47 +0800895 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 p_priv = usb_get_serial_port_data(port);
897
898 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700899 dev_dbg(&urb->dev->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100900 keyspan_usa90_send_setup(port->serial, port,
901 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 }
903}
904
Lucy McCoy0ca12682007-05-18 12:10:41 -0700905/* Status messages from the 28xg */
906static void usa67_instat_callback(struct urb *urb)
907{
908 int err;
909 unsigned char *data = urb->transfer_buffer;
910 struct keyspan_usa67_portStatusMessage *msg;
911 struct usb_serial *serial;
912 struct usb_serial_port *port;
913 struct keyspan_port_private *p_priv;
914 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700915 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700916
Lucy McCoy0ca12682007-05-18 12:10:41 -0700917 serial = urb->context;
918
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700919 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +0200920 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
921 __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700922 return;
923 }
924
Alan Coxdeb91682008-07-22 11:13:08 +0100925 if (urb->actual_length !=
926 sizeof(struct keyspan_usa67_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700927 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700928 return;
929 }
930
931
932 /* Now do something useful with the data */
933 msg = (struct keyspan_usa67_portStatusMessage *)data;
934
935 /* Check port number from message and retrieve private data */
936 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700937 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700938 return;
939 }
940
941 port = serial->port[msg->port];
942 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb5122232014-12-22 18:39:39 +0100943 if (!p_priv)
944 goto resubmit;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700945
946 /* Update handshaking pin state information */
947 old_dcd_state = p_priv->dcd_state;
948 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
949 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
950
Jiri Slabyaa27a092013-03-07 13:12:30 +0100951 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
952 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb5122232014-12-22 18:39:39 +0100953resubmit:
Lucy McCoy0ca12682007-05-18 12:10:41 -0700954 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700955 err = usb_submit_urb(urb, GFP_ATOMIC);
956 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700957 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700958}
959
960static void usa67_glocont_callback(struct urb *urb)
961{
962 struct usb_serial *serial;
963 struct usb_serial_port *port;
964 struct keyspan_port_private *p_priv;
965 int i;
966
Lucy McCoy0ca12682007-05-18 12:10:41 -0700967 serial = urb->context;
968 for (i = 0; i < serial->num_ports; ++i) {
969 port = serial->port[i];
970 p_priv = usb_get_serial_port_data(port);
971
972 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700973 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700974 keyspan_usa67_send_setup(serial, port,
975 p_priv->resend_cont - 1);
976 break;
977 }
978 }
979}
980
Alan Cox95da3102008-07-22 11:09:07 +0100981static int keyspan_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982{
Alan Cox95da3102008-07-22 11:09:07 +0100983 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 struct keyspan_port_private *p_priv;
985 const struct keyspan_device_details *d_details;
986 int flip;
987 int data_len;
988 struct urb *this_urb;
989
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 p_priv = usb_get_serial_port_data(port);
991 d_details = p_priv->device_details;
992
Alan Coxa5b6f602008-04-08 17:16:06 +0100993 /* FIXME: locking */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 if (d_details->msg_format == msg_usa90)
Alan Coxdeb91682008-07-22 11:13:08 +0100995 data_len = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 else
997 data_len = 63;
998
999 flip = p_priv->out_flip;
1000
1001 /* Check both endpoints to see if any are available. */
Alan Coxdeb91682008-07-22 11:13:08 +01001002 this_urb = p_priv->out_urbs[flip];
1003 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001005 return data_len;
1006 flip = (flip + 1) & d_details->outdat_endp_flip;
1007 this_urb = p_priv->out_urbs[flip];
1008 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001010 return data_len;
1011 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 }
Alan Coxa5b6f602008-04-08 17:16:06 +01001013 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014}
1015
1016
Alan Coxa509a7e2009-09-19 13:13:26 -07001017static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018{
Andrew Mortonf78ba152007-11-28 16:21:54 -08001019 struct keyspan_port_private *p_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 const struct keyspan_device_details *d_details;
1021 int i, err;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001022 int baud_rate, device_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 struct urb *urb;
Alan Cox95da3102008-07-22 11:09:07 +01001024 unsigned int cflag = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 p_priv = usb_get_serial_port_data(port);
1027 d_details = p_priv->device_details;
Borislav Petkov7eea4362007-11-14 17:00:39 -08001028
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 /* Set some sane defaults */
1030 p_priv->rts_state = 1;
1031 p_priv->dtr_state = 1;
1032 p_priv->baud = 9600;
1033
1034 /* force baud and lcr to be set on open */
1035 p_priv->old_baud = 0;
1036 p_priv->old_cflag = 0;
1037
1038 p_priv->out_flip = 0;
1039 p_priv->in_flip = 0;
1040
1041 /* Reset low level data toggle and start reading from endpoints */
1042 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001043 urb = p_priv->in_urbs[i];
1044 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046
Alan Coxdeb91682008-07-22 11:13:08 +01001047 /* make sure endpoint data toggle is synchronized
1048 with the device */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 usb_clear_halt(urb->dev, urb->pipe);
Alan Coxdeb91682008-07-22 11:13:08 +01001050 err = usb_submit_urb(urb, GFP_KERNEL);
1051 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001052 dev_dbg(&port->dev, "%s - submit urb %d failed (%d)\n", __func__, i, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 }
1054
1055 /* Reset low level data toggle on out endpoints */
1056 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001057 urb = p_priv->out_urbs[i];
1058 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 continue;
Alan Coxdeb91682008-07-22 11:13:08 +01001060 /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
1061 usb_pipeout(urb->pipe), 0); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 }
1063
Andrew Mortonf78ba152007-11-28 16:21:54 -08001064 /* get the terminal config for the setup message now so we don't
1065 * need to send 2 of them */
1066
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001067 device_port = port->port_number;
Alan Cox95da3102008-07-22 11:09:07 +01001068 if (tty) {
Alan Coxadc8d742012-07-14 15:31:47 +01001069 cflag = tty->termios.c_cflag;
Alan Cox95da3102008-07-22 11:09:07 +01001070 /* Baud rate calculation takes baud rate as an integer
1071 so other rates can be generated if desired. */
1072 baud_rate = tty_get_baud_rate(tty);
1073 /* If no match or invalid, leave as default */
1074 if (baud_rate >= 0
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001075 && d_details->calculate_baud_rate(port, baud_rate, d_details->baudclk,
Alan Cox95da3102008-07-22 11:09:07 +01001076 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
1077 p_priv->baud = baud_rate;
1078 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001079 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001080 /* set CTS/RTS handshake etc. */
1081 p_priv->cflag = cflag;
Ben Minerds2b982ab2012-07-12 00:10:16 +10001082 p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001083
1084 keyspan_send_setup(port, 1);
Alan Coxdeb91682008-07-22 11:13:08 +01001085 /* mdelay(100); */
1086 /* keyspan_set_termios(port, NULL); */
Andrew Mortonf78ba152007-11-28 16:21:54 -08001087
Alan Coxa5b6f602008-04-08 17:16:06 +01001088 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089}
1090
Alan Cox335f8512009-06-11 12:26:29 +01001091static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
1092{
1093 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
1094
1095 p_priv->rts_state = on;
1096 p_priv->dtr_state = on;
1097 keyspan_send_setup(port, 0);
1098}
1099
1100static void keyspan_close(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101{
1102 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 struct keyspan_port_private *p_priv;
1104
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +01001106
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 p_priv->rts_state = 0;
1108 p_priv->dtr_state = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001109
Johan Hovold80dfe0c2013-03-21 12:36:32 +01001110 keyspan_send_setup(port, 2);
1111 /* pilot-xfer seems to work best with this delay */
1112 mdelay(100);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113
1114 p_priv->out_flip = 0;
1115 p_priv->in_flip = 0;
1116
Johan Hovold61924502016-05-08 20:07:59 +02001117 usb_kill_urb(p_priv->inack_urb);
Johan Hovold80dfe0c2013-03-21 12:36:32 +01001118 for (i = 0; i < 2; i++) {
Johan Hovold61924502016-05-08 20:07:59 +02001119 usb_kill_urb(p_priv->in_urbs[i]);
1120 usb_kill_urb(p_priv->out_urbs[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122}
1123
Alan Coxdeb91682008-07-22 11:13:08 +01001124/* download the firmware to a pre-renumeration device */
1125static int keyspan_fake_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126{
Rene Buergel8d733e22012-09-18 09:02:01 +02001127 char *fw_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001129 dev_dbg(&serial->dev->dev, "Keyspan startup version %04x product %04x\n",
1130 le16_to_cpu(serial->dev->descriptor.bcdDevice),
1131 le16_to_cpu(serial->dev->descriptor.idProduct));
Alan Coxdeb91682008-07-22 11:13:08 +01001132
1133 if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000)
1134 != 0x8000) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001135 dev_dbg(&serial->dev->dev, "Firmware already loaded. Quitting.\n");
Alan Coxdeb91682008-07-22 11:13:08 +01001136 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 }
1138
1139 /* Select firmware image on the basis of idProduct */
1140 switch (le16_to_cpu(serial->dev->descriptor.idProduct)) {
1141 case keyspan_usa28_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001142 fw_name = "keyspan/usa28.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 break;
1144
1145 case keyspan_usa28x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001146 fw_name = "keyspan/usa28x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 break;
1148
1149 case keyspan_usa28xa_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001150 fw_name = "keyspan/usa28xa.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 break;
1152
1153 case keyspan_usa28xb_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001154 fw_name = "keyspan/usa28xb.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 break;
1156
1157 case keyspan_usa19_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001158 fw_name = "keyspan/usa19.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001160
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 case keyspan_usa19qi_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001162 fw_name = "keyspan/usa19qi.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_mpr_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001166 fw_name = "keyspan/mpr.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 break;
1168
1169 case keyspan_usa19qw_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001170 fw_name = "keyspan/usa19qw.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001172
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 case keyspan_usa18x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001174 fw_name = "keyspan/usa18x.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_usa19w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001178 fw_name = "keyspan/usa19w.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_usa49w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001182 fw_name = "keyspan/usa49w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 break;
1184
1185 case keyspan_usa49wlc_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001186 fw_name = "keyspan/usa49wlc.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 break;
1188
1189 default:
David Woodhouse2971c572008-05-30 14:04:03 +03001190 dev_err(&serial->dev->dev, "Unknown product ID (%04x)\n",
1191 le16_to_cpu(serial->dev->descriptor.idProduct));
1192 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193 }
1194
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001195 dev_dbg(&serial->dev->dev, "Uploading Keyspan %s firmware.\n", fw_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196
Rene Buergel8d733e22012-09-18 09:02:01 +02001197 if (ezusb_fx1_ihex_firmware_download(serial->dev, fw_name) < 0) {
1198 dev_err(&serial->dev->dev, "failed to load firmware \"%s\"\n",
1199 fw_name);
1200 return -ENOENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 }
1202
Rene Buergel8d733e22012-09-18 09:02:01 +02001203 /* after downloading firmware Renumeration will occur in a
1204 moment and the new device will bind to the real driver */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205
1206 /* we don't want this device to have a driver assigned to it. */
Alan Coxdeb91682008-07-22 11:13:08 +01001207 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208}
1209
1210/* Helper functions used by keyspan_setup_urbs */
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001211static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *serial,
1212 int endpoint)
1213{
1214 struct usb_host_interface *iface_desc;
1215 struct usb_endpoint_descriptor *ep;
1216 int i;
1217
1218 iface_desc = serial->interface->cur_altsetting;
1219 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1220 ep = &iface_desc->endpoint[i].desc;
1221 if (ep->bEndpointAddress == endpoint)
1222 return ep;
1223 }
Johan Hovold0cd782b2016-05-08 20:08:00 +02001224 dev_warn(&serial->interface->dev, "found no endpoint descriptor for endpoint %x\n",
1225 endpoint);
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001226 return NULL;
1227}
1228
Alan Coxdeb91682008-07-22 11:13:08 +01001229static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 int dir, void *ctx, char *buf, int len,
David Howells7d12e782006-10-05 14:55:46 +01001231 void (*callback)(struct urb *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232{
1233 struct urb *urb;
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001234 struct usb_endpoint_descriptor const *ep_desc;
1235 char const *ep_type_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236
1237 if (endpoint == -1)
1238 return NULL; /* endpoint not needed */
1239
Johan Hovold0cd782b2016-05-08 20:08:00 +02001240 dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %x\n",
1241 __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
Johan Hovold10c642d2013-12-29 19:22:56 +01001243 if (!urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245
Lucy McCoy0ca12682007-05-18 12:10:41 -07001246 if (endpoint == 0) {
1247 /* control EP filled in when used */
1248 return urb;
1249 }
1250
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001251 ep_desc = find_ep(serial, endpoint);
1252 if (!ep_desc) {
1253 /* leak the urb, something's wrong and the callers don't care */
1254 return urb;
1255 }
1256 if (usb_endpoint_xfer_int(ep_desc)) {
1257 ep_type_name = "INT";
1258 usb_fill_int_urb(urb, serial->dev,
1259 usb_sndintpipe(serial->dev, endpoint) | dir,
1260 buf, len, callback, ctx,
1261 ep_desc->bInterval);
1262 } else if (usb_endpoint_xfer_bulk(ep_desc)) {
1263 ep_type_name = "BULK";
1264 usb_fill_bulk_urb(urb, serial->dev,
1265 usb_sndbulkpipe(serial->dev, endpoint) | dir,
1266 buf, len, callback, ctx);
1267 } else {
1268 dev_warn(&serial->interface->dev,
1269 "unsupported endpoint type %x\n",
Julia Lawall2e0fe702008-12-29 11:22:14 +01001270 usb_endpoint_type(ep_desc));
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001271 usb_free_urb(urb);
1272 return NULL;
1273 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001275 dev_dbg(&serial->interface->dev, "%s - using urb %p for %s endpoint %x\n",
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001276 __func__, urb, ep_type_name, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 return urb;
1278}
1279
1280static struct callbacks {
David Howells7d12e782006-10-05 14:55:46 +01001281 void (*instat_callback)(struct urb *);
1282 void (*glocont_callback)(struct urb *);
1283 void (*indat_callback)(struct urb *);
1284 void (*outdat_callback)(struct urb *);
1285 void (*inack_callback)(struct urb *);
1286 void (*outcont_callback)(struct urb *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287} keyspan_callbacks[] = {
1288 {
1289 /* msg_usa26 callbacks */
1290 .instat_callback = usa26_instat_callback,
1291 .glocont_callback = usa26_glocont_callback,
1292 .indat_callback = usa26_indat_callback,
1293 .outdat_callback = usa2x_outdat_callback,
1294 .inack_callback = usa26_inack_callback,
1295 .outcont_callback = usa26_outcont_callback,
1296 }, {
1297 /* msg_usa28 callbacks */
1298 .instat_callback = usa28_instat_callback,
1299 .glocont_callback = usa28_glocont_callback,
1300 .indat_callback = usa28_indat_callback,
1301 .outdat_callback = usa2x_outdat_callback,
1302 .inack_callback = usa28_inack_callback,
1303 .outcont_callback = usa28_outcont_callback,
1304 }, {
1305 /* msg_usa49 callbacks */
1306 .instat_callback = usa49_instat_callback,
1307 .glocont_callback = usa49_glocont_callback,
1308 .indat_callback = usa49_indat_callback,
1309 .outdat_callback = usa2x_outdat_callback,
1310 .inack_callback = usa49_inack_callback,
1311 .outcont_callback = usa49_outcont_callback,
1312 }, {
1313 /* msg_usa90 callbacks */
1314 .instat_callback = usa90_instat_callback,
Alan Coxdeb91682008-07-22 11:13:08 +01001315 .glocont_callback = usa28_glocont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316 .indat_callback = usa90_indat_callback,
1317 .outdat_callback = usa2x_outdat_callback,
1318 .inack_callback = usa28_inack_callback,
1319 .outcont_callback = usa90_outcont_callback,
Lucy McCoy0ca12682007-05-18 12:10:41 -07001320 }, {
1321 /* msg_usa67 callbacks */
1322 .instat_callback = usa67_instat_callback,
1323 .glocont_callback = usa67_glocont_callback,
1324 .indat_callback = usa26_indat_callback,
1325 .outdat_callback = usa2x_outdat_callback,
1326 .inack_callback = usa26_inack_callback,
1327 .outcont_callback = usa26_outcont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328 }
1329};
1330
1331 /* Generic setup urbs function that uses
1332 data in device_details */
1333static void keyspan_setup_urbs(struct usb_serial *serial)
1334{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 struct keyspan_serial_private *s_priv;
1336 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 struct callbacks *cback;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 s_priv = usb_get_serial_data(serial);
1340 d_details = s_priv->device_details;
1341
Alan Coxdeb91682008-07-22 11:13:08 +01001342 /* Setup values for the various callback routines */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 cback = &keyspan_callbacks[d_details->msg_format];
1344
Alan Coxdeb91682008-07-22 11:13:08 +01001345 /* Allocate and set up urbs for each one that is in use,
1346 starting with instat endpoints */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 s_priv->instat_urb = keyspan_setup_urb
1348 (serial, d_details->instat_endpoint, USB_DIR_IN,
1349 serial, s_priv->instat_buf, INSTAT_BUFLEN,
1350 cback->instat_callback);
1351
Lucy McCoy0ca12682007-05-18 12:10:41 -07001352 s_priv->indat_urb = keyspan_setup_urb
1353 (serial, d_details->indat_endpoint, USB_DIR_IN,
1354 serial, s_priv->indat_buf, INDAT49W_BUFLEN,
1355 usa49wg_indat_callback);
1356
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 s_priv->glocont_urb = keyspan_setup_urb
1358 (serial, d_details->glocont_endpoint, USB_DIR_OUT,
1359 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
1360 cback->glocont_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361}
1362
1363/* usa19 function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001364static int keyspan_usa19_calc_baud(struct usb_serial_port *port,
1365 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 u8 *rate_low, u8 *prescaler, int portnum)
1367{
1368 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001369 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370 cnt; /* inverse of divisor (programmed into 8051) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001372 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373
Alan Coxdeb91682008-07-22 11:13:08 +01001374 /* prevent divide by zero... */
1375 b16 = baud_rate * 16L;
1376 if (b16 == 0)
1377 return KEYSPAN_INVALID_BAUD_RATE;
1378 /* Any "standard" rate over 57k6 is marginal on the USA-19
1379 as we run out of divisor resolution. */
1380 if (baud_rate > 57600)
1381 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382
Alan Coxdeb91682008-07-22 11:13:08 +01001383 /* calculate the divisor and the counter (its inverse) */
1384 div = baudclk / b16;
1385 if (div == 0)
1386 return KEYSPAN_INVALID_BAUD_RATE;
1387 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389
Alan Coxdeb91682008-07-22 11:13:08 +01001390 if (div > 0xffff)
1391 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392
Alan Coxdeb91682008-07-22 11:13:08 +01001393 /* return the counter values if non-null */
1394 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001396 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001398 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001399 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001400 __func__, baud_rate, *rate_hi, *rate_low);
1401 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402}
1403
1404/* usa19hs function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001405static int keyspan_usa19hs_calc_baud(struct usb_serial_port *port,
1406 u32 baud_rate, u32 baudclk, u8 *rate_hi,
1407 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408{
1409 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001410 div; /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001412 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413
Alan Coxdeb91682008-07-22 11:13:08 +01001414 /* prevent divide by zero... */
1415 b16 = baud_rate * 16L;
1416 if (b16 == 0)
1417 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418
Alan Coxdeb91682008-07-22 11:13:08 +01001419 /* calculate the divisor */
1420 div = baudclk / b16;
1421 if (div == 0)
1422 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423
Alan Coxdeb91682008-07-22 11:13:08 +01001424 if (div > 0xffff)
1425 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426
Alan Coxdeb91682008-07-22 11:13:08 +01001427 /* return the counter values if non-null */
1428 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001430
1431 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 *rate_hi = (u8) ((div >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001433
1434 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001435 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001436 __func__, baud_rate, *rate_hi, *rate_low);
1437
1438 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439}
1440
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001441static int keyspan_usa19w_calc_baud(struct usb_serial_port *port,
1442 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 u8 *rate_low, u8 *prescaler, int portnum)
1444{
1445 u32 b16, /* baud rate times 16 (actual rate used internally) */
1446 clk, /* clock with 13/8 prescaler */
Alan Coxdeb91682008-07-22 11:13:08 +01001447 div, /* divisor using 13/8 prescaler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 res, /* resulting baud rate using 13/8 prescaler */
1449 diff, /* error using 13/8 prescaler */
1450 smallest_diff;
1451 u8 best_prescaler;
1452 int i;
1453
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001454 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455
Alan Coxdeb91682008-07-22 11:13:08 +01001456 /* prevent divide by zero */
1457 b16 = baud_rate * 16L;
1458 if (b16 == 0)
1459 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460
Alan Coxdeb91682008-07-22 11:13:08 +01001461 /* Calculate prescaler by trying them all and looking
1462 for best fit */
1463
1464 /* start with largest possible difference */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 smallest_diff = 0xffffffff;
1466
1467 /* 0 is an invalid prescaler, used as a flag */
1468 best_prescaler = 0;
1469
Alan Coxdeb91682008-07-22 11:13:08 +01001470 for (i = 8; i <= 0xff; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 clk = (baudclk * 8) / (u32) i;
Alan Coxdeb91682008-07-22 11:13:08 +01001472
1473 div = clk / b16;
1474 if (div == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476
1477 res = clk / div;
Alan Coxdeb91682008-07-22 11:13:08 +01001478 diff = (res > b16) ? (res-b16) : (b16-res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479
Alan Coxdeb91682008-07-22 11:13:08 +01001480 if (diff < smallest_diff) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 best_prescaler = i;
1482 smallest_diff = diff;
1483 }
1484 }
1485
Alan Coxdeb91682008-07-22 11:13:08 +01001486 if (best_prescaler == 0)
1487 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488
1489 clk = (baudclk * 8) / (u32) best_prescaler;
1490 div = clk / b16;
1491
Alan Coxdeb91682008-07-22 11:13:08 +01001492 /* return the divisor and prescaler if non-null */
1493 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001495 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 *rate_hi = (u8) ((div >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 if (prescaler) {
1498 *prescaler = best_prescaler;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001499 /* dev_dbg(&port->dev, "%s - %d %d\n", __func__, *prescaler, div); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 }
Alan Coxdeb91682008-07-22 11:13:08 +01001501 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502}
1503
1504 /* USA-28 supports different maximum baud rates on each port */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001505static int keyspan_usa28_calc_baud(struct usb_serial_port *port,
1506 u32 baud_rate, u32 baudclk, u8 *rate_hi,
1507 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508{
1509 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001510 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 cnt; /* inverse of divisor (programmed into 8051) */
1512
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001513 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514
1515 /* prevent divide by zero */
Alan Coxdeb91682008-07-22 11:13:08 +01001516 b16 = baud_rate * 16L;
1517 if (b16 == 0)
1518 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519
Alan Coxdeb91682008-07-22 11:13:08 +01001520 /* calculate the divisor and the counter (its inverse) */
1521 div = KEYSPAN_USA28_BAUDCLK / b16;
1522 if (div == 0)
1523 return KEYSPAN_INVALID_BAUD_RATE;
1524 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526
Alan Coxdeb91682008-07-22 11:13:08 +01001527 /* check for out of range, based on portnum,
1528 and return result */
1529 if (portnum == 0) {
1530 if (div > 0xffff)
1531 return KEYSPAN_INVALID_BAUD_RATE;
1532 } else {
1533 if (portnum == 1) {
1534 if (div > 0xff)
1535 return KEYSPAN_INVALID_BAUD_RATE;
1536 } else
1537 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 }
1539
1540 /* return the counter values if not NULL
1541 (port 1 will ignore retHi) */
Alan Coxdeb91682008-07-22 11:13:08 +01001542 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001544 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001546 dev_dbg(&port->dev, "%s - %d OK.\n", __func__, baud_rate);
Alan Coxdeb91682008-07-22 11:13:08 +01001547 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548}
1549
1550static int keyspan_usa26_send_setup(struct usb_serial *serial,
1551 struct usb_serial_port *port,
1552 int reset_port)
1553{
Alan Coxdeb91682008-07-22 11:13:08 +01001554 struct keyspan_usa26_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555 struct keyspan_serial_private *s_priv;
1556 struct keyspan_port_private *p_priv;
1557 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 struct urb *this_urb;
1559 int device_port, err;
1560
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001561 dev_dbg(&port->dev, "%s reset=%d\n", __func__, reset_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562
1563 s_priv = usb_get_serial_data(serial);
1564 p_priv = usb_get_serial_port_data(port);
1565 d_details = s_priv->device_details;
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001566 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 this_urb = p_priv->outcont_urb;
1569
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570 /* Make sure we have an urb then send the message */
1571 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001572 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573 return -1;
1574 }
1575
Johan Hovold0cd782b2016-05-08 20:08:00 +02001576 dev_dbg(&port->dev, "%s - endpoint %x\n",
1577 __func__, usb_pipeendpoint(this_urb->pipe));
Rickard Strandqvistd5afce82014-05-16 17:39:13 +02001578
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001580 Don't overwrite resend for open/close condition. */
1581 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582 p_priv->resend_cont = reset_port + 1;
1583 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001584 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001586 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587 }
1588
Alan Coxdeb91682008-07-22 11:13:08 +01001589 memset(&msg, 0, sizeof(struct keyspan_usa26_portControlMessage));
1590
1591 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 if (p_priv->old_baud != p_priv->baud) {
1593 p_priv->old_baud = p_priv->baud;
1594 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001595 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1596 &msg.baudHi, &msg.baudLo, &msg.prescaler,
1597 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1598 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
1599 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600 msg.baudLo = 0;
1601 msg.baudHi = 125; /* Values for 9600 baud */
1602 msg.prescaler = 10;
1603 }
1604 msg.setPrescaler = 0xff;
1605 }
1606
Ben Minerds2b982ab2012-07-12 00:10:16 +10001607 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 switch (p_priv->cflag & CSIZE) {
1609 case CS5:
1610 msg.lcr |= USA_DATABITS_5;
1611 break;
1612 case CS6:
1613 msg.lcr |= USA_DATABITS_6;
1614 break;
1615 case CS7:
1616 msg.lcr |= USA_DATABITS_7;
1617 break;
1618 case CS8:
1619 msg.lcr |= USA_DATABITS_8;
1620 break;
1621 }
1622 if (p_priv->cflag & PARENB) {
1623 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10001624 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01001625 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 }
1627 msg.setLcr = 0xff;
1628
1629 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1630 msg.xonFlowControl = 0;
1631 msg.setFlowControl = 0xff;
1632 msg.forwardingLength = 16;
1633 msg.xonChar = 17;
1634 msg.xoffChar = 19;
1635
1636 /* Opening port */
1637 if (reset_port == 1) {
1638 msg._txOn = 1;
1639 msg._txOff = 0;
1640 msg.txFlush = 0;
1641 msg.txBreak = 0;
1642 msg.rxOn = 1;
1643 msg.rxOff = 0;
1644 msg.rxFlush = 1;
1645 msg.rxForward = 0;
1646 msg.returnStatus = 0;
1647 msg.resetDataToggle = 0xff;
1648 }
1649
1650 /* Closing port */
1651 else if (reset_port == 2) {
1652 msg._txOn = 0;
1653 msg._txOff = 1;
1654 msg.txFlush = 0;
1655 msg.txBreak = 0;
1656 msg.rxOn = 0;
1657 msg.rxOff = 1;
1658 msg.rxFlush = 1;
1659 msg.rxForward = 0;
1660 msg.returnStatus = 0;
1661 msg.resetDataToggle = 0;
1662 }
1663
1664 /* Sending intermediate configs */
1665 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001666 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667 msg._txOff = 0;
1668 msg.txFlush = 0;
1669 msg.txBreak = (p_priv->break_on);
1670 msg.rxOn = 0;
1671 msg.rxOff = 0;
1672 msg.rxFlush = 0;
1673 msg.rxForward = 0;
1674 msg.returnStatus = 0;
1675 msg.resetDataToggle = 0x0;
1676 }
1677
Alan Coxdeb91682008-07-22 11:13:08 +01001678 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679 msg.setTxTriState_setRts = 0xff;
1680 msg.txTriState_rts = p_priv->rts_state;
1681
1682 msg.setHskoa_setDtr = 0xff;
1683 msg.hskoa_dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01001684
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001686 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
1687
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688 /* send the data out the device on control endpoint */
1689 this_urb->transfer_buffer_length = sizeof(msg);
1690
Alan Coxdeb91682008-07-22 11:13:08 +01001691 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1692 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001693 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01001694 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695}
1696
1697static int keyspan_usa28_send_setup(struct usb_serial *serial,
1698 struct usb_serial_port *port,
1699 int reset_port)
1700{
Alan Coxdeb91682008-07-22 11:13:08 +01001701 struct keyspan_usa28_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 struct keyspan_serial_private *s_priv;
1703 struct keyspan_port_private *p_priv;
1704 const struct keyspan_device_details *d_details;
1705 struct urb *this_urb;
1706 int device_port, err;
1707
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 s_priv = usb_get_serial_data(serial);
1709 p_priv = usb_get_serial_port_data(port);
1710 d_details = s_priv->device_details;
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001711 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712
1713 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01001714 this_urb = p_priv->outcont_urb;
1715 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001716 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 return -1;
1718 }
1719
1720 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001721 Don't overwrite resend for open/close condition. */
1722 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723 p_priv->resend_cont = reset_port + 1;
1724 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001725 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001727 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 }
1729
Alan Coxdeb91682008-07-22 11:13:08 +01001730 memset(&msg, 0, sizeof(struct keyspan_usa28_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731
1732 msg.setBaudRate = 1;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001733 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1734 &msg.baudHi, &msg.baudLo, NULL,
1735 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1736 dev_dbg(&port->dev, "%s - Invalid baud rate requested %d.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001737 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738 msg.baudLo = 0xff;
1739 msg.baudHi = 0xb2; /* Values for 9600 baud */
1740 }
1741
1742 /* If parity is enabled, we must calculate it ourselves. */
1743 msg.parity = 0; /* XXX for now */
1744
1745 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1746 msg.xonFlowControl = 0;
1747
Alan Coxdeb91682008-07-22 11:13:08 +01001748 /* Do handshaking outputs, DTR is inverted relative to RTS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 msg.rts = p_priv->rts_state;
1750 msg.dtr = p_priv->dtr_state;
1751
1752 msg.forwardingLength = 16;
1753 msg.forwardMs = 10;
1754 msg.breakThreshold = 45;
1755 msg.xonChar = 17;
1756 msg.xoffChar = 19;
1757
1758 /*msg.returnStatus = 1;
1759 msg.resetDataToggle = 0xff;*/
1760 /* Opening port */
1761 if (reset_port == 1) {
1762 msg._txOn = 1;
1763 msg._txOff = 0;
1764 msg.txFlush = 0;
1765 msg.txForceXoff = 0;
1766 msg.txBreak = 0;
1767 msg.rxOn = 1;
1768 msg.rxOff = 0;
1769 msg.rxFlush = 1;
1770 msg.rxForward = 0;
1771 msg.returnStatus = 0;
1772 msg.resetDataToggle = 0xff;
1773 }
1774 /* Closing port */
1775 else if (reset_port == 2) {
1776 msg._txOn = 0;
1777 msg._txOff = 1;
1778 msg.txFlush = 0;
1779 msg.txForceXoff = 0;
1780 msg.txBreak = 0;
1781 msg.rxOn = 0;
1782 msg.rxOff = 1;
1783 msg.rxFlush = 1;
1784 msg.rxForward = 0;
1785 msg.returnStatus = 0;
1786 msg.resetDataToggle = 0;
1787 }
1788 /* Sending intermediate configs */
1789 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001790 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791 msg._txOff = 0;
1792 msg.txFlush = 0;
1793 msg.txForceXoff = 0;
1794 msg.txBreak = (p_priv->break_on);
1795 msg.rxOn = 0;
1796 msg.rxOff = 0;
1797 msg.rxFlush = 0;
1798 msg.rxForward = 0;
1799 msg.returnStatus = 0;
1800 msg.resetDataToggle = 0x0;
1801 }
1802
1803 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001804 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805
1806 /* send the data out the device on control endpoint */
1807 this_urb->transfer_buffer_length = sizeof(msg);
1808
Alan Coxdeb91682008-07-22 11:13:08 +01001809 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1810 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001811 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812
Alan Coxa5b6f602008-04-08 17:16:06 +01001813 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814}
1815
1816static int keyspan_usa49_send_setup(struct usb_serial *serial,
1817 struct usb_serial_port *port,
1818 int reset_port)
1819{
Lucy McCoy0ca12682007-05-18 12:10:41 -07001820 struct keyspan_usa49_portControlMessage msg;
1821 struct usb_ctrlrequest *dr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822 struct keyspan_serial_private *s_priv;
1823 struct keyspan_port_private *p_priv;
1824 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825 struct urb *this_urb;
1826 int err, device_port;
1827
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828 s_priv = usb_get_serial_data(serial);
1829 p_priv = usb_get_serial_port_data(port);
1830 d_details = s_priv->device_details;
1831
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 this_urb = s_priv->glocont_urb;
1833
Lucy McCoy0ca12682007-05-18 12:10:41 -07001834 /* Work out which port within the device is being setup */
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001835 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05301837 /* Make sure we have an urb then send the message */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 if (this_urb == NULL) {
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001839 dev_dbg(&port->dev, "%s - oops no urb for port.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840 return -1;
1841 }
1842
Johan Hovold0cd782b2016-05-08 20:08:00 +02001843 dev_dbg(&port->dev, "%s - endpoint %x (%d)\n",
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001844 __func__, usb_pipeendpoint(this_urb->pipe), device_port);
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05301845
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001847 Don't overwrite resend for open/close condition. */
1848 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 p_priv->resend_cont = reset_port + 1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001850
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001852 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001854 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 }
1856
Alan Coxdeb91682008-07-22 11:13:08 +01001857 memset(&msg, 0, sizeof(struct keyspan_usa49_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 msg.portNumber = device_port;
Alan Coxdeb91682008-07-22 11:13:08 +01001860
1861 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862 if (p_priv->old_baud != p_priv->baud) {
1863 p_priv->old_baud = p_priv->baud;
1864 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001865 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1866 &msg.baudHi, &msg.baudLo, &msg.prescaler,
1867 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1868 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
1869 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 msg.baudLo = 0;
1871 msg.baudHi = 125; /* Values for 9600 baud */
1872 msg.prescaler = 10;
1873 }
Alan Coxdeb91682008-07-22 11:13:08 +01001874 /* msg.setPrescaler = 0xff; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875 }
1876
Ben Minerds2b982ab2012-07-12 00:10:16 +10001877 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878 switch (p_priv->cflag & CSIZE) {
1879 case CS5:
1880 msg.lcr |= USA_DATABITS_5;
1881 break;
1882 case CS6:
1883 msg.lcr |= USA_DATABITS_6;
1884 break;
1885 case CS7:
1886 msg.lcr |= USA_DATABITS_7;
1887 break;
1888 case CS8:
1889 msg.lcr |= USA_DATABITS_8;
1890 break;
1891 }
1892 if (p_priv->cflag & PARENB) {
1893 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10001894 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01001895 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 }
1897 msg.setLcr = 0xff;
1898
1899 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1900 msg.xonFlowControl = 0;
1901 msg.setFlowControl = 0xff;
Alan Coxdeb91682008-07-22 11:13:08 +01001902
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 msg.forwardingLength = 16;
1904 msg.xonChar = 17;
1905 msg.xoffChar = 19;
1906
Alan Coxdeb91682008-07-22 11:13:08 +01001907 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908 if (reset_port == 1) {
1909 msg._txOn = 1;
1910 msg._txOff = 0;
1911 msg.txFlush = 0;
1912 msg.txBreak = 0;
1913 msg.rxOn = 1;
1914 msg.rxOff = 0;
1915 msg.rxFlush = 1;
1916 msg.rxForward = 0;
1917 msg.returnStatus = 0;
1918 msg.resetDataToggle = 0xff;
1919 msg.enablePort = 1;
1920 msg.disablePort = 0;
1921 }
1922 /* Closing port */
1923 else if (reset_port == 2) {
1924 msg._txOn = 0;
1925 msg._txOff = 1;
1926 msg.txFlush = 0;
1927 msg.txBreak = 0;
1928 msg.rxOn = 0;
1929 msg.rxOff = 1;
1930 msg.rxFlush = 1;
1931 msg.rxForward = 0;
1932 msg.returnStatus = 0;
1933 msg.resetDataToggle = 0;
1934 msg.enablePort = 0;
1935 msg.disablePort = 1;
1936 }
1937 /* Sending intermediate configs */
1938 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001939 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940 msg._txOff = 0;
1941 msg.txFlush = 0;
1942 msg.txBreak = (p_priv->break_on);
1943 msg.rxOn = 0;
1944 msg.rxOff = 0;
1945 msg.rxFlush = 0;
1946 msg.rxForward = 0;
1947 msg.returnStatus = 0;
1948 msg.resetDataToggle = 0x0;
1949 msg.enablePort = 0;
1950 msg.disablePort = 0;
1951 }
1952
Alan Coxdeb91682008-07-22 11:13:08 +01001953 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954 msg.setRts = 0xff;
1955 msg.rts = p_priv->rts_state;
1956
1957 msg.setDtr = 0xff;
1958 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01001959
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960 p_priv->resend_cont = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961
Alan Coxdeb91682008-07-22 11:13:08 +01001962 /* if the device is a 49wg, we send control message on usb
1963 control EP 0 */
Lucy McCoy0ca12682007-05-18 12:10:41 -07001964
1965 if (d_details->product_id == keyspan_usa49wg_product_id) {
1966 dr = (void *)(s_priv->ctrl_buf);
1967 dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT;
Mathieu OTHACEHE64248392016-02-04 19:01:30 +01001968 dr->bRequest = 0xB0; /* 49wg control message */
Lucy McCoy0ca12682007-05-18 12:10:41 -07001969 dr->wValue = 0;
1970 dr->wIndex = 0;
1971 dr->wLength = cpu_to_le16(sizeof(msg));
1972
Alan Coxdeb91682008-07-22 11:13:08 +01001973 memcpy(s_priv->glocont_buf, &msg, sizeof(msg));
Lucy McCoy0ca12682007-05-18 12:10:41 -07001974
Alan Coxdeb91682008-07-22 11:13:08 +01001975 usb_fill_control_urb(this_urb, serial->dev,
1976 usb_sndctrlpipe(serial->dev, 0),
1977 (unsigned char *)dr, s_priv->glocont_buf,
1978 sizeof(msg), usa49_glocont_callback, serial);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001979
1980 } else {
1981 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Alan Coxdeb91682008-07-22 11:13:08 +01001982
Lucy McCoy0ca12682007-05-18 12:10:41 -07001983 /* send the data out the device on control endpoint */
1984 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001985 }
Alan Coxdeb91682008-07-22 11:13:08 +01001986 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1987 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001988 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989
Alan Coxa5b6f602008-04-08 17:16:06 +01001990 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991}
1992
1993static int keyspan_usa90_send_setup(struct usb_serial *serial,
1994 struct usb_serial_port *port,
1995 int reset_port)
1996{
Alan Coxdeb91682008-07-22 11:13:08 +01001997 struct keyspan_usa90_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 struct keyspan_serial_private *s_priv;
1999 struct keyspan_port_private *p_priv;
2000 const struct keyspan_device_details *d_details;
2001 struct urb *this_urb;
2002 int err;
2003 u8 prescaler;
2004
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 s_priv = usb_get_serial_data(serial);
2006 p_priv = usb_get_serial_port_data(port);
2007 d_details = s_priv->device_details;
2008
2009 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01002010 this_urb = p_priv->outcont_urb;
2011 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002012 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013 return -1;
2014 }
2015
2016 /* Save reset port val for resend.
2017 Don't overwrite resend for open/close condition. */
2018 if ((reset_port + 1) > p_priv->resend_cont)
2019 p_priv->resend_cont = reset_port + 1;
2020 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002021 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002023 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024 }
2025
Alan Coxdeb91682008-07-22 11:13:08 +01002026 memset(&msg, 0, sizeof(struct keyspan_usa90_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027
Alan Coxdeb91682008-07-22 11:13:08 +01002028 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029 if (p_priv->old_baud != p_priv->baud) {
2030 p_priv->old_baud = p_priv->baud;
2031 msg.setClocking = 0x01;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002032 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2033 &msg.baudHi, &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) {
2034 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2035 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 p_priv->baud = 9600;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002037 d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038 &msg.baudHi, &msg.baudLo, &prescaler, 0);
2039 }
2040 msg.setRxMode = 1;
2041 msg.setTxMode = 1;
2042 }
2043
2044 /* modes must always be correctly specified */
Alan Coxdeb91682008-07-22 11:13:08 +01002045 if (p_priv->baud > 57600) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046 msg.rxMode = RXMODE_DMA;
2047 msg.txMode = TXMODE_DMA;
Alan Coxdeb91682008-07-22 11:13:08 +01002048 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049 msg.rxMode = RXMODE_BYHAND;
2050 msg.txMode = TXMODE_BYHAND;
2051 }
2052
Ben Minerds2b982ab2012-07-12 00:10:16 +10002053 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054 switch (p_priv->cflag & CSIZE) {
2055 case CS5:
2056 msg.lcr |= USA_DATABITS_5;
2057 break;
2058 case CS6:
2059 msg.lcr |= USA_DATABITS_6;
2060 break;
2061 case CS7:
2062 msg.lcr |= USA_DATABITS_7;
2063 break;
2064 case CS8:
2065 msg.lcr |= USA_DATABITS_8;
2066 break;
2067 }
2068 if (p_priv->cflag & PARENB) {
2069 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002070 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002071 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072 }
2073 if (p_priv->old_cflag != p_priv->cflag) {
2074 p_priv->old_cflag = p_priv->cflag;
2075 msg.setLcr = 0x01;
2076 }
2077
2078 if (p_priv->flow_control == flow_cts)
2079 msg.txFlowControl = TXFLOW_CTS;
2080 msg.setTxFlowControl = 0x01;
2081 msg.setRxFlowControl = 0x01;
Alan Coxdeb91682008-07-22 11:13:08 +01002082
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083 msg.rxForwardingLength = 16;
Alan Coxdeb91682008-07-22 11:13:08 +01002084 msg.rxForwardingTimeout = 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085 msg.txAckSetting = 0;
2086 msg.xonChar = 17;
2087 msg.xoffChar = 19;
2088
Alan Coxdeb91682008-07-22 11:13:08 +01002089 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090 if (reset_port == 1) {
2091 msg.portEnabled = 1;
2092 msg.rxFlush = 1;
2093 msg.txBreak = (p_priv->break_on);
2094 }
2095 /* Closing port */
Alan Coxdeb91682008-07-22 11:13:08 +01002096 else if (reset_port == 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097 msg.portEnabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098 /* Sending intermediate configs */
2099 else {
Alan Stern1f871582010-02-17 10:05:47 -05002100 msg.portEnabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101 msg.txBreak = (p_priv->break_on);
2102 }
2103
Alan Coxdeb91682008-07-22 11:13:08 +01002104 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 msg.setRts = 0x01;
2106 msg.rts = p_priv->rts_state;
2107
2108 msg.setDtr = 0x01;
2109 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002110
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01002112 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2113
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 /* send the data out the device on control endpoint */
2115 this_urb->transfer_buffer_length = sizeof(msg);
2116
Alan Coxdeb91682008-07-22 11:13:08 +01002117 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2118 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002119 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002120 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121}
2122
Lucy McCoy0ca12682007-05-18 12:10:41 -07002123static int keyspan_usa67_send_setup(struct usb_serial *serial,
2124 struct usb_serial_port *port,
2125 int reset_port)
2126{
2127 struct keyspan_usa67_portControlMessage msg;
2128 struct keyspan_serial_private *s_priv;
2129 struct keyspan_port_private *p_priv;
2130 const struct keyspan_device_details *d_details;
2131 struct urb *this_urb;
2132 int err, device_port;
2133
Lucy McCoy0ca12682007-05-18 12:10:41 -07002134 s_priv = usb_get_serial_data(serial);
2135 p_priv = usb_get_serial_port_data(port);
2136 d_details = s_priv->device_details;
2137
2138 this_urb = s_priv->glocont_urb;
2139
2140 /* Work out which port within the device is being setup */
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002141 device_port = port->port_number;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002142
2143 /* Make sure we have an urb then send the message */
2144 if (this_urb == NULL) {
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002145 dev_dbg(&port->dev, "%s - oops no urb for port.\n", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002146 return -1;
2147 }
2148
2149 /* Save reset port val for resend.
2150 Don't overwrite resend for open/close condition. */
2151 if ((reset_port + 1) > p_priv->resend_cont)
2152 p_priv->resend_cont = reset_port + 1;
2153 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002154 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002155 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002156 return -1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002157 }
2158
2159 memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
2160
2161 msg.port = device_port;
2162
2163 /* Only set baud rate if it's changed */
2164 if (p_priv->old_baud != p_priv->baud) {
2165 p_priv->old_baud = p_priv->baud;
2166 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002167 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2168 &msg.baudHi, &msg.baudLo, &msg.prescaler,
2169 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2170 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2171 __func__, p_priv->baud);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002172 msg.baudLo = 0;
2173 msg.baudHi = 125; /* Values for 9600 baud */
2174 msg.prescaler = 10;
2175 }
2176 msg.setPrescaler = 0xff;
2177 }
2178
2179 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
2180 switch (p_priv->cflag & CSIZE) {
2181 case CS5:
2182 msg.lcr |= USA_DATABITS_5;
2183 break;
2184 case CS6:
2185 msg.lcr |= USA_DATABITS_6;
2186 break;
2187 case CS7:
2188 msg.lcr |= USA_DATABITS_7;
2189 break;
2190 case CS8:
2191 msg.lcr |= USA_DATABITS_8;
2192 break;
2193 }
2194 if (p_priv->cflag & PARENB) {
2195 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002196 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002197 USA_PARITY_ODD : USA_PARITY_EVEN;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002198 }
2199 msg.setLcr = 0xff;
2200
2201 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2202 msg.xonFlowControl = 0;
2203 msg.setFlowControl = 0xff;
2204 msg.forwardingLength = 16;
2205 msg.xonChar = 17;
2206 msg.xoffChar = 19;
2207
2208 if (reset_port == 1) {
2209 /* Opening port */
2210 msg._txOn = 1;
2211 msg._txOff = 0;
2212 msg.txFlush = 0;
2213 msg.txBreak = 0;
2214 msg.rxOn = 1;
2215 msg.rxOff = 0;
2216 msg.rxFlush = 1;
2217 msg.rxForward = 0;
2218 msg.returnStatus = 0;
2219 msg.resetDataToggle = 0xff;
2220 } else if (reset_port == 2) {
2221 /* Closing port */
2222 msg._txOn = 0;
2223 msg._txOff = 1;
2224 msg.txFlush = 0;
2225 msg.txBreak = 0;
2226 msg.rxOn = 0;
2227 msg.rxOff = 1;
2228 msg.rxFlush = 1;
2229 msg.rxForward = 0;
2230 msg.returnStatus = 0;
2231 msg.resetDataToggle = 0;
2232 } else {
2233 /* Sending intermediate configs */
Alan Coxdeb91682008-07-22 11:13:08 +01002234 msg._txOn = (!p_priv->break_on);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002235 msg._txOff = 0;
2236 msg.txFlush = 0;
2237 msg.txBreak = (p_priv->break_on);
2238 msg.rxOn = 0;
2239 msg.rxOff = 0;
2240 msg.rxFlush = 0;
2241 msg.rxForward = 0;
2242 msg.returnStatus = 0;
2243 msg.resetDataToggle = 0x0;
2244 }
2245
2246 /* Do handshaking outputs */
2247 msg.setTxTriState_setRts = 0xff;
2248 msg.txTriState_rts = p_priv->rts_state;
2249
2250 msg.setHskoa_setDtr = 0xff;
2251 msg.hskoa_dtr = p_priv->dtr_state;
2252
2253 p_priv->resend_cont = 0;
2254
2255 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2256
2257 /* send the data out the device on control endpoint */
2258 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002259
2260 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2261 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002262 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002263 return 0;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002264}
2265
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
2267{
2268 struct usb_serial *serial = port->serial;
2269 struct keyspan_serial_private *s_priv;
2270 const struct keyspan_device_details *d_details;
2271
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 s_priv = usb_get_serial_data(serial);
2273 d_details = s_priv->device_details;
2274
2275 switch (d_details->msg_format) {
2276 case msg_usa26:
2277 keyspan_usa26_send_setup(serial, port, reset_port);
2278 break;
2279 case msg_usa28:
2280 keyspan_usa28_send_setup(serial, port, reset_port);
2281 break;
2282 case msg_usa49:
2283 keyspan_usa49_send_setup(serial, port, reset_port);
2284 break;
2285 case msg_usa90:
2286 keyspan_usa90_send_setup(serial, port, reset_port);
2287 break;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002288 case msg_usa67:
2289 keyspan_usa67_send_setup(serial, port, reset_port);
2290 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291 }
2292}
2293
2294
2295/* Gets called by the "real" driver (ie once firmware is loaded
2296 and renumeration has taken place. */
Alan Coxdeb91682008-07-22 11:13:08 +01002297static int keyspan_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298{
2299 int i, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301 const struct keyspan_device_details *d_details;
2302
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
Alan Coxdeb91682008-07-22 11:13:08 +01002304 if (d_details->product_id ==
2305 le16_to_cpu(serial->dev->descriptor.idProduct))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 break;
2307 if (d_details == NULL) {
Alan Coxdeb91682008-07-22 11:13:08 +01002308 dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
2309 __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
Johan Hovoldff8a43c2013-08-13 13:27:35 +02002310 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311 }
2312
2313 /* Setup private data for serial driver */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01002314 s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
Johan Hovold10c642d2013-12-29 19:22:56 +01002315 if (!s_priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317
Johan Hovold2fcd1c92013-08-13 13:27:36 +02002318 s_priv->instat_buf = kzalloc(INSTAT_BUFLEN, GFP_KERNEL);
2319 if (!s_priv->instat_buf)
2320 goto err_instat_buf;
2321
2322 s_priv->indat_buf = kzalloc(INDAT49W_BUFLEN, GFP_KERNEL);
2323 if (!s_priv->indat_buf)
2324 goto err_indat_buf;
2325
2326 s_priv->glocont_buf = kzalloc(GLOCONT_BUFLEN, GFP_KERNEL);
2327 if (!s_priv->glocont_buf)
2328 goto err_glocont_buf;
2329
2330 s_priv->ctrl_buf = kzalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
2331 if (!s_priv->ctrl_buf)
2332 goto err_ctrl_buf;
2333
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334 s_priv->device_details = d_details;
2335 usb_set_serial_data(serial, s_priv);
2336
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 keyspan_setup_urbs(serial);
2338
Lucy McCoy0ca12682007-05-18 12:10:41 -07002339 if (s_priv->instat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002340 err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
2341 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002342 dev_dbg(&serial->dev->dev, "%s - submit instat urb failed %d\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002343 }
2344 if (s_priv->indat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002345 err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
2346 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002347 dev_dbg(&serial->dev->dev, "%s - submit indat urb failed %d\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 }
Alan Coxdeb91682008-07-22 11:13:08 +01002349
Alan Coxa5b6f602008-04-08 17:16:06 +01002350 return 0;
Johan Hovold2fcd1c92013-08-13 13:27:36 +02002351
2352err_ctrl_buf:
2353 kfree(s_priv->glocont_buf);
2354err_glocont_buf:
2355 kfree(s_priv->indat_buf);
2356err_indat_buf:
2357 kfree(s_priv->instat_buf);
2358err_instat_buf:
2359 kfree(s_priv);
2360
2361 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362}
2363
Alan Sternf9c99bb2009-06-02 11:53:55 -04002364static void keyspan_disconnect(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002366 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368 s_priv = usb_get_serial_data(serial);
2369
Johan Hovold61924502016-05-08 20:07:59 +02002370 usb_kill_urb(s_priv->instat_urb);
2371 usb_kill_urb(s_priv->glocont_urb);
2372 usb_kill_urb(s_priv->indat_urb);
Alan Sternf9c99bb2009-06-02 11:53:55 -04002373}
2374
2375static void keyspan_release(struct usb_serial *serial)
2376{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002377 struct keyspan_serial_private *s_priv;
Alan Sternf9c99bb2009-06-02 11:53:55 -04002378
Alan Sternf9c99bb2009-06-02 11:53:55 -04002379 s_priv = usb_get_serial_data(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380
Johan Hovold35be1a72016-05-08 20:07:58 +02002381 /* Make sure to unlink the URBs submitted in attach. */
2382 usb_kill_urb(s_priv->instat_urb);
2383 usb_kill_urb(s_priv->indat_urb);
2384
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002385 usb_free_urb(s_priv->instat_urb);
2386 usb_free_urb(s_priv->indat_urb);
2387 usb_free_urb(s_priv->glocont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388
Johan Hovold2fcd1c92013-08-13 13:27:36 +02002389 kfree(s_priv->ctrl_buf);
2390 kfree(s_priv->glocont_buf);
2391 kfree(s_priv->indat_buf);
2392 kfree(s_priv->instat_buf);
2393
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002394 kfree(s_priv);
2395}
2396
2397static int keyspan_port_probe(struct usb_serial_port *port)
2398{
2399 struct usb_serial *serial = port->serial;
Bjørn Morkf0e3e352012-11-10 10:13:42 +01002400 struct keyspan_serial_private *s_priv;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002401 struct keyspan_port_private *p_priv;
2402 const struct keyspan_device_details *d_details;
2403 struct callbacks *cback;
2404 int endp;
2405 int port_num;
2406 int i;
2407
2408 s_priv = usb_get_serial_data(serial);
2409 d_details = s_priv->device_details;
2410
2411 p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL);
2412 if (!p_priv)
2413 return -ENOMEM;
2414
Johan Hovoldbad41a52013-08-13 13:27:37 +02002415 for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i) {
2416 p_priv->in_buffer[i] = kzalloc(IN_BUFLEN, GFP_KERNEL);
2417 if (!p_priv->in_buffer[i])
2418 goto err_in_buffer;
2419 }
2420
2421 for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i) {
2422 p_priv->out_buffer[i] = kzalloc(OUT_BUFLEN, GFP_KERNEL);
2423 if (!p_priv->out_buffer[i])
2424 goto err_out_buffer;
2425 }
2426
2427 p_priv->inack_buffer = kzalloc(INACK_BUFLEN, GFP_KERNEL);
2428 if (!p_priv->inack_buffer)
2429 goto err_inack_buffer;
2430
2431 p_priv->outcont_buffer = kzalloc(OUTCONT_BUFLEN, GFP_KERNEL);
2432 if (!p_priv->outcont_buffer)
2433 goto err_outcont_buffer;
2434
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002435 p_priv->device_details = d_details;
2436
2437 /* Setup values for the various callback routines */
2438 cback = &keyspan_callbacks[d_details->msg_format];
2439
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002440 port_num = port->port_number;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002441
2442 /* Do indat endpoints first, once for each flip */
2443 endp = d_details->indat_endpoints[port_num];
2444 for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) {
2445 p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp,
2446 USB_DIR_IN, port,
Johan Hovoldbad41a52013-08-13 13:27:37 +02002447 p_priv->in_buffer[i],
2448 IN_BUFLEN,
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002449 cback->indat_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450 }
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002451 /* outdat endpoints also have flip */
2452 endp = d_details->outdat_endpoints[port_num];
2453 for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) {
2454 p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp,
2455 USB_DIR_OUT, port,
Johan Hovoldbad41a52013-08-13 13:27:37 +02002456 p_priv->out_buffer[i],
2457 OUT_BUFLEN,
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002458 cback->outdat_callback);
2459 }
2460 /* inack endpoint */
2461 p_priv->inack_urb = keyspan_setup_urb(serial,
2462 d_details->inack_endpoints[port_num],
2463 USB_DIR_IN, port,
Johan Hovoldbad41a52013-08-13 13:27:37 +02002464 p_priv->inack_buffer,
2465 INACK_BUFLEN,
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002466 cback->inack_callback);
2467 /* outcont endpoint */
2468 p_priv->outcont_urb = keyspan_setup_urb(serial,
2469 d_details->outcont_endpoints[port_num],
2470 USB_DIR_OUT, port,
Johan Hovoldbad41a52013-08-13 13:27:37 +02002471 p_priv->outcont_buffer,
2472 OUTCONT_BUFLEN,
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002473 cback->outcont_callback);
2474
2475 usb_set_serial_port_data(port, p_priv);
2476
2477 return 0;
Johan Hovoldbad41a52013-08-13 13:27:37 +02002478
2479err_outcont_buffer:
2480 kfree(p_priv->inack_buffer);
2481err_inack_buffer:
2482 for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i)
2483 kfree(p_priv->out_buffer[i]);
2484err_out_buffer:
2485 for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i)
2486 kfree(p_priv->in_buffer[i]);
2487err_in_buffer:
2488 kfree(p_priv);
2489
2490 return -ENOMEM;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002491}
2492
2493static int keyspan_port_remove(struct usb_serial_port *port)
2494{
2495 struct keyspan_port_private *p_priv;
2496 int i;
2497
2498 p_priv = usb_get_serial_port_data(port);
2499
Johan Hovold61924502016-05-08 20:07:59 +02002500 usb_kill_urb(p_priv->inack_urb);
2501 usb_kill_urb(p_priv->outcont_urb);
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002502 for (i = 0; i < 2; i++) {
Johan Hovold61924502016-05-08 20:07:59 +02002503 usb_kill_urb(p_priv->in_urbs[i]);
2504 usb_kill_urb(p_priv->out_urbs[i]);
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002505 }
2506
2507 usb_free_urb(p_priv->inack_urb);
2508 usb_free_urb(p_priv->outcont_urb);
2509 for (i = 0; i < 2; i++) {
2510 usb_free_urb(p_priv->in_urbs[i]);
2511 usb_free_urb(p_priv->out_urbs[i]);
2512 }
2513
Johan Hovoldbad41a52013-08-13 13:27:37 +02002514 kfree(p_priv->outcont_buffer);
2515 kfree(p_priv->inack_buffer);
2516 for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i)
2517 kfree(p_priv->out_buffer[i]);
2518 for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i)
2519 kfree(p_priv->in_buffer[i]);
2520
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002521 kfree(p_priv);
2522
2523 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524}
2525
Alan Coxdeb91682008-07-22 11:13:08 +01002526MODULE_AUTHOR(DRIVER_AUTHOR);
2527MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528MODULE_LICENSE("GPL");
2529
David Woodhouse2971c572008-05-30 14:04:03 +03002530MODULE_FIRMWARE("keyspan/usa28.fw");
2531MODULE_FIRMWARE("keyspan/usa28x.fw");
2532MODULE_FIRMWARE("keyspan/usa28xa.fw");
2533MODULE_FIRMWARE("keyspan/usa28xb.fw");
2534MODULE_FIRMWARE("keyspan/usa19.fw");
2535MODULE_FIRMWARE("keyspan/usa19qi.fw");
2536MODULE_FIRMWARE("keyspan/mpr.fw");
2537MODULE_FIRMWARE("keyspan/usa19qw.fw");
2538MODULE_FIRMWARE("keyspan/usa18x.fw");
2539MODULE_FIRMWARE("keyspan/usa19w.fw");
2540MODULE_FIRMWARE("keyspan/usa49w.fw");
2541MODULE_FIRMWARE("keyspan/usa49wlc.fw");