blob: 7179b0c5f8148e183219b2a71c34d6d7bf7494a6 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 Keyspan USB to Serial Converter driver
Alan Coxdeb91682008-07-22 11:13:08 +01003
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 (C) Copyright (C) 2000-2001 Hugh Blemings <hugh@blemings.org>
5 (C) Copyright (C) 2002 Greg Kroah-Hartman <greg@kroah.com>
Alan Coxdeb91682008-07-22 11:13:08 +01006
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
Justin P. Mattock631dd1a2010-10-18 11:03:14 +020012 See http://blemings.org/hugh/keyspan.html for more information.
Alan Coxdeb91682008-07-22 11:13:08 +010013
Linus Torvalds1da177e2005-04-16 15:20:36 -070014 Code in this driver inspired by and in a number of places taken
15 from Brian Warner's original Keyspan-PDA driver.
16
17 This driver has been put together with the support of Innosys, Inc.
18 and Keyspan, Inc the manufacturers of the Keyspan USB-serial products.
19 Thanks Guys :)
Alan Coxdeb91682008-07-22 11:13:08 +010020
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 Thanks to Paulus for miscellaneous tidy ups, some largish chunks
22 of much nicer and/or completely new code and (perhaps most uniquely)
23 having the patience to sit down and explain why and where he'd changed
Alan Coxdeb91682008-07-22 11:13:08 +010024 stuff.
25
26 Tip 'o the hat to IBM (and previously Linuxcare :) for supporting
Linus Torvalds1da177e2005-04-16 15:20:36 -070027 staff in their work on open source projects.
Linus Torvalds1da177e2005-04-16 15:20:36 -070028*/
29
30
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/kernel.h>
32#include <linux/jiffies.h>
33#include <linux/errno.h>
34#include <linux/init.h>
35#include <linux/slab.h>
36#include <linux/tty.h>
37#include <linux/tty_driver.h>
38#include <linux/tty_flip.h>
39#include <linux/module.h>
40#include <linux/spinlock.h>
Alan Coxdeb91682008-07-22 11:13:08 +010041#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <linux/usb.h>
Greg Kroah-Hartmana9698882006-07-11 21:22:58 -070043#include <linux/usb/serial.h>
Rene Buergelcc183e22012-09-18 09:00:41 +020044#include <linux/usb/ezusb.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include "keyspan.h"
46
Linus Torvalds1da177e2005-04-16 15:20:36 -070047/*
48 * Version Information
49 */
Lucy McCoy0ca12682007-05-18 12:10:41 -070050#define DRIVER_VERSION "v1.1.5"
Linus Torvalds1da177e2005-04-16 15:20:36 -070051#define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu"
52#define DRIVER_DESC "Keyspan USB to Serial Converter Driver"
53
54#define INSTAT_BUFLEN 32
55#define GLOCONT_BUFLEN 64
Lucy McCoy0ca12682007-05-18 12:10:41 -070056#define INDAT49W_BUFLEN 512
Linus Torvalds1da177e2005-04-16 15:20:36 -070057
58 /* Per device and per port private data */
59struct keyspan_serial_private {
60 const struct keyspan_device_details *device_details;
61
62 struct urb *instat_urb;
63 char instat_buf[INSTAT_BUFLEN];
64
Alan Coxdeb91682008-07-22 11:13:08 +010065 /* added to support 49wg, where data from all 4 ports comes in
66 on 1 EP and high-speed supported */
Lucy McCoy0ca12682007-05-18 12:10:41 -070067 struct urb *indat_urb;
68 char indat_buf[INDAT49W_BUFLEN];
69
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 /* XXX this one probably will need a lock */
71 struct urb *glocont_urb;
72 char glocont_buf[GLOCONT_BUFLEN];
Alan Coxdeb91682008-07-22 11:13:08 +010073 char ctrl_buf[8]; /* for EP0 control message */
Linus Torvalds1da177e2005-04-16 15:20:36 -070074};
75
76struct keyspan_port_private {
77 /* Keep track of which input & output endpoints to use */
78 int in_flip;
79 int out_flip;
80
81 /* Keep duplicate of device details in each port
82 structure as well - simplifies some of the
83 callback functions etc. */
84 const struct keyspan_device_details *device_details;
85
86 /* Input endpoints and buffer for this port */
87 struct urb *in_urbs[2];
88 char in_buffer[2][64];
89 /* Output endpoints and buffer for this port */
90 struct urb *out_urbs[2];
91 char out_buffer[2][64];
92
93 /* Input ack endpoint */
94 struct urb *inack_urb;
95 char inack_buffer[1];
96
97 /* Output control endpoint */
98 struct urb *outcont_urb;
99 char outcont_buffer[64];
100
101 /* Settings for the port */
102 int baud;
103 int old_baud;
104 unsigned int cflag;
105 unsigned int old_cflag;
106 enum {flow_none, flow_cts, flow_xon} flow_control;
107 int rts_state; /* Handshaking pins (outputs) */
108 int dtr_state;
109 int cts_state; /* Handshaking pins (inputs) */
110 int dsr_state;
111 int dcd_state;
112 int ri_state;
113 int break_on;
114
115 unsigned long tx_start_time[2];
116 int resend_cont; /* need to resend control packet */
117};
118
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119/* Include Keyspan message headers. All current Keyspan Adapters
Lucy McCoy0ca12682007-05-18 12:10:41 -0700120 make use of one of five message formats which are referred
Alan Coxdeb91682008-07-22 11:13:08 +0100121 to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and
122 within this driver. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123#include "keyspan_usa26msg.h"
124#include "keyspan_usa28msg.h"
125#include "keyspan_usa49msg.h"
126#include "keyspan_usa90msg.h"
Lucy McCoy0ca12682007-05-18 12:10:41 -0700127#include "keyspan_usa67msg.h"
Alan Coxdeb91682008-07-22 11:13:08 +0100128
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -0700130module_usb_serial_driver(serial_drivers, keyspan_ids_combined);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131
Alan Cox95da3102008-07-22 11:09:07 +0100132static void keyspan_break_ctl(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133{
Alan Cox95da3102008-07-22 11:09:07 +0100134 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135 struct keyspan_port_private *p_priv;
136
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 p_priv = usb_get_serial_port_data(port);
138
139 if (break_state == -1)
140 p_priv->break_on = 1;
141 else
142 p_priv->break_on = 0;
143
144 keyspan_send_setup(port, 0);
145}
146
147
Alan Coxdeb91682008-07-22 11:13:08 +0100148static void keyspan_set_termios(struct tty_struct *tty,
Alan Cox95da3102008-07-22 11:09:07 +0100149 struct usb_serial_port *port, struct ktermios *old_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150{
151 int baud_rate, device_port;
152 struct keyspan_port_private *p_priv;
153 const struct keyspan_device_details *d_details;
154 unsigned int cflag;
155
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156 p_priv = usb_get_serial_port_data(port);
157 d_details = p_priv->device_details;
Alan Coxadc8d742012-07-14 15:31:47 +0100158 cflag = tty->termios.c_cflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 device_port = port->number - port->serial->minor;
160
161 /* Baud rate calculation takes baud rate as an integer
162 so other rates can be generated if desired. */
Alan Cox74240b02007-10-18 01:24:20 -0700163 baud_rate = tty_get_baud_rate(tty);
Alan Coxdeb91682008-07-22 11:13:08 +0100164 /* If no match or invalid, don't change */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700165 if (d_details->calculate_baud_rate(port, baud_rate, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
167 /* FIXME - more to do here to ensure rate changes cleanly */
Alan Cox74240b02007-10-18 01:24:20 -0700168 /* FIXME - calcuate exact rate from divisor ? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 p_priv->baud = baud_rate;
Alan Cox74240b02007-10-18 01:24:20 -0700170 } else
171 baud_rate = tty_termios_baud_rate(old_termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172
Alan Cox74240b02007-10-18 01:24:20 -0700173 tty_encode_baud_rate(tty, baud_rate, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 /* set CTS/RTS handshake etc. */
175 p_priv->cflag = cflag;
Ben Minerds2b982ab2012-07-12 00:10:16 +1000176 p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177
Alan Cox74240b02007-10-18 01:24:20 -0700178 /* Mark/Space not supported */
Alan Coxadc8d742012-07-14 15:31:47 +0100179 tty->termios.c_cflag &= ~CMSPAR;
Alan Cox74240b02007-10-18 01:24:20 -0700180
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 keyspan_send_setup(port, 0);
182}
183
Alan Cox60b33c12011-02-14 16:26:14 +0000184static int keyspan_tiocmget(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185{
Alan Cox95da3102008-07-22 11:09:07 +0100186 struct usb_serial_port *port = tty->driver_data;
187 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 unsigned int value;
Alan Coxdeb91682008-07-22 11:13:08 +0100189
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 value = ((p_priv->rts_state) ? TIOCM_RTS : 0) |
191 ((p_priv->dtr_state) ? TIOCM_DTR : 0) |
192 ((p_priv->cts_state) ? TIOCM_CTS : 0) |
193 ((p_priv->dsr_state) ? TIOCM_DSR : 0) |
194 ((p_priv->dcd_state) ? TIOCM_CAR : 0) |
Alan Coxdeb91682008-07-22 11:13:08 +0100195 ((p_priv->ri_state) ? TIOCM_RNG : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196
197 return value;
198}
199
Alan Cox20b9d172011-02-14 16:26:50 +0000200static int keyspan_tiocmset(struct tty_struct *tty,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201 unsigned int set, unsigned int clear)
202{
Alan Cox95da3102008-07-22 11:09:07 +0100203 struct usb_serial_port *port = tty->driver_data;
204 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100205
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 if (set & TIOCM_RTS)
207 p_priv->rts_state = 1;
208 if (set & TIOCM_DTR)
209 p_priv->dtr_state = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 if (clear & TIOCM_RTS)
211 p_priv->rts_state = 0;
212 if (clear & TIOCM_DTR)
213 p_priv->dtr_state = 0;
214 keyspan_send_setup(port, 0);
215 return 0;
216}
217
Alan Cox95da3102008-07-22 11:09:07 +0100218/* Write function is similar for the four protocols used
219 with only a minor change for usa90 (usa19hs) required */
220static int keyspan_write(struct tty_struct *tty,
221 struct usb_serial_port *port, const unsigned char *buf, int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222{
223 struct keyspan_port_private *p_priv;
224 const struct keyspan_device_details *d_details;
225 int flip;
226 int left, todo;
227 struct urb *this_urb;
Alan Coxdeb91682008-07-22 11:13:08 +0100228 int err, maxDataLen, dataOffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229
230 p_priv = usb_get_serial_port_data(port);
231 d_details = p_priv->device_details;
232
233 if (d_details->msg_format == msg_usa90) {
Alan Coxdeb91682008-07-22 11:13:08 +0100234 maxDataLen = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 dataOffset = 0;
236 } else {
237 maxDataLen = 63;
238 dataOffset = 1;
239 }
Alan Coxdeb91682008-07-22 11:13:08 +0100240
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700241 dev_dbg(&port->dev, "%s - for port %d (%d chars), flip=%d\n",
242 __func__, port->number, count, p_priv->out_flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243
244 for (left = count; left > 0; left -= todo) {
245 todo = left;
246 if (todo > maxDataLen)
247 todo = maxDataLen;
248
249 flip = p_priv->out_flip;
Alan Coxdeb91682008-07-22 11:13:08 +0100250
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 /* Check we have a valid urb/endpoint before we use it... */
Alan Coxdeb91682008-07-22 11:13:08 +0100252 this_urb = p_priv->out_urbs[flip];
253 if (this_urb == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 /* no bulk out, so return 0 bytes written */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700255 dev_dbg(&port->dev, "%s - no output urb :(\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 return count;
257 }
258
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700259 dev_dbg(&port->dev, "%s - endpoint %d flip %d\n",
Alan Coxdeb91682008-07-22 11:13:08 +0100260 __func__, usb_pipeendpoint(this_urb->pipe), flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261
262 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +0100263 if (time_before(jiffies,
264 p_priv->tx_start_time[flip] + 10 * HZ))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 usb_unlink_urb(this_urb);
267 break;
268 }
269
Alan Coxdeb91682008-07-22 11:13:08 +0100270 /* First byte in buffer is "last flag" (except for usa19hx)
271 - unused so for now so set to zero */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 ((char *)this_urb->transfer_buffer)[0] = 0;
273
Alan Coxdeb91682008-07-22 11:13:08 +0100274 memcpy(this_urb->transfer_buffer + dataOffset, buf, todo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 buf += todo;
276
277 /* send the data out the bulk port */
278 this_urb->transfer_buffer_length = todo + dataOffset;
279
Alan Coxdeb91682008-07-22 11:13:08 +0100280 err = usb_submit_urb(this_urb, GFP_ATOMIC);
281 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700282 dev_dbg(&port->dev, "usb_submit_urb(write bulk) failed (%d)\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 p_priv->tx_start_time[flip] = jiffies;
284
285 /* Flip for next time if usa26 or usa28 interface
286 (not used on usa49) */
287 p_priv->out_flip = (flip + 1) & d_details->outdat_endp_flip;
288 }
289
290 return count - left;
291}
292
David Howells7d12e782006-10-05 14:55:46 +0100293static void usa26_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294{
295 int i, err;
296 int endpoint;
297 struct usb_serial_port *port;
298 struct tty_struct *tty;
299 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700300 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 endpoint = usb_pipeendpoint(urb->pipe);
303
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700304 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700305 dev_dbg(&urb->dev->dev,"%s - nonzero status: %x on endpoint %d.\n",
306 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 return;
308 }
309
Ming Leicdc97792008-02-24 18:41:47 +0800310 port = urb->context;
Alan Cox4a90f092008-10-13 10:39:46 +0100311 tty = tty_port_tty_get(&port->port);
Alan Coxa5569a52008-01-21 17:18:24 -0800312 if (tty && urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313 /* 0x80 bit is error flag */
314 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100315 /* no errors on individual bytes, only
316 possible overrun err */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 if (data[0] & RXERROR_OVERRUN)
Alan Coxdeb91682008-07-22 11:13:08 +0100318 err = TTY_OVERRUN;
319 else
320 err = 0;
321 for (i = 1; i < urb->actual_length ; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 tty_insert_flip_char(tty, data[i], err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 } else {
324 /* some bytes had errors, every byte has status */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700325 dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 for (i = 0; i + 1 < urb->actual_length; i += 2) {
327 int stat = data[i], flag = 0;
328 if (stat & RXERROR_OVERRUN)
329 flag |= TTY_OVERRUN;
330 if (stat & RXERROR_FRAMING)
331 flag |= TTY_FRAME;
332 if (stat & RXERROR_PARITY)
333 flag |= TTY_PARITY;
334 /* XXX should handle break (0x10) */
335 tty_insert_flip_char(tty, data[i+1], flag);
336 }
337 }
338 tty_flip_buffer_push(tty);
339 }
Alan Cox4a90f092008-10-13 10:39:46 +0100340 tty_kref_put(tty);
Alan Coxdeb91682008-07-22 11:13:08 +0100341
342 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500343 err = usb_submit_urb(urb, GFP_ATOMIC);
344 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700345 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346}
347
Alan Coxdeb91682008-07-22 11:13:08 +0100348/* Outdat handling is common for all devices */
David Howells7d12e782006-10-05 14:55:46 +0100349static void usa2x_outdat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350{
351 struct usb_serial_port *port;
352 struct keyspan_port_private *p_priv;
353
Ming Leicdc97792008-02-24 18:41:47 +0800354 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 p_priv = usb_get_serial_port_data(port);
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700356 dev_dbg(&port->dev, "%s - urb %d\n", __func__, urb == p_priv->out_urbs[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357
Alan Stern1f871582010-02-17 10:05:47 -0500358 usb_serial_port_softint(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359}
360
David Howells7d12e782006-10-05 14:55:46 +0100361static void usa26_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363}
364
David Howells7d12e782006-10-05 14:55:46 +0100365static void usa26_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366{
367 struct usb_serial_port *port;
368 struct keyspan_port_private *p_priv;
369
Ming Leicdc97792008-02-24 18:41:47 +0800370 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 p_priv = usb_get_serial_port_data(port);
372
373 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700374 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100375 keyspan_usa26_send_setup(port->serial, port,
376 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 }
378}
379
David Howells7d12e782006-10-05 14:55:46 +0100380static void usa26_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381{
382 unsigned char *data = urb->transfer_buffer;
383 struct keyspan_usa26_portStatusMessage *msg;
384 struct usb_serial *serial;
385 struct usb_serial_port *port;
386 struct keyspan_port_private *p_priv;
Alan Cox4a90f092008-10-13 10:39:46 +0100387 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700389 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390
Ming Leicdc97792008-02-24 18:41:47 +0800391 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700393 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700394 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 return;
396 }
397 if (urb->actual_length != 9) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700398 dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 goto exit;
400 }
401
402 msg = (struct keyspan_usa26_portStatusMessage *)data;
403
404#if 0
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700405 dev_dbg(&urb->dev->dev,
406 "%s - port status: port %d cts %d dcd %d dsr %d ri %d toff %d txoff %d rxen %d cr %d",
407 __func__, msg->port, msg->hskia_cts, msg->gpia_dcd, msg->dsr,
408 msg->ri, msg->_txOff, msg->_txXoff, msg->rxEnabled,
409 msg->controlResponse);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410#endif
411
412 /* Now do something useful with the data */
413
414
Alan Coxdeb91682008-07-22 11:13:08 +0100415 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700417 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 goto exit;
419 }
420 port = serial->port[msg->port];
421 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100422
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 /* Update handshaking pin state information */
424 old_dcd_state = p_priv->dcd_state;
425 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
426 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
427 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
428 p_priv->ri_state = ((msg->ri) ? 1 : 0);
429
Alan Cox4a90f092008-10-13 10:39:46 +0100430 if (old_dcd_state != p_priv->dcd_state) {
431 tty = tty_port_tty_get(&port->port);
432 if (tty && !C_CLOCAL(tty))
433 tty_hangup(tty);
434 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 }
Alan Coxdeb91682008-07-22 11:13:08 +0100436
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100438 err = usb_submit_urb(urb, GFP_ATOMIC);
439 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700440 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441exit: ;
442}
443
David Howells7d12e782006-10-05 14:55:46 +0100444static void usa26_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446}
447
448
David Howells7d12e782006-10-05 14:55:46 +0100449static void usa28_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450{
Alan Coxf035a8a2008-07-22 11:13:32 +0100451 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 struct usb_serial_port *port;
453 struct tty_struct *tty;
454 unsigned char *data;
455 struct keyspan_port_private *p_priv;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700456 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457
Ming Leicdc97792008-02-24 18:41:47 +0800458 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 p_priv = usb_get_serial_port_data(port);
460 data = urb->transfer_buffer;
461
462 if (urb != p_priv->in_urbs[p_priv->in_flip])
463 return;
464
465 do {
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700466 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700467 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
468 __func__, status, usb_pipeendpoint(urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 return;
470 }
471
Ming Leicdc97792008-02-24 18:41:47 +0800472 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 p_priv = usb_get_serial_port_data(port);
474 data = urb->transfer_buffer;
475
Ben Minerds40adac82012-07-12 00:10:17 +1000476 tty = tty_port_tty_get(&port->port);
Alan Cox4a90f092008-10-13 10:39:46 +0100477 if (tty && urb->actual_length) {
Alan Coxf035a8a2008-07-22 11:13:32 +0100478 tty_insert_flip_string(tty, data, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479 tty_flip_buffer_push(tty);
480 }
Alan Cox4a90f092008-10-13 10:39:46 +0100481 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482
483 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500484 err = usb_submit_urb(urb, GFP_ATOMIC);
485 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700486 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n",
Alan Stern1f871582010-02-17 10:05:47 -0500487 __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 p_priv->in_flip ^= 1;
489
490 urb = p_priv->in_urbs[p_priv->in_flip];
491 } while (urb->status != -EINPROGRESS);
492}
493
David Howells7d12e782006-10-05 14:55:46 +0100494static void usa28_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496}
497
David Howells7d12e782006-10-05 14:55:46 +0100498static void usa28_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499{
500 struct usb_serial_port *port;
501 struct keyspan_port_private *p_priv;
502
Ming Leicdc97792008-02-24 18:41:47 +0800503 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 p_priv = usb_get_serial_port_data(port);
505
506 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700507 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100508 keyspan_usa28_send_setup(port->serial, port,
509 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 }
511}
512
David Howells7d12e782006-10-05 14:55:46 +0100513static void usa28_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514{
515 int err;
516 unsigned char *data = urb->transfer_buffer;
517 struct keyspan_usa28_portStatusMessage *msg;
518 struct usb_serial *serial;
519 struct usb_serial_port *port;
520 struct keyspan_port_private *p_priv;
Alan Cox4a90f092008-10-13 10:39:46 +0100521 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700523 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524
Ming Leicdc97792008-02-24 18:41:47 +0800525 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700527 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700528 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 return;
530 }
531
532 if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700533 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 goto exit;
535 }
536
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700537 /*
538 dev_dbg(&urb->dev->dev,
539 "%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__,
540 data[0], data[1], data[2], data[3], data[4], data[5],
541 data[6], data[7], data[8], data[9], data[10], data[11]);
542 */
Alan Coxdeb91682008-07-22 11:13:08 +0100543
544 /* Now do something useful with the data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 msg = (struct keyspan_usa28_portStatusMessage *)data;
546
Alan Coxdeb91682008-07-22 11:13:08 +0100547 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700549 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 goto exit;
551 }
552 port = serial->port[msg->port];
553 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100554
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 /* Update handshaking pin state information */
556 old_dcd_state = p_priv->dcd_state;
557 p_priv->cts_state = ((msg->cts) ? 1 : 0);
558 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
559 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
560 p_priv->ri_state = ((msg->ri) ? 1 : 0);
561
Ben Minerdsddc04ae2012-07-12 00:10:18 +1000562 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
Alan Cox4a90f092008-10-13 10:39:46 +0100563 tty = tty_port_tty_get(&port->port);
Ben Minerds878b5fd2012-07-12 00:10:19 +1000564 if (tty && !C_CLOCAL(tty))
Alan Cox4a90f092008-10-13 10:39:46 +0100565 tty_hangup(tty);
566 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 }
568
569 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100570 err = usb_submit_urb(urb, GFP_ATOMIC);
571 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700572 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573exit: ;
574}
575
David Howells7d12e782006-10-05 14:55:46 +0100576static void usa28_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578}
579
580
David Howells7d12e782006-10-05 14:55:46 +0100581static void usa49_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582{
583 struct usb_serial *serial;
584 struct usb_serial_port *port;
585 struct keyspan_port_private *p_priv;
586 int i;
587
Ming Leicdc97792008-02-24 18:41:47 +0800588 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 for (i = 0; i < serial->num_ports; ++i) {
590 port = serial->port[i];
591 p_priv = usb_get_serial_port_data(port);
592
593 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700594 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100595 keyspan_usa49_send_setup(serial, port,
596 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 break;
598 }
599 }
600}
601
602 /* This is actually called glostat in the Keyspan
603 doco */
David Howells7d12e782006-10-05 14:55:46 +0100604static void usa49_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605{
606 int err;
607 unsigned char *data = urb->transfer_buffer;
608 struct keyspan_usa49_portStatusMessage *msg;
609 struct usb_serial *serial;
610 struct usb_serial_port *port;
611 struct keyspan_port_private *p_priv;
612 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700613 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614
Ming Leicdc97792008-02-24 18:41:47 +0800615 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700617 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700618 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 return;
620 }
621
Alan Coxdeb91682008-07-22 11:13:08 +0100622 if (urb->actual_length !=
623 sizeof(struct keyspan_usa49_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700624 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 goto exit;
626 }
627
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700628 /*
629 dev_dbg(&urb->dev->dev, "%s: %x %x %x %x %x %x %x %x %x %x %x",
630 __func__, data[0], data[1], data[2], data[3], data[4],
631 data[5], data[6], data[7], data[8], data[9], data[10]);
632 */
Alan Coxdeb91682008-07-22 11:13:08 +0100633
634 /* Now do something useful with the data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 msg = (struct keyspan_usa49_portStatusMessage *)data;
636
Alan Coxdeb91682008-07-22 11:13:08 +0100637 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 if (msg->portNumber >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700639 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
640 __func__, msg->portNumber);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 goto exit;
642 }
643 port = serial->port[msg->portNumber];
644 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100645
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 /* Update handshaking pin state information */
647 old_dcd_state = p_priv->dcd_state;
648 p_priv->cts_state = ((msg->cts) ? 1 : 0);
649 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
650 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
651 p_priv->ri_state = ((msg->ri) ? 1 : 0);
652
Alan Cox4a90f092008-10-13 10:39:46 +0100653 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
654 struct tty_struct *tty = tty_port_tty_get(&port->port);
655 if (tty && !C_CLOCAL(tty))
656 tty_hangup(tty);
657 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 }
659
Alan Coxdeb91682008-07-22 11:13:08 +0100660 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100661 err = usb_submit_urb(urb, GFP_ATOMIC);
662 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700663 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664exit: ;
665}
666
David Howells7d12e782006-10-05 14:55:46 +0100667static void usa49_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669}
670
David Howells7d12e782006-10-05 14:55:46 +0100671static void usa49_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672{
673 int i, err;
674 int endpoint;
675 struct usb_serial_port *port;
676 struct tty_struct *tty;
677 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700678 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 endpoint = usb_pipeendpoint(urb->pipe);
681
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700682 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700683 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
684 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 return;
686 }
687
Ming Leicdc97792008-02-24 18:41:47 +0800688 port = urb->context;
Alan Cox4a90f092008-10-13 10:39:46 +0100689 tty = tty_port_tty_get(&port->port);
Alan Cox3004e532008-01-03 16:59:04 +0000690 if (tty && urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 /* 0x80 bit is error flag */
692 if ((data[0] & 0x80) == 0) {
693 /* no error on any byte */
Alan Coxf035a8a2008-07-22 11:13:32 +0100694 tty_insert_flip_string(tty, data + 1,
695 urb->actual_length - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 } else {
697 /* some bytes had errors, every byte has status */
698 for (i = 0; i + 1 < urb->actual_length; i += 2) {
699 int stat = data[i], flag = 0;
700 if (stat & RXERROR_OVERRUN)
701 flag |= TTY_OVERRUN;
702 if (stat & RXERROR_FRAMING)
703 flag |= TTY_FRAME;
704 if (stat & RXERROR_PARITY)
705 flag |= TTY_PARITY;
706 /* XXX should handle break (0x10) */
707 tty_insert_flip_char(tty, data[i+1], flag);
708 }
709 }
710 tty_flip_buffer_push(tty);
711 }
Alan Cox4a90f092008-10-13 10:39:46 +0100712 tty_kref_put(tty);
Alan Coxdeb91682008-07-22 11:13:08 +0100713
714 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500715 err = usb_submit_urb(urb, GFP_ATOMIC);
716 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700717 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718}
719
Lucy McCoy0ca12682007-05-18 12:10:41 -0700720static void usa49wg_indat_callback(struct urb *urb)
721{
722 int i, len, x, err;
723 struct usb_serial *serial;
724 struct usb_serial_port *port;
725 struct tty_struct *tty;
726 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700727 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700728
Lucy McCoy0ca12682007-05-18 12:10:41 -0700729 serial = urb->context;
730
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700731 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700732 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700733 return;
734 }
735
736 /* inbound data is in the form P#, len, status, data */
737 i = 0;
738 len = 0;
739
740 if (urb->actual_length) {
741 while (i < urb->actual_length) {
742
743 /* Check port number from message*/
744 if (data[i] >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700745 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800746 __func__, data[i]);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700747 return;
748 }
749 port = serial->port[data[i++]];
Alan Cox4a90f092008-10-13 10:39:46 +0100750 tty = tty_port_tty_get(&port->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700751 len = data[i++];
752
753 /* 0x80 bit is error flag */
754 if ((data[i] & 0x80) == 0) {
755 /* no error on any byte */
756 i++;
757 for (x = 1; x < len ; ++x)
Alan Stern1f871582010-02-17 10:05:47 -0500758 tty_insert_flip_char(tty, data[i++], 0);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700759 } else {
760 /*
761 * some bytes had errors, every byte has status
762 */
763 for (x = 0; x + 1 < len; x += 2) {
764 int stat = data[i], flag = 0;
765 if (stat & RXERROR_OVERRUN)
766 flag |= TTY_OVERRUN;
767 if (stat & RXERROR_FRAMING)
768 flag |= TTY_FRAME;
769 if (stat & RXERROR_PARITY)
770 flag |= TTY_PARITY;
771 /* XXX should handle break (0x10) */
Alan Stern1f871582010-02-17 10:05:47 -0500772 tty_insert_flip_char(tty,
Lucy McCoy0ca12682007-05-18 12:10:41 -0700773 data[i+1], flag);
774 i += 2;
775 }
776 }
Alan Stern1f871582010-02-17 10:05:47 -0500777 tty_flip_buffer_push(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100778 tty_kref_put(tty);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700779 }
780 }
781
782 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700783 err = usb_submit_urb(urb, GFP_ATOMIC);
784 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700785 dev_dbg(&urb->dev->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700786}
787
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788/* not used, usa-49 doesn't have per-port control endpoints */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700789static void usa49_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791}
792
Lucy McCoy0ca12682007-05-18 12:10:41 -0700793static void usa90_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794{
795 int i, err;
796 int endpoint;
797 struct usb_serial_port *port;
798 struct keyspan_port_private *p_priv;
799 struct tty_struct *tty;
800 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700801 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 endpoint = usb_pipeendpoint(urb->pipe);
804
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700805 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700806 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800807 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 return;
809 }
810
Ming Leicdc97792008-02-24 18:41:47 +0800811 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 p_priv = usb_get_serial_port_data(port);
813
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 if (urb->actual_length) {
Alan Cox4a90f092008-10-13 10:39:46 +0100815 tty = tty_port_tty_get(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 /* if current mode is DMA, looks like usa28 format
Alan Coxdeb91682008-07-22 11:13:08 +0100817 otherwise looks like usa26 data format */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818
Alan Coxf035a8a2008-07-22 11:13:32 +0100819 if (p_priv->baud > 57600)
820 tty_insert_flip_string(tty, data, urb->actual_length);
821 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 /* 0x80 bit is error flag */
823 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100824 /* no errors on individual bytes, only
825 possible overrun err*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 if (data[0] & RXERROR_OVERRUN)
Alan Coxdeb91682008-07-22 11:13:08 +0100827 err = TTY_OVERRUN;
828 else
829 err = 0;
830 for (i = 1; i < urb->actual_length ; ++i)
831 tty_insert_flip_char(tty, data[i],
832 err);
833 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 /* some bytes had errors, every byte has status */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700835 dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 for (i = 0; i + 1 < urb->actual_length; i += 2) {
837 int stat = data[i], flag = 0;
838 if (stat & RXERROR_OVERRUN)
839 flag |= TTY_OVERRUN;
840 if (stat & RXERROR_FRAMING)
841 flag |= TTY_FRAME;
842 if (stat & RXERROR_PARITY)
843 flag |= TTY_PARITY;
844 /* XXX should handle break (0x10) */
Alan Coxdeb91682008-07-22 11:13:08 +0100845 tty_insert_flip_char(tty, data[i+1],
846 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 }
848 }
849 }
850 tty_flip_buffer_push(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100851 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 }
Alan Coxdeb91682008-07-22 11:13:08 +0100853
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500855 err = usb_submit_urb(urb, GFP_ATOMIC);
856 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700857 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858}
859
860
David Howells7d12e782006-10-05 14:55:46 +0100861static void usa90_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862{
863 unsigned char *data = urb->transfer_buffer;
864 struct keyspan_usa90_portStatusMessage *msg;
865 struct usb_serial *serial;
866 struct usb_serial_port *port;
867 struct keyspan_port_private *p_priv;
Alan Cox4a90f092008-10-13 10:39:46 +0100868 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700870 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871
Ming Leicdc97792008-02-24 18:41:47 +0800872 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700874 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700875 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 return;
877 }
878 if (urb->actual_length < 14) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700879 dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 goto exit;
881 }
882
883 msg = (struct keyspan_usa90_portStatusMessage *)data;
884
885 /* Now do something useful with the data */
886
887 port = serial->port[0];
888 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100889
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 /* Update handshaking pin state information */
891 old_dcd_state = p_priv->dcd_state;
892 p_priv->cts_state = ((msg->cts) ? 1 : 0);
893 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
894 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
895 p_priv->ri_state = ((msg->ri) ? 1 : 0);
896
Alan Cox4a90f092008-10-13 10:39:46 +0100897 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
898 tty = tty_port_tty_get(&port->port);
899 if (tty && !C_CLOCAL(tty))
900 tty_hangup(tty);
901 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 }
Alan Coxdeb91682008-07-22 11:13:08 +0100903
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100905 err = usb_submit_urb(urb, GFP_ATOMIC);
906 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700907 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908exit:
909 ;
910}
911
David Howells7d12e782006-10-05 14:55:46 +0100912static void usa90_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913{
914 struct usb_serial_port *port;
915 struct keyspan_port_private *p_priv;
916
Ming Leicdc97792008-02-24 18:41:47 +0800917 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 p_priv = usb_get_serial_port_data(port);
919
920 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700921 dev_dbg(&urb->dev->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100922 keyspan_usa90_send_setup(port->serial, port,
923 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 }
925}
926
Lucy McCoy0ca12682007-05-18 12:10:41 -0700927/* Status messages from the 28xg */
928static void usa67_instat_callback(struct urb *urb)
929{
930 int err;
931 unsigned char *data = urb->transfer_buffer;
932 struct keyspan_usa67_portStatusMessage *msg;
933 struct usb_serial *serial;
934 struct usb_serial_port *port;
935 struct keyspan_port_private *p_priv;
936 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700937 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700938
Lucy McCoy0ca12682007-05-18 12:10:41 -0700939 serial = urb->context;
940
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700941 if (status) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700942 dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700943 return;
944 }
945
Alan Coxdeb91682008-07-22 11:13:08 +0100946 if (urb->actual_length !=
947 sizeof(struct keyspan_usa67_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700948 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700949 return;
950 }
951
952
953 /* Now do something useful with the data */
954 msg = (struct keyspan_usa67_portStatusMessage *)data;
955
956 /* Check port number from message and retrieve private data */
957 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700958 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700959 return;
960 }
961
962 port = serial->port[msg->port];
963 p_priv = usb_get_serial_port_data(port);
964
965 /* Update handshaking pin state information */
966 old_dcd_state = p_priv->dcd_state;
967 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
968 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
969
Alan Cox4a90f092008-10-13 10:39:46 +0100970 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
971 struct tty_struct *tty = tty_port_tty_get(&port->port);
972 if (tty && !C_CLOCAL(tty))
973 tty_hangup(tty);
974 tty_kref_put(tty);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700975 }
976
977 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700978 err = usb_submit_urb(urb, GFP_ATOMIC);
979 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700980 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700981}
982
983static void usa67_glocont_callback(struct urb *urb)
984{
985 struct usb_serial *serial;
986 struct usb_serial_port *port;
987 struct keyspan_port_private *p_priv;
988 int i;
989
Lucy McCoy0ca12682007-05-18 12:10:41 -0700990 serial = urb->context;
991 for (i = 0; i < serial->num_ports; ++i) {
992 port = serial->port[i];
993 p_priv = usb_get_serial_port_data(port);
994
995 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700996 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700997 keyspan_usa67_send_setup(serial, port,
998 p_priv->resend_cont - 1);
999 break;
1000 }
1001 }
1002}
1003
Alan Cox95da3102008-07-22 11:09:07 +01001004static int keyspan_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005{
Alan Cox95da3102008-07-22 11:09:07 +01001006 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 struct keyspan_port_private *p_priv;
1008 const struct keyspan_device_details *d_details;
1009 int flip;
1010 int data_len;
1011 struct urb *this_urb;
1012
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 p_priv = usb_get_serial_port_data(port);
1014 d_details = p_priv->device_details;
1015
Alan Coxa5b6f602008-04-08 17:16:06 +01001016 /* FIXME: locking */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 if (d_details->msg_format == msg_usa90)
Alan Coxdeb91682008-07-22 11:13:08 +01001018 data_len = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 else
1020 data_len = 63;
1021
1022 flip = p_priv->out_flip;
1023
1024 /* Check both endpoints to see if any are available. */
Alan Coxdeb91682008-07-22 11:13:08 +01001025 this_urb = p_priv->out_urbs[flip];
1026 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001028 return data_len;
1029 flip = (flip + 1) & d_details->outdat_endp_flip;
1030 this_urb = p_priv->out_urbs[flip];
1031 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001033 return data_len;
1034 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 }
Alan Coxa5b6f602008-04-08 17:16:06 +01001036 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037}
1038
1039
Alan Coxa509a7e2009-09-19 13:13:26 -07001040static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041{
Andrew Mortonf78ba152007-11-28 16:21:54 -08001042 struct keyspan_port_private *p_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 const struct keyspan_device_details *d_details;
1044 int i, err;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001045 int baud_rate, device_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 struct urb *urb;
Alan Cox95da3102008-07-22 11:09:07 +01001047 unsigned int cflag = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 p_priv = usb_get_serial_port_data(port);
1050 d_details = p_priv->device_details;
Borislav Petkov7eea4362007-11-14 17:00:39 -08001051
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 /* Set some sane defaults */
1053 p_priv->rts_state = 1;
1054 p_priv->dtr_state = 1;
1055 p_priv->baud = 9600;
1056
1057 /* force baud and lcr to be set on open */
1058 p_priv->old_baud = 0;
1059 p_priv->old_cflag = 0;
1060
1061 p_priv->out_flip = 0;
1062 p_priv->in_flip = 0;
1063
1064 /* Reset low level data toggle and start reading from endpoints */
1065 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001066 urb = p_priv->in_urbs[i];
1067 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
Alan Coxdeb91682008-07-22 11:13:08 +01001070 /* make sure endpoint data toggle is synchronized
1071 with the device */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 usb_clear_halt(urb->dev, urb->pipe);
Alan Coxdeb91682008-07-22 11:13:08 +01001073 err = usb_submit_urb(urb, GFP_KERNEL);
1074 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001075 dev_dbg(&port->dev, "%s - submit urb %d failed (%d)\n", __func__, i, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 }
1077
1078 /* Reset low level data toggle on out endpoints */
1079 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001080 urb = p_priv->out_urbs[i];
1081 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 continue;
Alan Coxdeb91682008-07-22 11:13:08 +01001083 /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
1084 usb_pipeout(urb->pipe), 0); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 }
1086
Andrew Mortonf78ba152007-11-28 16:21:54 -08001087 /* get the terminal config for the setup message now so we don't
1088 * need to send 2 of them */
1089
Andrew Mortonf78ba152007-11-28 16:21:54 -08001090 device_port = port->number - port->serial->minor;
Alan Cox95da3102008-07-22 11:09:07 +01001091 if (tty) {
Alan Coxadc8d742012-07-14 15:31:47 +01001092 cflag = tty->termios.c_cflag;
Alan Cox95da3102008-07-22 11:09:07 +01001093 /* Baud rate calculation takes baud rate as an integer
1094 so other rates can be generated if desired. */
1095 baud_rate = tty_get_baud_rate(tty);
1096 /* If no match or invalid, leave as default */
1097 if (baud_rate >= 0
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001098 && d_details->calculate_baud_rate(port, baud_rate, d_details->baudclk,
Alan Cox95da3102008-07-22 11:09:07 +01001099 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
1100 p_priv->baud = baud_rate;
1101 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001102 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001103 /* set CTS/RTS handshake etc. */
1104 p_priv->cflag = cflag;
Ben Minerds2b982ab2012-07-12 00:10:16 +10001105 p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001106
1107 keyspan_send_setup(port, 1);
Alan Coxdeb91682008-07-22 11:13:08 +01001108 /* mdelay(100); */
1109 /* keyspan_set_termios(port, NULL); */
Andrew Mortonf78ba152007-11-28 16:21:54 -08001110
Alan Coxa5b6f602008-04-08 17:16:06 +01001111 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112}
1113
1114static inline void stop_urb(struct urb *urb)
1115{
Greg Kroah-Hartman242cf672005-07-29 16:11:07 -04001116 if (urb && urb->status == -EINPROGRESS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 usb_kill_urb(urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118}
1119
Alan Cox335f8512009-06-11 12:26:29 +01001120static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
1121{
1122 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
1123
1124 p_priv->rts_state = on;
1125 p_priv->dtr_state = on;
1126 keyspan_send_setup(port, 0);
1127}
1128
1129static void keyspan_close(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130{
1131 int i;
1132 struct usb_serial *serial = port->serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 struct keyspan_port_private *p_priv;
1134
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +01001136
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 p_priv->rts_state = 0;
1138 p_priv->dtr_state = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001139
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 if (serial->dev) {
1141 keyspan_send_setup(port, 2);
1142 /* pilot-xfer seems to work best with this delay */
1143 mdelay(100);
Alan Coxdeb91682008-07-22 11:13:08 +01001144 /* keyspan_set_termios(port, NULL); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 }
1146
1147 /*while (p_priv->outcont_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001148 dev_dbg(&port->dev, "%s - urb in progress\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 }*/
1150
1151 p_priv->out_flip = 0;
1152 p_priv->in_flip = 0;
1153
1154 if (serial->dev) {
1155 /* Stop reading/writing urbs */
1156 stop_urb(p_priv->inack_urb);
1157 /* stop_urb(p_priv->outcont_urb); */
1158 for (i = 0; i < 2; i++) {
1159 stop_urb(p_priv->in_urbs[i]);
1160 stop_urb(p_priv->out_urbs[i]);
1161 }
1162 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163}
1164
Alan Coxdeb91682008-07-22 11:13:08 +01001165/* download the firmware to a pre-renumeration device */
1166static int keyspan_fake_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167{
Rene Buergel8d733e22012-09-18 09:02:01 +02001168 char *fw_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001170 dev_dbg(&serial->dev->dev, "Keyspan startup version %04x product %04x\n",
1171 le16_to_cpu(serial->dev->descriptor.bcdDevice),
1172 le16_to_cpu(serial->dev->descriptor.idProduct));
Alan Coxdeb91682008-07-22 11:13:08 +01001173
1174 if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000)
1175 != 0x8000) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001176 dev_dbg(&serial->dev->dev, "Firmware already loaded. Quitting.\n");
Alan Coxdeb91682008-07-22 11:13:08 +01001177 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 }
1179
1180 /* Select firmware image on the basis of idProduct */
1181 switch (le16_to_cpu(serial->dev->descriptor.idProduct)) {
1182 case keyspan_usa28_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001183 fw_name = "keyspan/usa28.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 break;
1185
1186 case keyspan_usa28x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001187 fw_name = "keyspan/usa28x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 break;
1189
1190 case keyspan_usa28xa_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001191 fw_name = "keyspan/usa28xa.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 break;
1193
1194 case keyspan_usa28xb_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001195 fw_name = "keyspan/usa28xb.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 break;
1197
1198 case keyspan_usa19_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001199 fw_name = "keyspan/usa19.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001201
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 case keyspan_usa19qi_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001203 fw_name = "keyspan/usa19qi.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001205
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 case keyspan_mpr_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001207 fw_name = "keyspan/mpr.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 break;
1209
1210 case keyspan_usa19qw_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001211 fw_name = "keyspan/usa19qw.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001213
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 case keyspan_usa18x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001215 fw_name = "keyspan/usa18x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001217
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 case keyspan_usa19w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001219 fw_name = "keyspan/usa19w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001221
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 case keyspan_usa49w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001223 fw_name = "keyspan/usa49w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 break;
1225
1226 case keyspan_usa49wlc_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001227 fw_name = "keyspan/usa49wlc.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 break;
1229
1230 default:
David Woodhouse2971c572008-05-30 14:04:03 +03001231 dev_err(&serial->dev->dev, "Unknown product ID (%04x)\n",
1232 le16_to_cpu(serial->dev->descriptor.idProduct));
1233 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 }
1235
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001236 dev_dbg(&serial->dev->dev, "Uploading Keyspan %s firmware.\n", fw_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237
Rene Buergel8d733e22012-09-18 09:02:01 +02001238 if (ezusb_fx1_ihex_firmware_download(serial->dev, fw_name) < 0) {
1239 dev_err(&serial->dev->dev, "failed to load firmware \"%s\"\n",
1240 fw_name);
1241 return -ENOENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 }
1243
Rene Buergel8d733e22012-09-18 09:02:01 +02001244 /* after downloading firmware Renumeration will occur in a
1245 moment and the new device will bind to the real driver */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246
1247 /* we don't want this device to have a driver assigned to it. */
Alan Coxdeb91682008-07-22 11:13:08 +01001248 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249}
1250
1251/* Helper functions used by keyspan_setup_urbs */
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001252static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *serial,
1253 int endpoint)
1254{
1255 struct usb_host_interface *iface_desc;
1256 struct usb_endpoint_descriptor *ep;
1257 int i;
1258
1259 iface_desc = serial->interface->cur_altsetting;
1260 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1261 ep = &iface_desc->endpoint[i].desc;
1262 if (ep->bEndpointAddress == endpoint)
1263 return ep;
1264 }
1265 dev_warn(&serial->interface->dev, "found no endpoint descriptor for "
1266 "endpoint %x\n", endpoint);
1267 return NULL;
1268}
1269
Alan Coxdeb91682008-07-22 11:13:08 +01001270static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 int dir, void *ctx, char *buf, int len,
David Howells7d12e782006-10-05 14:55:46 +01001272 void (*callback)(struct urb *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273{
1274 struct urb *urb;
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001275 struct usb_endpoint_descriptor const *ep_desc;
1276 char const *ep_type_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277
1278 if (endpoint == -1)
1279 return NULL; /* endpoint not needed */
1280
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001281 dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %d.\n", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
1283 if (urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001284 dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %d failed.\n", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 return NULL;
1286 }
1287
Lucy McCoy0ca12682007-05-18 12:10:41 -07001288 if (endpoint == 0) {
1289 /* control EP filled in when used */
1290 return urb;
1291 }
1292
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001293 ep_desc = find_ep(serial, endpoint);
1294 if (!ep_desc) {
1295 /* leak the urb, something's wrong and the callers don't care */
1296 return urb;
1297 }
1298 if (usb_endpoint_xfer_int(ep_desc)) {
1299 ep_type_name = "INT";
1300 usb_fill_int_urb(urb, serial->dev,
1301 usb_sndintpipe(serial->dev, endpoint) | dir,
1302 buf, len, callback, ctx,
1303 ep_desc->bInterval);
1304 } else if (usb_endpoint_xfer_bulk(ep_desc)) {
1305 ep_type_name = "BULK";
1306 usb_fill_bulk_urb(urb, serial->dev,
1307 usb_sndbulkpipe(serial->dev, endpoint) | dir,
1308 buf, len, callback, ctx);
1309 } else {
1310 dev_warn(&serial->interface->dev,
1311 "unsupported endpoint type %x\n",
Julia Lawall2e0fe702008-12-29 11:22:14 +01001312 usb_endpoint_type(ep_desc));
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001313 usb_free_urb(urb);
1314 return NULL;
1315 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001317 dev_dbg(&serial->interface->dev, "%s - using urb %p for %s endpoint %x\n",
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001318 __func__, urb, ep_type_name, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 return urb;
1320}
1321
1322static struct callbacks {
David Howells7d12e782006-10-05 14:55:46 +01001323 void (*instat_callback)(struct urb *);
1324 void (*glocont_callback)(struct urb *);
1325 void (*indat_callback)(struct urb *);
1326 void (*outdat_callback)(struct urb *);
1327 void (*inack_callback)(struct urb *);
1328 void (*outcont_callback)(struct urb *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329} keyspan_callbacks[] = {
1330 {
1331 /* msg_usa26 callbacks */
1332 .instat_callback = usa26_instat_callback,
1333 .glocont_callback = usa26_glocont_callback,
1334 .indat_callback = usa26_indat_callback,
1335 .outdat_callback = usa2x_outdat_callback,
1336 .inack_callback = usa26_inack_callback,
1337 .outcont_callback = usa26_outcont_callback,
1338 }, {
1339 /* msg_usa28 callbacks */
1340 .instat_callback = usa28_instat_callback,
1341 .glocont_callback = usa28_glocont_callback,
1342 .indat_callback = usa28_indat_callback,
1343 .outdat_callback = usa2x_outdat_callback,
1344 .inack_callback = usa28_inack_callback,
1345 .outcont_callback = usa28_outcont_callback,
1346 }, {
1347 /* msg_usa49 callbacks */
1348 .instat_callback = usa49_instat_callback,
1349 .glocont_callback = usa49_glocont_callback,
1350 .indat_callback = usa49_indat_callback,
1351 .outdat_callback = usa2x_outdat_callback,
1352 .inack_callback = usa49_inack_callback,
1353 .outcont_callback = usa49_outcont_callback,
1354 }, {
1355 /* msg_usa90 callbacks */
1356 .instat_callback = usa90_instat_callback,
Alan Coxdeb91682008-07-22 11:13:08 +01001357 .glocont_callback = usa28_glocont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 .indat_callback = usa90_indat_callback,
1359 .outdat_callback = usa2x_outdat_callback,
1360 .inack_callback = usa28_inack_callback,
1361 .outcont_callback = usa90_outcont_callback,
Lucy McCoy0ca12682007-05-18 12:10:41 -07001362 }, {
1363 /* msg_usa67 callbacks */
1364 .instat_callback = usa67_instat_callback,
1365 .glocont_callback = usa67_glocont_callback,
1366 .indat_callback = usa26_indat_callback,
1367 .outdat_callback = usa2x_outdat_callback,
1368 .inack_callback = usa26_inack_callback,
1369 .outcont_callback = usa26_outcont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370 }
1371};
1372
1373 /* Generic setup urbs function that uses
1374 data in device_details */
1375static void keyspan_setup_urbs(struct usb_serial *serial)
1376{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 struct keyspan_serial_private *s_priv;
1378 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 struct callbacks *cback;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 s_priv = usb_get_serial_data(serial);
1382 d_details = s_priv->device_details;
1383
Alan Coxdeb91682008-07-22 11:13:08 +01001384 /* Setup values for the various callback routines */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 cback = &keyspan_callbacks[d_details->msg_format];
1386
Alan Coxdeb91682008-07-22 11:13:08 +01001387 /* Allocate and set up urbs for each one that is in use,
1388 starting with instat endpoints */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 s_priv->instat_urb = keyspan_setup_urb
1390 (serial, d_details->instat_endpoint, USB_DIR_IN,
1391 serial, s_priv->instat_buf, INSTAT_BUFLEN,
1392 cback->instat_callback);
1393
Lucy McCoy0ca12682007-05-18 12:10:41 -07001394 s_priv->indat_urb = keyspan_setup_urb
1395 (serial, d_details->indat_endpoint, USB_DIR_IN,
1396 serial, s_priv->indat_buf, INDAT49W_BUFLEN,
1397 usa49wg_indat_callback);
1398
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 s_priv->glocont_urb = keyspan_setup_urb
1400 (serial, d_details->glocont_endpoint, USB_DIR_OUT,
1401 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
1402 cback->glocont_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403}
1404
1405/* usa19 function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001406static int keyspan_usa19_calc_baud(struct usb_serial_port *port,
1407 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 u8 *rate_low, u8 *prescaler, int portnum)
1409{
1410 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001411 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 cnt; /* inverse of divisor (programmed into 8051) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001414 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415
Alan Coxdeb91682008-07-22 11:13:08 +01001416 /* prevent divide by zero... */
1417 b16 = baud_rate * 16L;
1418 if (b16 == 0)
1419 return KEYSPAN_INVALID_BAUD_RATE;
1420 /* Any "standard" rate over 57k6 is marginal on the USA-19
1421 as we run out of divisor resolution. */
1422 if (baud_rate > 57600)
1423 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424
Alan Coxdeb91682008-07-22 11:13:08 +01001425 /* calculate the divisor and the counter (its inverse) */
1426 div = baudclk / b16;
1427 if (div == 0)
1428 return KEYSPAN_INVALID_BAUD_RATE;
1429 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431
Alan Coxdeb91682008-07-22 11:13:08 +01001432 if (div > 0xffff)
1433 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434
Alan Coxdeb91682008-07-22 11:13:08 +01001435 /* return the counter values if non-null */
1436 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001438 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001440 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001441 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001442 __func__, baud_rate, *rate_hi, *rate_low);
1443 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444}
1445
1446/* usa19hs function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001447static int keyspan_usa19hs_calc_baud(struct usb_serial_port *port,
1448 u32 baud_rate, u32 baudclk, u8 *rate_hi,
1449 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450{
1451 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001452 div; /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453
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 the divisor */
1462 div = baudclk / b16;
1463 if (div == 0)
1464 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465
Alan Coxdeb91682008-07-22 11:13:08 +01001466 if (div > 0xffff)
1467 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468
Alan Coxdeb91682008-07-22 11:13:08 +01001469 /* return the counter values if non-null */
1470 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001472
1473 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 *rate_hi = (u8) ((div >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001475
1476 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001477 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001478 __func__, baud_rate, *rate_hi, *rate_low);
1479
1480 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481}
1482
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001483static int keyspan_usa19w_calc_baud(struct usb_serial_port *port,
1484 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485 u8 *rate_low, u8 *prescaler, int portnum)
1486{
1487 u32 b16, /* baud rate times 16 (actual rate used internally) */
1488 clk, /* clock with 13/8 prescaler */
Alan Coxdeb91682008-07-22 11:13:08 +01001489 div, /* divisor using 13/8 prescaler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 res, /* resulting baud rate using 13/8 prescaler */
1491 diff, /* error using 13/8 prescaler */
1492 smallest_diff;
1493 u8 best_prescaler;
1494 int i;
1495
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001496 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497
Alan Coxdeb91682008-07-22 11:13:08 +01001498 /* prevent divide by zero */
1499 b16 = baud_rate * 16L;
1500 if (b16 == 0)
1501 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502
Alan Coxdeb91682008-07-22 11:13:08 +01001503 /* Calculate prescaler by trying them all and looking
1504 for best fit */
1505
1506 /* start with largest possible difference */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 smallest_diff = 0xffffffff;
1508
1509 /* 0 is an invalid prescaler, used as a flag */
1510 best_prescaler = 0;
1511
Alan Coxdeb91682008-07-22 11:13:08 +01001512 for (i = 8; i <= 0xff; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 clk = (baudclk * 8) / (u32) i;
Alan Coxdeb91682008-07-22 11:13:08 +01001514
1515 div = clk / b16;
1516 if (div == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518
1519 res = clk / div;
Alan Coxdeb91682008-07-22 11:13:08 +01001520 diff = (res > b16) ? (res-b16) : (b16-res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521
Alan Coxdeb91682008-07-22 11:13:08 +01001522 if (diff < smallest_diff) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 best_prescaler = i;
1524 smallest_diff = diff;
1525 }
1526 }
1527
Alan Coxdeb91682008-07-22 11:13:08 +01001528 if (best_prescaler == 0)
1529 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530
1531 clk = (baudclk * 8) / (u32) best_prescaler;
1532 div = clk / b16;
1533
Alan Coxdeb91682008-07-22 11:13:08 +01001534 /* return the divisor and prescaler if non-null */
1535 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001537 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 *rate_hi = (u8) ((div >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 if (prescaler) {
1540 *prescaler = best_prescaler;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001541 /* dev_dbg(&port->dev, "%s - %d %d\n", __func__, *prescaler, div); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 }
Alan Coxdeb91682008-07-22 11:13:08 +01001543 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544}
1545
1546 /* USA-28 supports different maximum baud rates on each port */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001547static int keyspan_usa28_calc_baud(struct usb_serial_port *port,
1548 u32 baud_rate, u32 baudclk, u8 *rate_hi,
1549 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550{
1551 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001552 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553 cnt; /* inverse of divisor (programmed into 8051) */
1554
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001555 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556
1557 /* prevent divide by zero */
Alan Coxdeb91682008-07-22 11:13:08 +01001558 b16 = baud_rate * 16L;
1559 if (b16 == 0)
1560 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561
Alan Coxdeb91682008-07-22 11:13:08 +01001562 /* calculate the divisor and the counter (its inverse) */
1563 div = KEYSPAN_USA28_BAUDCLK / b16;
1564 if (div == 0)
1565 return KEYSPAN_INVALID_BAUD_RATE;
1566 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568
Alan Coxdeb91682008-07-22 11:13:08 +01001569 /* check for out of range, based on portnum,
1570 and return result */
1571 if (portnum == 0) {
1572 if (div > 0xffff)
1573 return KEYSPAN_INVALID_BAUD_RATE;
1574 } else {
1575 if (portnum == 1) {
1576 if (div > 0xff)
1577 return KEYSPAN_INVALID_BAUD_RATE;
1578 } else
1579 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 }
1581
1582 /* return the counter values if not NULL
1583 (port 1 will ignore retHi) */
Alan Coxdeb91682008-07-22 11:13:08 +01001584 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001586 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001588 dev_dbg(&port->dev, "%s - %d OK.\n", __func__, baud_rate);
Alan Coxdeb91682008-07-22 11:13:08 +01001589 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590}
1591
1592static int keyspan_usa26_send_setup(struct usb_serial *serial,
1593 struct usb_serial_port *port,
1594 int reset_port)
1595{
Alan Coxdeb91682008-07-22 11:13:08 +01001596 struct keyspan_usa26_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597 struct keyspan_serial_private *s_priv;
1598 struct keyspan_port_private *p_priv;
1599 const struct keyspan_device_details *d_details;
1600 int outcont_urb;
1601 struct urb *this_urb;
1602 int device_port, err;
1603
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001604 dev_dbg(&port->dev, "%s reset=%d\n", __func__, reset_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605
1606 s_priv = usb_get_serial_data(serial);
1607 p_priv = usb_get_serial_port_data(port);
1608 d_details = s_priv->device_details;
1609 device_port = port->number - port->serial->minor;
1610
1611 outcont_urb = d_details->outcont_endpoints[port->number];
1612 this_urb = p_priv->outcont_urb;
1613
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001614 dev_dbg(&port->dev, "%s - endpoint %d\n", __func__, usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615
1616 /* Make sure we have an urb then send the message */
1617 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001618 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619 return -1;
1620 }
1621
1622 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001623 Don't overwrite resend for open/close condition. */
1624 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625 p_priv->resend_cont = reset_port + 1;
1626 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001627 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001629 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 }
1631
Alan Coxdeb91682008-07-22 11:13:08 +01001632 memset(&msg, 0, sizeof(struct keyspan_usa26_portControlMessage));
1633
1634 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 if (p_priv->old_baud != p_priv->baud) {
1636 p_priv->old_baud = p_priv->baud;
1637 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001638 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1639 &msg.baudHi, &msg.baudLo, &msg.prescaler,
1640 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1641 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
1642 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 msg.baudLo = 0;
1644 msg.baudHi = 125; /* Values for 9600 baud */
1645 msg.prescaler = 10;
1646 }
1647 msg.setPrescaler = 0xff;
1648 }
1649
Ben Minerds2b982ab2012-07-12 00:10:16 +10001650 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651 switch (p_priv->cflag & CSIZE) {
1652 case CS5:
1653 msg.lcr |= USA_DATABITS_5;
1654 break;
1655 case CS6:
1656 msg.lcr |= USA_DATABITS_6;
1657 break;
1658 case CS7:
1659 msg.lcr |= USA_DATABITS_7;
1660 break;
1661 case CS8:
1662 msg.lcr |= USA_DATABITS_8;
1663 break;
1664 }
1665 if (p_priv->cflag & PARENB) {
1666 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10001667 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01001668 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669 }
1670 msg.setLcr = 0xff;
1671
1672 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1673 msg.xonFlowControl = 0;
1674 msg.setFlowControl = 0xff;
1675 msg.forwardingLength = 16;
1676 msg.xonChar = 17;
1677 msg.xoffChar = 19;
1678
1679 /* Opening port */
1680 if (reset_port == 1) {
1681 msg._txOn = 1;
1682 msg._txOff = 0;
1683 msg.txFlush = 0;
1684 msg.txBreak = 0;
1685 msg.rxOn = 1;
1686 msg.rxOff = 0;
1687 msg.rxFlush = 1;
1688 msg.rxForward = 0;
1689 msg.returnStatus = 0;
1690 msg.resetDataToggle = 0xff;
1691 }
1692
1693 /* Closing port */
1694 else if (reset_port == 2) {
1695 msg._txOn = 0;
1696 msg._txOff = 1;
1697 msg.txFlush = 0;
1698 msg.txBreak = 0;
1699 msg.rxOn = 0;
1700 msg.rxOff = 1;
1701 msg.rxFlush = 1;
1702 msg.rxForward = 0;
1703 msg.returnStatus = 0;
1704 msg.resetDataToggle = 0;
1705 }
1706
1707 /* Sending intermediate configs */
1708 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001709 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 msg._txOff = 0;
1711 msg.txFlush = 0;
1712 msg.txBreak = (p_priv->break_on);
1713 msg.rxOn = 0;
1714 msg.rxOff = 0;
1715 msg.rxFlush = 0;
1716 msg.rxForward = 0;
1717 msg.returnStatus = 0;
1718 msg.resetDataToggle = 0x0;
1719 }
1720
Alan Coxdeb91682008-07-22 11:13:08 +01001721 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 msg.setTxTriState_setRts = 0xff;
1723 msg.txTriState_rts = p_priv->rts_state;
1724
1725 msg.setHskoa_setDtr = 0xff;
1726 msg.hskoa_dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01001727
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001729 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
1730
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 /* send the data out the device on control endpoint */
1732 this_urb->transfer_buffer_length = sizeof(msg);
1733
Alan Coxdeb91682008-07-22 11:13:08 +01001734 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1735 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001736 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737#if 0
1738 else {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001739 dev_dbg(&port->dev, "%s - usb_submit_urb(%d) OK %d bytes (end %d)\n", __func__
1740 outcont_urb, this_urb->transfer_buffer_length,
1741 usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 }
1743#endif
1744
Alan Coxa5b6f602008-04-08 17:16:06 +01001745 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746}
1747
1748static int keyspan_usa28_send_setup(struct usb_serial *serial,
1749 struct usb_serial_port *port,
1750 int reset_port)
1751{
Alan Coxdeb91682008-07-22 11:13:08 +01001752 struct keyspan_usa28_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 struct keyspan_serial_private *s_priv;
1754 struct keyspan_port_private *p_priv;
1755 const struct keyspan_device_details *d_details;
1756 struct urb *this_urb;
1757 int device_port, err;
1758
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759 s_priv = usb_get_serial_data(serial);
1760 p_priv = usb_get_serial_port_data(port);
1761 d_details = s_priv->device_details;
1762 device_port = port->number - port->serial->minor;
1763
1764 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01001765 this_urb = p_priv->outcont_urb;
1766 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001767 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768 return -1;
1769 }
1770
1771 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001772 Don't overwrite resend for open/close condition. */
1773 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774 p_priv->resend_cont = reset_port + 1;
1775 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001776 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001778 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779 }
1780
Alan Coxdeb91682008-07-22 11:13:08 +01001781 memset(&msg, 0, sizeof(struct keyspan_usa28_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782
1783 msg.setBaudRate = 1;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001784 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1785 &msg.baudHi, &msg.baudLo, NULL,
1786 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1787 dev_dbg(&port->dev, "%s - Invalid baud rate requested %d.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001788 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789 msg.baudLo = 0xff;
1790 msg.baudHi = 0xb2; /* Values for 9600 baud */
1791 }
1792
1793 /* If parity is enabled, we must calculate it ourselves. */
1794 msg.parity = 0; /* XXX for now */
1795
1796 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1797 msg.xonFlowControl = 0;
1798
Alan Coxdeb91682008-07-22 11:13:08 +01001799 /* Do handshaking outputs, DTR is inverted relative to RTS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800 msg.rts = p_priv->rts_state;
1801 msg.dtr = p_priv->dtr_state;
1802
1803 msg.forwardingLength = 16;
1804 msg.forwardMs = 10;
1805 msg.breakThreshold = 45;
1806 msg.xonChar = 17;
1807 msg.xoffChar = 19;
1808
1809 /*msg.returnStatus = 1;
1810 msg.resetDataToggle = 0xff;*/
1811 /* Opening port */
1812 if (reset_port == 1) {
1813 msg._txOn = 1;
1814 msg._txOff = 0;
1815 msg.txFlush = 0;
1816 msg.txForceXoff = 0;
1817 msg.txBreak = 0;
1818 msg.rxOn = 1;
1819 msg.rxOff = 0;
1820 msg.rxFlush = 1;
1821 msg.rxForward = 0;
1822 msg.returnStatus = 0;
1823 msg.resetDataToggle = 0xff;
1824 }
1825 /* Closing port */
1826 else if (reset_port == 2) {
1827 msg._txOn = 0;
1828 msg._txOff = 1;
1829 msg.txFlush = 0;
1830 msg.txForceXoff = 0;
1831 msg.txBreak = 0;
1832 msg.rxOn = 0;
1833 msg.rxOff = 1;
1834 msg.rxFlush = 1;
1835 msg.rxForward = 0;
1836 msg.returnStatus = 0;
1837 msg.resetDataToggle = 0;
1838 }
1839 /* Sending intermediate configs */
1840 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001841 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 msg._txOff = 0;
1843 msg.txFlush = 0;
1844 msg.txForceXoff = 0;
1845 msg.txBreak = (p_priv->break_on);
1846 msg.rxOn = 0;
1847 msg.rxOff = 0;
1848 msg.rxFlush = 0;
1849 msg.rxForward = 0;
1850 msg.returnStatus = 0;
1851 msg.resetDataToggle = 0x0;
1852 }
1853
1854 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001855 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856
1857 /* send the data out the device on control endpoint */
1858 this_urb->transfer_buffer_length = sizeof(msg);
1859
Alan Coxdeb91682008-07-22 11:13:08 +01001860 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1861 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001862 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863#if 0
1864 else {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001865 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) OK %d bytes\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866 this_urb->transfer_buffer_length);
1867 }
1868#endif
1869
Alan Coxa5b6f602008-04-08 17:16:06 +01001870 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871}
1872
1873static int keyspan_usa49_send_setup(struct usb_serial *serial,
1874 struct usb_serial_port *port,
1875 int reset_port)
1876{
Lucy McCoy0ca12682007-05-18 12:10:41 -07001877 struct keyspan_usa49_portControlMessage msg;
1878 struct usb_ctrlrequest *dr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879 struct keyspan_serial_private *s_priv;
1880 struct keyspan_port_private *p_priv;
1881 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882 struct urb *this_urb;
1883 int err, device_port;
1884
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 s_priv = usb_get_serial_data(serial);
1886 p_priv = usb_get_serial_port_data(port);
1887 d_details = s_priv->device_details;
1888
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 this_urb = s_priv->glocont_urb;
1890
Lucy McCoy0ca12682007-05-18 12:10:41 -07001891 /* Work out which port within the device is being setup */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 device_port = port->number - port->serial->minor;
1893
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05301894 /* Make sure we have an urb then send the message */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001896 dev_dbg(&port->dev, "%s - oops no urb for port %d.\n", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897 return -1;
1898 }
1899
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001900 dev_dbg(&port->dev, "%s - endpoint %d port %d (%d)\n",
1901 __func__, usb_pipeendpoint(this_urb->pipe),
1902 port->number, device_port);
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05301903
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001905 Don't overwrite resend for open/close condition. */
1906 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907 p_priv->resend_cont = reset_port + 1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001908
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001910 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001912 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 }
1914
Alan Coxdeb91682008-07-22 11:13:08 +01001915 memset(&msg, 0, sizeof(struct keyspan_usa49_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916
1917 /*msg.portNumber = port->number;*/
1918 msg.portNumber = device_port;
Alan Coxdeb91682008-07-22 11:13:08 +01001919
1920 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921 if (p_priv->old_baud != p_priv->baud) {
1922 p_priv->old_baud = p_priv->baud;
1923 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001924 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
1925 &msg.baudHi, &msg.baudLo, &msg.prescaler,
1926 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1927 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
1928 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929 msg.baudLo = 0;
1930 msg.baudHi = 125; /* Values for 9600 baud */
1931 msg.prescaler = 10;
1932 }
Alan Coxdeb91682008-07-22 11:13:08 +01001933 /* msg.setPrescaler = 0xff; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934 }
1935
Ben Minerds2b982ab2012-07-12 00:10:16 +10001936 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937 switch (p_priv->cflag & CSIZE) {
1938 case CS5:
1939 msg.lcr |= USA_DATABITS_5;
1940 break;
1941 case CS6:
1942 msg.lcr |= USA_DATABITS_6;
1943 break;
1944 case CS7:
1945 msg.lcr |= USA_DATABITS_7;
1946 break;
1947 case CS8:
1948 msg.lcr |= USA_DATABITS_8;
1949 break;
1950 }
1951 if (p_priv->cflag & PARENB) {
1952 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10001953 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01001954 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955 }
1956 msg.setLcr = 0xff;
1957
1958 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1959 msg.xonFlowControl = 0;
1960 msg.setFlowControl = 0xff;
Alan Coxdeb91682008-07-22 11:13:08 +01001961
Linus Torvalds1da177e2005-04-16 15:20:36 -07001962 msg.forwardingLength = 16;
1963 msg.xonChar = 17;
1964 msg.xoffChar = 19;
1965
Alan Coxdeb91682008-07-22 11:13:08 +01001966 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967 if (reset_port == 1) {
1968 msg._txOn = 1;
1969 msg._txOff = 0;
1970 msg.txFlush = 0;
1971 msg.txBreak = 0;
1972 msg.rxOn = 1;
1973 msg.rxOff = 0;
1974 msg.rxFlush = 1;
1975 msg.rxForward = 0;
1976 msg.returnStatus = 0;
1977 msg.resetDataToggle = 0xff;
1978 msg.enablePort = 1;
1979 msg.disablePort = 0;
1980 }
1981 /* Closing port */
1982 else if (reset_port == 2) {
1983 msg._txOn = 0;
1984 msg._txOff = 1;
1985 msg.txFlush = 0;
1986 msg.txBreak = 0;
1987 msg.rxOn = 0;
1988 msg.rxOff = 1;
1989 msg.rxFlush = 1;
1990 msg.rxForward = 0;
1991 msg.returnStatus = 0;
1992 msg.resetDataToggle = 0;
1993 msg.enablePort = 0;
1994 msg.disablePort = 1;
1995 }
1996 /* Sending intermediate configs */
1997 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001998 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999 msg._txOff = 0;
2000 msg.txFlush = 0;
2001 msg.txBreak = (p_priv->break_on);
2002 msg.rxOn = 0;
2003 msg.rxOff = 0;
2004 msg.rxFlush = 0;
2005 msg.rxForward = 0;
2006 msg.returnStatus = 0;
2007 msg.resetDataToggle = 0x0;
2008 msg.enablePort = 0;
2009 msg.disablePort = 0;
2010 }
2011
Alan Coxdeb91682008-07-22 11:13:08 +01002012 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013 msg.setRts = 0xff;
2014 msg.rts = p_priv->rts_state;
2015
2016 msg.setDtr = 0xff;
2017 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002018
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019 p_priv->resend_cont = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020
Alan Coxdeb91682008-07-22 11:13:08 +01002021 /* if the device is a 49wg, we send control message on usb
2022 control EP 0 */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002023
2024 if (d_details->product_id == keyspan_usa49wg_product_id) {
2025 dr = (void *)(s_priv->ctrl_buf);
2026 dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT;
2027 dr->bRequest = 0xB0; /* 49wg control message */;
2028 dr->wValue = 0;
2029 dr->wIndex = 0;
2030 dr->wLength = cpu_to_le16(sizeof(msg));
2031
Alan Coxdeb91682008-07-22 11:13:08 +01002032 memcpy(s_priv->glocont_buf, &msg, sizeof(msg));
Lucy McCoy0ca12682007-05-18 12:10:41 -07002033
Alan Coxdeb91682008-07-22 11:13:08 +01002034 usb_fill_control_urb(this_urb, serial->dev,
2035 usb_sndctrlpipe(serial->dev, 0),
2036 (unsigned char *)dr, s_priv->glocont_buf,
2037 sizeof(msg), usa49_glocont_callback, serial);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002038
2039 } else {
2040 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Alan Coxdeb91682008-07-22 11:13:08 +01002041
Lucy McCoy0ca12682007-05-18 12:10:41 -07002042 /* send the data out the device on control endpoint */
2043 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002044 }
Alan Coxdeb91682008-07-22 11:13:08 +01002045 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2046 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002047 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048#if 0
2049 else {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002050 dev_dbg(&port->dev, "%s - usb_submit_urb(%d) OK %d bytes (end %d)\n", __func__,
2051 outcont_urb, this_urb->transfer_buffer_length,
2052 usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 }
2054#endif
2055
Alan Coxa5b6f602008-04-08 17:16:06 +01002056 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057}
2058
2059static int keyspan_usa90_send_setup(struct usb_serial *serial,
2060 struct usb_serial_port *port,
2061 int reset_port)
2062{
Alan Coxdeb91682008-07-22 11:13:08 +01002063 struct keyspan_usa90_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 struct keyspan_serial_private *s_priv;
2065 struct keyspan_port_private *p_priv;
2066 const struct keyspan_device_details *d_details;
2067 struct urb *this_urb;
2068 int err;
2069 u8 prescaler;
2070
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071 s_priv = usb_get_serial_data(serial);
2072 p_priv = usb_get_serial_port_data(port);
2073 d_details = s_priv->device_details;
2074
2075 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01002076 this_urb = p_priv->outcont_urb;
2077 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002078 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079 return -1;
2080 }
2081
2082 /* Save reset port val for resend.
2083 Don't overwrite resend for open/close condition. */
2084 if ((reset_port + 1) > p_priv->resend_cont)
2085 p_priv->resend_cont = reset_port + 1;
2086 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002087 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002089 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090 }
2091
Alan Coxdeb91682008-07-22 11:13:08 +01002092 memset(&msg, 0, sizeof(struct keyspan_usa90_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093
Alan Coxdeb91682008-07-22 11:13:08 +01002094 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095 if (p_priv->old_baud != p_priv->baud) {
2096 p_priv->old_baud = p_priv->baud;
2097 msg.setClocking = 0x01;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002098 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2099 &msg.baudHi, &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) {
2100 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2101 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102 p_priv->baud = 9600;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002103 d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104 &msg.baudHi, &msg.baudLo, &prescaler, 0);
2105 }
2106 msg.setRxMode = 1;
2107 msg.setTxMode = 1;
2108 }
2109
2110 /* modes must always be correctly specified */
Alan Coxdeb91682008-07-22 11:13:08 +01002111 if (p_priv->baud > 57600) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112 msg.rxMode = RXMODE_DMA;
2113 msg.txMode = TXMODE_DMA;
Alan Coxdeb91682008-07-22 11:13:08 +01002114 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 msg.rxMode = RXMODE_BYHAND;
2116 msg.txMode = TXMODE_BYHAND;
2117 }
2118
Ben Minerds2b982ab2012-07-12 00:10:16 +10002119 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120 switch (p_priv->cflag & CSIZE) {
2121 case CS5:
2122 msg.lcr |= USA_DATABITS_5;
2123 break;
2124 case CS6:
2125 msg.lcr |= USA_DATABITS_6;
2126 break;
2127 case CS7:
2128 msg.lcr |= USA_DATABITS_7;
2129 break;
2130 case CS8:
2131 msg.lcr |= USA_DATABITS_8;
2132 break;
2133 }
2134 if (p_priv->cflag & PARENB) {
2135 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002136 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002137 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138 }
2139 if (p_priv->old_cflag != p_priv->cflag) {
2140 p_priv->old_cflag = p_priv->cflag;
2141 msg.setLcr = 0x01;
2142 }
2143
2144 if (p_priv->flow_control == flow_cts)
2145 msg.txFlowControl = TXFLOW_CTS;
2146 msg.setTxFlowControl = 0x01;
2147 msg.setRxFlowControl = 0x01;
Alan Coxdeb91682008-07-22 11:13:08 +01002148
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 msg.rxForwardingLength = 16;
Alan Coxdeb91682008-07-22 11:13:08 +01002150 msg.rxForwardingTimeout = 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 msg.txAckSetting = 0;
2152 msg.xonChar = 17;
2153 msg.xoffChar = 19;
2154
Alan Coxdeb91682008-07-22 11:13:08 +01002155 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156 if (reset_port == 1) {
2157 msg.portEnabled = 1;
2158 msg.rxFlush = 1;
2159 msg.txBreak = (p_priv->break_on);
2160 }
2161 /* Closing port */
Alan Coxdeb91682008-07-22 11:13:08 +01002162 else if (reset_port == 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 msg.portEnabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 /* Sending intermediate configs */
2165 else {
Alan Stern1f871582010-02-17 10:05:47 -05002166 msg.portEnabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 msg.txBreak = (p_priv->break_on);
2168 }
2169
Alan Coxdeb91682008-07-22 11:13:08 +01002170 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 msg.setRts = 0x01;
2172 msg.rts = p_priv->rts_state;
2173
2174 msg.setDtr = 0x01;
2175 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002176
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01002178 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2179
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180 /* send the data out the device on control endpoint */
2181 this_urb->transfer_buffer_length = sizeof(msg);
2182
Alan Coxdeb91682008-07-22 11:13:08 +01002183 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2184 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002185 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002186 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187}
2188
Lucy McCoy0ca12682007-05-18 12:10:41 -07002189static int keyspan_usa67_send_setup(struct usb_serial *serial,
2190 struct usb_serial_port *port,
2191 int reset_port)
2192{
2193 struct keyspan_usa67_portControlMessage msg;
2194 struct keyspan_serial_private *s_priv;
2195 struct keyspan_port_private *p_priv;
2196 const struct keyspan_device_details *d_details;
2197 struct urb *this_urb;
2198 int err, device_port;
2199
Lucy McCoy0ca12682007-05-18 12:10:41 -07002200 s_priv = usb_get_serial_data(serial);
2201 p_priv = usb_get_serial_port_data(port);
2202 d_details = s_priv->device_details;
2203
2204 this_urb = s_priv->glocont_urb;
2205
2206 /* Work out which port within the device is being setup */
2207 device_port = port->number - port->serial->minor;
2208
2209 /* Make sure we have an urb then send the message */
2210 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002211 dev_dbg(&port->dev, "%s - oops no urb for port %d.\n", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002212 port->number);
2213 return -1;
2214 }
2215
2216 /* Save reset port val for resend.
2217 Don't overwrite resend for open/close condition. */
2218 if ((reset_port + 1) > p_priv->resend_cont)
2219 p_priv->resend_cont = reset_port + 1;
2220 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002221 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002222 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002223 return -1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002224 }
2225
2226 memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
2227
2228 msg.port = device_port;
2229
2230 /* Only set baud rate if it's changed */
2231 if (p_priv->old_baud != p_priv->baud) {
2232 p_priv->old_baud = p_priv->baud;
2233 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002234 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2235 &msg.baudHi, &msg.baudLo, &msg.prescaler,
2236 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2237 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2238 __func__, p_priv->baud);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002239 msg.baudLo = 0;
2240 msg.baudHi = 125; /* Values for 9600 baud */
2241 msg.prescaler = 10;
2242 }
2243 msg.setPrescaler = 0xff;
2244 }
2245
2246 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
2247 switch (p_priv->cflag & CSIZE) {
2248 case CS5:
2249 msg.lcr |= USA_DATABITS_5;
2250 break;
2251 case CS6:
2252 msg.lcr |= USA_DATABITS_6;
2253 break;
2254 case CS7:
2255 msg.lcr |= USA_DATABITS_7;
2256 break;
2257 case CS8:
2258 msg.lcr |= USA_DATABITS_8;
2259 break;
2260 }
2261 if (p_priv->cflag & PARENB) {
2262 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002263 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002264 USA_PARITY_ODD : USA_PARITY_EVEN;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002265 }
2266 msg.setLcr = 0xff;
2267
2268 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2269 msg.xonFlowControl = 0;
2270 msg.setFlowControl = 0xff;
2271 msg.forwardingLength = 16;
2272 msg.xonChar = 17;
2273 msg.xoffChar = 19;
2274
2275 if (reset_port == 1) {
2276 /* Opening port */
2277 msg._txOn = 1;
2278 msg._txOff = 0;
2279 msg.txFlush = 0;
2280 msg.txBreak = 0;
2281 msg.rxOn = 1;
2282 msg.rxOff = 0;
2283 msg.rxFlush = 1;
2284 msg.rxForward = 0;
2285 msg.returnStatus = 0;
2286 msg.resetDataToggle = 0xff;
2287 } else if (reset_port == 2) {
2288 /* Closing port */
2289 msg._txOn = 0;
2290 msg._txOff = 1;
2291 msg.txFlush = 0;
2292 msg.txBreak = 0;
2293 msg.rxOn = 0;
2294 msg.rxOff = 1;
2295 msg.rxFlush = 1;
2296 msg.rxForward = 0;
2297 msg.returnStatus = 0;
2298 msg.resetDataToggle = 0;
2299 } else {
2300 /* Sending intermediate configs */
Alan Coxdeb91682008-07-22 11:13:08 +01002301 msg._txOn = (!p_priv->break_on);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002302 msg._txOff = 0;
2303 msg.txFlush = 0;
2304 msg.txBreak = (p_priv->break_on);
2305 msg.rxOn = 0;
2306 msg.rxOff = 0;
2307 msg.rxFlush = 0;
2308 msg.rxForward = 0;
2309 msg.returnStatus = 0;
2310 msg.resetDataToggle = 0x0;
2311 }
2312
2313 /* Do handshaking outputs */
2314 msg.setTxTriState_setRts = 0xff;
2315 msg.txTriState_rts = p_priv->rts_state;
2316
2317 msg.setHskoa_setDtr = 0xff;
2318 msg.hskoa_dtr = p_priv->dtr_state;
2319
2320 p_priv->resend_cont = 0;
2321
2322 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2323
2324 /* send the data out the device on control endpoint */
2325 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002326
2327 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2328 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002329 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002330 return 0;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002331}
2332
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
2334{
2335 struct usb_serial *serial = port->serial;
2336 struct keyspan_serial_private *s_priv;
2337 const struct keyspan_device_details *d_details;
2338
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339 s_priv = usb_get_serial_data(serial);
2340 d_details = s_priv->device_details;
2341
2342 switch (d_details->msg_format) {
2343 case msg_usa26:
2344 keyspan_usa26_send_setup(serial, port, reset_port);
2345 break;
2346 case msg_usa28:
2347 keyspan_usa28_send_setup(serial, port, reset_port);
2348 break;
2349 case msg_usa49:
2350 keyspan_usa49_send_setup(serial, port, reset_port);
2351 break;
2352 case msg_usa90:
2353 keyspan_usa90_send_setup(serial, port, reset_port);
2354 break;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002355 case msg_usa67:
2356 keyspan_usa67_send_setup(serial, port, reset_port);
2357 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358 }
2359}
2360
2361
2362/* Gets called by the "real" driver (ie once firmware is loaded
2363 and renumeration has taken place. */
Alan Coxdeb91682008-07-22 11:13:08 +01002364static int keyspan_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365{
2366 int i, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368 const struct keyspan_device_details *d_details;
2369
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370 for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
Alan Coxdeb91682008-07-22 11:13:08 +01002371 if (d_details->product_id ==
2372 le16_to_cpu(serial->dev->descriptor.idProduct))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373 break;
2374 if (d_details == NULL) {
Alan Coxdeb91682008-07-22 11:13:08 +01002375 dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
2376 __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377 return 1;
2378 }
2379
2380 /* Setup private data for serial driver */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01002381 s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002382 if (!s_priv) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002383 dev_dbg(&serial->dev->dev, "%s - kmalloc for keyspan_serial_private failed.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384 return -ENOMEM;
2385 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386
2387 s_priv->device_details = d_details;
2388 usb_set_serial_data(serial, s_priv);
2389
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390 keyspan_setup_urbs(serial);
2391
Lucy McCoy0ca12682007-05-18 12:10:41 -07002392 if (s_priv->instat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002393 err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
2394 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002395 dev_dbg(&serial->dev->dev, "%s - submit instat urb failed %d\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002396 }
2397 if (s_priv->indat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002398 err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
2399 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002400 dev_dbg(&serial->dev->dev, "%s - submit indat urb failed %d\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401 }
Alan Coxdeb91682008-07-22 11:13:08 +01002402
Alan Coxa5b6f602008-04-08 17:16:06 +01002403 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404}
2405
Alan Sternf9c99bb2009-06-02 11:53:55 -04002406static void keyspan_disconnect(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002408 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410 s_priv = usb_get_serial_data(serial);
2411
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412 stop_urb(s_priv->instat_urb);
2413 stop_urb(s_priv->glocont_urb);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002414 stop_urb(s_priv->indat_urb);
Alan Sternf9c99bb2009-06-02 11:53:55 -04002415}
2416
2417static void keyspan_release(struct usb_serial *serial)
2418{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002419 struct keyspan_serial_private *s_priv;
Alan Sternf9c99bb2009-06-02 11:53:55 -04002420
Alan Sternf9c99bb2009-06-02 11:53:55 -04002421 s_priv = usb_get_serial_data(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002423 usb_free_urb(s_priv->instat_urb);
2424 usb_free_urb(s_priv->indat_urb);
2425 usb_free_urb(s_priv->glocont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002427 kfree(s_priv);
2428}
2429
2430static int keyspan_port_probe(struct usb_serial_port *port)
2431{
2432 struct usb_serial *serial = port->serial;
2433 struct keyspan_port_private *s_priv;
2434 struct keyspan_port_private *p_priv;
2435 const struct keyspan_device_details *d_details;
2436 struct callbacks *cback;
2437 int endp;
2438 int port_num;
2439 int i;
2440
2441 s_priv = usb_get_serial_data(serial);
2442 d_details = s_priv->device_details;
2443
2444 p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL);
2445 if (!p_priv)
2446 return -ENOMEM;
2447
2448 s_priv = usb_get_serial_data(port->serial);
2449 p_priv->device_details = d_details;
2450
2451 /* Setup values for the various callback routines */
2452 cback = &keyspan_callbacks[d_details->msg_format];
2453
2454 port_num = port->number - port->serial->minor;
2455
2456 /* Do indat endpoints first, once for each flip */
2457 endp = d_details->indat_endpoints[port_num];
2458 for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) {
2459 p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp,
2460 USB_DIR_IN, port,
2461 p_priv->in_buffer[i], 64,
2462 cback->indat_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463 }
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002464 /* outdat endpoints also have flip */
2465 endp = d_details->outdat_endpoints[port_num];
2466 for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) {
2467 p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp,
2468 USB_DIR_OUT, port,
2469 p_priv->out_buffer[i], 64,
2470 cback->outdat_callback);
2471 }
2472 /* inack endpoint */
2473 p_priv->inack_urb = keyspan_setup_urb(serial,
2474 d_details->inack_endpoints[port_num],
2475 USB_DIR_IN, port,
2476 p_priv->inack_buffer, 1,
2477 cback->inack_callback);
2478 /* outcont endpoint */
2479 p_priv->outcont_urb = keyspan_setup_urb(serial,
2480 d_details->outcont_endpoints[port_num],
2481 USB_DIR_OUT, port,
2482 p_priv->outcont_buffer, 64,
2483 cback->outcont_callback);
2484
2485 usb_set_serial_port_data(port, p_priv);
2486
2487 return 0;
2488}
2489
2490static int keyspan_port_remove(struct usb_serial_port *port)
2491{
2492 struct keyspan_port_private *p_priv;
2493 int i;
2494
2495 p_priv = usb_get_serial_port_data(port);
2496
2497 stop_urb(p_priv->inack_urb);
2498 stop_urb(p_priv->outcont_urb);
2499 for (i = 0; i < 2; i++) {
2500 stop_urb(p_priv->in_urbs[i]);
2501 stop_urb(p_priv->out_urbs[i]);
2502 }
2503
2504 usb_free_urb(p_priv->inack_urb);
2505 usb_free_urb(p_priv->outcont_urb);
2506 for (i = 0; i < 2; i++) {
2507 usb_free_urb(p_priv->in_urbs[i]);
2508 usb_free_urb(p_priv->out_urbs[i]);
2509 }
2510
2511 kfree(p_priv);
2512
2513 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514}
2515
Alan Coxdeb91682008-07-22 11:13:08 +01002516MODULE_AUTHOR(DRIVER_AUTHOR);
2517MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002518MODULE_LICENSE("GPL");
2519
David Woodhouse2971c572008-05-30 14:04:03 +03002520MODULE_FIRMWARE("keyspan/usa28.fw");
2521MODULE_FIRMWARE("keyspan/usa28x.fw");
2522MODULE_FIRMWARE("keyspan/usa28xa.fw");
2523MODULE_FIRMWARE("keyspan/usa28xb.fw");
2524MODULE_FIRMWARE("keyspan/usa19.fw");
2525MODULE_FIRMWARE("keyspan/usa19qi.fw");
2526MODULE_FIRMWARE("keyspan/mpr.fw");
2527MODULE_FIRMWARE("keyspan/usa19qw.fw");
2528MODULE_FIRMWARE("keyspan/usa18x.fw");
2529MODULE_FIRMWARE("keyspan/usa19w.fw");
2530MODULE_FIRMWARE("keyspan/usa49w.fw");
2531MODULE_FIRMWARE("keyspan/usa49wlc.fw");