blob: 5662d324edd2e3b356c247ed2b024a44766013d9 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 Keyspan USB to Serial Converter driver
Alan Coxdeb91682008-07-22 11:13:08 +01003
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 (C) Copyright (C) 2000-2001 Hugh Blemings <hugh@blemings.org>
5 (C) Copyright (C) 2002 Greg Kroah-Hartman <greg@kroah.com>
Alan Coxdeb91682008-07-22 11:13:08 +01006
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
Justin P. Mattock631dd1a2010-10-18 11:03:14 +020012 See http://blemings.org/hugh/keyspan.html for more information.
Alan Coxdeb91682008-07-22 11:13:08 +010013
Linus Torvalds1da177e2005-04-16 15:20:36 -070014 Code in this driver inspired by and in a number of places taken
15 from Brian Warner's original Keyspan-PDA driver.
16
17 This driver has been put together with the support of Innosys, Inc.
18 and Keyspan, Inc the manufacturers of the Keyspan USB-serial products.
19 Thanks Guys :)
Alan Coxdeb91682008-07-22 11:13:08 +010020
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 Thanks to Paulus for miscellaneous tidy ups, some largish chunks
22 of much nicer and/or completely new code and (perhaps most uniquely)
23 having the patience to sit down and explain why and where he'd changed
Alan Coxdeb91682008-07-22 11:13:08 +010024 stuff.
25
26 Tip 'o the hat to IBM (and previously Linuxcare :) for supporting
Linus Torvalds1da177e2005-04-16 15:20:36 -070027 staff in their work on open source projects.
Linus Torvalds1da177e2005-04-16 15:20:36 -070028*/
29
30
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/kernel.h>
32#include <linux/jiffies.h>
33#include <linux/errno.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/slab.h>
35#include <linux/tty.h>
36#include <linux/tty_driver.h>
37#include <linux/tty_flip.h>
38#include <linux/module.h>
39#include <linux/spinlock.h>
Alan Coxdeb91682008-07-22 11:13:08 +010040#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/usb.h>
Greg Kroah-Hartmana9698882006-07-11 21:22:58 -070042#include <linux/usb/serial.h>
Rene Buergelcc183e22012-09-18 09:00:41 +020043#include <linux/usb/ezusb.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070044
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu"
46#define DRIVER_DESC "Keyspan USB to Serial Converter Driver"
47
Johan Hovoldbeabdc32017-02-15 11:09:51 +010048/* Function prototypes for Keyspan serial converter */
49static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port);
50static void keyspan_close(struct usb_serial_port *port);
51static void keyspan_dtr_rts(struct usb_serial_port *port, int on);
52static int keyspan_startup(struct usb_serial *serial);
53static void keyspan_disconnect(struct usb_serial *serial);
54static void keyspan_release(struct usb_serial *serial);
55static int keyspan_port_probe(struct usb_serial_port *port);
56static int keyspan_port_remove(struct usb_serial_port *port);
57static int keyspan_write_room(struct tty_struct *tty);
58static int keyspan_write(struct tty_struct *tty, struct usb_serial_port *port,
59 const unsigned char *buf, int count);
60static void keyspan_send_setup(struct usb_serial_port *port, int reset_port);
61static void keyspan_set_termios(struct tty_struct *tty,
62 struct usb_serial_port *port,
63 struct ktermios *old);
64static void keyspan_break_ctl(struct tty_struct *tty, int break_state);
65static int keyspan_tiocmget(struct tty_struct *tty);
66static int keyspan_tiocmset(struct tty_struct *tty, unsigned int set,
67 unsigned int clear);
68static int keyspan_fake_startup(struct usb_serial *serial);
69
70static int keyspan_usa19_calc_baud(struct usb_serial_port *port,
71 u32 baud_rate, u32 baudclk,
72 u8 *rate_hi, u8 *rate_low,
73 u8 *prescaler, int portnum);
74static int keyspan_usa19w_calc_baud(struct usb_serial_port *port,
75 u32 baud_rate, u32 baudclk,
76 u8 *rate_hi, u8 *rate_low,
77 u8 *prescaler, int portnum);
78static int keyspan_usa28_calc_baud(struct usb_serial_port *port,
79 u32 baud_rate, u32 baudclk,
80 u8 *rate_hi, u8 *rate_low,
81 u8 *prescaler, int portnum);
82static int keyspan_usa19hs_calc_baud(struct usb_serial_port *port,
83 u32 baud_rate, u32 baudclk,
84 u8 *rate_hi, u8 *rate_low,
85 u8 *prescaler, int portnum);
86
87static int keyspan_usa28_send_setup(struct usb_serial *serial,
88 struct usb_serial_port *port,
89 int reset_port);
90static int keyspan_usa26_send_setup(struct usb_serial *serial,
91 struct usb_serial_port *port,
92 int reset_port);
93static int keyspan_usa49_send_setup(struct usb_serial *serial,
94 struct usb_serial_port *port,
95 int reset_port);
96static int keyspan_usa90_send_setup(struct usb_serial *serial,
97 struct usb_serial_port *port,
98 int reset_port);
99static int keyspan_usa67_send_setup(struct usb_serial *serial,
100 struct usb_serial_port *port,
101 int reset_port);
102
103/* Values used for baud rate calculation - device specific */
104#define KEYSPAN_INVALID_BAUD_RATE (-1)
105#define KEYSPAN_BAUD_RATE_OK (0)
106#define KEYSPAN_USA18X_BAUDCLK (12000000L) /* a guess */
107#define KEYSPAN_USA19_BAUDCLK (12000000L)
108#define KEYSPAN_USA19W_BAUDCLK (24000000L)
109#define KEYSPAN_USA19HS_BAUDCLK (14769231L)
110#define KEYSPAN_USA28_BAUDCLK (1843200L)
111#define KEYSPAN_USA28X_BAUDCLK (12000000L)
112#define KEYSPAN_USA49W_BAUDCLK (48000000L)
113
114/* Some constants used to characterise each device. */
115#define KEYSPAN_MAX_NUM_PORTS (4)
116#define KEYSPAN_MAX_FLIPS (2)
117
118/*
119 * Device info for the Keyspan serial converter, used by the overall
120 * usb-serial probe function.
121 */
122#define KEYSPAN_VENDOR_ID (0x06cd)
123
124/* Product IDs for the products supported, pre-renumeration */
125#define keyspan_usa18x_pre_product_id 0x0105
126#define keyspan_usa19_pre_product_id 0x0103
127#define keyspan_usa19qi_pre_product_id 0x010b
128#define keyspan_mpr_pre_product_id 0x011b
129#define keyspan_usa19qw_pre_product_id 0x0118
130#define keyspan_usa19w_pre_product_id 0x0106
131#define keyspan_usa28_pre_product_id 0x0101
132#define keyspan_usa28x_pre_product_id 0x0102
133#define keyspan_usa28xa_pre_product_id 0x0114
134#define keyspan_usa28xb_pre_product_id 0x0113
135#define keyspan_usa49w_pre_product_id 0x0109
136#define keyspan_usa49wlc_pre_product_id 0x011a
137
138/*
139 * Product IDs post-renumeration. Note that the 28x and 28xb have the same
140 * id's post-renumeration but behave identically so it's not an issue. As
141 * such, the 28xb is not listed in any of the device tables.
142 */
143#define keyspan_usa18x_product_id 0x0112
144#define keyspan_usa19_product_id 0x0107
145#define keyspan_usa19qi_product_id 0x010c
146#define keyspan_usa19hs_product_id 0x0121
147#define keyspan_mpr_product_id 0x011c
148#define keyspan_usa19qw_product_id 0x0119
149#define keyspan_usa19w_product_id 0x0108
150#define keyspan_usa28_product_id 0x010f
151#define keyspan_usa28x_product_id 0x0110
152#define keyspan_usa28xa_product_id 0x0115
153#define keyspan_usa28xb_product_id 0x0110
154#define keyspan_usa28xg_product_id 0x0135
155#define keyspan_usa49w_product_id 0x010a
156#define keyspan_usa49wlc_product_id 0x012a
157#define keyspan_usa49wg_product_id 0x0131
158
159struct keyspan_device_details {
160 /* product ID value */
161 int product_id;
162
163 enum {msg_usa26, msg_usa28, msg_usa49, msg_usa90, msg_usa67} msg_format;
164
165 /* Number of physical ports */
166 int num_ports;
167
168 /* 1 if endpoint flipping used on input, 0 if not */
169 int indat_endp_flip;
170
171 /* 1 if endpoint flipping used on output, 0 if not */
172 int outdat_endp_flip;
173
174 /*
175 * Table mapping input data endpoint IDs to physical port
176 * number and flip if used
177 */
178 int indat_endpoints[KEYSPAN_MAX_NUM_PORTS];
179
180 /* Same for output endpoints */
181 int outdat_endpoints[KEYSPAN_MAX_NUM_PORTS];
182
183 /* Input acknowledge endpoints */
184 int inack_endpoints[KEYSPAN_MAX_NUM_PORTS];
185
186 /* Output control endpoints */
187 int outcont_endpoints[KEYSPAN_MAX_NUM_PORTS];
188
189 /* Endpoint used for input status */
190 int instat_endpoint;
191
192 /* Endpoint used for input data 49WG only */
193 int indat_endpoint;
194
195 /* Endpoint used for global control functions */
196 int glocont_endpoint;
197
198 int (*calculate_baud_rate)(struct usb_serial_port *port,
199 u32 baud_rate, u32 baudclk,
200 u8 *rate_hi, u8 *rate_low, u8 *prescaler,
201 int portnum);
202 u32 baudclk;
203};
204
205/*
206 * Now for each device type we setup the device detail structure with the
207 * appropriate information (provided in Keyspan's documentation)
208 */
209
210static const struct keyspan_device_details usa18x_device_details = {
211 .product_id = keyspan_usa18x_product_id,
212 .msg_format = msg_usa26,
213 .num_ports = 1,
214 .indat_endp_flip = 0,
215 .outdat_endp_flip = 1,
216 .indat_endpoints = {0x81},
217 .outdat_endpoints = {0x01},
218 .inack_endpoints = {0x85},
219 .outcont_endpoints = {0x05},
220 .instat_endpoint = 0x87,
221 .indat_endpoint = -1,
222 .glocont_endpoint = 0x07,
223 .calculate_baud_rate = keyspan_usa19w_calc_baud,
224 .baudclk = KEYSPAN_USA18X_BAUDCLK,
225};
226
227static const struct keyspan_device_details usa19_device_details = {
228 .product_id = keyspan_usa19_product_id,
229 .msg_format = msg_usa28,
230 .num_ports = 1,
231 .indat_endp_flip = 1,
232 .outdat_endp_flip = 1,
233 .indat_endpoints = {0x81},
234 .outdat_endpoints = {0x01},
235 .inack_endpoints = {0x83},
236 .outcont_endpoints = {0x03},
237 .instat_endpoint = 0x84,
238 .indat_endpoint = -1,
239 .glocont_endpoint = -1,
240 .calculate_baud_rate = keyspan_usa19_calc_baud,
241 .baudclk = KEYSPAN_USA19_BAUDCLK,
242};
243
244static const struct keyspan_device_details usa19qi_device_details = {
245 .product_id = keyspan_usa19qi_product_id,
246 .msg_format = msg_usa28,
247 .num_ports = 1,
248 .indat_endp_flip = 1,
249 .outdat_endp_flip = 1,
250 .indat_endpoints = {0x81},
251 .outdat_endpoints = {0x01},
252 .inack_endpoints = {0x83},
253 .outcont_endpoints = {0x03},
254 .instat_endpoint = 0x84,
255 .indat_endpoint = -1,
256 .glocont_endpoint = -1,
257 .calculate_baud_rate = keyspan_usa28_calc_baud,
258 .baudclk = KEYSPAN_USA19_BAUDCLK,
259};
260
261static const struct keyspan_device_details mpr_device_details = {
262 .product_id = keyspan_mpr_product_id,
263 .msg_format = msg_usa28,
264 .num_ports = 1,
265 .indat_endp_flip = 1,
266 .outdat_endp_flip = 1,
267 .indat_endpoints = {0x81},
268 .outdat_endpoints = {0x01},
269 .inack_endpoints = {0x83},
270 .outcont_endpoints = {0x03},
271 .instat_endpoint = 0x84,
272 .indat_endpoint = -1,
273 .glocont_endpoint = -1,
274 .calculate_baud_rate = keyspan_usa28_calc_baud,
275 .baudclk = KEYSPAN_USA19_BAUDCLK,
276};
277
278static const struct keyspan_device_details usa19qw_device_details = {
279 .product_id = keyspan_usa19qw_product_id,
280 .msg_format = msg_usa26,
281 .num_ports = 1,
282 .indat_endp_flip = 0,
283 .outdat_endp_flip = 1,
284 .indat_endpoints = {0x81},
285 .outdat_endpoints = {0x01},
286 .inack_endpoints = {0x85},
287 .outcont_endpoints = {0x05},
288 .instat_endpoint = 0x87,
289 .indat_endpoint = -1,
290 .glocont_endpoint = 0x07,
291 .calculate_baud_rate = keyspan_usa19w_calc_baud,
292 .baudclk = KEYSPAN_USA19W_BAUDCLK,
293};
294
295static const struct keyspan_device_details usa19w_device_details = {
296 .product_id = keyspan_usa19w_product_id,
297 .msg_format = msg_usa26,
298 .num_ports = 1,
299 .indat_endp_flip = 0,
300 .outdat_endp_flip = 1,
301 .indat_endpoints = {0x81},
302 .outdat_endpoints = {0x01},
303 .inack_endpoints = {0x85},
304 .outcont_endpoints = {0x05},
305 .instat_endpoint = 0x87,
306 .indat_endpoint = -1,
307 .glocont_endpoint = 0x07,
308 .calculate_baud_rate = keyspan_usa19w_calc_baud,
309 .baudclk = KEYSPAN_USA19W_BAUDCLK,
310};
311
312static const struct keyspan_device_details usa19hs_device_details = {
313 .product_id = keyspan_usa19hs_product_id,
314 .msg_format = msg_usa90,
315 .num_ports = 1,
316 .indat_endp_flip = 0,
317 .outdat_endp_flip = 0,
318 .indat_endpoints = {0x81},
319 .outdat_endpoints = {0x01},
320 .inack_endpoints = {-1},
321 .outcont_endpoints = {0x02},
322 .instat_endpoint = 0x82,
323 .indat_endpoint = -1,
324 .glocont_endpoint = -1,
325 .calculate_baud_rate = keyspan_usa19hs_calc_baud,
326 .baudclk = KEYSPAN_USA19HS_BAUDCLK,
327};
328
329static const struct keyspan_device_details usa28_device_details = {
330 .product_id = keyspan_usa28_product_id,
331 .msg_format = msg_usa28,
332 .num_ports = 2,
333 .indat_endp_flip = 1,
334 .outdat_endp_flip = 1,
335 .indat_endpoints = {0x81, 0x83},
336 .outdat_endpoints = {0x01, 0x03},
337 .inack_endpoints = {0x85, 0x86},
338 .outcont_endpoints = {0x05, 0x06},
339 .instat_endpoint = 0x87,
340 .indat_endpoint = -1,
341 .glocont_endpoint = 0x07,
342 .calculate_baud_rate = keyspan_usa28_calc_baud,
343 .baudclk = KEYSPAN_USA28_BAUDCLK,
344};
345
346static const struct keyspan_device_details usa28x_device_details = {
347 .product_id = keyspan_usa28x_product_id,
348 .msg_format = msg_usa26,
349 .num_ports = 2,
350 .indat_endp_flip = 0,
351 .outdat_endp_flip = 1,
352 .indat_endpoints = {0x81, 0x83},
353 .outdat_endpoints = {0x01, 0x03},
354 .inack_endpoints = {0x85, 0x86},
355 .outcont_endpoints = {0x05, 0x06},
356 .instat_endpoint = 0x87,
357 .indat_endpoint = -1,
358 .glocont_endpoint = 0x07,
359 .calculate_baud_rate = keyspan_usa19w_calc_baud,
360 .baudclk = KEYSPAN_USA28X_BAUDCLK,
361};
362
363static const struct keyspan_device_details usa28xa_device_details = {
364 .product_id = keyspan_usa28xa_product_id,
365 .msg_format = msg_usa26,
366 .num_ports = 2,
367 .indat_endp_flip = 0,
368 .outdat_endp_flip = 1,
369 .indat_endpoints = {0x81, 0x83},
370 .outdat_endpoints = {0x01, 0x03},
371 .inack_endpoints = {0x85, 0x86},
372 .outcont_endpoints = {0x05, 0x06},
373 .instat_endpoint = 0x87,
374 .indat_endpoint = -1,
375 .glocont_endpoint = 0x07,
376 .calculate_baud_rate = keyspan_usa19w_calc_baud,
377 .baudclk = KEYSPAN_USA28X_BAUDCLK,
378};
379
380static const struct keyspan_device_details usa28xg_device_details = {
381 .product_id = keyspan_usa28xg_product_id,
382 .msg_format = msg_usa67,
383 .num_ports = 2,
384 .indat_endp_flip = 0,
385 .outdat_endp_flip = 0,
386 .indat_endpoints = {0x84, 0x88},
387 .outdat_endpoints = {0x02, 0x06},
388 .inack_endpoints = {-1, -1},
389 .outcont_endpoints = {-1, -1},
390 .instat_endpoint = 0x81,
391 .indat_endpoint = -1,
392 .glocont_endpoint = 0x01,
393 .calculate_baud_rate = keyspan_usa19w_calc_baud,
394 .baudclk = KEYSPAN_USA28X_BAUDCLK,
395};
396/*
397 * We don't need a separate entry for the usa28xb as it appears as a 28x
398 * anyway.
399 */
400
401static const struct keyspan_device_details usa49w_device_details = {
402 .product_id = keyspan_usa49w_product_id,
403 .msg_format = msg_usa49,
404 .num_ports = 4,
405 .indat_endp_flip = 0,
406 .outdat_endp_flip = 0,
407 .indat_endpoints = {0x81, 0x82, 0x83, 0x84},
408 .outdat_endpoints = {0x01, 0x02, 0x03, 0x04},
409 .inack_endpoints = {-1, -1, -1, -1},
410 .outcont_endpoints = {-1, -1, -1, -1},
411 .instat_endpoint = 0x87,
412 .indat_endpoint = -1,
413 .glocont_endpoint = 0x07,
414 .calculate_baud_rate = keyspan_usa19w_calc_baud,
415 .baudclk = KEYSPAN_USA49W_BAUDCLK,
416};
417
418static const struct keyspan_device_details usa49wlc_device_details = {
419 .product_id = keyspan_usa49wlc_product_id,
420 .msg_format = msg_usa49,
421 .num_ports = 4,
422 .indat_endp_flip = 0,
423 .outdat_endp_flip = 0,
424 .indat_endpoints = {0x81, 0x82, 0x83, 0x84},
425 .outdat_endpoints = {0x01, 0x02, 0x03, 0x04},
426 .inack_endpoints = {-1, -1, -1, -1},
427 .outcont_endpoints = {-1, -1, -1, -1},
428 .instat_endpoint = 0x87,
429 .indat_endpoint = -1,
430 .glocont_endpoint = 0x07,
431 .calculate_baud_rate = keyspan_usa19w_calc_baud,
432 .baudclk = KEYSPAN_USA19W_BAUDCLK,
433};
434
435static const struct keyspan_device_details usa49wg_device_details = {
436 .product_id = keyspan_usa49wg_product_id,
437 .msg_format = msg_usa49,
438 .num_ports = 4,
439 .indat_endp_flip = 0,
440 .outdat_endp_flip = 0,
441 .indat_endpoints = {-1, -1, -1, -1}, /* single 'global' data in EP */
442 .outdat_endpoints = {0x01, 0x02, 0x04, 0x06},
443 .inack_endpoints = {-1, -1, -1, -1},
444 .outcont_endpoints = {-1, -1, -1, -1},
445 .instat_endpoint = 0x81,
446 .indat_endpoint = 0x88,
447 .glocont_endpoint = 0x00, /* uses control EP */
448 .calculate_baud_rate = keyspan_usa19w_calc_baud,
449 .baudclk = KEYSPAN_USA19W_BAUDCLK,
450};
451
452static const struct keyspan_device_details *keyspan_devices[] = {
453 &usa18x_device_details,
454 &usa19_device_details,
455 &usa19qi_device_details,
456 &mpr_device_details,
457 &usa19qw_device_details,
458 &usa19w_device_details,
459 &usa19hs_device_details,
460 &usa28_device_details,
461 &usa28x_device_details,
462 &usa28xa_device_details,
463 &usa28xg_device_details,
464 /* 28xb not required as it renumerates as a 28x */
465 &usa49w_device_details,
466 &usa49wlc_device_details,
467 &usa49wg_device_details,
468 NULL,
469};
470
471static const struct usb_device_id keyspan_ids_combined[] = {
472 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa18x_pre_product_id) },
473 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19_pre_product_id) },
474 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19w_pre_product_id) },
475 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qi_pre_product_id) },
476 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qw_pre_product_id) },
477 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_mpr_pre_product_id) },
478 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_pre_product_id) },
479 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_pre_product_id) },
480 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_pre_product_id) },
481 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_pre_product_id) },
482 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_pre_product_id) },
483 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_pre_product_id) },
484 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa18x_product_id) },
485 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19_product_id) },
486 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19w_product_id) },
487 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qi_product_id) },
488 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qw_product_id) },
489 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19hs_product_id) },
490 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_mpr_product_id) },
491 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
492 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
493 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) },
494 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xg_product_id) },
495 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id)},
496 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)},
497 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wg_product_id)},
498 { } /* Terminating entry */
499};
500
501MODULE_DEVICE_TABLE(usb, keyspan_ids_combined);
502
503/* usb_device_id table for the pre-firmware download keyspan devices */
504static const struct usb_device_id keyspan_pre_ids[] = {
505 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa18x_pre_product_id) },
506 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19_pre_product_id) },
507 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qi_pre_product_id) },
508 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qw_pre_product_id) },
509 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19w_pre_product_id) },
510 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_mpr_pre_product_id) },
511 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_pre_product_id) },
512 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_pre_product_id) },
513 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_pre_product_id) },
514 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_pre_product_id) },
515 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_pre_product_id) },
516 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_pre_product_id) },
517 { } /* Terminating entry */
518};
519
520static const struct usb_device_id keyspan_1port_ids[] = {
521 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa18x_product_id) },
522 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19_product_id) },
523 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qi_product_id) },
524 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qw_product_id) },
525 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19w_product_id) },
526 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19hs_product_id) },
527 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_mpr_product_id) },
528 { } /* Terminating entry */
529};
530
531static const struct usb_device_id keyspan_2port_ids[] = {
532 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
533 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
534 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) },
535 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xg_product_id) },
536 { } /* Terminating entry */
537};
538
539static const struct usb_device_id keyspan_4port_ids[] = {
540 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id) },
541 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)},
542 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wg_product_id)},
543 { } /* Terminating entry */
544};
545
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546#define INSTAT_BUFLEN 32
547#define GLOCONT_BUFLEN 64
Lucy McCoy0ca12682007-05-18 12:10:41 -0700548#define INDAT49W_BUFLEN 512
Johan Hovoldbad41a52013-08-13 13:27:37 +0200549#define IN_BUFLEN 64
550#define OUT_BUFLEN 64
551#define INACK_BUFLEN 1
552#define OUTCONT_BUFLEN 64
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553
554 /* Per device and per port private data */
555struct keyspan_serial_private {
556 const struct keyspan_device_details *device_details;
557
558 struct urb *instat_urb;
Johan Hovold2fcd1c92013-08-13 13:27:36 +0200559 char *instat_buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560
Alan Coxdeb91682008-07-22 11:13:08 +0100561 /* added to support 49wg, where data from all 4 ports comes in
562 on 1 EP and high-speed supported */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700563 struct urb *indat_urb;
Johan Hovold2fcd1c92013-08-13 13:27:36 +0200564 char *indat_buf;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700565
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 /* XXX this one probably will need a lock */
567 struct urb *glocont_urb;
Johan Hovold2fcd1c92013-08-13 13:27:36 +0200568 char *glocont_buf;
569 char *ctrl_buf; /* for EP0 control message */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570};
571
572struct keyspan_port_private {
573 /* Keep track of which input & output endpoints to use */
574 int in_flip;
575 int out_flip;
576
577 /* Keep duplicate of device details in each port
578 structure as well - simplifies some of the
579 callback functions etc. */
580 const struct keyspan_device_details *device_details;
581
582 /* Input endpoints and buffer for this port */
583 struct urb *in_urbs[2];
Johan Hovoldbad41a52013-08-13 13:27:37 +0200584 char *in_buffer[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 /* Output endpoints and buffer for this port */
586 struct urb *out_urbs[2];
Johan Hovoldbad41a52013-08-13 13:27:37 +0200587 char *out_buffer[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588
589 /* Input ack endpoint */
590 struct urb *inack_urb;
Johan Hovoldbad41a52013-08-13 13:27:37 +0200591 char *inack_buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592
593 /* Output control endpoint */
594 struct urb *outcont_urb;
Johan Hovoldbad41a52013-08-13 13:27:37 +0200595 char *outcont_buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596
597 /* Settings for the port */
598 int baud;
599 int old_baud;
600 unsigned int cflag;
601 unsigned int old_cflag;
602 enum {flow_none, flow_cts, flow_xon} flow_control;
603 int rts_state; /* Handshaking pins (outputs) */
604 int dtr_state;
605 int cts_state; /* Handshaking pins (inputs) */
606 int dsr_state;
607 int dcd_state;
608 int ri_state;
609 int break_on;
610
611 unsigned long tx_start_time[2];
612 int resend_cont; /* need to resend control packet */
613};
614
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615/* Include Keyspan message headers. All current Keyspan Adapters
Lucy McCoy0ca12682007-05-18 12:10:41 -0700616 make use of one of five message formats which are referred
Alan Coxdeb91682008-07-22 11:13:08 +0100617 to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and
618 within this driver. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619#include "keyspan_usa26msg.h"
620#include "keyspan_usa28msg.h"
621#include "keyspan_usa49msg.h"
622#include "keyspan_usa90msg.h"
Lucy McCoy0ca12682007-05-18 12:10:41 -0700623#include "keyspan_usa67msg.h"
Alan Coxdeb91682008-07-22 11:13:08 +0100624
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625
Alan Cox95da3102008-07-22 11:09:07 +0100626static void keyspan_break_ctl(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627{
Alan Cox95da3102008-07-22 11:09:07 +0100628 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 struct keyspan_port_private *p_priv;
630
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 p_priv = usb_get_serial_port_data(port);
632
633 if (break_state == -1)
634 p_priv->break_on = 1;
635 else
636 p_priv->break_on = 0;
637
638 keyspan_send_setup(port, 0);
639}
640
641
Alan Coxdeb91682008-07-22 11:13:08 +0100642static void keyspan_set_termios(struct tty_struct *tty,
Alan Cox95da3102008-07-22 11:09:07 +0100643 struct usb_serial_port *port, struct ktermios *old_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644{
645 int baud_rate, device_port;
646 struct keyspan_port_private *p_priv;
647 const struct keyspan_device_details *d_details;
648 unsigned int cflag;
649
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 p_priv = usb_get_serial_port_data(port);
651 d_details = p_priv->device_details;
Alan Coxadc8d742012-07-14 15:31:47 +0100652 cflag = tty->termios.c_cflag;
Greg Kroah-Hartman11438322013-06-06 10:32:00 -0700653 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654
655 /* Baud rate calculation takes baud rate as an integer
656 so other rates can be generated if desired. */
Alan Cox74240b02007-10-18 01:24:20 -0700657 baud_rate = tty_get_baud_rate(tty);
Alan Coxdeb91682008-07-22 11:13:08 +0100658 /* If no match or invalid, don't change */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700659 if (d_details->calculate_baud_rate(port, baud_rate, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
661 /* FIXME - more to do here to ensure rate changes cleanly */
Rahul Bedarkarcd8c5052014-01-02 19:29:24 +0530662 /* FIXME - calculate exact rate from divisor ? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 p_priv->baud = baud_rate;
Alan Cox74240b02007-10-18 01:24:20 -0700664 } else
665 baud_rate = tty_termios_baud_rate(old_termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666
Alan Cox74240b02007-10-18 01:24:20 -0700667 tty_encode_baud_rate(tty, baud_rate, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 /* set CTS/RTS handshake etc. */
669 p_priv->cflag = cflag;
Ben Minerds2b982ab2012-07-12 00:10:16 +1000670 p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671
Alan Cox74240b02007-10-18 01:24:20 -0700672 /* Mark/Space not supported */
Alan Coxadc8d742012-07-14 15:31:47 +0100673 tty->termios.c_cflag &= ~CMSPAR;
Alan Cox74240b02007-10-18 01:24:20 -0700674
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675 keyspan_send_setup(port, 0);
676}
677
Alan Cox60b33c12011-02-14 16:26:14 +0000678static int keyspan_tiocmget(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679{
Alan Cox95da3102008-07-22 11:09:07 +0100680 struct usb_serial_port *port = tty->driver_data;
681 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 unsigned int value;
Alan Coxdeb91682008-07-22 11:13:08 +0100683
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 value = ((p_priv->rts_state) ? TIOCM_RTS : 0) |
685 ((p_priv->dtr_state) ? TIOCM_DTR : 0) |
686 ((p_priv->cts_state) ? TIOCM_CTS : 0) |
687 ((p_priv->dsr_state) ? TIOCM_DSR : 0) |
688 ((p_priv->dcd_state) ? TIOCM_CAR : 0) |
Alan Coxdeb91682008-07-22 11:13:08 +0100689 ((p_priv->ri_state) ? TIOCM_RNG : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690
691 return value;
692}
693
Alan Cox20b9d172011-02-14 16:26:50 +0000694static int keyspan_tiocmset(struct tty_struct *tty,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 unsigned int set, unsigned int clear)
696{
Alan Cox95da3102008-07-22 11:09:07 +0100697 struct usb_serial_port *port = tty->driver_data;
698 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100699
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 if (set & TIOCM_RTS)
701 p_priv->rts_state = 1;
702 if (set & TIOCM_DTR)
703 p_priv->dtr_state = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 if (clear & TIOCM_RTS)
705 p_priv->rts_state = 0;
706 if (clear & TIOCM_DTR)
707 p_priv->dtr_state = 0;
708 keyspan_send_setup(port, 0);
709 return 0;
710}
711
Alan Cox95da3102008-07-22 11:09:07 +0100712/* Write function is similar for the four protocols used
713 with only a minor change for usa90 (usa19hs) required */
714static int keyspan_write(struct tty_struct *tty,
715 struct usb_serial_port *port, const unsigned char *buf, int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716{
717 struct keyspan_port_private *p_priv;
718 const struct keyspan_device_details *d_details;
719 int flip;
720 int left, todo;
721 struct urb *this_urb;
Alan Coxdeb91682008-07-22 11:13:08 +0100722 int err, maxDataLen, dataOffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723
724 p_priv = usb_get_serial_port_data(port);
725 d_details = p_priv->device_details;
726
727 if (d_details->msg_format == msg_usa90) {
Alan Coxdeb91682008-07-22 11:13:08 +0100728 maxDataLen = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 dataOffset = 0;
730 } else {
731 maxDataLen = 63;
732 dataOffset = 1;
733 }
Alan Coxdeb91682008-07-22 11:13:08 +0100734
Greg Kroah-Hartman11438322013-06-06 10:32:00 -0700735 dev_dbg(&port->dev, "%s - %d chars, flip=%d\n", __func__, count,
736 p_priv->out_flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737
738 for (left = count; left > 0; left -= todo) {
739 todo = left;
740 if (todo > maxDataLen)
741 todo = maxDataLen;
742
743 flip = p_priv->out_flip;
Alan Coxdeb91682008-07-22 11:13:08 +0100744
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 /* Check we have a valid urb/endpoint before we use it... */
Alan Coxdeb91682008-07-22 11:13:08 +0100746 this_urb = p_priv->out_urbs[flip];
747 if (this_urb == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 /* no bulk out, so return 0 bytes written */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700749 dev_dbg(&port->dev, "%s - no output urb :(\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 return count;
751 }
752
Johan Hovold0cd782b2016-05-08 20:08:00 +0200753 dev_dbg(&port->dev, "%s - endpoint %x flip %d\n",
Alan Coxdeb91682008-07-22 11:13:08 +0100754 __func__, usb_pipeendpoint(this_urb->pipe), flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755
756 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +0100757 if (time_before(jiffies,
758 p_priv->tx_start_time[flip] + 10 * HZ))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 usb_unlink_urb(this_urb);
761 break;
762 }
763
Alan Coxdeb91682008-07-22 11:13:08 +0100764 /* First byte in buffer is "last flag" (except for usa19hx)
765 - unused so for now so set to zero */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 ((char *)this_urb->transfer_buffer)[0] = 0;
767
Alan Coxdeb91682008-07-22 11:13:08 +0100768 memcpy(this_urb->transfer_buffer + dataOffset, buf, todo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 buf += todo;
770
771 /* send the data out the bulk port */
772 this_urb->transfer_buffer_length = todo + dataOffset;
773
Alan Coxdeb91682008-07-22 11:13:08 +0100774 err = usb_submit_urb(this_urb, GFP_ATOMIC);
775 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700776 dev_dbg(&port->dev, "usb_submit_urb(write bulk) failed (%d)\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 p_priv->tx_start_time[flip] = jiffies;
778
779 /* Flip for next time if usa26 or usa28 interface
780 (not used on usa49) */
781 p_priv->out_flip = (flip + 1) & d_details->outdat_endp_flip;
782 }
783
784 return count - left;
785}
786
David Howells7d12e782006-10-05 14:55:46 +0100787static void usa26_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788{
789 int i, err;
790 int endpoint;
791 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700793 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 endpoint = usb_pipeendpoint(urb->pipe);
796
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700797 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +0200798 dev_dbg(&urb->dev->dev, "%s - nonzero status %d on endpoint %x\n",
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700799 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 return;
801 }
802
Ming Leicdc97792008-02-24 18:41:47 +0800803 port = urb->context;
Jiri Slaby2e124b42013-01-03 15:53:06 +0100804 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 /* 0x80 bit is error flag */
806 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100807 /* no errors on individual bytes, only
808 possible overrun err */
Johan Hovold855515a2014-11-18 11:25:20 +0100809 if (data[0] & RXERROR_OVERRUN) {
810 tty_insert_flip_char(&port->port, 0,
811 TTY_OVERRUN);
812 }
Alan Coxdeb91682008-07-22 11:13:08 +0100813 for (i = 1; i < urb->actual_length ; ++i)
Johan Hovold855515a2014-11-18 11:25:20 +0100814 tty_insert_flip_char(&port->port, data[i],
815 TTY_NORMAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 } else {
817 /* some bytes had errors, every byte has status */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700818 dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 for (i = 0; i + 1 < urb->actual_length; i += 2) {
Johan Hovold5d1678a2014-11-18 11:25:19 +0100820 int stat = data[i];
821 int flag = TTY_NORMAL;
822
823 if (stat & RXERROR_OVERRUN) {
824 tty_insert_flip_char(&port->port, 0,
825 TTY_OVERRUN);
826 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 /* XXX should handle break (0x10) */
Johan Hovold5d1678a2014-11-18 11:25:19 +0100828 if (stat & RXERROR_PARITY)
829 flag = TTY_PARITY;
830 else if (stat & RXERROR_FRAMING)
831 flag = TTY_FRAME;
832
Jiri Slaby92a19f92013-01-03 15:53:03 +0100833 tty_insert_flip_char(&port->port, data[i+1],
834 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 }
836 }
Jiri Slaby2e124b42013-01-03 15:53:06 +0100837 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 }
Alan Coxdeb91682008-07-22 11:13:08 +0100839
840 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500841 err = usb_submit_urb(urb, GFP_ATOMIC);
842 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700843 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844}
845
Alan Coxdeb91682008-07-22 11:13:08 +0100846/* Outdat handling is common for all devices */
David Howells7d12e782006-10-05 14:55:46 +0100847static void usa2x_outdat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848{
849 struct usb_serial_port *port;
850 struct keyspan_port_private *p_priv;
851
Ming Leicdc97792008-02-24 18:41:47 +0800852 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 p_priv = usb_get_serial_port_data(port);
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700854 dev_dbg(&port->dev, "%s - urb %d\n", __func__, urb == p_priv->out_urbs[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855
Alan Stern1f871582010-02-17 10:05:47 -0500856 usb_serial_port_softint(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857}
858
David Howells7d12e782006-10-05 14:55:46 +0100859static void usa26_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861}
862
David Howells7d12e782006-10-05 14:55:46 +0100863static void usa26_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864{
865 struct usb_serial_port *port;
866 struct keyspan_port_private *p_priv;
867
Ming Leicdc97792008-02-24 18:41:47 +0800868 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 p_priv = usb_get_serial_port_data(port);
870
871 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700872 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100873 keyspan_usa26_send_setup(port->serial, port,
874 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 }
876}
877
David Howells7d12e782006-10-05 14:55:46 +0100878static void usa26_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879{
880 unsigned char *data = urb->transfer_buffer;
881 struct keyspan_usa26_portStatusMessage *msg;
882 struct usb_serial *serial;
883 struct usb_serial_port *port;
884 struct keyspan_port_private *p_priv;
885 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700886 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887
Ming Leicdc97792008-02-24 18:41:47 +0800888 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700890 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +0200891 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
892 __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 return;
894 }
895 if (urb->actual_length != 9) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700896 dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 goto exit;
898 }
899
900 msg = (struct keyspan_usa26_portStatusMessage *)data;
901
Alan Coxdeb91682008-07-22 11:13:08 +0100902 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700904 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 goto exit;
906 }
907 port = serial->port[msg->port];
908 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb5122232014-12-22 18:39:39 +0100909 if (!p_priv)
910 goto resubmit;
Alan Coxdeb91682008-07-22 11:13:08 +0100911
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 /* Update handshaking pin state information */
913 old_dcd_state = p_priv->dcd_state;
914 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
915 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
916 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
917 p_priv->ri_state = ((msg->ri) ? 1 : 0);
918
Jiri Slabyaa27a092013-03-07 13:12:30 +0100919 if (old_dcd_state != p_priv->dcd_state)
920 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb5122232014-12-22 18:39:39 +0100921resubmit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100923 err = usb_submit_urb(urb, GFP_ATOMIC);
924 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700925 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926exit: ;
927}
928
David Howells7d12e782006-10-05 14:55:46 +0100929static void usa26_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931}
932
933
David Howells7d12e782006-10-05 14:55:46 +0100934static void usa28_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935{
Alan Coxf035a8a2008-07-22 11:13:32 +0100936 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 unsigned char *data;
939 struct keyspan_port_private *p_priv;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700940 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941
Ming Leicdc97792008-02-24 18:41:47 +0800942 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 p_priv = usb_get_serial_port_data(port);
944 data = urb->transfer_buffer;
945
946 if (urb != p_priv->in_urbs[p_priv->in_flip])
947 return;
948
949 do {
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700950 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +0200951 dev_dbg(&urb->dev->dev, "%s - nonzero status %d on endpoint %x\n",
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700952 __func__, status, usb_pipeendpoint(urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 return;
954 }
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 data = urb->transfer_buffer;
959
Jiri Slaby2e124b42013-01-03 15:53:06 +0100960 if (urb->actual_length) {
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100961 tty_insert_flip_string(&port->port, data,
962 urb->actual_length);
Jiri Slaby2e124b42013-01-03 15:53:06 +0100963 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 }
965
966 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500967 err = usb_submit_urb(urb, GFP_ATOMIC);
968 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700969 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n",
Alan Stern1f871582010-02-17 10:05:47 -0500970 __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 p_priv->in_flip ^= 1;
972
973 urb = p_priv->in_urbs[p_priv->in_flip];
974 } while (urb->status != -EINPROGRESS);
975}
976
David Howells7d12e782006-10-05 14:55:46 +0100977static void usa28_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979}
980
David Howells7d12e782006-10-05 14:55:46 +0100981static void usa28_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982{
983 struct usb_serial_port *port;
984 struct keyspan_port_private *p_priv;
985
Ming Leicdc97792008-02-24 18:41:47 +0800986 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 p_priv = usb_get_serial_port_data(port);
988
989 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700990 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100991 keyspan_usa28_send_setup(port->serial, port,
992 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 }
994}
995
David Howells7d12e782006-10-05 14:55:46 +0100996static void usa28_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997{
998 int err;
999 unsigned char *data = urb->transfer_buffer;
1000 struct keyspan_usa28_portStatusMessage *msg;
1001 struct usb_serial *serial;
1002 struct usb_serial_port *port;
1003 struct keyspan_port_private *p_priv;
1004 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001005 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006
Ming Leicdc97792008-02-24 18:41:47 +08001007 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001009 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +02001010 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
1011 __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 return;
1013 }
1014
1015 if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001016 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 goto exit;
1018 }
1019
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 msg = (struct keyspan_usa28_portStatusMessage *)data;
1021
Alan Coxdeb91682008-07-22 11:13:08 +01001022 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001024 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 goto exit;
1026 }
1027 port = serial->port[msg->port];
1028 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb5122232014-12-22 18:39:39 +01001029 if (!p_priv)
1030 goto resubmit;
Alan Coxdeb91682008-07-22 11:13:08 +01001031
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 /* Update handshaking pin state information */
1033 old_dcd_state = p_priv->dcd_state;
1034 p_priv->cts_state = ((msg->cts) ? 1 : 0);
1035 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
1036 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
1037 p_priv->ri_state = ((msg->ri) ? 1 : 0);
1038
Jiri Slabyaa27a092013-03-07 13:12:30 +01001039 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
1040 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb5122232014-12-22 18:39:39 +01001041resubmit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +01001043 err = usb_submit_urb(urb, GFP_ATOMIC);
1044 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001045 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046exit: ;
1047}
1048
David Howells7d12e782006-10-05 14:55:46 +01001049static void usa28_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051}
1052
1053
David Howells7d12e782006-10-05 14:55:46 +01001054static void usa49_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055{
1056 struct usb_serial *serial;
1057 struct usb_serial_port *port;
1058 struct keyspan_port_private *p_priv;
1059 int i;
1060
Ming Leicdc97792008-02-24 18:41:47 +08001061 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 for (i = 0; i < serial->num_ports; ++i) {
1063 port = serial->port[i];
1064 p_priv = usb_get_serial_port_data(port);
1065
1066 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001067 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +01001068 keyspan_usa49_send_setup(serial, port,
1069 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 break;
1071 }
1072 }
1073}
1074
1075 /* This is actually called glostat in the Keyspan
1076 doco */
David Howells7d12e782006-10-05 14:55:46 +01001077static void usa49_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078{
1079 int err;
1080 unsigned char *data = urb->transfer_buffer;
1081 struct keyspan_usa49_portStatusMessage *msg;
1082 struct usb_serial *serial;
1083 struct usb_serial_port *port;
1084 struct keyspan_port_private *p_priv;
1085 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001086 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087
Ming Leicdc97792008-02-24 18:41:47 +08001088 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001090 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +02001091 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
1092 __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 return;
1094 }
1095
Alan Coxdeb91682008-07-22 11:13:08 +01001096 if (urb->actual_length !=
1097 sizeof(struct keyspan_usa49_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001098 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 goto exit;
1100 }
1101
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 msg = (struct keyspan_usa49_portStatusMessage *)data;
1103
Alan Coxdeb91682008-07-22 11:13:08 +01001104 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 if (msg->portNumber >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001106 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
1107 __func__, msg->portNumber);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 goto exit;
1109 }
1110 port = serial->port[msg->portNumber];
1111 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb5122232014-12-22 18:39:39 +01001112 if (!p_priv)
1113 goto resubmit;
Alan Coxdeb91682008-07-22 11:13:08 +01001114
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 /* Update handshaking pin state information */
1116 old_dcd_state = p_priv->dcd_state;
1117 p_priv->cts_state = ((msg->cts) ? 1 : 0);
1118 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
1119 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
1120 p_priv->ri_state = ((msg->ri) ? 1 : 0);
1121
Jiri Slabyaa27a092013-03-07 13:12:30 +01001122 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
1123 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb5122232014-12-22 18:39:39 +01001124resubmit:
Alan Coxdeb91682008-07-22 11:13:08 +01001125 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +01001126 err = usb_submit_urb(urb, GFP_ATOMIC);
1127 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001128 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129exit: ;
1130}
1131
David Howells7d12e782006-10-05 14:55:46 +01001132static void usa49_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134}
1135
David Howells7d12e782006-10-05 14:55:46 +01001136static void usa49_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137{
1138 int i, err;
1139 int endpoint;
1140 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001142 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 endpoint = usb_pipeendpoint(urb->pipe);
1145
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001146 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +02001147 dev_dbg(&urb->dev->dev, "%s - nonzero status %d on endpoint %x\n",
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001148 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 return;
1150 }
1151
Ming Leicdc97792008-02-24 18:41:47 +08001152 port = urb->context;
Jiri Slaby2e124b42013-01-03 15:53:06 +01001153 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 /* 0x80 bit is error flag */
1155 if ((data[0] & 0x80) == 0) {
1156 /* no error on any byte */
Jiri Slaby05c7cd32013-01-03 15:53:04 +01001157 tty_insert_flip_string(&port->port, data + 1,
Alan Coxf035a8a2008-07-22 11:13:32 +01001158 urb->actual_length - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 } else {
1160 /* some bytes had errors, every byte has status */
1161 for (i = 0; i + 1 < urb->actual_length; i += 2) {
Johan Hovold5d1678a2014-11-18 11:25:19 +01001162 int stat = data[i];
1163 int flag = TTY_NORMAL;
1164
1165 if (stat & RXERROR_OVERRUN) {
1166 tty_insert_flip_char(&port->port, 0,
1167 TTY_OVERRUN);
1168 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 /* XXX should handle break (0x10) */
Johan Hovold5d1678a2014-11-18 11:25:19 +01001170 if (stat & RXERROR_PARITY)
1171 flag = TTY_PARITY;
1172 else if (stat & RXERROR_FRAMING)
1173 flag = TTY_FRAME;
1174
Jiri Slaby92a19f92013-01-03 15:53:03 +01001175 tty_insert_flip_char(&port->port, data[i+1],
1176 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 }
1178 }
Jiri Slaby2e124b42013-01-03 15:53:06 +01001179 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 }
Alan Coxdeb91682008-07-22 11:13:08 +01001181
1182 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -05001183 err = usb_submit_urb(urb, GFP_ATOMIC);
1184 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001185 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186}
1187
Lucy McCoy0ca12682007-05-18 12:10:41 -07001188static void usa49wg_indat_callback(struct urb *urb)
1189{
1190 int i, len, x, err;
1191 struct usb_serial *serial;
1192 struct usb_serial_port *port;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001193 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001194 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001195
Lucy McCoy0ca12682007-05-18 12:10:41 -07001196 serial = urb->context;
1197
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001198 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +02001199 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
1200 __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001201 return;
1202 }
1203
1204 /* inbound data is in the form P#, len, status, data */
1205 i = 0;
1206 len = 0;
1207
Dan Carpenter6a3ae842013-04-05 08:42:41 +03001208 while (i < urb->actual_length) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07001209
Dan Carpenter6a3ae842013-04-05 08:42:41 +03001210 /* Check port number from message */
1211 if (data[i] >= serial->num_ports) {
1212 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
1213 __func__, data[i]);
1214 return;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001215 }
Dan Carpenter6a3ae842013-04-05 08:42:41 +03001216 port = serial->port[data[i++]];
1217 len = data[i++];
1218
1219 /* 0x80 bit is error flag */
1220 if ((data[i] & 0x80) == 0) {
1221 /* no error on any byte */
1222 i++;
Dan Carpenter01a60e72013-04-05 08:43:20 +03001223 for (x = 1; x < len && i < urb->actual_length; ++x)
Dan Carpenter6a3ae842013-04-05 08:42:41 +03001224 tty_insert_flip_char(&port->port,
1225 data[i++], 0);
1226 } else {
1227 /*
1228 * some bytes had errors, every byte has status
1229 */
Dan Carpenter01a60e72013-04-05 08:43:20 +03001230 for (x = 0; x + 1 < len &&
1231 i + 1 < urb->actual_length; x += 2) {
Johan Hovold5d1678a2014-11-18 11:25:19 +01001232 int stat = data[i];
1233 int flag = TTY_NORMAL;
Dan Carpenter6a3ae842013-04-05 08:42:41 +03001234
Johan Hovold5d1678a2014-11-18 11:25:19 +01001235 if (stat & RXERROR_OVERRUN) {
1236 tty_insert_flip_char(&port->port, 0,
1237 TTY_OVERRUN);
1238 }
Dan Carpenter6a3ae842013-04-05 08:42:41 +03001239 /* XXX should handle break (0x10) */
Johan Hovold5d1678a2014-11-18 11:25:19 +01001240 if (stat & RXERROR_PARITY)
1241 flag = TTY_PARITY;
1242 else if (stat & RXERROR_FRAMING)
1243 flag = TTY_FRAME;
1244
Dan Carpenter6a3ae842013-04-05 08:42:41 +03001245 tty_insert_flip_char(&port->port, data[i+1],
1246 flag);
1247 i += 2;
1248 }
1249 }
1250 tty_flip_buffer_push(&port->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001251 }
1252
1253 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -07001254 err = usb_submit_urb(urb, GFP_ATOMIC);
1255 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001256 dev_dbg(&urb->dev->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001257}
1258
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259/* not used, usa-49 doesn't have per-port control endpoints */
Lucy McCoy0ca12682007-05-18 12:10:41 -07001260static void usa49_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262}
1263
Lucy McCoy0ca12682007-05-18 12:10:41 -07001264static void usa90_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265{
1266 int i, err;
1267 int endpoint;
1268 struct usb_serial_port *port;
1269 struct keyspan_port_private *p_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001271 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 endpoint = usb_pipeendpoint(urb->pipe);
1274
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001275 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +02001276 dev_dbg(&urb->dev->dev, "%s - nonzero status %d on endpoint %x\n",
1277 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 return;
1279 }
1280
Ming Leicdc97792008-02-24 18:41:47 +08001281 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 p_priv = usb_get_serial_port_data(port);
1283
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 /* if current mode is DMA, looks like usa28 format
Alan Coxdeb91682008-07-22 11:13:08 +01001286 otherwise looks like usa26 data format */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287
Alan Coxf035a8a2008-07-22 11:13:32 +01001288 if (p_priv->baud > 57600)
Jiri Slaby05c7cd32013-01-03 15:53:04 +01001289 tty_insert_flip_string(&port->port, data,
1290 urb->actual_length);
Alan Coxf035a8a2008-07-22 11:13:32 +01001291 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 /* 0x80 bit is error flag */
1293 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +01001294 /* no errors on individual bytes, only
1295 possible overrun err*/
Johan Hovold855515a2014-11-18 11:25:20 +01001296 if (data[0] & RXERROR_OVERRUN) {
1297 tty_insert_flip_char(&port->port, 0,
1298 TTY_OVERRUN);
1299 }
Alan Coxdeb91682008-07-22 11:13:08 +01001300 for (i = 1; i < urb->actual_length ; ++i)
Jiri Slaby92a19f92013-01-03 15:53:03 +01001301 tty_insert_flip_char(&port->port,
Johan Hovold855515a2014-11-18 11:25:20 +01001302 data[i], TTY_NORMAL);
Alan Coxdeb91682008-07-22 11:13:08 +01001303 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 /* some bytes had errors, every byte has status */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001305 dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 for (i = 0; i + 1 < urb->actual_length; i += 2) {
Johan Hovold5d1678a2014-11-18 11:25:19 +01001307 int stat = data[i];
1308 int flag = TTY_NORMAL;
1309
1310 if (stat & RXERROR_OVERRUN) {
1311 tty_insert_flip_char(
1312 &port->port, 0,
1313 TTY_OVERRUN);
1314 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315 /* XXX should handle break (0x10) */
Johan Hovold5d1678a2014-11-18 11:25:19 +01001316 if (stat & RXERROR_PARITY)
1317 flag = TTY_PARITY;
1318 else if (stat & RXERROR_FRAMING)
1319 flag = TTY_FRAME;
1320
Jiri Slaby92a19f92013-01-03 15:53:03 +01001321 tty_insert_flip_char(&port->port,
1322 data[i+1], flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 }
1324 }
1325 }
Jiri Slaby2e124b42013-01-03 15:53:06 +01001326 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 }
Alan Coxdeb91682008-07-22 11:13:08 +01001328
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -05001330 err = usb_submit_urb(urb, GFP_ATOMIC);
1331 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001332 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333}
1334
1335
David Howells7d12e782006-10-05 14:55:46 +01001336static void usa90_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337{
1338 unsigned char *data = urb->transfer_buffer;
1339 struct keyspan_usa90_portStatusMessage *msg;
1340 struct usb_serial *serial;
1341 struct usb_serial_port *port;
1342 struct keyspan_port_private *p_priv;
1343 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001344 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345
Ming Leicdc97792008-02-24 18:41:47 +08001346 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001348 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +02001349 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
1350 __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 return;
1352 }
1353 if (urb->actual_length < 14) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001354 dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 goto exit;
1356 }
1357
1358 msg = (struct keyspan_usa90_portStatusMessage *)data;
1359
1360 /* Now do something useful with the data */
1361
1362 port = serial->port[0];
1363 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb5122232014-12-22 18:39:39 +01001364 if (!p_priv)
1365 goto resubmit;
Alan Coxdeb91682008-07-22 11:13:08 +01001366
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 /* Update handshaking pin state information */
1368 old_dcd_state = p_priv->dcd_state;
1369 p_priv->cts_state = ((msg->cts) ? 1 : 0);
1370 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
1371 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
1372 p_priv->ri_state = ((msg->ri) ? 1 : 0);
1373
Jiri Slabyaa27a092013-03-07 13:12:30 +01001374 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
1375 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb5122232014-12-22 18:39:39 +01001376resubmit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +01001378 err = usb_submit_urb(urb, GFP_ATOMIC);
1379 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001380 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381exit:
1382 ;
1383}
1384
David Howells7d12e782006-10-05 14:55:46 +01001385static void usa90_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386{
1387 struct usb_serial_port *port;
1388 struct keyspan_port_private *p_priv;
1389
Ming Leicdc97792008-02-24 18:41:47 +08001390 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 p_priv = usb_get_serial_port_data(port);
1392
1393 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001394 dev_dbg(&urb->dev->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +01001395 keyspan_usa90_send_setup(port->serial, port,
1396 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 }
1398}
1399
Lucy McCoy0ca12682007-05-18 12:10:41 -07001400/* Status messages from the 28xg */
1401static void usa67_instat_callback(struct urb *urb)
1402{
1403 int err;
1404 unsigned char *data = urb->transfer_buffer;
1405 struct keyspan_usa67_portStatusMessage *msg;
1406 struct usb_serial *serial;
1407 struct usb_serial_port *port;
1408 struct keyspan_port_private *p_priv;
1409 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001410 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001411
Lucy McCoy0ca12682007-05-18 12:10:41 -07001412 serial = urb->context;
1413
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001414 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +02001415 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
1416 __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001417 return;
1418 }
1419
Alan Coxdeb91682008-07-22 11:13:08 +01001420 if (urb->actual_length !=
1421 sizeof(struct keyspan_usa67_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001422 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001423 return;
1424 }
1425
1426
1427 /* Now do something useful with the data */
1428 msg = (struct keyspan_usa67_portStatusMessage *)data;
1429
1430 /* Check port number from message and retrieve private data */
1431 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001432 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001433 return;
1434 }
1435
1436 port = serial->port[msg->port];
1437 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb5122232014-12-22 18:39:39 +01001438 if (!p_priv)
1439 goto resubmit;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001440
1441 /* Update handshaking pin state information */
1442 old_dcd_state = p_priv->dcd_state;
1443 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
1444 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
1445
Jiri Slabyaa27a092013-03-07 13:12:30 +01001446 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
1447 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb5122232014-12-22 18:39:39 +01001448resubmit:
Lucy McCoy0ca12682007-05-18 12:10:41 -07001449 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -07001450 err = usb_submit_urb(urb, GFP_ATOMIC);
1451 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001452 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001453}
1454
1455static void usa67_glocont_callback(struct urb *urb)
1456{
1457 struct usb_serial *serial;
1458 struct usb_serial_port *port;
1459 struct keyspan_port_private *p_priv;
1460 int i;
1461
Lucy McCoy0ca12682007-05-18 12:10:41 -07001462 serial = urb->context;
1463 for (i = 0; i < serial->num_ports; ++i) {
1464 port = serial->port[i];
1465 p_priv = usb_get_serial_port_data(port);
1466
1467 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001468 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001469 keyspan_usa67_send_setup(serial, port,
1470 p_priv->resend_cont - 1);
1471 break;
1472 }
1473 }
1474}
1475
Alan Cox95da3102008-07-22 11:09:07 +01001476static int keyspan_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477{
Alan Cox95da3102008-07-22 11:09:07 +01001478 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 struct keyspan_port_private *p_priv;
1480 const struct keyspan_device_details *d_details;
1481 int flip;
1482 int data_len;
1483 struct urb *this_urb;
1484
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485 p_priv = usb_get_serial_port_data(port);
1486 d_details = p_priv->device_details;
1487
Alan Coxa5b6f602008-04-08 17:16:06 +01001488 /* FIXME: locking */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 if (d_details->msg_format == msg_usa90)
Alan Coxdeb91682008-07-22 11:13:08 +01001490 data_len = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 else
1492 data_len = 63;
1493
1494 flip = p_priv->out_flip;
1495
1496 /* Check both endpoints to see if any are available. */
Alan Coxdeb91682008-07-22 11:13:08 +01001497 this_urb = p_priv->out_urbs[flip];
1498 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001500 return data_len;
1501 flip = (flip + 1) & d_details->outdat_endp_flip;
1502 this_urb = p_priv->out_urbs[flip];
1503 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001505 return data_len;
1506 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 }
Alan Coxa5b6f602008-04-08 17:16:06 +01001508 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509}
1510
1511
Alan Coxa509a7e2009-09-19 13:13:26 -07001512static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513{
Andrew Mortonf78ba152007-11-28 16:21:54 -08001514 struct keyspan_port_private *p_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 const struct keyspan_device_details *d_details;
1516 int i, err;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001517 int baud_rate, device_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 struct urb *urb;
Alan Cox95da3102008-07-22 11:09:07 +01001519 unsigned int cflag = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 p_priv = usb_get_serial_port_data(port);
1522 d_details = p_priv->device_details;
Borislav Petkov7eea4362007-11-14 17:00:39 -08001523
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 /* Set some sane defaults */
1525 p_priv->rts_state = 1;
1526 p_priv->dtr_state = 1;
1527 p_priv->baud = 9600;
1528
1529 /* force baud and lcr to be set on open */
1530 p_priv->old_baud = 0;
1531 p_priv->old_cflag = 0;
1532
1533 p_priv->out_flip = 0;
1534 p_priv->in_flip = 0;
1535
1536 /* Reset low level data toggle and start reading from endpoints */
1537 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001538 urb = p_priv->in_urbs[i];
1539 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541
Alan Coxdeb91682008-07-22 11:13:08 +01001542 /* make sure endpoint data toggle is synchronized
1543 with the device */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 usb_clear_halt(urb->dev, urb->pipe);
Alan Coxdeb91682008-07-22 11:13:08 +01001545 err = usb_submit_urb(urb, GFP_KERNEL);
1546 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001547 dev_dbg(&port->dev, "%s - submit urb %d failed (%d)\n", __func__, i, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 }
1549
1550 /* Reset low level data toggle on out endpoints */
1551 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001552 urb = p_priv->out_urbs[i];
1553 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554 continue;
Alan Coxdeb91682008-07-22 11:13:08 +01001555 /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
1556 usb_pipeout(urb->pipe), 0); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 }
1558
Andrew Mortonf78ba152007-11-28 16:21:54 -08001559 /* get the terminal config for the setup message now so we don't
1560 * need to send 2 of them */
1561
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001562 device_port = port->port_number;
Alan Cox95da3102008-07-22 11:09:07 +01001563 if (tty) {
Alan Coxadc8d742012-07-14 15:31:47 +01001564 cflag = tty->termios.c_cflag;
Alan Cox95da3102008-07-22 11:09:07 +01001565 /* Baud rate calculation takes baud rate as an integer
1566 so other rates can be generated if desired. */
1567 baud_rate = tty_get_baud_rate(tty);
1568 /* If no match or invalid, leave as default */
1569 if (baud_rate >= 0
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001570 && d_details->calculate_baud_rate(port, baud_rate, d_details->baudclk,
Alan Cox95da3102008-07-22 11:09:07 +01001571 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
1572 p_priv->baud = baud_rate;
1573 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001574 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001575 /* set CTS/RTS handshake etc. */
1576 p_priv->cflag = cflag;
Ben Minerds2b982ab2012-07-12 00:10:16 +10001577 p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001578
1579 keyspan_send_setup(port, 1);
Alan Coxdeb91682008-07-22 11:13:08 +01001580 /* mdelay(100); */
1581 /* keyspan_set_termios(port, NULL); */
Andrew Mortonf78ba152007-11-28 16:21:54 -08001582
Alan Coxa5b6f602008-04-08 17:16:06 +01001583 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584}
1585
Alan Cox335f8512009-06-11 12:26:29 +01001586static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
1587{
1588 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
1589
1590 p_priv->rts_state = on;
1591 p_priv->dtr_state = on;
1592 keyspan_send_setup(port, 0);
1593}
1594
1595static void keyspan_close(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596{
1597 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598 struct keyspan_port_private *p_priv;
1599
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +01001601
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602 p_priv->rts_state = 0;
1603 p_priv->dtr_state = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001604
Johan Hovold80dfe0c2013-03-21 12:36:32 +01001605 keyspan_send_setup(port, 2);
1606 /* pilot-xfer seems to work best with this delay */
1607 mdelay(100);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608
1609 p_priv->out_flip = 0;
1610 p_priv->in_flip = 0;
1611
Johan Hovold61924502016-05-08 20:07:59 +02001612 usb_kill_urb(p_priv->inack_urb);
Johan Hovold80dfe0c2013-03-21 12:36:32 +01001613 for (i = 0; i < 2; i++) {
Johan Hovold61924502016-05-08 20:07:59 +02001614 usb_kill_urb(p_priv->in_urbs[i]);
1615 usb_kill_urb(p_priv->out_urbs[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617}
1618
Alan Coxdeb91682008-07-22 11:13:08 +01001619/* download the firmware to a pre-renumeration device */
1620static int keyspan_fake_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621{
Rene Buergel8d733e22012-09-18 09:02:01 +02001622 char *fw_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001624 dev_dbg(&serial->dev->dev, "Keyspan startup version %04x product %04x\n",
1625 le16_to_cpu(serial->dev->descriptor.bcdDevice),
1626 le16_to_cpu(serial->dev->descriptor.idProduct));
Alan Coxdeb91682008-07-22 11:13:08 +01001627
1628 if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000)
1629 != 0x8000) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001630 dev_dbg(&serial->dev->dev, "Firmware already loaded. Quitting.\n");
Alan Coxdeb91682008-07-22 11:13:08 +01001631 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632 }
1633
1634 /* Select firmware image on the basis of idProduct */
1635 switch (le16_to_cpu(serial->dev->descriptor.idProduct)) {
1636 case keyspan_usa28_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001637 fw_name = "keyspan/usa28.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 break;
1639
1640 case keyspan_usa28x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001641 fw_name = "keyspan/usa28x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642 break;
1643
1644 case keyspan_usa28xa_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001645 fw_name = "keyspan/usa28xa.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 break;
1647
1648 case keyspan_usa28xb_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001649 fw_name = "keyspan/usa28xb.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650 break;
1651
1652 case keyspan_usa19_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001653 fw_name = "keyspan/usa19.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001655
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656 case keyspan_usa19qi_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001657 fw_name = "keyspan/usa19qi.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001659
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 case keyspan_mpr_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001661 fw_name = "keyspan/mpr.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 break;
1663
1664 case keyspan_usa19qw_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001665 fw_name = "keyspan/usa19qw.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001667
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 case keyspan_usa18x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001669 fw_name = "keyspan/usa18x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001671
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 case keyspan_usa19w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001673 fw_name = "keyspan/usa19w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001675
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676 case keyspan_usa49w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001677 fw_name = "keyspan/usa49w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 break;
1679
1680 case keyspan_usa49wlc_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001681 fw_name = "keyspan/usa49wlc.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 break;
1683
1684 default:
David Woodhouse2971c572008-05-30 14:04:03 +03001685 dev_err(&serial->dev->dev, "Unknown product ID (%04x)\n",
1686 le16_to_cpu(serial->dev->descriptor.idProduct));
1687 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688 }
1689
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001690 dev_dbg(&serial->dev->dev, "Uploading Keyspan %s firmware.\n", fw_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691
Rene Buergel8d733e22012-09-18 09:02:01 +02001692 if (ezusb_fx1_ihex_firmware_download(serial->dev, fw_name) < 0) {
1693 dev_err(&serial->dev->dev, "failed to load firmware \"%s\"\n",
1694 fw_name);
1695 return -ENOENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 }
1697
Rene Buergel8d733e22012-09-18 09:02:01 +02001698 /* after downloading firmware Renumeration will occur in a
1699 moment and the new device will bind to the real driver */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700
1701 /* we don't want this device to have a driver assigned to it. */
Alan Coxdeb91682008-07-22 11:13:08 +01001702 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703}
1704
1705/* Helper functions used by keyspan_setup_urbs */
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001706static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *serial,
1707 int endpoint)
1708{
1709 struct usb_host_interface *iface_desc;
1710 struct usb_endpoint_descriptor *ep;
1711 int i;
1712
1713 iface_desc = serial->interface->cur_altsetting;
1714 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1715 ep = &iface_desc->endpoint[i].desc;
1716 if (ep->bEndpointAddress == endpoint)
1717 return ep;
1718 }
Johan Hovold0cd782b2016-05-08 20:08:00 +02001719 dev_warn(&serial->interface->dev, "found no endpoint descriptor for endpoint %x\n",
1720 endpoint);
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001721 return NULL;
1722}
1723
Alan Coxdeb91682008-07-22 11:13:08 +01001724static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725 int dir, void *ctx, char *buf, int len,
David Howells7d12e782006-10-05 14:55:46 +01001726 void (*callback)(struct urb *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727{
1728 struct urb *urb;
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001729 struct usb_endpoint_descriptor const *ep_desc;
1730 char const *ep_type_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731
1732 if (endpoint == -1)
1733 return NULL; /* endpoint not needed */
1734
Johan Hovold0cd782b2016-05-08 20:08:00 +02001735 dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %x\n",
1736 __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
Johan Hovold10c642d2013-12-29 19:22:56 +01001738 if (!urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740
Lucy McCoy0ca12682007-05-18 12:10:41 -07001741 if (endpoint == 0) {
1742 /* control EP filled in when used */
1743 return urb;
1744 }
1745
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001746 ep_desc = find_ep(serial, endpoint);
1747 if (!ep_desc) {
1748 /* leak the urb, something's wrong and the callers don't care */
1749 return urb;
1750 }
1751 if (usb_endpoint_xfer_int(ep_desc)) {
1752 ep_type_name = "INT";
1753 usb_fill_int_urb(urb, serial->dev,
1754 usb_sndintpipe(serial->dev, endpoint) | dir,
1755 buf, len, callback, ctx,
1756 ep_desc->bInterval);
1757 } else if (usb_endpoint_xfer_bulk(ep_desc)) {
1758 ep_type_name = "BULK";
1759 usb_fill_bulk_urb(urb, serial->dev,
1760 usb_sndbulkpipe(serial->dev, endpoint) | dir,
1761 buf, len, callback, ctx);
1762 } else {
1763 dev_warn(&serial->interface->dev,
1764 "unsupported endpoint type %x\n",
Julia Lawall2e0fe702008-12-29 11:22:14 +01001765 usb_endpoint_type(ep_desc));
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001766 usb_free_urb(urb);
1767 return NULL;
1768 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001770 dev_dbg(&serial->interface->dev, "%s - using urb %p for %s endpoint %x\n",
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001771 __func__, urb, ep_type_name, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772 return urb;
1773}
1774
1775static struct callbacks {
David Howells7d12e782006-10-05 14:55:46 +01001776 void (*instat_callback)(struct urb *);
1777 void (*glocont_callback)(struct urb *);
1778 void (*indat_callback)(struct urb *);
1779 void (*outdat_callback)(struct urb *);
1780 void (*inack_callback)(struct urb *);
1781 void (*outcont_callback)(struct urb *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782} keyspan_callbacks[] = {
1783 {
1784 /* msg_usa26 callbacks */
1785 .instat_callback = usa26_instat_callback,
1786 .glocont_callback = usa26_glocont_callback,
1787 .indat_callback = usa26_indat_callback,
1788 .outdat_callback = usa2x_outdat_callback,
1789 .inack_callback = usa26_inack_callback,
1790 .outcont_callback = usa26_outcont_callback,
1791 }, {
1792 /* msg_usa28 callbacks */
1793 .instat_callback = usa28_instat_callback,
1794 .glocont_callback = usa28_glocont_callback,
1795 .indat_callback = usa28_indat_callback,
1796 .outdat_callback = usa2x_outdat_callback,
1797 .inack_callback = usa28_inack_callback,
1798 .outcont_callback = usa28_outcont_callback,
1799 }, {
1800 /* msg_usa49 callbacks */
1801 .instat_callback = usa49_instat_callback,
1802 .glocont_callback = usa49_glocont_callback,
1803 .indat_callback = usa49_indat_callback,
1804 .outdat_callback = usa2x_outdat_callback,
1805 .inack_callback = usa49_inack_callback,
1806 .outcont_callback = usa49_outcont_callback,
1807 }, {
1808 /* msg_usa90 callbacks */
1809 .instat_callback = usa90_instat_callback,
Alan Coxdeb91682008-07-22 11:13:08 +01001810 .glocont_callback = usa28_glocont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811 .indat_callback = usa90_indat_callback,
1812 .outdat_callback = usa2x_outdat_callback,
1813 .inack_callback = usa28_inack_callback,
1814 .outcont_callback = usa90_outcont_callback,
Lucy McCoy0ca12682007-05-18 12:10:41 -07001815 }, {
1816 /* msg_usa67 callbacks */
1817 .instat_callback = usa67_instat_callback,
1818 .glocont_callback = usa67_glocont_callback,
1819 .indat_callback = usa26_indat_callback,
1820 .outdat_callback = usa2x_outdat_callback,
1821 .inack_callback = usa26_inack_callback,
1822 .outcont_callback = usa26_outcont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823 }
1824};
1825
1826 /* Generic setup urbs function that uses
1827 data in device_details */
1828static void keyspan_setup_urbs(struct usb_serial *serial)
1829{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 struct keyspan_serial_private *s_priv;
1831 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 struct callbacks *cback;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834 s_priv = usb_get_serial_data(serial);
1835 d_details = s_priv->device_details;
1836
Alan Coxdeb91682008-07-22 11:13:08 +01001837 /* Setup values for the various callback routines */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 cback = &keyspan_callbacks[d_details->msg_format];
1839
Alan Coxdeb91682008-07-22 11:13:08 +01001840 /* Allocate and set up urbs for each one that is in use,
1841 starting with instat endpoints */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 s_priv->instat_urb = keyspan_setup_urb
1843 (serial, d_details->instat_endpoint, USB_DIR_IN,
1844 serial, s_priv->instat_buf, INSTAT_BUFLEN,
1845 cback->instat_callback);
1846
Lucy McCoy0ca12682007-05-18 12:10:41 -07001847 s_priv->indat_urb = keyspan_setup_urb
1848 (serial, d_details->indat_endpoint, USB_DIR_IN,
1849 serial, s_priv->indat_buf, INDAT49W_BUFLEN,
1850 usa49wg_indat_callback);
1851
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 s_priv->glocont_urb = keyspan_setup_urb
1853 (serial, d_details->glocont_endpoint, USB_DIR_OUT,
1854 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
1855 cback->glocont_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856}
1857
1858/* usa19 function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001859static int keyspan_usa19_calc_baud(struct usb_serial_port *port,
1860 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 u8 *rate_low, u8 *prescaler, int portnum)
1862{
1863 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001864 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865 cnt; /* inverse of divisor (programmed into 8051) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001867 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868
Alan Coxdeb91682008-07-22 11:13:08 +01001869 /* prevent divide by zero... */
1870 b16 = baud_rate * 16L;
1871 if (b16 == 0)
1872 return KEYSPAN_INVALID_BAUD_RATE;
1873 /* Any "standard" rate over 57k6 is marginal on the USA-19
1874 as we run out of divisor resolution. */
1875 if (baud_rate > 57600)
1876 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877
Alan Coxdeb91682008-07-22 11:13:08 +01001878 /* calculate the divisor and the counter (its inverse) */
1879 div = baudclk / b16;
1880 if (div == 0)
1881 return KEYSPAN_INVALID_BAUD_RATE;
1882 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884
Alan Coxdeb91682008-07-22 11:13:08 +01001885 if (div > 0xffff)
1886 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887
Alan Coxdeb91682008-07-22 11:13:08 +01001888 /* return the counter values if non-null */
1889 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001891 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001893 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001894 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001895 __func__, baud_rate, *rate_hi, *rate_low);
1896 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897}
1898
1899/* usa19hs function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001900static int keyspan_usa19hs_calc_baud(struct usb_serial_port *port,
1901 u32 baud_rate, u32 baudclk, u8 *rate_hi,
1902 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903{
1904 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001905 div; /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001907 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908
Alan Coxdeb91682008-07-22 11:13:08 +01001909 /* prevent divide by zero... */
1910 b16 = baud_rate * 16L;
1911 if (b16 == 0)
1912 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913
Alan Coxdeb91682008-07-22 11:13:08 +01001914 /* calculate the divisor */
1915 div = baudclk / b16;
1916 if (div == 0)
1917 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918
Alan Coxdeb91682008-07-22 11:13:08 +01001919 if (div > 0xffff)
1920 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921
Alan Coxdeb91682008-07-22 11:13:08 +01001922 /* return the counter values if non-null */
1923 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001925
1926 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927 *rate_hi = (u8) ((div >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001928
1929 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001930 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001931 __func__, baud_rate, *rate_hi, *rate_low);
1932
1933 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934}
1935
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001936static int keyspan_usa19w_calc_baud(struct usb_serial_port *port,
1937 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 u8 *rate_low, u8 *prescaler, int portnum)
1939{
1940 u32 b16, /* baud rate times 16 (actual rate used internally) */
1941 clk, /* clock with 13/8 prescaler */
Alan Coxdeb91682008-07-22 11:13:08 +01001942 div, /* divisor using 13/8 prescaler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943 res, /* resulting baud rate using 13/8 prescaler */
1944 diff, /* error using 13/8 prescaler */
1945 smallest_diff;
1946 u8 best_prescaler;
1947 int i;
1948
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001949 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950
Alan Coxdeb91682008-07-22 11:13:08 +01001951 /* prevent divide by zero */
1952 b16 = baud_rate * 16L;
1953 if (b16 == 0)
1954 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955
Alan Coxdeb91682008-07-22 11:13:08 +01001956 /* Calculate prescaler by trying them all and looking
1957 for best fit */
1958
1959 /* start with largest possible difference */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960 smallest_diff = 0xffffffff;
1961
1962 /* 0 is an invalid prescaler, used as a flag */
1963 best_prescaler = 0;
1964
Alan Coxdeb91682008-07-22 11:13:08 +01001965 for (i = 8; i <= 0xff; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966 clk = (baudclk * 8) / (u32) i;
Alan Coxdeb91682008-07-22 11:13:08 +01001967
1968 div = clk / b16;
1969 if (div == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971
1972 res = clk / div;
Alan Coxdeb91682008-07-22 11:13:08 +01001973 diff = (res > b16) ? (res-b16) : (b16-res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974
Alan Coxdeb91682008-07-22 11:13:08 +01001975 if (diff < smallest_diff) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 best_prescaler = i;
1977 smallest_diff = diff;
1978 }
1979 }
1980
Alan Coxdeb91682008-07-22 11:13:08 +01001981 if (best_prescaler == 0)
1982 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983
1984 clk = (baudclk * 8) / (u32) best_prescaler;
1985 div = clk / b16;
1986
Alan Coxdeb91682008-07-22 11:13:08 +01001987 /* return the divisor and prescaler if non-null */
1988 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001990 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991 *rate_hi = (u8) ((div >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 if (prescaler) {
1993 *prescaler = best_prescaler;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001994 /* dev_dbg(&port->dev, "%s - %d %d\n", __func__, *prescaler, div); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995 }
Alan Coxdeb91682008-07-22 11:13:08 +01001996 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997}
1998
1999 /* USA-28 supports different maximum baud rates on each port */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002000static int keyspan_usa28_calc_baud(struct usb_serial_port *port,
2001 u32 baud_rate, u32 baudclk, u8 *rate_hi,
2002 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003{
2004 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01002005 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006 cnt; /* inverse of divisor (programmed into 8051) */
2007
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002008 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009
2010 /* prevent divide by zero */
Alan Coxdeb91682008-07-22 11:13:08 +01002011 b16 = baud_rate * 16L;
2012 if (b16 == 0)
2013 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014
Alan Coxdeb91682008-07-22 11:13:08 +01002015 /* calculate the divisor and the counter (its inverse) */
2016 div = KEYSPAN_USA28_BAUDCLK / b16;
2017 if (div == 0)
2018 return KEYSPAN_INVALID_BAUD_RATE;
2019 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021
Alan Coxdeb91682008-07-22 11:13:08 +01002022 /* check for out of range, based on portnum,
2023 and return result */
2024 if (portnum == 0) {
2025 if (div > 0xffff)
2026 return KEYSPAN_INVALID_BAUD_RATE;
2027 } else {
2028 if (portnum == 1) {
2029 if (div > 0xff)
2030 return KEYSPAN_INVALID_BAUD_RATE;
2031 } else
2032 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 }
2034
2035 /* return the counter values if not NULL
2036 (port 1 will ignore retHi) */
Alan Coxdeb91682008-07-22 11:13:08 +01002037 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01002039 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002041 dev_dbg(&port->dev, "%s - %d OK.\n", __func__, baud_rate);
Alan Coxdeb91682008-07-22 11:13:08 +01002042 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043}
2044
2045static int keyspan_usa26_send_setup(struct usb_serial *serial,
2046 struct usb_serial_port *port,
2047 int reset_port)
2048{
Alan Coxdeb91682008-07-22 11:13:08 +01002049 struct keyspan_usa26_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050 struct keyspan_serial_private *s_priv;
2051 struct keyspan_port_private *p_priv;
2052 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 struct urb *this_urb;
2054 int device_port, err;
2055
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002056 dev_dbg(&port->dev, "%s reset=%d\n", __func__, reset_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057
2058 s_priv = usb_get_serial_data(serial);
2059 p_priv = usb_get_serial_port_data(port);
2060 d_details = s_priv->device_details;
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002061 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 this_urb = p_priv->outcont_urb;
2064
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 /* Make sure we have an urb then send the message */
2066 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002067 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068 return -1;
2069 }
2070
Johan Hovold0cd782b2016-05-08 20:08:00 +02002071 dev_dbg(&port->dev, "%s - endpoint %x\n",
2072 __func__, usb_pipeendpoint(this_urb->pipe));
Rickard Strandqvistd5afce82014-05-16 17:39:13 +02002073
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07002075 Don't overwrite resend for open/close condition. */
2076 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077 p_priv->resend_cont = reset_port + 1;
2078 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002079 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002081 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082 }
2083
Alan Coxdeb91682008-07-22 11:13:08 +01002084 memset(&msg, 0, sizeof(struct keyspan_usa26_portControlMessage));
2085
2086 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 if (p_priv->old_baud != p_priv->baud) {
2088 p_priv->old_baud = p_priv->baud;
2089 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002090 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2091 &msg.baudHi, &msg.baudLo, &msg.prescaler,
2092 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2093 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2094 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095 msg.baudLo = 0;
2096 msg.baudHi = 125; /* Values for 9600 baud */
2097 msg.prescaler = 10;
2098 }
2099 msg.setPrescaler = 0xff;
2100 }
2101
Ben Minerds2b982ab2012-07-12 00:10:16 +10002102 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 switch (p_priv->cflag & CSIZE) {
2104 case CS5:
2105 msg.lcr |= USA_DATABITS_5;
2106 break;
2107 case CS6:
2108 msg.lcr |= USA_DATABITS_6;
2109 break;
2110 case CS7:
2111 msg.lcr |= USA_DATABITS_7;
2112 break;
2113 case CS8:
2114 msg.lcr |= USA_DATABITS_8;
2115 break;
2116 }
2117 if (p_priv->cflag & PARENB) {
2118 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002119 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002120 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 }
2122 msg.setLcr = 0xff;
2123
2124 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2125 msg.xonFlowControl = 0;
2126 msg.setFlowControl = 0xff;
2127 msg.forwardingLength = 16;
2128 msg.xonChar = 17;
2129 msg.xoffChar = 19;
2130
2131 /* Opening port */
2132 if (reset_port == 1) {
2133 msg._txOn = 1;
2134 msg._txOff = 0;
2135 msg.txFlush = 0;
2136 msg.txBreak = 0;
2137 msg.rxOn = 1;
2138 msg.rxOff = 0;
2139 msg.rxFlush = 1;
2140 msg.rxForward = 0;
2141 msg.returnStatus = 0;
2142 msg.resetDataToggle = 0xff;
2143 }
2144
2145 /* Closing port */
2146 else if (reset_port == 2) {
2147 msg._txOn = 0;
2148 msg._txOff = 1;
2149 msg.txFlush = 0;
2150 msg.txBreak = 0;
2151 msg.rxOn = 0;
2152 msg.rxOff = 1;
2153 msg.rxFlush = 1;
2154 msg.rxForward = 0;
2155 msg.returnStatus = 0;
2156 msg.resetDataToggle = 0;
2157 }
2158
2159 /* Sending intermediate configs */
2160 else {
Alan Coxdeb91682008-07-22 11:13:08 +01002161 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 msg._txOff = 0;
2163 msg.txFlush = 0;
2164 msg.txBreak = (p_priv->break_on);
2165 msg.rxOn = 0;
2166 msg.rxOff = 0;
2167 msg.rxFlush = 0;
2168 msg.rxForward = 0;
2169 msg.returnStatus = 0;
2170 msg.resetDataToggle = 0x0;
2171 }
2172
Alan Coxdeb91682008-07-22 11:13:08 +01002173 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174 msg.setTxTriState_setRts = 0xff;
2175 msg.txTriState_rts = p_priv->rts_state;
2176
2177 msg.setHskoa_setDtr = 0xff;
2178 msg.hskoa_dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002179
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01002181 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2182
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183 /* send the data out the device on control endpoint */
2184 this_urb->transfer_buffer_length = sizeof(msg);
2185
Alan Coxdeb91682008-07-22 11:13:08 +01002186 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2187 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002188 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002189 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190}
2191
2192static int keyspan_usa28_send_setup(struct usb_serial *serial,
2193 struct usb_serial_port *port,
2194 int reset_port)
2195{
Alan Coxdeb91682008-07-22 11:13:08 +01002196 struct keyspan_usa28_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197 struct keyspan_serial_private *s_priv;
2198 struct keyspan_port_private *p_priv;
2199 const struct keyspan_device_details *d_details;
2200 struct urb *this_urb;
2201 int device_port, err;
2202
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203 s_priv = usb_get_serial_data(serial);
2204 p_priv = usb_get_serial_port_data(port);
2205 d_details = s_priv->device_details;
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002206 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207
2208 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01002209 this_urb = p_priv->outcont_urb;
2210 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002211 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212 return -1;
2213 }
2214
2215 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07002216 Don't overwrite resend for open/close condition. */
2217 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218 p_priv->resend_cont = reset_port + 1;
2219 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002220 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002222 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223 }
2224
Alan Coxdeb91682008-07-22 11:13:08 +01002225 memset(&msg, 0, sizeof(struct keyspan_usa28_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226
2227 msg.setBaudRate = 1;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002228 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2229 &msg.baudHi, &msg.baudLo, NULL,
2230 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2231 dev_dbg(&port->dev, "%s - Invalid baud rate requested %d.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01002232 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233 msg.baudLo = 0xff;
2234 msg.baudHi = 0xb2; /* Values for 9600 baud */
2235 }
2236
2237 /* If parity is enabled, we must calculate it ourselves. */
2238 msg.parity = 0; /* XXX for now */
2239
2240 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2241 msg.xonFlowControl = 0;
2242
Alan Coxdeb91682008-07-22 11:13:08 +01002243 /* Do handshaking outputs, DTR is inverted relative to RTS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244 msg.rts = p_priv->rts_state;
2245 msg.dtr = p_priv->dtr_state;
2246
2247 msg.forwardingLength = 16;
2248 msg.forwardMs = 10;
2249 msg.breakThreshold = 45;
2250 msg.xonChar = 17;
2251 msg.xoffChar = 19;
2252
2253 /*msg.returnStatus = 1;
2254 msg.resetDataToggle = 0xff;*/
2255 /* Opening port */
2256 if (reset_port == 1) {
2257 msg._txOn = 1;
2258 msg._txOff = 0;
2259 msg.txFlush = 0;
2260 msg.txForceXoff = 0;
2261 msg.txBreak = 0;
2262 msg.rxOn = 1;
2263 msg.rxOff = 0;
2264 msg.rxFlush = 1;
2265 msg.rxForward = 0;
2266 msg.returnStatus = 0;
2267 msg.resetDataToggle = 0xff;
2268 }
2269 /* Closing port */
2270 else if (reset_port == 2) {
2271 msg._txOn = 0;
2272 msg._txOff = 1;
2273 msg.txFlush = 0;
2274 msg.txForceXoff = 0;
2275 msg.txBreak = 0;
2276 msg.rxOn = 0;
2277 msg.rxOff = 1;
2278 msg.rxFlush = 1;
2279 msg.rxForward = 0;
2280 msg.returnStatus = 0;
2281 msg.resetDataToggle = 0;
2282 }
2283 /* Sending intermediate configs */
2284 else {
Alan Coxdeb91682008-07-22 11:13:08 +01002285 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286 msg._txOff = 0;
2287 msg.txFlush = 0;
2288 msg.txForceXoff = 0;
2289 msg.txBreak = (p_priv->break_on);
2290 msg.rxOn = 0;
2291 msg.rxOff = 0;
2292 msg.rxFlush = 0;
2293 msg.rxForward = 0;
2294 msg.returnStatus = 0;
2295 msg.resetDataToggle = 0x0;
2296 }
2297
2298 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01002299 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300
2301 /* 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)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002306 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307
Alan Coxa5b6f602008-04-08 17:16:06 +01002308 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309}
2310
2311static int keyspan_usa49_send_setup(struct usb_serial *serial,
2312 struct usb_serial_port *port,
2313 int reset_port)
2314{
Lucy McCoy0ca12682007-05-18 12:10:41 -07002315 struct keyspan_usa49_portControlMessage msg;
2316 struct usb_ctrlrequest *dr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 struct keyspan_serial_private *s_priv;
2318 struct keyspan_port_private *p_priv;
2319 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 struct urb *this_urb;
2321 int err, device_port;
2322
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323 s_priv = usb_get_serial_data(serial);
2324 p_priv = usb_get_serial_port_data(port);
2325 d_details = s_priv->device_details;
2326
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327 this_urb = s_priv->glocont_urb;
2328
Lucy McCoy0ca12682007-05-18 12:10:41 -07002329 /* Work out which port within the device is being setup */
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002330 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05302332 /* Make sure we have an urb then send the message */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333 if (this_urb == NULL) {
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002334 dev_dbg(&port->dev, "%s - oops no urb for port.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 return -1;
2336 }
2337
Johan Hovold0cd782b2016-05-08 20:08:00 +02002338 dev_dbg(&port->dev, "%s - endpoint %x (%d)\n",
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002339 __func__, usb_pipeendpoint(this_urb->pipe), device_port);
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05302340
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07002342 Don't overwrite resend for open/close condition. */
2343 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344 p_priv->resend_cont = reset_port + 1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002345
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002347 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002349 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 }
2351
Alan Coxdeb91682008-07-22 11:13:08 +01002352 memset(&msg, 0, sizeof(struct keyspan_usa49_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 msg.portNumber = device_port;
Alan Coxdeb91682008-07-22 11:13:08 +01002355
2356 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 if (p_priv->old_baud != p_priv->baud) {
2358 p_priv->old_baud = p_priv->baud;
2359 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002360 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2361 &msg.baudHi, &msg.baudLo, &msg.prescaler,
2362 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2363 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2364 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 msg.baudLo = 0;
2366 msg.baudHi = 125; /* Values for 9600 baud */
2367 msg.prescaler = 10;
2368 }
Alan Coxdeb91682008-07-22 11:13:08 +01002369 /* msg.setPrescaler = 0xff; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370 }
2371
Ben Minerds2b982ab2012-07-12 00:10:16 +10002372 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373 switch (p_priv->cflag & CSIZE) {
2374 case CS5:
2375 msg.lcr |= USA_DATABITS_5;
2376 break;
2377 case CS6:
2378 msg.lcr |= USA_DATABITS_6;
2379 break;
2380 case CS7:
2381 msg.lcr |= USA_DATABITS_7;
2382 break;
2383 case CS8:
2384 msg.lcr |= USA_DATABITS_8;
2385 break;
2386 }
2387 if (p_priv->cflag & PARENB) {
2388 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002389 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002390 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 }
2392 msg.setLcr = 0xff;
2393
2394 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2395 msg.xonFlowControl = 0;
2396 msg.setFlowControl = 0xff;
Alan Coxdeb91682008-07-22 11:13:08 +01002397
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 msg.forwardingLength = 16;
2399 msg.xonChar = 17;
2400 msg.xoffChar = 19;
2401
Alan Coxdeb91682008-07-22 11:13:08 +01002402 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403 if (reset_port == 1) {
2404 msg._txOn = 1;
2405 msg._txOff = 0;
2406 msg.txFlush = 0;
2407 msg.txBreak = 0;
2408 msg.rxOn = 1;
2409 msg.rxOff = 0;
2410 msg.rxFlush = 1;
2411 msg.rxForward = 0;
2412 msg.returnStatus = 0;
2413 msg.resetDataToggle = 0xff;
2414 msg.enablePort = 1;
2415 msg.disablePort = 0;
2416 }
2417 /* Closing port */
2418 else if (reset_port == 2) {
2419 msg._txOn = 0;
2420 msg._txOff = 1;
2421 msg.txFlush = 0;
2422 msg.txBreak = 0;
2423 msg.rxOn = 0;
2424 msg.rxOff = 1;
2425 msg.rxFlush = 1;
2426 msg.rxForward = 0;
2427 msg.returnStatus = 0;
2428 msg.resetDataToggle = 0;
2429 msg.enablePort = 0;
2430 msg.disablePort = 1;
2431 }
2432 /* Sending intermediate configs */
2433 else {
Alan Coxdeb91682008-07-22 11:13:08 +01002434 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435 msg._txOff = 0;
2436 msg.txFlush = 0;
2437 msg.txBreak = (p_priv->break_on);
2438 msg.rxOn = 0;
2439 msg.rxOff = 0;
2440 msg.rxFlush = 0;
2441 msg.rxForward = 0;
2442 msg.returnStatus = 0;
2443 msg.resetDataToggle = 0x0;
2444 msg.enablePort = 0;
2445 msg.disablePort = 0;
2446 }
2447
Alan Coxdeb91682008-07-22 11:13:08 +01002448 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002449 msg.setRts = 0xff;
2450 msg.rts = p_priv->rts_state;
2451
2452 msg.setDtr = 0xff;
2453 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002454
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 p_priv->resend_cont = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456
Alan Coxdeb91682008-07-22 11:13:08 +01002457 /* if the device is a 49wg, we send control message on usb
2458 control EP 0 */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002459
2460 if (d_details->product_id == keyspan_usa49wg_product_id) {
2461 dr = (void *)(s_priv->ctrl_buf);
2462 dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT;
Mathieu OTHACEHE64248392016-02-04 19:01:30 +01002463 dr->bRequest = 0xB0; /* 49wg control message */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002464 dr->wValue = 0;
2465 dr->wIndex = 0;
2466 dr->wLength = cpu_to_le16(sizeof(msg));
2467
Alan Coxdeb91682008-07-22 11:13:08 +01002468 memcpy(s_priv->glocont_buf, &msg, sizeof(msg));
Lucy McCoy0ca12682007-05-18 12:10:41 -07002469
Alan Coxdeb91682008-07-22 11:13:08 +01002470 usb_fill_control_urb(this_urb, serial->dev,
2471 usb_sndctrlpipe(serial->dev, 0),
2472 (unsigned char *)dr, s_priv->glocont_buf,
2473 sizeof(msg), usa49_glocont_callback, serial);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002474
2475 } else {
2476 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Alan Coxdeb91682008-07-22 11:13:08 +01002477
Lucy McCoy0ca12682007-05-18 12:10:41 -07002478 /* send the data out the device on control endpoint */
2479 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002480 }
Alan Coxdeb91682008-07-22 11:13:08 +01002481 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2482 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002483 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484
Alan Coxa5b6f602008-04-08 17:16:06 +01002485 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486}
2487
2488static int keyspan_usa90_send_setup(struct usb_serial *serial,
2489 struct usb_serial_port *port,
2490 int reset_port)
2491{
Alan Coxdeb91682008-07-22 11:13:08 +01002492 struct keyspan_usa90_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493 struct keyspan_serial_private *s_priv;
2494 struct keyspan_port_private *p_priv;
2495 const struct keyspan_device_details *d_details;
2496 struct urb *this_urb;
2497 int err;
2498 u8 prescaler;
2499
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500 s_priv = usb_get_serial_data(serial);
2501 p_priv = usb_get_serial_port_data(port);
2502 d_details = s_priv->device_details;
2503
2504 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01002505 this_urb = p_priv->outcont_urb;
2506 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002507 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508 return -1;
2509 }
2510
2511 /* Save reset port val for resend.
2512 Don't overwrite resend for open/close condition. */
2513 if ((reset_port + 1) > p_priv->resend_cont)
2514 p_priv->resend_cont = reset_port + 1;
2515 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002516 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002518 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519 }
2520
Alan Coxdeb91682008-07-22 11:13:08 +01002521 memset(&msg, 0, sizeof(struct keyspan_usa90_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522
Alan Coxdeb91682008-07-22 11:13:08 +01002523 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524 if (p_priv->old_baud != p_priv->baud) {
2525 p_priv->old_baud = p_priv->baud;
2526 msg.setClocking = 0x01;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002527 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2528 &msg.baudHi, &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) {
2529 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2530 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531 p_priv->baud = 9600;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002532 d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533 &msg.baudHi, &msg.baudLo, &prescaler, 0);
2534 }
2535 msg.setRxMode = 1;
2536 msg.setTxMode = 1;
2537 }
2538
2539 /* modes must always be correctly specified */
Alan Coxdeb91682008-07-22 11:13:08 +01002540 if (p_priv->baud > 57600) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541 msg.rxMode = RXMODE_DMA;
2542 msg.txMode = TXMODE_DMA;
Alan Coxdeb91682008-07-22 11:13:08 +01002543 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544 msg.rxMode = RXMODE_BYHAND;
2545 msg.txMode = TXMODE_BYHAND;
2546 }
2547
Ben Minerds2b982ab2012-07-12 00:10:16 +10002548 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549 switch (p_priv->cflag & CSIZE) {
2550 case CS5:
2551 msg.lcr |= USA_DATABITS_5;
2552 break;
2553 case CS6:
2554 msg.lcr |= USA_DATABITS_6;
2555 break;
2556 case CS7:
2557 msg.lcr |= USA_DATABITS_7;
2558 break;
2559 case CS8:
2560 msg.lcr |= USA_DATABITS_8;
2561 break;
2562 }
2563 if (p_priv->cflag & PARENB) {
2564 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002565 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002566 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567 }
2568 if (p_priv->old_cflag != p_priv->cflag) {
2569 p_priv->old_cflag = p_priv->cflag;
2570 msg.setLcr = 0x01;
2571 }
2572
2573 if (p_priv->flow_control == flow_cts)
2574 msg.txFlowControl = TXFLOW_CTS;
2575 msg.setTxFlowControl = 0x01;
2576 msg.setRxFlowControl = 0x01;
Alan Coxdeb91682008-07-22 11:13:08 +01002577
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578 msg.rxForwardingLength = 16;
Alan Coxdeb91682008-07-22 11:13:08 +01002579 msg.rxForwardingTimeout = 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 msg.txAckSetting = 0;
2581 msg.xonChar = 17;
2582 msg.xoffChar = 19;
2583
Alan Coxdeb91682008-07-22 11:13:08 +01002584 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585 if (reset_port == 1) {
2586 msg.portEnabled = 1;
2587 msg.rxFlush = 1;
2588 msg.txBreak = (p_priv->break_on);
2589 }
2590 /* Closing port */
Alan Coxdeb91682008-07-22 11:13:08 +01002591 else if (reset_port == 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592 msg.portEnabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593 /* Sending intermediate configs */
2594 else {
Alan Stern1f871582010-02-17 10:05:47 -05002595 msg.portEnabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596 msg.txBreak = (p_priv->break_on);
2597 }
2598
Alan Coxdeb91682008-07-22 11:13:08 +01002599 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600 msg.setRts = 0x01;
2601 msg.rts = p_priv->rts_state;
2602
2603 msg.setDtr = 0x01;
2604 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002605
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01002607 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2608
Linus Torvalds1da177e2005-04-16 15:20:36 -07002609 /* send the data out the device on control endpoint */
2610 this_urb->transfer_buffer_length = sizeof(msg);
2611
Alan Coxdeb91682008-07-22 11:13:08 +01002612 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2613 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002614 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002615 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616}
2617
Lucy McCoy0ca12682007-05-18 12:10:41 -07002618static int keyspan_usa67_send_setup(struct usb_serial *serial,
2619 struct usb_serial_port *port,
2620 int reset_port)
2621{
2622 struct keyspan_usa67_portControlMessage msg;
2623 struct keyspan_serial_private *s_priv;
2624 struct keyspan_port_private *p_priv;
2625 const struct keyspan_device_details *d_details;
2626 struct urb *this_urb;
2627 int err, device_port;
2628
Lucy McCoy0ca12682007-05-18 12:10:41 -07002629 s_priv = usb_get_serial_data(serial);
2630 p_priv = usb_get_serial_port_data(port);
2631 d_details = s_priv->device_details;
2632
2633 this_urb = s_priv->glocont_urb;
2634
2635 /* Work out which port within the device is being setup */
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002636 device_port = port->port_number;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002637
2638 /* Make sure we have an urb then send the message */
2639 if (this_urb == NULL) {
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002640 dev_dbg(&port->dev, "%s - oops no urb for port.\n", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002641 return -1;
2642 }
2643
2644 /* Save reset port val for resend.
2645 Don't overwrite resend for open/close condition. */
2646 if ((reset_port + 1) > p_priv->resend_cont)
2647 p_priv->resend_cont = reset_port + 1;
2648 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002649 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002650 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002651 return -1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002652 }
2653
2654 memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
2655
2656 msg.port = device_port;
2657
2658 /* Only set baud rate if it's changed */
2659 if (p_priv->old_baud != p_priv->baud) {
2660 p_priv->old_baud = p_priv->baud;
2661 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002662 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2663 &msg.baudHi, &msg.baudLo, &msg.prescaler,
2664 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2665 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2666 __func__, p_priv->baud);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002667 msg.baudLo = 0;
2668 msg.baudHi = 125; /* Values for 9600 baud */
2669 msg.prescaler = 10;
2670 }
2671 msg.setPrescaler = 0xff;
2672 }
2673
2674 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
2675 switch (p_priv->cflag & CSIZE) {
2676 case CS5:
2677 msg.lcr |= USA_DATABITS_5;
2678 break;
2679 case CS6:
2680 msg.lcr |= USA_DATABITS_6;
2681 break;
2682 case CS7:
2683 msg.lcr |= USA_DATABITS_7;
2684 break;
2685 case CS8:
2686 msg.lcr |= USA_DATABITS_8;
2687 break;
2688 }
2689 if (p_priv->cflag & PARENB) {
2690 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002691 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002692 USA_PARITY_ODD : USA_PARITY_EVEN;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002693 }
2694 msg.setLcr = 0xff;
2695
2696 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2697 msg.xonFlowControl = 0;
2698 msg.setFlowControl = 0xff;
2699 msg.forwardingLength = 16;
2700 msg.xonChar = 17;
2701 msg.xoffChar = 19;
2702
2703 if (reset_port == 1) {
2704 /* Opening port */
2705 msg._txOn = 1;
2706 msg._txOff = 0;
2707 msg.txFlush = 0;
2708 msg.txBreak = 0;
2709 msg.rxOn = 1;
2710 msg.rxOff = 0;
2711 msg.rxFlush = 1;
2712 msg.rxForward = 0;
2713 msg.returnStatus = 0;
2714 msg.resetDataToggle = 0xff;
2715 } else if (reset_port == 2) {
2716 /* Closing port */
2717 msg._txOn = 0;
2718 msg._txOff = 1;
2719 msg.txFlush = 0;
2720 msg.txBreak = 0;
2721 msg.rxOn = 0;
2722 msg.rxOff = 1;
2723 msg.rxFlush = 1;
2724 msg.rxForward = 0;
2725 msg.returnStatus = 0;
2726 msg.resetDataToggle = 0;
2727 } else {
2728 /* Sending intermediate configs */
Alan Coxdeb91682008-07-22 11:13:08 +01002729 msg._txOn = (!p_priv->break_on);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002730 msg._txOff = 0;
2731 msg.txFlush = 0;
2732 msg.txBreak = (p_priv->break_on);
2733 msg.rxOn = 0;
2734 msg.rxOff = 0;
2735 msg.rxFlush = 0;
2736 msg.rxForward = 0;
2737 msg.returnStatus = 0;
2738 msg.resetDataToggle = 0x0;
2739 }
2740
2741 /* Do handshaking outputs */
2742 msg.setTxTriState_setRts = 0xff;
2743 msg.txTriState_rts = p_priv->rts_state;
2744
2745 msg.setHskoa_setDtr = 0xff;
2746 msg.hskoa_dtr = p_priv->dtr_state;
2747
2748 p_priv->resend_cont = 0;
2749
2750 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2751
2752 /* send the data out the device on control endpoint */
2753 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002754
2755 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2756 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002757 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002758 return 0;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002759}
2760
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
2762{
2763 struct usb_serial *serial = port->serial;
2764 struct keyspan_serial_private *s_priv;
2765 const struct keyspan_device_details *d_details;
2766
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 s_priv = usb_get_serial_data(serial);
2768 d_details = s_priv->device_details;
2769
2770 switch (d_details->msg_format) {
2771 case msg_usa26:
2772 keyspan_usa26_send_setup(serial, port, reset_port);
2773 break;
2774 case msg_usa28:
2775 keyspan_usa28_send_setup(serial, port, reset_port);
2776 break;
2777 case msg_usa49:
2778 keyspan_usa49_send_setup(serial, port, reset_port);
2779 break;
2780 case msg_usa90:
2781 keyspan_usa90_send_setup(serial, port, reset_port);
2782 break;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002783 case msg_usa67:
2784 keyspan_usa67_send_setup(serial, port, reset_port);
2785 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002786 }
2787}
2788
2789
2790/* Gets called by the "real" driver (ie once firmware is loaded
2791 and renumeration has taken place. */
Alan Coxdeb91682008-07-22 11:13:08 +01002792static int keyspan_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793{
2794 int i, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796 const struct keyspan_device_details *d_details;
2797
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798 for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
Alan Coxdeb91682008-07-22 11:13:08 +01002799 if (d_details->product_id ==
2800 le16_to_cpu(serial->dev->descriptor.idProduct))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801 break;
2802 if (d_details == NULL) {
Alan Coxdeb91682008-07-22 11:13:08 +01002803 dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
2804 __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
Johan Hovoldff8a43c2013-08-13 13:27:35 +02002805 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002806 }
2807
2808 /* Setup private data for serial driver */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01002809 s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
Johan Hovold10c642d2013-12-29 19:22:56 +01002810 if (!s_priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812
Johan Hovold2fcd1c92013-08-13 13:27:36 +02002813 s_priv->instat_buf = kzalloc(INSTAT_BUFLEN, GFP_KERNEL);
2814 if (!s_priv->instat_buf)
2815 goto err_instat_buf;
2816
2817 s_priv->indat_buf = kzalloc(INDAT49W_BUFLEN, GFP_KERNEL);
2818 if (!s_priv->indat_buf)
2819 goto err_indat_buf;
2820
2821 s_priv->glocont_buf = kzalloc(GLOCONT_BUFLEN, GFP_KERNEL);
2822 if (!s_priv->glocont_buf)
2823 goto err_glocont_buf;
2824
2825 s_priv->ctrl_buf = kzalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
2826 if (!s_priv->ctrl_buf)
2827 goto err_ctrl_buf;
2828
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829 s_priv->device_details = d_details;
2830 usb_set_serial_data(serial, s_priv);
2831
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832 keyspan_setup_urbs(serial);
2833
Lucy McCoy0ca12682007-05-18 12:10:41 -07002834 if (s_priv->instat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002835 err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
2836 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002837 dev_dbg(&serial->dev->dev, "%s - submit instat urb failed %d\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002838 }
2839 if (s_priv->indat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002840 err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
2841 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002842 dev_dbg(&serial->dev->dev, "%s - submit indat urb failed %d\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843 }
Alan Coxdeb91682008-07-22 11:13:08 +01002844
Alan Coxa5b6f602008-04-08 17:16:06 +01002845 return 0;
Johan Hovold2fcd1c92013-08-13 13:27:36 +02002846
2847err_ctrl_buf:
2848 kfree(s_priv->glocont_buf);
2849err_glocont_buf:
2850 kfree(s_priv->indat_buf);
2851err_indat_buf:
2852 kfree(s_priv->instat_buf);
2853err_instat_buf:
2854 kfree(s_priv);
2855
2856 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002857}
2858
Alan Sternf9c99bb2009-06-02 11:53:55 -04002859static void keyspan_disconnect(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002861 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862
Linus Torvalds1da177e2005-04-16 15:20:36 -07002863 s_priv = usb_get_serial_data(serial);
2864
Johan Hovold61924502016-05-08 20:07:59 +02002865 usb_kill_urb(s_priv->instat_urb);
2866 usb_kill_urb(s_priv->glocont_urb);
2867 usb_kill_urb(s_priv->indat_urb);
Alan Sternf9c99bb2009-06-02 11:53:55 -04002868}
2869
2870static void keyspan_release(struct usb_serial *serial)
2871{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002872 struct keyspan_serial_private *s_priv;
Alan Sternf9c99bb2009-06-02 11:53:55 -04002873
Alan Sternf9c99bb2009-06-02 11:53:55 -04002874 s_priv = usb_get_serial_data(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002875
Johan Hovold35be1a72016-05-08 20:07:58 +02002876 /* Make sure to unlink the URBs submitted in attach. */
2877 usb_kill_urb(s_priv->instat_urb);
2878 usb_kill_urb(s_priv->indat_urb);
2879
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002880 usb_free_urb(s_priv->instat_urb);
2881 usb_free_urb(s_priv->indat_urb);
2882 usb_free_urb(s_priv->glocont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883
Johan Hovold2fcd1c92013-08-13 13:27:36 +02002884 kfree(s_priv->ctrl_buf);
2885 kfree(s_priv->glocont_buf);
2886 kfree(s_priv->indat_buf);
2887 kfree(s_priv->instat_buf);
2888
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002889 kfree(s_priv);
2890}
2891
2892static int keyspan_port_probe(struct usb_serial_port *port)
2893{
2894 struct usb_serial *serial = port->serial;
Bjørn Morkf0e3e352012-11-10 10:13:42 +01002895 struct keyspan_serial_private *s_priv;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002896 struct keyspan_port_private *p_priv;
2897 const struct keyspan_device_details *d_details;
2898 struct callbacks *cback;
2899 int endp;
2900 int port_num;
2901 int i;
2902
2903 s_priv = usb_get_serial_data(serial);
2904 d_details = s_priv->device_details;
2905
2906 p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL);
2907 if (!p_priv)
2908 return -ENOMEM;
2909
Johan Hovoldbad41a52013-08-13 13:27:37 +02002910 for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i) {
2911 p_priv->in_buffer[i] = kzalloc(IN_BUFLEN, GFP_KERNEL);
2912 if (!p_priv->in_buffer[i])
2913 goto err_in_buffer;
2914 }
2915
2916 for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i) {
2917 p_priv->out_buffer[i] = kzalloc(OUT_BUFLEN, GFP_KERNEL);
2918 if (!p_priv->out_buffer[i])
2919 goto err_out_buffer;
2920 }
2921
2922 p_priv->inack_buffer = kzalloc(INACK_BUFLEN, GFP_KERNEL);
2923 if (!p_priv->inack_buffer)
2924 goto err_inack_buffer;
2925
2926 p_priv->outcont_buffer = kzalloc(OUTCONT_BUFLEN, GFP_KERNEL);
2927 if (!p_priv->outcont_buffer)
2928 goto err_outcont_buffer;
2929
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002930 p_priv->device_details = d_details;
2931
2932 /* Setup values for the various callback routines */
2933 cback = &keyspan_callbacks[d_details->msg_format];
2934
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002935 port_num = port->port_number;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002936
2937 /* Do indat endpoints first, once for each flip */
2938 endp = d_details->indat_endpoints[port_num];
2939 for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) {
2940 p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp,
2941 USB_DIR_IN, port,
Johan Hovoldbad41a52013-08-13 13:27:37 +02002942 p_priv->in_buffer[i],
2943 IN_BUFLEN,
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002944 cback->indat_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002945 }
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002946 /* outdat endpoints also have flip */
2947 endp = d_details->outdat_endpoints[port_num];
2948 for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) {
2949 p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp,
2950 USB_DIR_OUT, port,
Johan Hovoldbad41a52013-08-13 13:27:37 +02002951 p_priv->out_buffer[i],
2952 OUT_BUFLEN,
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002953 cback->outdat_callback);
2954 }
2955 /* inack endpoint */
2956 p_priv->inack_urb = keyspan_setup_urb(serial,
2957 d_details->inack_endpoints[port_num],
2958 USB_DIR_IN, port,
Johan Hovoldbad41a52013-08-13 13:27:37 +02002959 p_priv->inack_buffer,
2960 INACK_BUFLEN,
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002961 cback->inack_callback);
2962 /* outcont endpoint */
2963 p_priv->outcont_urb = keyspan_setup_urb(serial,
2964 d_details->outcont_endpoints[port_num],
2965 USB_DIR_OUT, port,
Johan Hovoldbad41a52013-08-13 13:27:37 +02002966 p_priv->outcont_buffer,
2967 OUTCONT_BUFLEN,
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002968 cback->outcont_callback);
2969
2970 usb_set_serial_port_data(port, p_priv);
2971
2972 return 0;
Johan Hovoldbad41a52013-08-13 13:27:37 +02002973
2974err_outcont_buffer:
2975 kfree(p_priv->inack_buffer);
2976err_inack_buffer:
2977 for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i)
2978 kfree(p_priv->out_buffer[i]);
2979err_out_buffer:
2980 for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i)
2981 kfree(p_priv->in_buffer[i]);
2982err_in_buffer:
2983 kfree(p_priv);
2984
2985 return -ENOMEM;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002986}
2987
2988static int keyspan_port_remove(struct usb_serial_port *port)
2989{
2990 struct keyspan_port_private *p_priv;
2991 int i;
2992
2993 p_priv = usb_get_serial_port_data(port);
2994
Johan Hovold61924502016-05-08 20:07:59 +02002995 usb_kill_urb(p_priv->inack_urb);
2996 usb_kill_urb(p_priv->outcont_urb);
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002997 for (i = 0; i < 2; i++) {
Johan Hovold61924502016-05-08 20:07:59 +02002998 usb_kill_urb(p_priv->in_urbs[i]);
2999 usb_kill_urb(p_priv->out_urbs[i]);
Johan Hovoldf79b2d02012-10-25 10:29:15 +02003000 }
3001
3002 usb_free_urb(p_priv->inack_urb);
3003 usb_free_urb(p_priv->outcont_urb);
3004 for (i = 0; i < 2; i++) {
3005 usb_free_urb(p_priv->in_urbs[i]);
3006 usb_free_urb(p_priv->out_urbs[i]);
3007 }
3008
Johan Hovoldbad41a52013-08-13 13:27:37 +02003009 kfree(p_priv->outcont_buffer);
3010 kfree(p_priv->inack_buffer);
3011 for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i)
3012 kfree(p_priv->out_buffer[i]);
3013 for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i)
3014 kfree(p_priv->in_buffer[i]);
3015
Johan Hovoldf79b2d02012-10-25 10:29:15 +02003016 kfree(p_priv);
3017
3018 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003019}
3020
Johan Hovoldbeabdc32017-02-15 11:09:51 +01003021/* Structs for the devices, pre and post renumeration. */
3022static struct usb_serial_driver keyspan_pre_device = {
3023 .driver = {
3024 .owner = THIS_MODULE,
3025 .name = "keyspan_no_firm",
3026 },
3027 .description = "Keyspan - (without firmware)",
3028 .id_table = keyspan_pre_ids,
3029 .num_ports = 1,
3030 .attach = keyspan_fake_startup,
3031};
3032
3033static struct usb_serial_driver keyspan_1port_device = {
3034 .driver = {
3035 .owner = THIS_MODULE,
3036 .name = "keyspan_1",
3037 },
3038 .description = "Keyspan 1 port adapter",
3039 .id_table = keyspan_1port_ids,
3040 .num_ports = 1,
3041 .open = keyspan_open,
3042 .close = keyspan_close,
3043 .dtr_rts = keyspan_dtr_rts,
3044 .write = keyspan_write,
3045 .write_room = keyspan_write_room,
3046 .set_termios = keyspan_set_termios,
3047 .break_ctl = keyspan_break_ctl,
3048 .tiocmget = keyspan_tiocmget,
3049 .tiocmset = keyspan_tiocmset,
3050 .attach = keyspan_startup,
3051 .disconnect = keyspan_disconnect,
3052 .release = keyspan_release,
3053 .port_probe = keyspan_port_probe,
3054 .port_remove = keyspan_port_remove,
3055};
3056
3057static struct usb_serial_driver keyspan_2port_device = {
3058 .driver = {
3059 .owner = THIS_MODULE,
3060 .name = "keyspan_2",
3061 },
3062 .description = "Keyspan 2 port adapter",
3063 .id_table = keyspan_2port_ids,
3064 .num_ports = 2,
3065 .open = keyspan_open,
3066 .close = keyspan_close,
3067 .dtr_rts = keyspan_dtr_rts,
3068 .write = keyspan_write,
3069 .write_room = keyspan_write_room,
3070 .set_termios = keyspan_set_termios,
3071 .break_ctl = keyspan_break_ctl,
3072 .tiocmget = keyspan_tiocmget,
3073 .tiocmset = keyspan_tiocmset,
3074 .attach = keyspan_startup,
3075 .disconnect = keyspan_disconnect,
3076 .release = keyspan_release,
3077 .port_probe = keyspan_port_probe,
3078 .port_remove = keyspan_port_remove,
3079};
3080
3081static struct usb_serial_driver keyspan_4port_device = {
3082 .driver = {
3083 .owner = THIS_MODULE,
3084 .name = "keyspan_4",
3085 },
3086 .description = "Keyspan 4 port adapter",
3087 .id_table = keyspan_4port_ids,
3088 .num_ports = 4,
3089 .open = keyspan_open,
3090 .close = keyspan_close,
3091 .dtr_rts = keyspan_dtr_rts,
3092 .write = keyspan_write,
3093 .write_room = keyspan_write_room,
3094 .set_termios = keyspan_set_termios,
3095 .break_ctl = keyspan_break_ctl,
3096 .tiocmget = keyspan_tiocmget,
3097 .tiocmset = keyspan_tiocmset,
3098 .attach = keyspan_startup,
3099 .disconnect = keyspan_disconnect,
3100 .release = keyspan_release,
3101 .port_probe = keyspan_port_probe,
3102 .port_remove = keyspan_port_remove,
3103};
3104
3105static struct usb_serial_driver * const serial_drivers[] = {
3106 &keyspan_pre_device, &keyspan_1port_device,
3107 &keyspan_2port_device, &keyspan_4port_device, NULL
3108};
3109
3110module_usb_serial_driver(serial_drivers, keyspan_ids_combined);
3111
Alan Coxdeb91682008-07-22 11:13:08 +01003112MODULE_AUTHOR(DRIVER_AUTHOR);
3113MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114MODULE_LICENSE("GPL");
3115
David Woodhouse2971c572008-05-30 14:04:03 +03003116MODULE_FIRMWARE("keyspan/usa28.fw");
3117MODULE_FIRMWARE("keyspan/usa28x.fw");
3118MODULE_FIRMWARE("keyspan/usa28xa.fw");
3119MODULE_FIRMWARE("keyspan/usa28xb.fw");
3120MODULE_FIRMWARE("keyspan/usa19.fw");
3121MODULE_FIRMWARE("keyspan/usa19qi.fw");
3122MODULE_FIRMWARE("keyspan/mpr.fw");
3123MODULE_FIRMWARE("keyspan/usa19qw.fw");
3124MODULE_FIRMWARE("keyspan/usa18x.fw");
3125MODULE_FIRMWARE("keyspan/usa19w.fw");
3126MODULE_FIRMWARE("keyspan/usa49w.fw");
3127MODULE_FIRMWARE("keyspan/usa49wlc.fw");