blob: 0d5d3025a6632c5660878421aa95791eafa399c7 [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>
David Woodhouse2971c572008-05-30 14:04:03 +030041#include <linux/firmware.h>
42#include <linux/ihex.h>
Alan Coxdeb91682008-07-22 11:13:08 +010043#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <linux/usb.h>
Greg Kroah-Hartmana9698882006-07-11 21:22:58 -070045#include <linux/usb/serial.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070046#include "keyspan.h"
47
Rusty Russell90ab5ee2012-01-13 09:32:20 +103048static bool debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
50/*
51 * Version Information
52 */
Lucy McCoy0ca12682007-05-18 12:10:41 -070053#define DRIVER_VERSION "v1.1.5"
Linus Torvalds1da177e2005-04-16 15:20:36 -070054#define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu"
55#define DRIVER_DESC "Keyspan USB to Serial Converter Driver"
56
57#define INSTAT_BUFLEN 32
58#define GLOCONT_BUFLEN 64
Lucy McCoy0ca12682007-05-18 12:10:41 -070059#define INDAT49W_BUFLEN 512
Linus Torvalds1da177e2005-04-16 15:20:36 -070060
61 /* Per device and per port private data */
62struct keyspan_serial_private {
63 const struct keyspan_device_details *device_details;
64
65 struct urb *instat_urb;
66 char instat_buf[INSTAT_BUFLEN];
67
Alan Coxdeb91682008-07-22 11:13:08 +010068 /* added to support 49wg, where data from all 4 ports comes in
69 on 1 EP and high-speed supported */
Lucy McCoy0ca12682007-05-18 12:10:41 -070070 struct urb *indat_urb;
71 char indat_buf[INDAT49W_BUFLEN];
72
Linus Torvalds1da177e2005-04-16 15:20:36 -070073 /* XXX this one probably will need a lock */
74 struct urb *glocont_urb;
75 char glocont_buf[GLOCONT_BUFLEN];
Alan Coxdeb91682008-07-22 11:13:08 +010076 char ctrl_buf[8]; /* for EP0 control message */
Linus Torvalds1da177e2005-04-16 15:20:36 -070077};
78
79struct keyspan_port_private {
80 /* Keep track of which input & output endpoints to use */
81 int in_flip;
82 int out_flip;
83
84 /* Keep duplicate of device details in each port
85 structure as well - simplifies some of the
86 callback functions etc. */
87 const struct keyspan_device_details *device_details;
88
89 /* Input endpoints and buffer for this port */
90 struct urb *in_urbs[2];
91 char in_buffer[2][64];
92 /* Output endpoints and buffer for this port */
93 struct urb *out_urbs[2];
94 char out_buffer[2][64];
95
96 /* Input ack endpoint */
97 struct urb *inack_urb;
98 char inack_buffer[1];
99
100 /* Output control endpoint */
101 struct urb *outcont_urb;
102 char outcont_buffer[64];
103
104 /* Settings for the port */
105 int baud;
106 int old_baud;
107 unsigned int cflag;
108 unsigned int old_cflag;
109 enum {flow_none, flow_cts, flow_xon} flow_control;
110 int rts_state; /* Handshaking pins (outputs) */
111 int dtr_state;
112 int cts_state; /* Handshaking pins (inputs) */
113 int dsr_state;
114 int dcd_state;
115 int ri_state;
116 int break_on;
117
118 unsigned long tx_start_time[2];
119 int resend_cont; /* need to resend control packet */
120};
121
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122/* Include Keyspan message headers. All current Keyspan Adapters
Lucy McCoy0ca12682007-05-18 12:10:41 -0700123 make use of one of five message formats which are referred
Alan Coxdeb91682008-07-22 11:13:08 +0100124 to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and
125 within this driver. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126#include "keyspan_usa26msg.h"
127#include "keyspan_usa28msg.h"
128#include "keyspan_usa49msg.h"
129#include "keyspan_usa90msg.h"
Lucy McCoy0ca12682007-05-18 12:10:41 -0700130#include "keyspan_usa67msg.h"
Alan Coxdeb91682008-07-22 11:13:08 +0100131
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
133/* Functions used by new usb-serial code. */
Alan Coxdeb91682008-07-22 11:13:08 +0100134static int __init keyspan_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135{
136 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137
Alan Stern4d2a7af2012-02-23 14:57:09 -0500138 retval = usb_serial_register_drivers(&keyspan_driver, serial_drivers);
139 if (retval == 0)
140 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
141 DRIVER_DESC "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 return retval;
143}
144
Alan Coxdeb91682008-07-22 11:13:08 +0100145static void __exit keyspan_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146{
Alan Stern4d2a7af2012-02-23 14:57:09 -0500147 usb_serial_deregister_drivers(&keyspan_driver, serial_drivers);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148}
149
150module_init(keyspan_init);
151module_exit(keyspan_exit);
152
Alan Cox95da3102008-07-22 11:09:07 +0100153static void keyspan_break_ctl(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154{
Alan Cox95da3102008-07-22 11:09:07 +0100155 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156 struct keyspan_port_private *p_priv;
157
Alan Coxdeb91682008-07-22 11:13:08 +0100158 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159
160 p_priv = usb_get_serial_port_data(port);
161
162 if (break_state == -1)
163 p_priv->break_on = 1;
164 else
165 p_priv->break_on = 0;
166
167 keyspan_send_setup(port, 0);
168}
169
170
Alan Coxdeb91682008-07-22 11:13:08 +0100171static void keyspan_set_termios(struct tty_struct *tty,
Alan Cox95da3102008-07-22 11:09:07 +0100172 struct usb_serial_port *port, struct ktermios *old_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173{
174 int baud_rate, device_port;
175 struct keyspan_port_private *p_priv;
176 const struct keyspan_device_details *d_details;
177 unsigned int cflag;
178
Harvey Harrison441b62c2008-03-03 16:08:34 -0800179 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180
181 p_priv = usb_get_serial_port_data(port);
182 d_details = p_priv->device_details;
Alan Cox74240b02007-10-18 01:24:20 -0700183 cflag = tty->termios->c_cflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 device_port = port->number - port->serial->minor;
185
186 /* Baud rate calculation takes baud rate as an integer
187 so other rates can be generated if desired. */
Alan Cox74240b02007-10-18 01:24:20 -0700188 baud_rate = tty_get_baud_rate(tty);
Alan Coxdeb91682008-07-22 11:13:08 +0100189 /* If no match or invalid, don't change */
Alan Cox74240b02007-10-18 01:24:20 -0700190 if (d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
192 /* FIXME - more to do here to ensure rate changes cleanly */
Alan Cox74240b02007-10-18 01:24:20 -0700193 /* FIXME - calcuate exact rate from divisor ? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 p_priv->baud = baud_rate;
Alan Cox74240b02007-10-18 01:24:20 -0700195 } else
196 baud_rate = tty_termios_baud_rate(old_termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197
Alan Cox74240b02007-10-18 01:24:20 -0700198 tty_encode_baud_rate(tty, baud_rate, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 /* set CTS/RTS handshake etc. */
200 p_priv->cflag = cflag;
201 p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none;
202
Alan Cox74240b02007-10-18 01:24:20 -0700203 /* Mark/Space not supported */
204 tty->termios->c_cflag &= ~CMSPAR;
205
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 keyspan_send_setup(port, 0);
207}
208
Alan Cox60b33c12011-02-14 16:26:14 +0000209static int keyspan_tiocmget(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210{
Alan Cox95da3102008-07-22 11:09:07 +0100211 struct usb_serial_port *port = tty->driver_data;
212 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 unsigned int value;
Alan Coxdeb91682008-07-22 11:13:08 +0100214
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 value = ((p_priv->rts_state) ? TIOCM_RTS : 0) |
216 ((p_priv->dtr_state) ? TIOCM_DTR : 0) |
217 ((p_priv->cts_state) ? TIOCM_CTS : 0) |
218 ((p_priv->dsr_state) ? TIOCM_DSR : 0) |
219 ((p_priv->dcd_state) ? TIOCM_CAR : 0) |
Alan Coxdeb91682008-07-22 11:13:08 +0100220 ((p_priv->ri_state) ? TIOCM_RNG : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221
222 return value;
223}
224
Alan Cox20b9d172011-02-14 16:26:50 +0000225static int keyspan_tiocmset(struct tty_struct *tty,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 unsigned int set, unsigned int clear)
227{
Alan Cox95da3102008-07-22 11:09:07 +0100228 struct usb_serial_port *port = tty->driver_data;
229 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100230
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 if (set & TIOCM_RTS)
232 p_priv->rts_state = 1;
233 if (set & TIOCM_DTR)
234 p_priv->dtr_state = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 if (clear & TIOCM_RTS)
236 p_priv->rts_state = 0;
237 if (clear & TIOCM_DTR)
238 p_priv->dtr_state = 0;
239 keyspan_send_setup(port, 0);
240 return 0;
241}
242
Alan Cox95da3102008-07-22 11:09:07 +0100243/* Write function is similar for the four protocols used
244 with only a minor change for usa90 (usa19hs) required */
245static int keyspan_write(struct tty_struct *tty,
246 struct usb_serial_port *port, const unsigned char *buf, int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247{
248 struct keyspan_port_private *p_priv;
249 const struct keyspan_device_details *d_details;
250 int flip;
251 int left, todo;
252 struct urb *this_urb;
Alan Coxdeb91682008-07-22 11:13:08 +0100253 int err, maxDataLen, dataOffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254
255 p_priv = usb_get_serial_port_data(port);
256 d_details = p_priv->device_details;
257
258 if (d_details->msg_format == msg_usa90) {
Alan Coxdeb91682008-07-22 11:13:08 +0100259 maxDataLen = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 dataOffset = 0;
261 } else {
262 maxDataLen = 63;
263 dataOffset = 1;
264 }
Alan Coxdeb91682008-07-22 11:13:08 +0100265
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 dbg("%s - for port %d (%d chars), flip=%d",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800267 __func__, port->number, count, p_priv->out_flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268
269 for (left = count; left > 0; left -= todo) {
270 todo = left;
271 if (todo > maxDataLen)
272 todo = maxDataLen;
273
274 flip = p_priv->out_flip;
Alan Coxdeb91682008-07-22 11:13:08 +0100275
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 /* Check we have a valid urb/endpoint before we use it... */
Alan Coxdeb91682008-07-22 11:13:08 +0100277 this_urb = p_priv->out_urbs[flip];
278 if (this_urb == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 /* no bulk out, so return 0 bytes written */
Harvey Harrison441b62c2008-03-03 16:08:34 -0800280 dbg("%s - no output urb :(", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 return count;
282 }
283
Alan Coxdeb91682008-07-22 11:13:08 +0100284 dbg("%s - endpoint %d flip %d",
285 __func__, usb_pipeendpoint(this_urb->pipe), flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286
287 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +0100288 if (time_before(jiffies,
289 p_priv->tx_start_time[flip] + 10 * HZ))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 usb_unlink_urb(this_urb);
292 break;
293 }
294
Alan Coxdeb91682008-07-22 11:13:08 +0100295 /* First byte in buffer is "last flag" (except for usa19hx)
296 - unused so for now so set to zero */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 ((char *)this_urb->transfer_buffer)[0] = 0;
298
Alan Coxdeb91682008-07-22 11:13:08 +0100299 memcpy(this_urb->transfer_buffer + dataOffset, buf, todo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 buf += todo;
301
302 /* send the data out the bulk port */
303 this_urb->transfer_buffer_length = todo + dataOffset;
304
Alan Coxdeb91682008-07-22 11:13:08 +0100305 err = usb_submit_urb(this_urb, GFP_ATOMIC);
306 if (err != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 dbg("usb_submit_urb(write bulk) failed (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 p_priv->tx_start_time[flip] = jiffies;
309
310 /* Flip for next time if usa26 or usa28 interface
311 (not used on usa49) */
312 p_priv->out_flip = (flip + 1) & d_details->outdat_endp_flip;
313 }
314
315 return count - left;
316}
317
David Howells7d12e782006-10-05 14:55:46 +0100318static void usa26_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319{
320 int i, err;
321 int endpoint;
322 struct usb_serial_port *port;
323 struct tty_struct *tty;
324 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700325 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326
Alan Coxdeb91682008-07-22 11:13:08 +0100327 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328
329 endpoint = usb_pipeendpoint(urb->pipe);
330
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700331 if (status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 dbg("%s - nonzero status: %x on endpoint %d.",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800333 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 return;
335 }
336
Ming Leicdc97792008-02-24 18:41:47 +0800337 port = urb->context;
Alan Cox4a90f092008-10-13 10:39:46 +0100338 tty = tty_port_tty_get(&port->port);
Alan Coxa5569a52008-01-21 17:18:24 -0800339 if (tty && urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 /* 0x80 bit is error flag */
341 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100342 /* no errors on individual bytes, only
343 possible overrun err */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 if (data[0] & RXERROR_OVERRUN)
Alan Coxdeb91682008-07-22 11:13:08 +0100345 err = TTY_OVERRUN;
346 else
347 err = 0;
348 for (i = 1; i < urb->actual_length ; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 tty_insert_flip_char(tty, data[i], err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 } else {
351 /* some bytes had errors, every byte has status */
Harvey Harrison441b62c2008-03-03 16:08:34 -0800352 dbg("%s - RX error!!!!", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 for (i = 0; i + 1 < urb->actual_length; i += 2) {
354 int stat = data[i], flag = 0;
355 if (stat & RXERROR_OVERRUN)
356 flag |= TTY_OVERRUN;
357 if (stat & RXERROR_FRAMING)
358 flag |= TTY_FRAME;
359 if (stat & RXERROR_PARITY)
360 flag |= TTY_PARITY;
361 /* XXX should handle break (0x10) */
362 tty_insert_flip_char(tty, data[i+1], flag);
363 }
364 }
365 tty_flip_buffer_push(tty);
366 }
Alan Cox4a90f092008-10-13 10:39:46 +0100367 tty_kref_put(tty);
Alan Coxdeb91682008-07-22 11:13:08 +0100368
369 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500370 err = usb_submit_urb(urb, GFP_ATOMIC);
371 if (err != 0)
372 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373}
374
Alan Coxdeb91682008-07-22 11:13:08 +0100375/* Outdat handling is common for all devices */
David Howells7d12e782006-10-05 14:55:46 +0100376static void usa2x_outdat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377{
378 struct usb_serial_port *port;
379 struct keyspan_port_private *p_priv;
380
Ming Leicdc97792008-02-24 18:41:47 +0800381 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100383 dbg("%s - urb %d", __func__, urb == p_priv->out_urbs[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384
Alan Stern1f871582010-02-17 10:05:47 -0500385 usb_serial_port_softint(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386}
387
David Howells7d12e782006-10-05 14:55:46 +0100388static void usa26_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389{
Alan Coxdeb91682008-07-22 11:13:08 +0100390 dbg("%s", __func__);
391
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392}
393
David Howells7d12e782006-10-05 14:55:46 +0100394static void usa26_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395{
396 struct usb_serial_port *port;
397 struct keyspan_port_private *p_priv;
398
Ming Leicdc97792008-02-24 18:41:47 +0800399 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 p_priv = usb_get_serial_port_data(port);
401
402 if (p_priv->resend_cont) {
Alan Coxdeb91682008-07-22 11:13:08 +0100403 dbg("%s - sending setup", __func__);
404 keyspan_usa26_send_setup(port->serial, port,
405 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 }
407}
408
David Howells7d12e782006-10-05 14:55:46 +0100409static void usa26_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410{
411 unsigned char *data = urb->transfer_buffer;
412 struct keyspan_usa26_portStatusMessage *msg;
413 struct usb_serial *serial;
414 struct usb_serial_port *port;
415 struct keyspan_port_private *p_priv;
Alan Cox4a90f092008-10-13 10:39:46 +0100416 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700418 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419
Ming Leicdc97792008-02-24 18:41:47 +0800420 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700422 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800423 dbg("%s - nonzero status: %x", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 return;
425 }
426 if (urb->actual_length != 9) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800427 dbg("%s - %d byte report??", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 goto exit;
429 }
430
431 msg = (struct keyspan_usa26_portStatusMessage *)data;
432
433#if 0
434 dbg("%s - port status: port %d cts %d dcd %d dsr %d ri %d toff %d txoff %d rxen %d cr %d",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800435 __func__, msg->port, msg->hskia_cts, msg->gpia_dcd, msg->dsr, msg->ri, msg->_txOff,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 msg->_txXoff, msg->rxEnabled, msg->controlResponse);
437#endif
438
439 /* Now do something useful with the data */
440
441
Alan Coxdeb91682008-07-22 11:13:08 +0100442 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 if (msg->port >= serial->num_ports) {
Alan Coxdeb91682008-07-22 11:13:08 +0100444 dbg("%s - Unexpected port number %d", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 goto exit;
446 }
447 port = serial->port[msg->port];
448 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100449
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 /* Update handshaking pin state information */
451 old_dcd_state = p_priv->dcd_state;
452 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
453 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
454 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
455 p_priv->ri_state = ((msg->ri) ? 1 : 0);
456
Alan Cox4a90f092008-10-13 10:39:46 +0100457 if (old_dcd_state != p_priv->dcd_state) {
458 tty = tty_port_tty_get(&port->port);
459 if (tty && !C_CLOCAL(tty))
460 tty_hangup(tty);
461 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 }
Alan Coxdeb91682008-07-22 11:13:08 +0100463
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100465 err = usb_submit_urb(urb, GFP_ATOMIC);
466 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800467 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468exit: ;
469}
470
David Howells7d12e782006-10-05 14:55:46 +0100471static void usa26_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472{
Alan Coxdeb91682008-07-22 11:13:08 +0100473 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474}
475
476
David Howells7d12e782006-10-05 14:55:46 +0100477static void usa28_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478{
Alan Coxf035a8a2008-07-22 11:13:32 +0100479 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 struct usb_serial_port *port;
481 struct tty_struct *tty;
482 unsigned char *data;
483 struct keyspan_port_private *p_priv;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700484 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485
Alan Coxdeb91682008-07-22 11:13:08 +0100486 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487
Ming Leicdc97792008-02-24 18:41:47 +0800488 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 p_priv = usb_get_serial_port_data(port);
490 data = urb->transfer_buffer;
491
492 if (urb != p_priv->in_urbs[p_priv->in_flip])
493 return;
494
495 do {
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700496 if (status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 dbg("%s - nonzero status: %x on endpoint %d.",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800498 __func__, status, usb_pipeendpoint(urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 return;
500 }
501
Ming Leicdc97792008-02-24 18:41:47 +0800502 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 p_priv = usb_get_serial_port_data(port);
504 data = urb->transfer_buffer;
505
Alan Cox4a90f092008-10-13 10:39:46 +0100506 tty =tty_port_tty_get(&port->port);
507 if (tty && urb->actual_length) {
Alan Coxf035a8a2008-07-22 11:13:32 +0100508 tty_insert_flip_string(tty, data, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 tty_flip_buffer_push(tty);
510 }
Alan Cox4a90f092008-10-13 10:39:46 +0100511 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
513 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500514 err = usb_submit_urb(urb, GFP_ATOMIC);
515 if (err != 0)
516 dbg("%s - resubmit read urb failed. (%d)",
517 __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 p_priv->in_flip ^= 1;
519
520 urb = p_priv->in_urbs[p_priv->in_flip];
521 } while (urb->status != -EINPROGRESS);
522}
523
David Howells7d12e782006-10-05 14:55:46 +0100524static void usa28_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525{
Alan Coxdeb91682008-07-22 11:13:08 +0100526 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527}
528
David Howells7d12e782006-10-05 14:55:46 +0100529static void usa28_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530{
531 struct usb_serial_port *port;
532 struct keyspan_port_private *p_priv;
533
Ming Leicdc97792008-02-24 18:41:47 +0800534 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 p_priv = usb_get_serial_port_data(port);
536
537 if (p_priv->resend_cont) {
Alan Coxdeb91682008-07-22 11:13:08 +0100538 dbg("%s - sending setup", __func__);
539 keyspan_usa28_send_setup(port->serial, port,
540 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 }
542}
543
David Howells7d12e782006-10-05 14:55:46 +0100544static void usa28_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545{
546 int err;
547 unsigned char *data = urb->transfer_buffer;
548 struct keyspan_usa28_portStatusMessage *msg;
549 struct usb_serial *serial;
550 struct usb_serial_port *port;
551 struct keyspan_port_private *p_priv;
Alan Cox4a90f092008-10-13 10:39:46 +0100552 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700554 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555
Ming Leicdc97792008-02-24 18:41:47 +0800556 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700558 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800559 dbg("%s - nonzero status: %x", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 return;
561 }
562
563 if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800564 dbg("%s - bad length %d", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 goto exit;
566 }
567
Harvey Harrison441b62c2008-03-03 16:08:34 -0800568 /*dbg("%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 data[0], data[1], data[2], data[3], data[4], data[5],
570 data[6], data[7], data[8], data[9], data[10], data[11]);*/
Alan Coxdeb91682008-07-22 11:13:08 +0100571
572 /* Now do something useful with the data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 msg = (struct keyspan_usa28_portStatusMessage *)data;
574
Alan Coxdeb91682008-07-22 11:13:08 +0100575 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 if (msg->port >= serial->num_ports) {
Alan Coxdeb91682008-07-22 11:13:08 +0100577 dbg("%s - Unexpected port number %d", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 goto exit;
579 }
580 port = serial->port[msg->port];
581 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100582
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 /* Update handshaking pin state information */
584 old_dcd_state = p_priv->dcd_state;
585 p_priv->cts_state = ((msg->cts) ? 1 : 0);
586 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
587 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
588 p_priv->ri_state = ((msg->ri) ? 1 : 0);
589
Alan Cox4a90f092008-10-13 10:39:46 +0100590 if( old_dcd_state != p_priv->dcd_state && old_dcd_state) {
591 tty = tty_port_tty_get(&port->port);
592 if (tty && !C_CLOCAL(tty))
593 tty_hangup(tty);
594 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 }
596
597 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100598 err = usb_submit_urb(urb, GFP_ATOMIC);
599 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800600 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601exit: ;
602}
603
David Howells7d12e782006-10-05 14:55:46 +0100604static void usa28_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605{
Alan Coxdeb91682008-07-22 11:13:08 +0100606 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607}
608
609
David Howells7d12e782006-10-05 14:55:46 +0100610static void usa49_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611{
612 struct usb_serial *serial;
613 struct usb_serial_port *port;
614 struct keyspan_port_private *p_priv;
615 int i;
616
Alan Coxdeb91682008-07-22 11:13:08 +0100617 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618
Ming Leicdc97792008-02-24 18:41:47 +0800619 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 for (i = 0; i < serial->num_ports; ++i) {
621 port = serial->port[i];
622 p_priv = usb_get_serial_port_data(port);
623
624 if (p_priv->resend_cont) {
Alan Coxdeb91682008-07-22 11:13:08 +0100625 dbg("%s - sending setup", __func__);
626 keyspan_usa49_send_setup(serial, port,
627 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 break;
629 }
630 }
631}
632
633 /* This is actually called glostat in the Keyspan
634 doco */
David Howells7d12e782006-10-05 14:55:46 +0100635static void usa49_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636{
637 int err;
638 unsigned char *data = urb->transfer_buffer;
639 struct keyspan_usa49_portStatusMessage *msg;
640 struct usb_serial *serial;
641 struct usb_serial_port *port;
642 struct keyspan_port_private *p_priv;
643 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700644 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645
Alan Coxdeb91682008-07-22 11:13:08 +0100646 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647
Ming Leicdc97792008-02-24 18:41:47 +0800648 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700650 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800651 dbg("%s - nonzero status: %x", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 return;
653 }
654
Alan Coxdeb91682008-07-22 11:13:08 +0100655 if (urb->actual_length !=
656 sizeof(struct keyspan_usa49_portStatusMessage)) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800657 dbg("%s - bad length %d", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 goto exit;
659 }
660
Harvey Harrison441b62c2008-03-03 16:08:34 -0800661 /*dbg(" %x %x %x %x %x %x %x %x %x %x %x", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 data[0], data[1], data[2], data[3], data[4], data[5],
663 data[6], data[7], data[8], data[9], data[10]);*/
Alan Coxdeb91682008-07-22 11:13:08 +0100664
665 /* Now do something useful with the data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 msg = (struct keyspan_usa49_portStatusMessage *)data;
667
Alan Coxdeb91682008-07-22 11:13:08 +0100668 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669 if (msg->portNumber >= serial->num_ports) {
Alan Coxdeb91682008-07-22 11:13:08 +0100670 dbg("%s - Unexpected port number %d",
671 __func__, msg->portNumber);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 goto exit;
673 }
674 port = serial->port[msg->portNumber];
675 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100676
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 /* Update handshaking pin state information */
678 old_dcd_state = p_priv->dcd_state;
679 p_priv->cts_state = ((msg->cts) ? 1 : 0);
680 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
681 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
682 p_priv->ri_state = ((msg->ri) ? 1 : 0);
683
Alan Cox4a90f092008-10-13 10:39:46 +0100684 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
685 struct tty_struct *tty = tty_port_tty_get(&port->port);
686 if (tty && !C_CLOCAL(tty))
687 tty_hangup(tty);
688 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 }
690
Alan Coxdeb91682008-07-22 11:13:08 +0100691 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100692 err = usb_submit_urb(urb, GFP_ATOMIC);
693 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800694 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695exit: ;
696}
697
David Howells7d12e782006-10-05 14:55:46 +0100698static void usa49_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699{
Alan Coxdeb91682008-07-22 11:13:08 +0100700 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701}
702
David Howells7d12e782006-10-05 14:55:46 +0100703static void usa49_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704{
705 int i, err;
706 int endpoint;
707 struct usb_serial_port *port;
708 struct tty_struct *tty;
709 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700710 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
Alan Coxdeb91682008-07-22 11:13:08 +0100712 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713
714 endpoint = usb_pipeendpoint(urb->pipe);
715
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700716 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800717 dbg("%s - nonzero status: %x on endpoint %d.", __func__,
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700718 status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 return;
720 }
721
Ming Leicdc97792008-02-24 18:41:47 +0800722 port = urb->context;
Alan Cox4a90f092008-10-13 10:39:46 +0100723 tty = tty_port_tty_get(&port->port);
Alan Cox3004e532008-01-03 16:59:04 +0000724 if (tty && urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 /* 0x80 bit is error flag */
726 if ((data[0] & 0x80) == 0) {
727 /* no error on any byte */
Alan Coxf035a8a2008-07-22 11:13:32 +0100728 tty_insert_flip_string(tty, data + 1,
729 urb->actual_length - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 } else {
731 /* some bytes had errors, every byte has status */
732 for (i = 0; i + 1 < urb->actual_length; i += 2) {
733 int stat = data[i], flag = 0;
734 if (stat & RXERROR_OVERRUN)
735 flag |= TTY_OVERRUN;
736 if (stat & RXERROR_FRAMING)
737 flag |= TTY_FRAME;
738 if (stat & RXERROR_PARITY)
739 flag |= TTY_PARITY;
740 /* XXX should handle break (0x10) */
741 tty_insert_flip_char(tty, data[i+1], flag);
742 }
743 }
744 tty_flip_buffer_push(tty);
745 }
Alan Cox4a90f092008-10-13 10:39:46 +0100746 tty_kref_put(tty);
Alan Coxdeb91682008-07-22 11:13:08 +0100747
748 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500749 err = usb_submit_urb(urb, GFP_ATOMIC);
750 if (err != 0)
751 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752}
753
Lucy McCoy0ca12682007-05-18 12:10:41 -0700754static void usa49wg_indat_callback(struct urb *urb)
755{
756 int i, len, x, err;
757 struct usb_serial *serial;
758 struct usb_serial_port *port;
759 struct tty_struct *tty;
760 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700761 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700762
Alan Coxdeb91682008-07-22 11:13:08 +0100763 dbg("%s", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700764
765 serial = urb->context;
766
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700767 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800768 dbg("%s - nonzero status: %x", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700769 return;
770 }
771
772 /* inbound data is in the form P#, len, status, data */
773 i = 0;
774 len = 0;
775
776 if (urb->actual_length) {
777 while (i < urb->actual_length) {
778
779 /* Check port number from message*/
780 if (data[i] >= serial->num_ports) {
Alan Coxdeb91682008-07-22 11:13:08 +0100781 dbg("%s - Unexpected port number %d",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800782 __func__, data[i]);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700783 return;
784 }
785 port = serial->port[data[i++]];
Alan Cox4a90f092008-10-13 10:39:46 +0100786 tty = tty_port_tty_get(&port->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700787 len = data[i++];
788
789 /* 0x80 bit is error flag */
790 if ((data[i] & 0x80) == 0) {
791 /* no error on any byte */
792 i++;
793 for (x = 1; x < len ; ++x)
Alan Stern1f871582010-02-17 10:05:47 -0500794 tty_insert_flip_char(tty, data[i++], 0);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700795 } else {
796 /*
797 * some bytes had errors, every byte has status
798 */
799 for (x = 0; x + 1 < len; x += 2) {
800 int stat = data[i], flag = 0;
801 if (stat & RXERROR_OVERRUN)
802 flag |= TTY_OVERRUN;
803 if (stat & RXERROR_FRAMING)
804 flag |= TTY_FRAME;
805 if (stat & RXERROR_PARITY)
806 flag |= TTY_PARITY;
807 /* XXX should handle break (0x10) */
Alan Stern1f871582010-02-17 10:05:47 -0500808 tty_insert_flip_char(tty,
Lucy McCoy0ca12682007-05-18 12:10:41 -0700809 data[i+1], flag);
810 i += 2;
811 }
812 }
Alan Stern1f871582010-02-17 10:05:47 -0500813 tty_flip_buffer_push(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100814 tty_kref_put(tty);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700815 }
816 }
817
818 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700819 err = usb_submit_urb(urb, GFP_ATOMIC);
820 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800821 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700822}
823
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824/* not used, usa-49 doesn't have per-port control endpoints */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700825static void usa49_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826{
Alan Coxdeb91682008-07-22 11:13:08 +0100827 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828}
829
Lucy McCoy0ca12682007-05-18 12:10:41 -0700830static void usa90_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831{
832 int i, err;
833 int endpoint;
834 struct usb_serial_port *port;
835 struct keyspan_port_private *p_priv;
836 struct tty_struct *tty;
837 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700838 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839
Alan Coxdeb91682008-07-22 11:13:08 +0100840 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841
842 endpoint = usb_pipeendpoint(urb->pipe);
843
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700844 if (status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 dbg("%s - nonzero status: %x on endpoint %d.",
Harvey Harrison441b62c2008-03-03 16:08:34 -0800846 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 return;
848 }
849
Ming Leicdc97792008-02-24 18:41:47 +0800850 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 p_priv = usb_get_serial_port_data(port);
852
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 if (urb->actual_length) {
Alan Cox4a90f092008-10-13 10:39:46 +0100854 tty = tty_port_tty_get(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 /* if current mode is DMA, looks like usa28 format
Alan Coxdeb91682008-07-22 11:13:08 +0100856 otherwise looks like usa26 data format */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857
Alan Coxf035a8a2008-07-22 11:13:32 +0100858 if (p_priv->baud > 57600)
859 tty_insert_flip_string(tty, data, urb->actual_length);
860 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 /* 0x80 bit is error flag */
862 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100863 /* no errors on individual bytes, only
864 possible overrun err*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 if (data[0] & RXERROR_OVERRUN)
Alan Coxdeb91682008-07-22 11:13:08 +0100866 err = TTY_OVERRUN;
867 else
868 err = 0;
869 for (i = 1; i < urb->actual_length ; ++i)
870 tty_insert_flip_char(tty, data[i],
871 err);
872 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 /* some bytes had errors, every byte has status */
Harvey Harrison441b62c2008-03-03 16:08:34 -0800874 dbg("%s - RX error!!!!", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 for (i = 0; i + 1 < urb->actual_length; i += 2) {
876 int stat = data[i], flag = 0;
877 if (stat & RXERROR_OVERRUN)
878 flag |= TTY_OVERRUN;
879 if (stat & RXERROR_FRAMING)
880 flag |= TTY_FRAME;
881 if (stat & RXERROR_PARITY)
882 flag |= TTY_PARITY;
883 /* XXX should handle break (0x10) */
Alan Coxdeb91682008-07-22 11:13:08 +0100884 tty_insert_flip_char(tty, data[i+1],
885 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 }
887 }
888 }
889 tty_flip_buffer_push(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100890 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 }
Alan Coxdeb91682008-07-22 11:13:08 +0100892
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500894 err = usb_submit_urb(urb, GFP_ATOMIC);
895 if (err != 0)
896 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897}
898
899
David Howells7d12e782006-10-05 14:55:46 +0100900static void usa90_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901{
902 unsigned char *data = urb->transfer_buffer;
903 struct keyspan_usa90_portStatusMessage *msg;
904 struct usb_serial *serial;
905 struct usb_serial_port *port;
906 struct keyspan_port_private *p_priv;
Alan Cox4a90f092008-10-13 10:39:46 +0100907 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700909 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910
Ming Leicdc97792008-02-24 18:41:47 +0800911 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700913 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800914 dbg("%s - nonzero status: %x", __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 return;
916 }
917 if (urb->actual_length < 14) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800918 dbg("%s - %d byte report??", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 goto exit;
920 }
921
922 msg = (struct keyspan_usa90_portStatusMessage *)data;
923
924 /* Now do something useful with the data */
925
926 port = serial->port[0];
927 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100928
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 /* Update handshaking pin state information */
930 old_dcd_state = p_priv->dcd_state;
931 p_priv->cts_state = ((msg->cts) ? 1 : 0);
932 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
933 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
934 p_priv->ri_state = ((msg->ri) ? 1 : 0);
935
Alan Cox4a90f092008-10-13 10:39:46 +0100936 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
937 tty = tty_port_tty_get(&port->port);
938 if (tty && !C_CLOCAL(tty))
939 tty_hangup(tty);
940 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 }
Alan Coxdeb91682008-07-22 11:13:08 +0100942
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100944 err = usb_submit_urb(urb, GFP_ATOMIC);
945 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -0800946 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947exit:
948 ;
949}
950
David Howells7d12e782006-10-05 14:55:46 +0100951static void usa90_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952{
953 struct usb_serial_port *port;
954 struct keyspan_port_private *p_priv;
955
Ming Leicdc97792008-02-24 18:41:47 +0800956 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 p_priv = usb_get_serial_port_data(port);
958
959 if (p_priv->resend_cont) {
Alan Coxdeb91682008-07-22 11:13:08 +0100960 dbg("%s - sending setup", __func__);
961 keyspan_usa90_send_setup(port->serial, port,
962 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 }
964}
965
Lucy McCoy0ca12682007-05-18 12:10:41 -0700966/* Status messages from the 28xg */
967static void usa67_instat_callback(struct urb *urb)
968{
969 int err;
970 unsigned char *data = urb->transfer_buffer;
971 struct keyspan_usa67_portStatusMessage *msg;
972 struct usb_serial *serial;
973 struct usb_serial_port *port;
974 struct keyspan_port_private *p_priv;
975 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700976 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700977
Alan Coxdeb91682008-07-22 11:13:08 +0100978 dbg("%s", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700979
980 serial = urb->context;
981
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700982 if (status) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800983 dbg("%s - nonzero status: %x", __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700984 return;
985 }
986
Alan Coxdeb91682008-07-22 11:13:08 +0100987 if (urb->actual_length !=
988 sizeof(struct keyspan_usa67_portStatusMessage)) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800989 dbg("%s - bad length %d", __func__, urb->actual_length);
Lucy McCoy0ca12682007-05-18 12:10:41 -0700990 return;
991 }
992
993
994 /* Now do something useful with the data */
995 msg = (struct keyspan_usa67_portStatusMessage *)data;
996
997 /* Check port number from message and retrieve private data */
998 if (msg->port >= serial->num_ports) {
Alan Coxdeb91682008-07-22 11:13:08 +0100999 dbg("%s - Unexpected port number %d", __func__, msg->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001000 return;
1001 }
1002
1003 port = serial->port[msg->port];
1004 p_priv = usb_get_serial_port_data(port);
1005
1006 /* Update handshaking pin state information */
1007 old_dcd_state = p_priv->dcd_state;
1008 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
1009 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
1010
Alan Cox4a90f092008-10-13 10:39:46 +01001011 if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
1012 struct tty_struct *tty = tty_port_tty_get(&port->port);
1013 if (tty && !C_CLOCAL(tty))
1014 tty_hangup(tty);
1015 tty_kref_put(tty);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001016 }
1017
1018 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -07001019 err = usb_submit_urb(urb, GFP_ATOMIC);
1020 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08001021 dbg("%s - resubmit read urb failed. (%d)", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001022}
1023
1024static void usa67_glocont_callback(struct urb *urb)
1025{
1026 struct usb_serial *serial;
1027 struct usb_serial_port *port;
1028 struct keyspan_port_private *p_priv;
1029 int i;
1030
Alan Coxdeb91682008-07-22 11:13:08 +01001031 dbg("%s", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001032
1033 serial = urb->context;
1034 for (i = 0; i < serial->num_ports; ++i) {
1035 port = serial->port[i];
1036 p_priv = usb_get_serial_port_data(port);
1037
1038 if (p_priv->resend_cont) {
Alan Coxdeb91682008-07-22 11:13:08 +01001039 dbg("%s - sending setup", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001040 keyspan_usa67_send_setup(serial, port,
1041 p_priv->resend_cont - 1);
1042 break;
1043 }
1044 }
1045}
1046
Alan Cox95da3102008-07-22 11:09:07 +01001047static int keyspan_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048{
Alan Cox95da3102008-07-22 11:09:07 +01001049 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 struct keyspan_port_private *p_priv;
1051 const struct keyspan_device_details *d_details;
1052 int flip;
1053 int data_len;
1054 struct urb *this_urb;
1055
Harvey Harrison441b62c2008-03-03 16:08:34 -08001056 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 p_priv = usb_get_serial_port_data(port);
1058 d_details = p_priv->device_details;
1059
Alan Coxa5b6f602008-04-08 17:16:06 +01001060 /* FIXME: locking */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 if (d_details->msg_format == msg_usa90)
Alan Coxdeb91682008-07-22 11:13:08 +01001062 data_len = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 else
1064 data_len = 63;
1065
1066 flip = p_priv->out_flip;
1067
1068 /* Check both endpoints to see if any are available. */
Alan Coxdeb91682008-07-22 11:13:08 +01001069 this_urb = p_priv->out_urbs[flip];
1070 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001072 return data_len;
1073 flip = (flip + 1) & d_details->outdat_endp_flip;
1074 this_urb = p_priv->out_urbs[flip];
1075 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001077 return data_len;
1078 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 }
Alan Coxa5b6f602008-04-08 17:16:06 +01001080 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081}
1082
1083
Alan Coxa509a7e2009-09-19 13:13:26 -07001084static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085{
Andrew Mortonf78ba152007-11-28 16:21:54 -08001086 struct keyspan_port_private *p_priv;
1087 struct keyspan_serial_private *s_priv;
1088 struct usb_serial *serial = port->serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 const struct keyspan_device_details *d_details;
1090 int i, err;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001091 int baud_rate, device_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 struct urb *urb;
Alan Cox95da3102008-07-22 11:09:07 +01001093 unsigned int cflag = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094
1095 s_priv = usb_get_serial_data(serial);
1096 p_priv = usb_get_serial_port_data(port);
1097 d_details = p_priv->device_details;
Borislav Petkov7eea4362007-11-14 17:00:39 -08001098
Harvey Harrison441b62c2008-03-03 16:08:34 -08001099 dbg("%s - port%d.", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100
1101 /* Set some sane defaults */
1102 p_priv->rts_state = 1;
1103 p_priv->dtr_state = 1;
1104 p_priv->baud = 9600;
1105
1106 /* force baud and lcr to be set on open */
1107 p_priv->old_baud = 0;
1108 p_priv->old_cflag = 0;
1109
1110 p_priv->out_flip = 0;
1111 p_priv->in_flip = 0;
1112
1113 /* Reset low level data toggle and start reading from endpoints */
1114 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001115 urb = p_priv->in_urbs[i];
1116 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118
Alan Coxdeb91682008-07-22 11:13:08 +01001119 /* make sure endpoint data toggle is synchronized
1120 with the device */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 usb_clear_halt(urb->dev, urb->pipe);
Alan Coxdeb91682008-07-22 11:13:08 +01001122 err = usb_submit_urb(urb, GFP_KERNEL);
1123 if (err != 0)
1124 dbg("%s - submit urb %d failed (%d)",
1125 __func__, i, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 }
1127
1128 /* Reset low level data toggle on out endpoints */
1129 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001130 urb = p_priv->out_urbs[i];
1131 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 continue;
Alan Coxdeb91682008-07-22 11:13:08 +01001133 /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
1134 usb_pipeout(urb->pipe), 0); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 }
1136
Andrew Mortonf78ba152007-11-28 16:21:54 -08001137 /* get the terminal config for the setup message now so we don't
1138 * need to send 2 of them */
1139
Andrew Mortonf78ba152007-11-28 16:21:54 -08001140 device_port = port->number - port->serial->minor;
Alan Cox95da3102008-07-22 11:09:07 +01001141 if (tty) {
1142 cflag = tty->termios->c_cflag;
1143 /* Baud rate calculation takes baud rate as an integer
1144 so other rates can be generated if desired. */
1145 baud_rate = tty_get_baud_rate(tty);
1146 /* If no match or invalid, leave as default */
1147 if (baud_rate >= 0
1148 && d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
1149 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
1150 p_priv->baud = baud_rate;
1151 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001152 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001153 /* set CTS/RTS handshake etc. */
1154 p_priv->cflag = cflag;
1155 p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none;
1156
1157 keyspan_send_setup(port, 1);
Alan Coxdeb91682008-07-22 11:13:08 +01001158 /* mdelay(100); */
1159 /* keyspan_set_termios(port, NULL); */
Andrew Mortonf78ba152007-11-28 16:21:54 -08001160
Alan Coxa5b6f602008-04-08 17:16:06 +01001161 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162}
1163
1164static inline void stop_urb(struct urb *urb)
1165{
Greg Kroah-Hartman242cf672005-07-29 16:11:07 -04001166 if (urb && urb->status == -EINPROGRESS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 usb_kill_urb(urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168}
1169
Alan Cox335f8512009-06-11 12:26:29 +01001170static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
1171{
1172 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
1173
1174 p_priv->rts_state = on;
1175 p_priv->dtr_state = on;
1176 keyspan_send_setup(port, 0);
1177}
1178
1179static void keyspan_close(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180{
1181 int i;
1182 struct usb_serial *serial = port->serial;
1183 struct keyspan_serial_private *s_priv;
1184 struct keyspan_port_private *p_priv;
1185
Harvey Harrison441b62c2008-03-03 16:08:34 -08001186 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 s_priv = usb_get_serial_data(serial);
1188 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +01001189
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 p_priv->rts_state = 0;
1191 p_priv->dtr_state = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001192
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193 if (serial->dev) {
1194 keyspan_send_setup(port, 2);
1195 /* pilot-xfer seems to work best with this delay */
1196 mdelay(100);
Alan Coxdeb91682008-07-22 11:13:08 +01001197 /* keyspan_set_termios(port, NULL); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 }
1199
1200 /*while (p_priv->outcont_urb->status == -EINPROGRESS) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001201 dbg("%s - urb in progress", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 }*/
1203
1204 p_priv->out_flip = 0;
1205 p_priv->in_flip = 0;
1206
1207 if (serial->dev) {
1208 /* Stop reading/writing urbs */
1209 stop_urb(p_priv->inack_urb);
1210 /* stop_urb(p_priv->outcont_urb); */
1211 for (i = 0; i < 2; i++) {
1212 stop_urb(p_priv->in_urbs[i]);
1213 stop_urb(p_priv->out_urbs[i]);
1214 }
1215 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216}
1217
Alan Coxdeb91682008-07-22 11:13:08 +01001218/* download the firmware to a pre-renumeration device */
1219static int keyspan_fake_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220{
1221 int response;
David Woodhouse2971c572008-05-30 14:04:03 +03001222 const struct ihex_binrec *record;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 char *fw_name;
David Woodhouse2971c572008-05-30 14:04:03 +03001224 const struct firmware *fw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225
1226 dbg("Keyspan startup version %04x product %04x",
1227 le16_to_cpu(serial->dev->descriptor.bcdDevice),
1228 le16_to_cpu(serial->dev->descriptor.idProduct));
Alan Coxdeb91682008-07-22 11:13:08 +01001229
1230 if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000)
1231 != 0x8000) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 dbg("Firmware already loaded. Quitting.");
Alan Coxdeb91682008-07-22 11:13:08 +01001233 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 }
1235
1236 /* Select firmware image on the basis of idProduct */
1237 switch (le16_to_cpu(serial->dev->descriptor.idProduct)) {
1238 case keyspan_usa28_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001239 fw_name = "keyspan/usa28.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 break;
1241
1242 case keyspan_usa28x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001243 fw_name = "keyspan/usa28x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 break;
1245
1246 case keyspan_usa28xa_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001247 fw_name = "keyspan/usa28xa.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 break;
1249
1250 case keyspan_usa28xb_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001251 fw_name = "keyspan/usa28xb.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 break;
1253
1254 case keyspan_usa19_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001255 fw_name = "keyspan/usa19.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001257
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 case keyspan_usa19qi_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001259 fw_name = "keyspan/usa19qi.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001261
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 case keyspan_mpr_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001263 fw_name = "keyspan/mpr.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 break;
1265
1266 case keyspan_usa19qw_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001267 fw_name = "keyspan/usa19qw.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001269
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 case keyspan_usa18x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001271 fw_name = "keyspan/usa18x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001273
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274 case keyspan_usa19w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001275 fw_name = "keyspan/usa19w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001277
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 case keyspan_usa49w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001279 fw_name = "keyspan/usa49w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 break;
1281
1282 case keyspan_usa49wlc_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001283 fw_name = "keyspan/usa49wlc.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 break;
1285
1286 default:
David Woodhouse2971c572008-05-30 14:04:03 +03001287 dev_err(&serial->dev->dev, "Unknown product ID (%04x)\n",
1288 le16_to_cpu(serial->dev->descriptor.idProduct));
1289 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 }
1291
David Woodhouse2971c572008-05-30 14:04:03 +03001292 if (request_ihex_firmware(&fw, fw_name, &serial->dev->dev)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 dev_err(&serial->dev->dev, "Required keyspan firmware image (%s) unavailable.\n", fw_name);
1294 return(1);
1295 }
1296
1297 dbg("Uploading Keyspan %s firmware.", fw_name);
1298
1299 /* download the firmware image */
1300 response = ezusb_set_reset(serial, 1);
1301
David Woodhouse2971c572008-05-30 14:04:03 +03001302 record = (const struct ihex_binrec *)fw->data;
1303
1304 while (record) {
1305 response = ezusb_writememory(serial, be32_to_cpu(record->addr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 (unsigned char *)record->data,
David Woodhouse2971c572008-05-30 14:04:03 +03001307 be16_to_cpu(record->len), 0xa0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 if (response < 0) {
Alan Coxdeb91682008-07-22 11:13:08 +01001309 dev_err(&serial->dev->dev, "ezusb_writememory failed for Keyspan firmware (%d %04X %p %d)\n",
David Woodhouse2971c572008-05-30 14:04:03 +03001310 response, be32_to_cpu(record->addr),
1311 record->data, be16_to_cpu(record->len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 break;
1313 }
David Woodhouse2971c572008-05-30 14:04:03 +03001314 record = ihex_next_binrec(record);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315 }
David Woodhouse2971c572008-05-30 14:04:03 +03001316 release_firmware(fw);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 /* bring device out of reset. Renumeration will occur in a
1318 moment and the new device will bind to the real driver */
1319 response = ezusb_set_reset(serial, 0);
1320
1321 /* we don't want this device to have a driver assigned to it. */
Alan Coxdeb91682008-07-22 11:13:08 +01001322 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323}
1324
1325/* Helper functions used by keyspan_setup_urbs */
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001326static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *serial,
1327 int endpoint)
1328{
1329 struct usb_host_interface *iface_desc;
1330 struct usb_endpoint_descriptor *ep;
1331 int i;
1332
1333 iface_desc = serial->interface->cur_altsetting;
1334 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1335 ep = &iface_desc->endpoint[i].desc;
1336 if (ep->bEndpointAddress == endpoint)
1337 return ep;
1338 }
1339 dev_warn(&serial->interface->dev, "found no endpoint descriptor for "
1340 "endpoint %x\n", endpoint);
1341 return NULL;
1342}
1343
Alan Coxdeb91682008-07-22 11:13:08 +01001344static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 int dir, void *ctx, char *buf, int len,
David Howells7d12e782006-10-05 14:55:46 +01001346 void (*callback)(struct urb *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347{
1348 struct urb *urb;
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001349 struct usb_endpoint_descriptor const *ep_desc;
1350 char const *ep_type_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351
1352 if (endpoint == -1)
1353 return NULL; /* endpoint not needed */
1354
Alan Coxdeb91682008-07-22 11:13:08 +01001355 dbg("%s - alloc for endpoint %d.", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
1357 if (urb == NULL) {
Alan Coxdeb91682008-07-22 11:13:08 +01001358 dbg("%s - alloc for endpoint %d failed.", __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 return NULL;
1360 }
1361
Lucy McCoy0ca12682007-05-18 12:10:41 -07001362 if (endpoint == 0) {
1363 /* control EP filled in when used */
1364 return urb;
1365 }
1366
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001367 ep_desc = find_ep(serial, endpoint);
1368 if (!ep_desc) {
1369 /* leak the urb, something's wrong and the callers don't care */
1370 return urb;
1371 }
1372 if (usb_endpoint_xfer_int(ep_desc)) {
1373 ep_type_name = "INT";
1374 usb_fill_int_urb(urb, serial->dev,
1375 usb_sndintpipe(serial->dev, endpoint) | dir,
1376 buf, len, callback, ctx,
1377 ep_desc->bInterval);
1378 } else if (usb_endpoint_xfer_bulk(ep_desc)) {
1379 ep_type_name = "BULK";
1380 usb_fill_bulk_urb(urb, serial->dev,
1381 usb_sndbulkpipe(serial->dev, endpoint) | dir,
1382 buf, len, callback, ctx);
1383 } else {
1384 dev_warn(&serial->interface->dev,
1385 "unsupported endpoint type %x\n",
Julia Lawall2e0fe702008-12-29 11:22:14 +01001386 usb_endpoint_type(ep_desc));
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001387 usb_free_urb(urb);
1388 return NULL;
1389 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001391 dbg("%s - using urb %p for %s endpoint %x",
1392 __func__, urb, ep_type_name, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 return urb;
1394}
1395
1396static struct callbacks {
David Howells7d12e782006-10-05 14:55:46 +01001397 void (*instat_callback)(struct urb *);
1398 void (*glocont_callback)(struct urb *);
1399 void (*indat_callback)(struct urb *);
1400 void (*outdat_callback)(struct urb *);
1401 void (*inack_callback)(struct urb *);
1402 void (*outcont_callback)(struct urb *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403} keyspan_callbacks[] = {
1404 {
1405 /* msg_usa26 callbacks */
1406 .instat_callback = usa26_instat_callback,
1407 .glocont_callback = usa26_glocont_callback,
1408 .indat_callback = usa26_indat_callback,
1409 .outdat_callback = usa2x_outdat_callback,
1410 .inack_callback = usa26_inack_callback,
1411 .outcont_callback = usa26_outcont_callback,
1412 }, {
1413 /* msg_usa28 callbacks */
1414 .instat_callback = usa28_instat_callback,
1415 .glocont_callback = usa28_glocont_callback,
1416 .indat_callback = usa28_indat_callback,
1417 .outdat_callback = usa2x_outdat_callback,
1418 .inack_callback = usa28_inack_callback,
1419 .outcont_callback = usa28_outcont_callback,
1420 }, {
1421 /* msg_usa49 callbacks */
1422 .instat_callback = usa49_instat_callback,
1423 .glocont_callback = usa49_glocont_callback,
1424 .indat_callback = usa49_indat_callback,
1425 .outdat_callback = usa2x_outdat_callback,
1426 .inack_callback = usa49_inack_callback,
1427 .outcont_callback = usa49_outcont_callback,
1428 }, {
1429 /* msg_usa90 callbacks */
1430 .instat_callback = usa90_instat_callback,
Alan Coxdeb91682008-07-22 11:13:08 +01001431 .glocont_callback = usa28_glocont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 .indat_callback = usa90_indat_callback,
1433 .outdat_callback = usa2x_outdat_callback,
1434 .inack_callback = usa28_inack_callback,
1435 .outcont_callback = usa90_outcont_callback,
Lucy McCoy0ca12682007-05-18 12:10:41 -07001436 }, {
1437 /* msg_usa67 callbacks */
1438 .instat_callback = usa67_instat_callback,
1439 .glocont_callback = usa67_glocont_callback,
1440 .indat_callback = usa26_indat_callback,
1441 .outdat_callback = usa2x_outdat_callback,
1442 .inack_callback = usa26_inack_callback,
1443 .outcont_callback = usa26_outcont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444 }
1445};
1446
1447 /* Generic setup urbs function that uses
1448 data in device_details */
1449static void keyspan_setup_urbs(struct usb_serial *serial)
1450{
1451 int i, j;
1452 struct keyspan_serial_private *s_priv;
1453 const struct keyspan_device_details *d_details;
1454 struct usb_serial_port *port;
1455 struct keyspan_port_private *p_priv;
1456 struct callbacks *cback;
1457 int endp;
1458
Alan Coxdeb91682008-07-22 11:13:08 +01001459 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460
1461 s_priv = usb_get_serial_data(serial);
1462 d_details = s_priv->device_details;
1463
Alan Coxdeb91682008-07-22 11:13:08 +01001464 /* Setup values for the various callback routines */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 cback = &keyspan_callbacks[d_details->msg_format];
1466
Alan Coxdeb91682008-07-22 11:13:08 +01001467 /* Allocate and set up urbs for each one that is in use,
1468 starting with instat endpoints */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 s_priv->instat_urb = keyspan_setup_urb
1470 (serial, d_details->instat_endpoint, USB_DIR_IN,
1471 serial, s_priv->instat_buf, INSTAT_BUFLEN,
1472 cback->instat_callback);
1473
Lucy McCoy0ca12682007-05-18 12:10:41 -07001474 s_priv->indat_urb = keyspan_setup_urb
1475 (serial, d_details->indat_endpoint, USB_DIR_IN,
1476 serial, s_priv->indat_buf, INDAT49W_BUFLEN,
1477 usa49wg_indat_callback);
1478
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 s_priv->glocont_urb = keyspan_setup_urb
1480 (serial, d_details->glocont_endpoint, USB_DIR_OUT,
1481 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
1482 cback->glocont_callback);
1483
Alan Coxdeb91682008-07-22 11:13:08 +01001484 /* Setup endpoints for each port specific thing */
1485 for (i = 0; i < d_details->num_ports; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486 port = serial->port[i];
1487 p_priv = usb_get_serial_port_data(port);
1488
1489 /* Do indat endpoints first, once for each flip */
1490 endp = d_details->indat_endpoints[i];
1491 for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) {
1492 p_priv->in_urbs[j] = keyspan_setup_urb
1493 (serial, endp, USB_DIR_IN, port,
1494 p_priv->in_buffer[j], 64,
1495 cback->indat_callback);
1496 }
1497 for (; j < 2; ++j)
1498 p_priv->in_urbs[j] = NULL;
1499
1500 /* outdat endpoints also have flip */
1501 endp = d_details->outdat_endpoints[i];
1502 for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) {
1503 p_priv->out_urbs[j] = keyspan_setup_urb
1504 (serial, endp, USB_DIR_OUT, port,
1505 p_priv->out_buffer[j], 64,
1506 cback->outdat_callback);
1507 }
1508 for (; j < 2; ++j)
1509 p_priv->out_urbs[j] = NULL;
1510
1511 /* inack endpoint */
1512 p_priv->inack_urb = keyspan_setup_urb
1513 (serial, d_details->inack_endpoints[i], USB_DIR_IN,
1514 port, p_priv->inack_buffer, 1, cback->inack_callback);
1515
1516 /* outcont endpoint */
1517 p_priv->outcont_urb = keyspan_setup_urb
1518 (serial, d_details->outcont_endpoints[i], USB_DIR_OUT,
1519 port, p_priv->outcont_buffer, 64,
1520 cback->outcont_callback);
Alan Coxdeb91682008-07-22 11:13:08 +01001521 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522}
1523
1524/* usa19 function doesn't require prescaler */
1525static int keyspan_usa19_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
1526 u8 *rate_low, u8 *prescaler, int portnum)
1527{
1528 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001529 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 cnt; /* inverse of divisor (programmed into 8051) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531
Alan Coxdeb91682008-07-22 11:13:08 +01001532 dbg("%s - %d.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533
Alan Coxdeb91682008-07-22 11:13:08 +01001534 /* prevent divide by zero... */
1535 b16 = baud_rate * 16L;
1536 if (b16 == 0)
1537 return KEYSPAN_INVALID_BAUD_RATE;
1538 /* Any "standard" rate over 57k6 is marginal on the USA-19
1539 as we run out of divisor resolution. */
1540 if (baud_rate > 57600)
1541 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542
Alan Coxdeb91682008-07-22 11:13:08 +01001543 /* calculate the divisor and the counter (its inverse) */
1544 div = baudclk / b16;
1545 if (div == 0)
1546 return KEYSPAN_INVALID_BAUD_RATE;
1547 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549
Alan Coxdeb91682008-07-22 11:13:08 +01001550 if (div > 0xffff)
1551 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552
Alan Coxdeb91682008-07-22 11:13:08 +01001553 /* return the counter values if non-null */
1554 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001556 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001558 if (rate_low && rate_hi)
1559 dbg("%s - %d %02x %02x.",
1560 __func__, baud_rate, *rate_hi, *rate_low);
1561 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562}
1563
1564/* usa19hs function doesn't require prescaler */
1565static int keyspan_usa19hs_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
1566 u8 *rate_low, u8 *prescaler, int portnum)
1567{
1568 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001569 div; /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570
Alan Coxdeb91682008-07-22 11:13:08 +01001571 dbg("%s - %d.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572
Alan Coxdeb91682008-07-22 11:13:08 +01001573 /* prevent divide by zero... */
1574 b16 = baud_rate * 16L;
1575 if (b16 == 0)
1576 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577
Alan Coxdeb91682008-07-22 11:13:08 +01001578 /* calculate the divisor */
1579 div = baudclk / b16;
1580 if (div == 0)
1581 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582
Alan Coxdeb91682008-07-22 11:13:08 +01001583 if (div > 0xffff)
1584 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585
Alan Coxdeb91682008-07-22 11:13:08 +01001586 /* return the counter values if non-null */
1587 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001589
1590 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 *rate_hi = (u8) ((div >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001592
1593 if (rate_low && rate_hi)
1594 dbg("%s - %d %02x %02x.",
1595 __func__, baud_rate, *rate_hi, *rate_low);
1596
1597 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598}
1599
1600static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
1601 u8 *rate_low, u8 *prescaler, int portnum)
1602{
1603 u32 b16, /* baud rate times 16 (actual rate used internally) */
1604 clk, /* clock with 13/8 prescaler */
Alan Coxdeb91682008-07-22 11:13:08 +01001605 div, /* divisor using 13/8 prescaler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 res, /* resulting baud rate using 13/8 prescaler */
1607 diff, /* error using 13/8 prescaler */
1608 smallest_diff;
1609 u8 best_prescaler;
1610 int i;
1611
Alan Coxdeb91682008-07-22 11:13:08 +01001612 dbg("%s - %d.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613
Alan Coxdeb91682008-07-22 11:13:08 +01001614 /* prevent divide by zero */
1615 b16 = baud_rate * 16L;
1616 if (b16 == 0)
1617 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618
Alan Coxdeb91682008-07-22 11:13:08 +01001619 /* Calculate prescaler by trying them all and looking
1620 for best fit */
1621
1622 /* start with largest possible difference */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623 smallest_diff = 0xffffffff;
1624
1625 /* 0 is an invalid prescaler, used as a flag */
1626 best_prescaler = 0;
1627
Alan Coxdeb91682008-07-22 11:13:08 +01001628 for (i = 8; i <= 0xff; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 clk = (baudclk * 8) / (u32) i;
Alan Coxdeb91682008-07-22 11:13:08 +01001630
1631 div = clk / b16;
1632 if (div == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634
1635 res = clk / div;
Alan Coxdeb91682008-07-22 11:13:08 +01001636 diff = (res > b16) ? (res-b16) : (b16-res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637
Alan Coxdeb91682008-07-22 11:13:08 +01001638 if (diff < smallest_diff) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 best_prescaler = i;
1640 smallest_diff = diff;
1641 }
1642 }
1643
Alan Coxdeb91682008-07-22 11:13:08 +01001644 if (best_prescaler == 0)
1645 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646
1647 clk = (baudclk * 8) / (u32) best_prescaler;
1648 div = clk / b16;
1649
Alan Coxdeb91682008-07-22 11:13:08 +01001650 /* return the divisor and prescaler if non-null */
1651 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001653 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 *rate_hi = (u8) ((div >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 if (prescaler) {
1656 *prescaler = best_prescaler;
Harvey Harrison441b62c2008-03-03 16:08:34 -08001657 /* dbg("%s - %d %d", __func__, *prescaler, div); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 }
Alan Coxdeb91682008-07-22 11:13:08 +01001659 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660}
1661
1662 /* USA-28 supports different maximum baud rates on each port */
1663static int keyspan_usa28_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
1664 u8 *rate_low, u8 *prescaler, int portnum)
1665{
1666 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001667 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 cnt; /* inverse of divisor (programmed into 8051) */
1669
Alan Coxdeb91682008-07-22 11:13:08 +01001670 dbg("%s - %d.", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671
1672 /* prevent divide by zero */
Alan Coxdeb91682008-07-22 11:13:08 +01001673 b16 = baud_rate * 16L;
1674 if (b16 == 0)
1675 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676
Alan Coxdeb91682008-07-22 11:13:08 +01001677 /* calculate the divisor and the counter (its inverse) */
1678 div = KEYSPAN_USA28_BAUDCLK / b16;
1679 if (div == 0)
1680 return KEYSPAN_INVALID_BAUD_RATE;
1681 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683
Alan Coxdeb91682008-07-22 11:13:08 +01001684 /* check for out of range, based on portnum,
1685 and return result */
1686 if (portnum == 0) {
1687 if (div > 0xffff)
1688 return KEYSPAN_INVALID_BAUD_RATE;
1689 } else {
1690 if (portnum == 1) {
1691 if (div > 0xff)
1692 return KEYSPAN_INVALID_BAUD_RATE;
1693 } else
1694 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695 }
1696
1697 /* return the counter values if not NULL
1698 (port 1 will ignore retHi) */
Alan Coxdeb91682008-07-22 11:13:08 +01001699 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001701 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001703 dbg("%s - %d OK.", __func__, baud_rate);
1704 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705}
1706
1707static int keyspan_usa26_send_setup(struct usb_serial *serial,
1708 struct usb_serial_port *port,
1709 int reset_port)
1710{
Alan Coxdeb91682008-07-22 11:13:08 +01001711 struct keyspan_usa26_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 struct keyspan_serial_private *s_priv;
1713 struct keyspan_port_private *p_priv;
1714 const struct keyspan_device_details *d_details;
1715 int outcont_urb;
1716 struct urb *this_urb;
1717 int device_port, err;
1718
Alan Coxdeb91682008-07-22 11:13:08 +01001719 dbg("%s reset=%d", __func__, reset_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720
1721 s_priv = usb_get_serial_data(serial);
1722 p_priv = usb_get_serial_port_data(port);
1723 d_details = s_priv->device_details;
1724 device_port = port->number - port->serial->minor;
1725
1726 outcont_urb = d_details->outcont_endpoints[port->number];
1727 this_urb = p_priv->outcont_urb;
1728
Harvey Harrison441b62c2008-03-03 16:08:34 -08001729 dbg("%s - endpoint %d", __func__, usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730
1731 /* Make sure we have an urb then send the message */
1732 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001733 dbg("%s - oops no urb.", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 return -1;
1735 }
1736
1737 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001738 Don't overwrite resend for open/close condition. */
1739 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 p_priv->resend_cont = reset_port + 1;
1741 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +01001742 /* dbg("%s - already writing", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001744 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745 }
1746
Alan Coxdeb91682008-07-22 11:13:08 +01001747 memset(&msg, 0, sizeof(struct keyspan_usa26_portControlMessage));
1748
1749 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750 if (p_priv->old_baud != p_priv->baud) {
1751 p_priv->old_baud = p_priv->baud;
1752 msg.setClocking = 0xff;
1753 if (d_details->calculate_baud_rate
1754 (p_priv->baud, d_details->baudclk, &msg.baudHi,
Alan Coxdeb91682008-07-22 11:13:08 +01001755 &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1756 dbg("%s - Invalid baud rate %d requested, using 9600.",
1757 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758 msg.baudLo = 0;
1759 msg.baudHi = 125; /* Values for 9600 baud */
1760 msg.prescaler = 10;
1761 }
1762 msg.setPrescaler = 0xff;
1763 }
1764
1765 msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
1766 switch (p_priv->cflag & CSIZE) {
1767 case CS5:
1768 msg.lcr |= USA_DATABITS_5;
1769 break;
1770 case CS6:
1771 msg.lcr |= USA_DATABITS_6;
1772 break;
1773 case CS7:
1774 msg.lcr |= USA_DATABITS_7;
1775 break;
1776 case CS8:
1777 msg.lcr |= USA_DATABITS_8;
1778 break;
1779 }
1780 if (p_priv->cflag & PARENB) {
1781 /* note USA_PARITY_NONE == 0 */
1782 msg.lcr |= (p_priv->cflag & PARODD)?
Alan Coxdeb91682008-07-22 11:13:08 +01001783 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784 }
1785 msg.setLcr = 0xff;
1786
1787 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1788 msg.xonFlowControl = 0;
1789 msg.setFlowControl = 0xff;
1790 msg.forwardingLength = 16;
1791 msg.xonChar = 17;
1792 msg.xoffChar = 19;
1793
1794 /* Opening port */
1795 if (reset_port == 1) {
1796 msg._txOn = 1;
1797 msg._txOff = 0;
1798 msg.txFlush = 0;
1799 msg.txBreak = 0;
1800 msg.rxOn = 1;
1801 msg.rxOff = 0;
1802 msg.rxFlush = 1;
1803 msg.rxForward = 0;
1804 msg.returnStatus = 0;
1805 msg.resetDataToggle = 0xff;
1806 }
1807
1808 /* Closing port */
1809 else if (reset_port == 2) {
1810 msg._txOn = 0;
1811 msg._txOff = 1;
1812 msg.txFlush = 0;
1813 msg.txBreak = 0;
1814 msg.rxOn = 0;
1815 msg.rxOff = 1;
1816 msg.rxFlush = 1;
1817 msg.rxForward = 0;
1818 msg.returnStatus = 0;
1819 msg.resetDataToggle = 0;
1820 }
1821
1822 /* Sending intermediate configs */
1823 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001824 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825 msg._txOff = 0;
1826 msg.txFlush = 0;
1827 msg.txBreak = (p_priv->break_on);
1828 msg.rxOn = 0;
1829 msg.rxOff = 0;
1830 msg.rxFlush = 0;
1831 msg.rxForward = 0;
1832 msg.returnStatus = 0;
1833 msg.resetDataToggle = 0x0;
1834 }
1835
Alan Coxdeb91682008-07-22 11:13:08 +01001836 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837 msg.setTxTriState_setRts = 0xff;
1838 msg.txTriState_rts = p_priv->rts_state;
1839
1840 msg.setHskoa_setDtr = 0xff;
1841 msg.hskoa_dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01001842
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001844 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
1845
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 /* send the data out the device on control endpoint */
1847 this_urb->transfer_buffer_length = sizeof(msg);
1848
Alan Coxdeb91682008-07-22 11:13:08 +01001849 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1850 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08001851 dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852#if 0
1853 else {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001854 dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 outcont_urb, this_urb->transfer_buffer_length,
1856 usb_pipeendpoint(this_urb->pipe));
1857 }
1858#endif
1859
Alan Coxa5b6f602008-04-08 17:16:06 +01001860 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861}
1862
1863static int keyspan_usa28_send_setup(struct usb_serial *serial,
1864 struct usb_serial_port *port,
1865 int reset_port)
1866{
Alan Coxdeb91682008-07-22 11:13:08 +01001867 struct keyspan_usa28_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868 struct keyspan_serial_private *s_priv;
1869 struct keyspan_port_private *p_priv;
1870 const struct keyspan_device_details *d_details;
1871 struct urb *this_urb;
1872 int device_port, err;
1873
Alan Coxdeb91682008-07-22 11:13:08 +01001874 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875
1876 s_priv = usb_get_serial_data(serial);
1877 p_priv = usb_get_serial_port_data(port);
1878 d_details = s_priv->device_details;
1879 device_port = port->number - port->serial->minor;
1880
1881 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01001882 this_urb = p_priv->outcont_urb;
1883 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001884 dbg("%s - oops no urb.", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 return -1;
1886 }
1887
1888 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07001889 Don't overwrite resend for open/close condition. */
1890 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891 p_priv->resend_cont = reset_port + 1;
1892 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +01001893 dbg("%s already writing", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01001895 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 }
1897
Alan Coxdeb91682008-07-22 11:13:08 +01001898 memset(&msg, 0, sizeof(struct keyspan_usa28_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899
1900 msg.setBaudRate = 1;
1901 if (d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk,
Alan Coxdeb91682008-07-22 11:13:08 +01001902 &msg.baudHi, &msg.baudLo, NULL, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
1903 dbg("%s - Invalid baud rate requested %d.",
1904 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905 msg.baudLo = 0xff;
1906 msg.baudHi = 0xb2; /* Values for 9600 baud */
1907 }
1908
1909 /* If parity is enabled, we must calculate it ourselves. */
1910 msg.parity = 0; /* XXX for now */
1911
1912 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
1913 msg.xonFlowControl = 0;
1914
Alan Coxdeb91682008-07-22 11:13:08 +01001915 /* Do handshaking outputs, DTR is inverted relative to RTS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 msg.rts = p_priv->rts_state;
1917 msg.dtr = p_priv->dtr_state;
1918
1919 msg.forwardingLength = 16;
1920 msg.forwardMs = 10;
1921 msg.breakThreshold = 45;
1922 msg.xonChar = 17;
1923 msg.xoffChar = 19;
1924
1925 /*msg.returnStatus = 1;
1926 msg.resetDataToggle = 0xff;*/
1927 /* Opening port */
1928 if (reset_port == 1) {
1929 msg._txOn = 1;
1930 msg._txOff = 0;
1931 msg.txFlush = 0;
1932 msg.txForceXoff = 0;
1933 msg.txBreak = 0;
1934 msg.rxOn = 1;
1935 msg.rxOff = 0;
1936 msg.rxFlush = 1;
1937 msg.rxForward = 0;
1938 msg.returnStatus = 0;
1939 msg.resetDataToggle = 0xff;
1940 }
1941 /* Closing port */
1942 else if (reset_port == 2) {
1943 msg._txOn = 0;
1944 msg._txOff = 1;
1945 msg.txFlush = 0;
1946 msg.txForceXoff = 0;
1947 msg.txBreak = 0;
1948 msg.rxOn = 0;
1949 msg.rxOff = 1;
1950 msg.rxFlush = 1;
1951 msg.rxForward = 0;
1952 msg.returnStatus = 0;
1953 msg.resetDataToggle = 0;
1954 }
1955 /* Sending intermediate configs */
1956 else {
Alan Coxdeb91682008-07-22 11:13:08 +01001957 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 msg._txOff = 0;
1959 msg.txFlush = 0;
1960 msg.txForceXoff = 0;
1961 msg.txBreak = (p_priv->break_on);
1962 msg.rxOn = 0;
1963 msg.rxOff = 0;
1964 msg.rxFlush = 0;
1965 msg.rxForward = 0;
1966 msg.returnStatus = 0;
1967 msg.resetDataToggle = 0x0;
1968 }
1969
1970 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001971 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972
1973 /* send the data out the device on control endpoint */
1974 this_urb->transfer_buffer_length = sizeof(msg);
1975
Alan Coxdeb91682008-07-22 11:13:08 +01001976 err = usb_submit_urb(this_urb, GFP_ATOMIC);
1977 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08001978 dbg("%s - usb_submit_urb(setup) failed", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979#if 0
1980 else {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001981 dbg("%s - usb_submit_urb(setup) OK %d bytes", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982 this_urb->transfer_buffer_length);
1983 }
1984#endif
1985
Alan Coxa5b6f602008-04-08 17:16:06 +01001986 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987}
1988
1989static int keyspan_usa49_send_setup(struct usb_serial *serial,
1990 struct usb_serial_port *port,
1991 int reset_port)
1992{
Lucy McCoy0ca12682007-05-18 12:10:41 -07001993 struct keyspan_usa49_portControlMessage msg;
1994 struct usb_ctrlrequest *dr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995 struct keyspan_serial_private *s_priv;
1996 struct keyspan_port_private *p_priv;
1997 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 struct urb *this_urb;
1999 int err, device_port;
2000
Alan Coxdeb91682008-07-22 11:13:08 +01002001 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002
2003 s_priv = usb_get_serial_data(serial);
2004 p_priv = usb_get_serial_port_data(port);
2005 d_details = s_priv->device_details;
2006
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007 this_urb = s_priv->glocont_urb;
2008
Lucy McCoy0ca12682007-05-18 12:10:41 -07002009 /* Work out which port within the device is being setup */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010 device_port = port->number - port->serial->minor;
2011
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05302012 /* Make sure we have an urb then send the message */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002014 dbg("%s - oops no urb for port %d.", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015 return -1;
2016 }
2017
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05302018 dbg("%s - endpoint %d port %d (%d)",
2019 __func__, usb_pipeendpoint(this_urb->pipe),
2020 port->number, device_port);
2021
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07002023 Don't overwrite resend for open/close condition. */
2024 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025 p_priv->resend_cont = reset_port + 1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002026
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +01002028 /* dbg("%s - already writing", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002030 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031 }
2032
Alan Coxdeb91682008-07-22 11:13:08 +01002033 memset(&msg, 0, sizeof(struct keyspan_usa49_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034
2035 /*msg.portNumber = port->number;*/
2036 msg.portNumber = device_port;
Alan Coxdeb91682008-07-22 11:13:08 +01002037
2038 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039 if (p_priv->old_baud != p_priv->baud) {
2040 p_priv->old_baud = p_priv->baud;
2041 msg.setClocking = 0xff;
2042 if (d_details->calculate_baud_rate
2043 (p_priv->baud, d_details->baudclk, &msg.baudHi,
Alan Coxdeb91682008-07-22 11:13:08 +01002044 &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2045 dbg("%s - Invalid baud rate %d requested, using 9600.",
2046 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047 msg.baudLo = 0;
2048 msg.baudHi = 125; /* Values for 9600 baud */
2049 msg.prescaler = 10;
2050 }
Alan Coxdeb91682008-07-22 11:13:08 +01002051 /* msg.setPrescaler = 0xff; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052 }
2053
2054 msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
2055 switch (p_priv->cflag & CSIZE) {
2056 case CS5:
2057 msg.lcr |= USA_DATABITS_5;
2058 break;
2059 case CS6:
2060 msg.lcr |= USA_DATABITS_6;
2061 break;
2062 case CS7:
2063 msg.lcr |= USA_DATABITS_7;
2064 break;
2065 case CS8:
2066 msg.lcr |= USA_DATABITS_8;
2067 break;
2068 }
2069 if (p_priv->cflag & PARENB) {
2070 /* note USA_PARITY_NONE == 0 */
2071 msg.lcr |= (p_priv->cflag & PARODD)?
Alan Coxdeb91682008-07-22 11:13:08 +01002072 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073 }
2074 msg.setLcr = 0xff;
2075
2076 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2077 msg.xonFlowControl = 0;
2078 msg.setFlowControl = 0xff;
Alan Coxdeb91682008-07-22 11:13:08 +01002079
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 msg.forwardingLength = 16;
2081 msg.xonChar = 17;
2082 msg.xoffChar = 19;
2083
Alan Coxdeb91682008-07-22 11:13:08 +01002084 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085 if (reset_port == 1) {
2086 msg._txOn = 1;
2087 msg._txOff = 0;
2088 msg.txFlush = 0;
2089 msg.txBreak = 0;
2090 msg.rxOn = 1;
2091 msg.rxOff = 0;
2092 msg.rxFlush = 1;
2093 msg.rxForward = 0;
2094 msg.returnStatus = 0;
2095 msg.resetDataToggle = 0xff;
2096 msg.enablePort = 1;
2097 msg.disablePort = 0;
2098 }
2099 /* Closing port */
2100 else if (reset_port == 2) {
2101 msg._txOn = 0;
2102 msg._txOff = 1;
2103 msg.txFlush = 0;
2104 msg.txBreak = 0;
2105 msg.rxOn = 0;
2106 msg.rxOff = 1;
2107 msg.rxFlush = 1;
2108 msg.rxForward = 0;
2109 msg.returnStatus = 0;
2110 msg.resetDataToggle = 0;
2111 msg.enablePort = 0;
2112 msg.disablePort = 1;
2113 }
2114 /* Sending intermediate configs */
2115 else {
Alan Coxdeb91682008-07-22 11:13:08 +01002116 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117 msg._txOff = 0;
2118 msg.txFlush = 0;
2119 msg.txBreak = (p_priv->break_on);
2120 msg.rxOn = 0;
2121 msg.rxOff = 0;
2122 msg.rxFlush = 0;
2123 msg.rxForward = 0;
2124 msg.returnStatus = 0;
2125 msg.resetDataToggle = 0x0;
2126 msg.enablePort = 0;
2127 msg.disablePort = 0;
2128 }
2129
Alan Coxdeb91682008-07-22 11:13:08 +01002130 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 msg.setRts = 0xff;
2132 msg.rts = p_priv->rts_state;
2133
2134 msg.setDtr = 0xff;
2135 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002136
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137 p_priv->resend_cont = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138
Alan Coxdeb91682008-07-22 11:13:08 +01002139 /* if the device is a 49wg, we send control message on usb
2140 control EP 0 */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002141
2142 if (d_details->product_id == keyspan_usa49wg_product_id) {
2143 dr = (void *)(s_priv->ctrl_buf);
2144 dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT;
2145 dr->bRequest = 0xB0; /* 49wg control message */;
2146 dr->wValue = 0;
2147 dr->wIndex = 0;
2148 dr->wLength = cpu_to_le16(sizeof(msg));
2149
Alan Coxdeb91682008-07-22 11:13:08 +01002150 memcpy(s_priv->glocont_buf, &msg, sizeof(msg));
Lucy McCoy0ca12682007-05-18 12:10:41 -07002151
Alan Coxdeb91682008-07-22 11:13:08 +01002152 usb_fill_control_urb(this_urb, serial->dev,
2153 usb_sndctrlpipe(serial->dev, 0),
2154 (unsigned char *)dr, s_priv->glocont_buf,
2155 sizeof(msg), usa49_glocont_callback, serial);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002156
2157 } else {
2158 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Alan Coxdeb91682008-07-22 11:13:08 +01002159
Lucy McCoy0ca12682007-05-18 12:10:41 -07002160 /* send the data out the device on control endpoint */
2161 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002162 }
Alan Coxdeb91682008-07-22 11:13:08 +01002163 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2164 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002165 dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166#if 0
2167 else {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002168 dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002169 outcont_urb, this_urb->transfer_buffer_length,
2170 usb_pipeendpoint(this_urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 }
2172#endif
2173
Alan Coxa5b6f602008-04-08 17:16:06 +01002174 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002175}
2176
2177static int keyspan_usa90_send_setup(struct usb_serial *serial,
2178 struct usb_serial_port *port,
2179 int reset_port)
2180{
Alan Coxdeb91682008-07-22 11:13:08 +01002181 struct keyspan_usa90_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182 struct keyspan_serial_private *s_priv;
2183 struct keyspan_port_private *p_priv;
2184 const struct keyspan_device_details *d_details;
2185 struct urb *this_urb;
2186 int err;
2187 u8 prescaler;
2188
Alan Coxdeb91682008-07-22 11:13:08 +01002189 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190
2191 s_priv = usb_get_serial_data(serial);
2192 p_priv = usb_get_serial_port_data(port);
2193 d_details = s_priv->device_details;
2194
2195 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01002196 this_urb = p_priv->outcont_urb;
2197 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002198 dbg("%s - oops no urb.", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199 return -1;
2200 }
2201
2202 /* Save reset port val for resend.
2203 Don't overwrite resend for open/close condition. */
2204 if ((reset_port + 1) > p_priv->resend_cont)
2205 p_priv->resend_cont = reset_port + 1;
2206 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +01002207 dbg("%s already writing", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002209 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210 }
2211
Alan Coxdeb91682008-07-22 11:13:08 +01002212 memset(&msg, 0, sizeof(struct keyspan_usa90_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213
Alan Coxdeb91682008-07-22 11:13:08 +01002214 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 if (p_priv->old_baud != p_priv->baud) {
2216 p_priv->old_baud = p_priv->baud;
2217 msg.setClocking = 0x01;
2218 if (d_details->calculate_baud_rate
2219 (p_priv->baud, d_details->baudclk, &msg.baudHi,
Alan Coxdeb91682008-07-22 11:13:08 +01002220 &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) {
2221 dbg("%s - Invalid baud rate %d requested, using 9600.",
2222 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223 p_priv->baud = 9600;
Alan Coxdeb91682008-07-22 11:13:08 +01002224 d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225 &msg.baudHi, &msg.baudLo, &prescaler, 0);
2226 }
2227 msg.setRxMode = 1;
2228 msg.setTxMode = 1;
2229 }
2230
2231 /* modes must always be correctly specified */
Alan Coxdeb91682008-07-22 11:13:08 +01002232 if (p_priv->baud > 57600) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233 msg.rxMode = RXMODE_DMA;
2234 msg.txMode = TXMODE_DMA;
Alan Coxdeb91682008-07-22 11:13:08 +01002235 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236 msg.rxMode = RXMODE_BYHAND;
2237 msg.txMode = TXMODE_BYHAND;
2238 }
2239
2240 msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
2241 switch (p_priv->cflag & CSIZE) {
2242 case CS5:
2243 msg.lcr |= USA_DATABITS_5;
2244 break;
2245 case CS6:
2246 msg.lcr |= USA_DATABITS_6;
2247 break;
2248 case CS7:
2249 msg.lcr |= USA_DATABITS_7;
2250 break;
2251 case CS8:
2252 msg.lcr |= USA_DATABITS_8;
2253 break;
2254 }
2255 if (p_priv->cflag & PARENB) {
2256 /* note USA_PARITY_NONE == 0 */
2257 msg.lcr |= (p_priv->cflag & PARODD)?
Alan Coxdeb91682008-07-22 11:13:08 +01002258 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259 }
2260 if (p_priv->old_cflag != p_priv->cflag) {
2261 p_priv->old_cflag = p_priv->cflag;
2262 msg.setLcr = 0x01;
2263 }
2264
2265 if (p_priv->flow_control == flow_cts)
2266 msg.txFlowControl = TXFLOW_CTS;
2267 msg.setTxFlowControl = 0x01;
2268 msg.setRxFlowControl = 0x01;
Alan Coxdeb91682008-07-22 11:13:08 +01002269
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270 msg.rxForwardingLength = 16;
Alan Coxdeb91682008-07-22 11:13:08 +01002271 msg.rxForwardingTimeout = 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 msg.txAckSetting = 0;
2273 msg.xonChar = 17;
2274 msg.xoffChar = 19;
2275
Alan Coxdeb91682008-07-22 11:13:08 +01002276 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277 if (reset_port == 1) {
2278 msg.portEnabled = 1;
2279 msg.rxFlush = 1;
2280 msg.txBreak = (p_priv->break_on);
2281 }
2282 /* Closing port */
Alan Coxdeb91682008-07-22 11:13:08 +01002283 else if (reset_port == 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284 msg.portEnabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285 /* Sending intermediate configs */
2286 else {
Alan Stern1f871582010-02-17 10:05:47 -05002287 msg.portEnabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288 msg.txBreak = (p_priv->break_on);
2289 }
2290
Alan Coxdeb91682008-07-22 11:13:08 +01002291 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292 msg.setRts = 0x01;
2293 msg.rts = p_priv->rts_state;
2294
2295 msg.setDtr = 0x01;
2296 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002297
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01002299 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2300
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301 /* send the data out the device on control endpoint */
2302 this_urb->transfer_buffer_length = sizeof(msg);
2303
Alan Coxdeb91682008-07-22 11:13:08 +01002304 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2305 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002306 dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002307 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308}
2309
Lucy McCoy0ca12682007-05-18 12:10:41 -07002310static int keyspan_usa67_send_setup(struct usb_serial *serial,
2311 struct usb_serial_port *port,
2312 int reset_port)
2313{
2314 struct keyspan_usa67_portControlMessage msg;
2315 struct keyspan_serial_private *s_priv;
2316 struct keyspan_port_private *p_priv;
2317 const struct keyspan_device_details *d_details;
2318 struct urb *this_urb;
2319 int err, device_port;
2320
Alan Coxdeb91682008-07-22 11:13:08 +01002321 dbg("%s", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002322
2323 s_priv = usb_get_serial_data(serial);
2324 p_priv = usb_get_serial_port_data(port);
2325 d_details = s_priv->device_details;
2326
2327 this_urb = s_priv->glocont_urb;
2328
2329 /* Work out which port within the device is being setup */
2330 device_port = port->number - port->serial->minor;
2331
2332 /* Make sure we have an urb then send the message */
2333 if (this_urb == NULL) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002334 dbg("%s - oops no urb for port %d.", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002335 port->number);
2336 return -1;
2337 }
2338
2339 /* Save reset port val for resend.
2340 Don't overwrite resend for open/close condition. */
2341 if ((reset_port + 1) > p_priv->resend_cont)
2342 p_priv->resend_cont = reset_port + 1;
2343 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +01002344 /* dbg("%s - already writing", __func__); */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002345 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002346 return -1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002347 }
2348
2349 memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
2350
2351 msg.port = device_port;
2352
2353 /* Only set baud rate if it's changed */
2354 if (p_priv->old_baud != p_priv->baud) {
2355 p_priv->old_baud = p_priv->baud;
2356 msg.setClocking = 0xff;
2357 if (d_details->calculate_baud_rate
2358 (p_priv->baud, d_details->baudclk, &msg.baudHi,
Alan Coxdeb91682008-07-22 11:13:08 +01002359 &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2360 dbg("%s - Invalid baud rate %d requested, using 9600.",
2361 __func__, p_priv->baud);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002362 msg.baudLo = 0;
2363 msg.baudHi = 125; /* Values for 9600 baud */
2364 msg.prescaler = 10;
2365 }
2366 msg.setPrescaler = 0xff;
2367 }
2368
2369 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
2370 switch (p_priv->cflag & CSIZE) {
2371 case CS5:
2372 msg.lcr |= USA_DATABITS_5;
2373 break;
2374 case CS6:
2375 msg.lcr |= USA_DATABITS_6;
2376 break;
2377 case CS7:
2378 msg.lcr |= USA_DATABITS_7;
2379 break;
2380 case CS8:
2381 msg.lcr |= USA_DATABITS_8;
2382 break;
2383 }
2384 if (p_priv->cflag & PARENB) {
2385 /* note USA_PARITY_NONE == 0 */
2386 msg.lcr |= (p_priv->cflag & PARODD)?
Alan Coxdeb91682008-07-22 11:13:08 +01002387 USA_PARITY_ODD : USA_PARITY_EVEN;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002388 }
2389 msg.setLcr = 0xff;
2390
2391 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2392 msg.xonFlowControl = 0;
2393 msg.setFlowControl = 0xff;
2394 msg.forwardingLength = 16;
2395 msg.xonChar = 17;
2396 msg.xoffChar = 19;
2397
2398 if (reset_port == 1) {
2399 /* Opening port */
2400 msg._txOn = 1;
2401 msg._txOff = 0;
2402 msg.txFlush = 0;
2403 msg.txBreak = 0;
2404 msg.rxOn = 1;
2405 msg.rxOff = 0;
2406 msg.rxFlush = 1;
2407 msg.rxForward = 0;
2408 msg.returnStatus = 0;
2409 msg.resetDataToggle = 0xff;
2410 } else if (reset_port == 2) {
2411 /* Closing port */
2412 msg._txOn = 0;
2413 msg._txOff = 1;
2414 msg.txFlush = 0;
2415 msg.txBreak = 0;
2416 msg.rxOn = 0;
2417 msg.rxOff = 1;
2418 msg.rxFlush = 1;
2419 msg.rxForward = 0;
2420 msg.returnStatus = 0;
2421 msg.resetDataToggle = 0;
2422 } else {
2423 /* Sending intermediate configs */
Alan Coxdeb91682008-07-22 11:13:08 +01002424 msg._txOn = (!p_priv->break_on);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002425 msg._txOff = 0;
2426 msg.txFlush = 0;
2427 msg.txBreak = (p_priv->break_on);
2428 msg.rxOn = 0;
2429 msg.rxOff = 0;
2430 msg.rxFlush = 0;
2431 msg.rxForward = 0;
2432 msg.returnStatus = 0;
2433 msg.resetDataToggle = 0x0;
2434 }
2435
2436 /* Do handshaking outputs */
2437 msg.setTxTriState_setRts = 0xff;
2438 msg.txTriState_rts = p_priv->rts_state;
2439
2440 msg.setHskoa_setDtr = 0xff;
2441 msg.hskoa_dtr = p_priv->dtr_state;
2442
2443 p_priv->resend_cont = 0;
2444
2445 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2446
2447 /* send the data out the device on control endpoint */
2448 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002449
2450 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2451 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002452 dbg("%s - usb_submit_urb(setup) failed (%d)", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002453 err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002454 return 0;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002455}
2456
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
2458{
2459 struct usb_serial *serial = port->serial;
2460 struct keyspan_serial_private *s_priv;
2461 const struct keyspan_device_details *d_details;
2462
Alan Coxdeb91682008-07-22 11:13:08 +01002463 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464
2465 s_priv = usb_get_serial_data(serial);
2466 d_details = s_priv->device_details;
2467
2468 switch (d_details->msg_format) {
2469 case msg_usa26:
2470 keyspan_usa26_send_setup(serial, port, reset_port);
2471 break;
2472 case msg_usa28:
2473 keyspan_usa28_send_setup(serial, port, reset_port);
2474 break;
2475 case msg_usa49:
2476 keyspan_usa49_send_setup(serial, port, reset_port);
2477 break;
2478 case msg_usa90:
2479 keyspan_usa90_send_setup(serial, port, reset_port);
2480 break;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002481 case msg_usa67:
2482 keyspan_usa67_send_setup(serial, port, reset_port);
2483 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484 }
2485}
2486
2487
2488/* Gets called by the "real" driver (ie once firmware is loaded
2489 and renumeration has taken place. */
Alan Coxdeb91682008-07-22 11:13:08 +01002490static int keyspan_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491{
2492 int i, err;
2493 struct usb_serial_port *port;
2494 struct keyspan_serial_private *s_priv;
2495 struct keyspan_port_private *p_priv;
2496 const struct keyspan_device_details *d_details;
2497
Harvey Harrison441b62c2008-03-03 16:08:34 -08002498 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499
2500 for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
Alan Coxdeb91682008-07-22 11:13:08 +01002501 if (d_details->product_id ==
2502 le16_to_cpu(serial->dev->descriptor.idProduct))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503 break;
2504 if (d_details == NULL) {
Alan Coxdeb91682008-07-22 11:13:08 +01002505 dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
2506 __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507 return 1;
2508 }
2509
2510 /* Setup private data for serial driver */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01002511 s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512 if (!s_priv) {
Alan Coxdeb91682008-07-22 11:13:08 +01002513 dbg("%s - kmalloc for keyspan_serial_private failed.",
2514 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515 return -ENOMEM;
2516 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517
2518 s_priv->device_details = d_details;
2519 usb_set_serial_data(serial, s_priv);
2520
2521 /* Now setup per port private data */
2522 for (i = 0; i < serial->num_ports; i++) {
2523 port = serial->port[i];
Alan Coxdeb91682008-07-22 11:13:08 +01002524 p_priv = kzalloc(sizeof(struct keyspan_port_private),
2525 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526 if (!p_priv) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08002527 dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __func__, i);
Alan Coxdeb91682008-07-22 11:13:08 +01002528 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530 p_priv->device_details = d_details;
2531 usb_set_serial_port_data(port, p_priv);
2532 }
2533
2534 keyspan_setup_urbs(serial);
2535
Lucy McCoy0ca12682007-05-18 12:10:41 -07002536 if (s_priv->instat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002537 err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
2538 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002539 dbg("%s - submit instat urb failed %d", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002540 err);
2541 }
2542 if (s_priv->indat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002543 err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
2544 if (err != 0)
Harvey Harrison441b62c2008-03-03 16:08:34 -08002545 dbg("%s - submit indat urb failed %d", __func__,
Lucy McCoy0ca12682007-05-18 12:10:41 -07002546 err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547 }
Alan Coxdeb91682008-07-22 11:13:08 +01002548
Alan Coxa5b6f602008-04-08 17:16:06 +01002549 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002550}
2551
Alan Sternf9c99bb2009-06-02 11:53:55 -04002552static void keyspan_disconnect(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553{
2554 int i, j;
2555 struct usb_serial_port *port;
2556 struct keyspan_serial_private *s_priv;
2557 struct keyspan_port_private *p_priv;
2558
Harvey Harrison441b62c2008-03-03 16:08:34 -08002559 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560
2561 s_priv = usb_get_serial_data(serial);
2562
2563 /* Stop reading/writing urbs */
2564 stop_urb(s_priv->instat_urb);
2565 stop_urb(s_priv->glocont_urb);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002566 stop_urb(s_priv->indat_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567 for (i = 0; i < serial->num_ports; ++i) {
2568 port = serial->port[i];
2569 p_priv = usb_get_serial_port_data(port);
2570 stop_urb(p_priv->inack_urb);
2571 stop_urb(p_priv->outcont_urb);
2572 for (j = 0; j < 2; j++) {
2573 stop_urb(p_priv->in_urbs[j]);
2574 stop_urb(p_priv->out_urbs[j]);
2575 }
2576 }
2577
2578 /* Now free them */
Mariusz Kozlowski1cadc132006-11-08 15:36:34 +01002579 usb_free_urb(s_priv->instat_urb);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002580 usb_free_urb(s_priv->indat_urb);
Mariusz Kozlowski1cadc132006-11-08 15:36:34 +01002581 usb_free_urb(s_priv->glocont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582 for (i = 0; i < serial->num_ports; ++i) {
2583 port = serial->port[i];
2584 p_priv = usb_get_serial_port_data(port);
Mariusz Kozlowski1cadc132006-11-08 15:36:34 +01002585 usb_free_urb(p_priv->inack_urb);
2586 usb_free_urb(p_priv->outcont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587 for (j = 0; j < 2; j++) {
Mariusz Kozlowski1cadc132006-11-08 15:36:34 +01002588 usb_free_urb(p_priv->in_urbs[j]);
2589 usb_free_urb(p_priv->out_urbs[j]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590 }
2591 }
Alan Sternf9c99bb2009-06-02 11:53:55 -04002592}
2593
2594static void keyspan_release(struct usb_serial *serial)
2595{
2596 int i;
2597 struct usb_serial_port *port;
2598 struct keyspan_serial_private *s_priv;
2599
2600 dbg("%s", __func__);
2601
2602 s_priv = usb_get_serial_data(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603
2604 /* dbg("Freeing serial->private."); */
2605 kfree(s_priv);
2606
2607 /* dbg("Freeing port->private."); */
2608 /* Now free per port private data */
2609 for (i = 0; i < serial->num_ports; i++) {
2610 port = serial->port[i];
2611 kfree(usb_get_serial_port_data(port));
2612 }
2613}
2614
Alan Coxdeb91682008-07-22 11:13:08 +01002615MODULE_AUTHOR(DRIVER_AUTHOR);
2616MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617MODULE_LICENSE("GPL");
2618
David Woodhouse2971c572008-05-30 14:04:03 +03002619MODULE_FIRMWARE("keyspan/usa28.fw");
2620MODULE_FIRMWARE("keyspan/usa28x.fw");
2621MODULE_FIRMWARE("keyspan/usa28xa.fw");
2622MODULE_FIRMWARE("keyspan/usa28xb.fw");
2623MODULE_FIRMWARE("keyspan/usa19.fw");
2624MODULE_FIRMWARE("keyspan/usa19qi.fw");
2625MODULE_FIRMWARE("keyspan/mpr.fw");
2626MODULE_FIRMWARE("keyspan/usa19qw.fw");
2627MODULE_FIRMWARE("keyspan/usa18x.fw");
2628MODULE_FIRMWARE("keyspan/usa19w.fw");
2629MODULE_FIRMWARE("keyspan/usa49w.fw");
2630MODULE_FIRMWARE("keyspan/usa49wlc.fw");
2631
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632module_param(debug, bool, S_IRUGO | S_IWUSR);
2633MODULE_PARM_DESC(debug, "Debug enabled or not");
2634