blob: e66a59ef43a1cb59cfa0d41b8af8c7316ededa69 [file] [log] [blame]
Greg Kroah-Hartman5fd54ac2017-11-03 11:28:30 +01001// SPDX-License-Identifier: GPL-2.0+
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 Keyspan USB to Serial Converter driver
Alan Coxdeb91682008-07-22 11:13:08 +01004
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 (C) Copyright (C) 2000-2001 Hugh Blemings <hugh@blemings.org>
6 (C) Copyright (C) 2002 Greg Kroah-Hartman <greg@kroah.com>
Alan Coxdeb91682008-07-22 11:13:08 +01007
Justin P. Mattock631dd1a2010-10-18 11:03:14 +02008 See http://blemings.org/hugh/keyspan.html for more information.
Alan Coxdeb91682008-07-22 11:13:08 +01009
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 Code in this driver inspired by and in a number of places taken
11 from Brian Warner's original Keyspan-PDA driver.
12
13 This driver has been put together with the support of Innosys, Inc.
14 and Keyspan, Inc the manufacturers of the Keyspan USB-serial products.
15 Thanks Guys :)
Alan Coxdeb91682008-07-22 11:13:08 +010016
Linus Torvalds1da177e2005-04-16 15:20:36 -070017 Thanks to Paulus for miscellaneous tidy ups, some largish chunks
18 of much nicer and/or completely new code and (perhaps most uniquely)
19 having the patience to sit down and explain why and where he'd changed
Alan Coxdeb91682008-07-22 11:13:08 +010020 stuff.
21
22 Tip 'o the hat to IBM (and previously Linuxcare :) for supporting
Linus Torvalds1da177e2005-04-16 15:20:36 -070023 staff in their work on open source projects.
Linus Torvalds1da177e2005-04-16 15:20:36 -070024*/
25
26
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <linux/kernel.h>
28#include <linux/jiffies.h>
29#include <linux/errno.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/slab.h>
31#include <linux/tty.h>
32#include <linux/tty_driver.h>
33#include <linux/tty_flip.h>
34#include <linux/module.h>
35#include <linux/spinlock.h>
Alan Coxdeb91682008-07-22 11:13:08 +010036#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <linux/usb.h>
Greg Kroah-Hartmana9698882006-07-11 21:22:58 -070038#include <linux/usb/serial.h>
Rene Buergelcc183e22012-09-18 09:00:41 +020039#include <linux/usb/ezusb.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu"
42#define DRIVER_DESC "Keyspan USB to Serial Converter Driver"
43
Johan Hovoldbeabdc32017-02-15 11:09:51 +010044/* Function prototypes for Keyspan serial converter */
45static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port);
46static void keyspan_close(struct usb_serial_port *port);
47static void keyspan_dtr_rts(struct usb_serial_port *port, int on);
48static int keyspan_startup(struct usb_serial *serial);
49static void keyspan_disconnect(struct usb_serial *serial);
50static void keyspan_release(struct usb_serial *serial);
51static int keyspan_port_probe(struct usb_serial_port *port);
52static int keyspan_port_remove(struct usb_serial_port *port);
53static int keyspan_write_room(struct tty_struct *tty);
54static int keyspan_write(struct tty_struct *tty, struct usb_serial_port *port,
55 const unsigned char *buf, int count);
56static void keyspan_send_setup(struct usb_serial_port *port, int reset_port);
57static void keyspan_set_termios(struct tty_struct *tty,
58 struct usb_serial_port *port,
59 struct ktermios *old);
60static void keyspan_break_ctl(struct tty_struct *tty, int break_state);
61static int keyspan_tiocmget(struct tty_struct *tty);
62static int keyspan_tiocmset(struct tty_struct *tty, unsigned int set,
63 unsigned int clear);
64static int keyspan_fake_startup(struct usb_serial *serial);
65
66static int keyspan_usa19_calc_baud(struct usb_serial_port *port,
67 u32 baud_rate, u32 baudclk,
68 u8 *rate_hi, u8 *rate_low,
69 u8 *prescaler, int portnum);
70static int keyspan_usa19w_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_usa28_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_usa19hs_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);
82
83static int keyspan_usa28_send_setup(struct usb_serial *serial,
84 struct usb_serial_port *port,
85 int reset_port);
86static int keyspan_usa26_send_setup(struct usb_serial *serial,
87 struct usb_serial_port *port,
88 int reset_port);
89static int keyspan_usa49_send_setup(struct usb_serial *serial,
90 struct usb_serial_port *port,
91 int reset_port);
92static int keyspan_usa90_send_setup(struct usb_serial *serial,
93 struct usb_serial_port *port,
94 int reset_port);
95static int keyspan_usa67_send_setup(struct usb_serial *serial,
96 struct usb_serial_port *port,
97 int reset_port);
98
99/* Values used for baud rate calculation - device specific */
100#define KEYSPAN_INVALID_BAUD_RATE (-1)
101#define KEYSPAN_BAUD_RATE_OK (0)
102#define KEYSPAN_USA18X_BAUDCLK (12000000L) /* a guess */
103#define KEYSPAN_USA19_BAUDCLK (12000000L)
104#define KEYSPAN_USA19W_BAUDCLK (24000000L)
105#define KEYSPAN_USA19HS_BAUDCLK (14769231L)
106#define KEYSPAN_USA28_BAUDCLK (1843200L)
107#define KEYSPAN_USA28X_BAUDCLK (12000000L)
108#define KEYSPAN_USA49W_BAUDCLK (48000000L)
109
110/* Some constants used to characterise each device. */
111#define KEYSPAN_MAX_NUM_PORTS (4)
112#define KEYSPAN_MAX_FLIPS (2)
113
114/*
115 * Device info for the Keyspan serial converter, used by the overall
116 * usb-serial probe function.
117 */
118#define KEYSPAN_VENDOR_ID (0x06cd)
119
120/* Product IDs for the products supported, pre-renumeration */
121#define keyspan_usa18x_pre_product_id 0x0105
122#define keyspan_usa19_pre_product_id 0x0103
123#define keyspan_usa19qi_pre_product_id 0x010b
124#define keyspan_mpr_pre_product_id 0x011b
125#define keyspan_usa19qw_pre_product_id 0x0118
126#define keyspan_usa19w_pre_product_id 0x0106
127#define keyspan_usa28_pre_product_id 0x0101
128#define keyspan_usa28x_pre_product_id 0x0102
129#define keyspan_usa28xa_pre_product_id 0x0114
130#define keyspan_usa28xb_pre_product_id 0x0113
131#define keyspan_usa49w_pre_product_id 0x0109
132#define keyspan_usa49wlc_pre_product_id 0x011a
133
134/*
135 * Product IDs post-renumeration. Note that the 28x and 28xb have the same
136 * id's post-renumeration but behave identically so it's not an issue. As
137 * such, the 28xb is not listed in any of the device tables.
138 */
139#define keyspan_usa18x_product_id 0x0112
140#define keyspan_usa19_product_id 0x0107
141#define keyspan_usa19qi_product_id 0x010c
142#define keyspan_usa19hs_product_id 0x0121
143#define keyspan_mpr_product_id 0x011c
144#define keyspan_usa19qw_product_id 0x0119
145#define keyspan_usa19w_product_id 0x0108
146#define keyspan_usa28_product_id 0x010f
147#define keyspan_usa28x_product_id 0x0110
148#define keyspan_usa28xa_product_id 0x0115
149#define keyspan_usa28xb_product_id 0x0110
150#define keyspan_usa28xg_product_id 0x0135
151#define keyspan_usa49w_product_id 0x010a
152#define keyspan_usa49wlc_product_id 0x012a
153#define keyspan_usa49wg_product_id 0x0131
154
155struct keyspan_device_details {
156 /* product ID value */
157 int product_id;
158
159 enum {msg_usa26, msg_usa28, msg_usa49, msg_usa90, msg_usa67} msg_format;
160
161 /* Number of physical ports */
162 int num_ports;
163
164 /* 1 if endpoint flipping used on input, 0 if not */
165 int indat_endp_flip;
166
167 /* 1 if endpoint flipping used on output, 0 if not */
168 int outdat_endp_flip;
169
170 /*
171 * Table mapping input data endpoint IDs to physical port
172 * number and flip if used
173 */
174 int indat_endpoints[KEYSPAN_MAX_NUM_PORTS];
175
176 /* Same for output endpoints */
177 int outdat_endpoints[KEYSPAN_MAX_NUM_PORTS];
178
179 /* Input acknowledge endpoints */
180 int inack_endpoints[KEYSPAN_MAX_NUM_PORTS];
181
182 /* Output control endpoints */
183 int outcont_endpoints[KEYSPAN_MAX_NUM_PORTS];
184
185 /* Endpoint used for input status */
186 int instat_endpoint;
187
188 /* Endpoint used for input data 49WG only */
189 int indat_endpoint;
190
191 /* Endpoint used for global control functions */
192 int glocont_endpoint;
193
194 int (*calculate_baud_rate)(struct usb_serial_port *port,
195 u32 baud_rate, u32 baudclk,
196 u8 *rate_hi, u8 *rate_low, u8 *prescaler,
197 int portnum);
198 u32 baudclk;
199};
200
201/*
202 * Now for each device type we setup the device detail structure with the
203 * appropriate information (provided in Keyspan's documentation)
204 */
205
206static const struct keyspan_device_details usa18x_device_details = {
207 .product_id = keyspan_usa18x_product_id,
208 .msg_format = msg_usa26,
209 .num_ports = 1,
210 .indat_endp_flip = 0,
211 .outdat_endp_flip = 1,
212 .indat_endpoints = {0x81},
213 .outdat_endpoints = {0x01},
214 .inack_endpoints = {0x85},
215 .outcont_endpoints = {0x05},
216 .instat_endpoint = 0x87,
217 .indat_endpoint = -1,
218 .glocont_endpoint = 0x07,
219 .calculate_baud_rate = keyspan_usa19w_calc_baud,
220 .baudclk = KEYSPAN_USA18X_BAUDCLK,
221};
222
223static const struct keyspan_device_details usa19_device_details = {
224 .product_id = keyspan_usa19_product_id,
225 .msg_format = msg_usa28,
226 .num_ports = 1,
227 .indat_endp_flip = 1,
228 .outdat_endp_flip = 1,
229 .indat_endpoints = {0x81},
230 .outdat_endpoints = {0x01},
231 .inack_endpoints = {0x83},
232 .outcont_endpoints = {0x03},
233 .instat_endpoint = 0x84,
234 .indat_endpoint = -1,
235 .glocont_endpoint = -1,
236 .calculate_baud_rate = keyspan_usa19_calc_baud,
237 .baudclk = KEYSPAN_USA19_BAUDCLK,
238};
239
240static const struct keyspan_device_details usa19qi_device_details = {
241 .product_id = keyspan_usa19qi_product_id,
242 .msg_format = msg_usa28,
243 .num_ports = 1,
244 .indat_endp_flip = 1,
245 .outdat_endp_flip = 1,
246 .indat_endpoints = {0x81},
247 .outdat_endpoints = {0x01},
248 .inack_endpoints = {0x83},
249 .outcont_endpoints = {0x03},
250 .instat_endpoint = 0x84,
251 .indat_endpoint = -1,
252 .glocont_endpoint = -1,
253 .calculate_baud_rate = keyspan_usa28_calc_baud,
254 .baudclk = KEYSPAN_USA19_BAUDCLK,
255};
256
257static const struct keyspan_device_details mpr_device_details = {
258 .product_id = keyspan_mpr_product_id,
259 .msg_format = msg_usa28,
260 .num_ports = 1,
261 .indat_endp_flip = 1,
262 .outdat_endp_flip = 1,
263 .indat_endpoints = {0x81},
264 .outdat_endpoints = {0x01},
265 .inack_endpoints = {0x83},
266 .outcont_endpoints = {0x03},
267 .instat_endpoint = 0x84,
268 .indat_endpoint = -1,
269 .glocont_endpoint = -1,
270 .calculate_baud_rate = keyspan_usa28_calc_baud,
271 .baudclk = KEYSPAN_USA19_BAUDCLK,
272};
273
274static const struct keyspan_device_details usa19qw_device_details = {
275 .product_id = keyspan_usa19qw_product_id,
276 .msg_format = msg_usa26,
277 .num_ports = 1,
278 .indat_endp_flip = 0,
279 .outdat_endp_flip = 1,
280 .indat_endpoints = {0x81},
281 .outdat_endpoints = {0x01},
282 .inack_endpoints = {0x85},
283 .outcont_endpoints = {0x05},
284 .instat_endpoint = 0x87,
285 .indat_endpoint = -1,
286 .glocont_endpoint = 0x07,
287 .calculate_baud_rate = keyspan_usa19w_calc_baud,
288 .baudclk = KEYSPAN_USA19W_BAUDCLK,
289};
290
291static const struct keyspan_device_details usa19w_device_details = {
292 .product_id = keyspan_usa19w_product_id,
293 .msg_format = msg_usa26,
294 .num_ports = 1,
295 .indat_endp_flip = 0,
296 .outdat_endp_flip = 1,
297 .indat_endpoints = {0x81},
298 .outdat_endpoints = {0x01},
299 .inack_endpoints = {0x85},
300 .outcont_endpoints = {0x05},
301 .instat_endpoint = 0x87,
302 .indat_endpoint = -1,
303 .glocont_endpoint = 0x07,
304 .calculate_baud_rate = keyspan_usa19w_calc_baud,
305 .baudclk = KEYSPAN_USA19W_BAUDCLK,
306};
307
308static const struct keyspan_device_details usa19hs_device_details = {
309 .product_id = keyspan_usa19hs_product_id,
310 .msg_format = msg_usa90,
311 .num_ports = 1,
312 .indat_endp_flip = 0,
313 .outdat_endp_flip = 0,
314 .indat_endpoints = {0x81},
315 .outdat_endpoints = {0x01},
316 .inack_endpoints = {-1},
317 .outcont_endpoints = {0x02},
318 .instat_endpoint = 0x82,
319 .indat_endpoint = -1,
320 .glocont_endpoint = -1,
321 .calculate_baud_rate = keyspan_usa19hs_calc_baud,
322 .baudclk = KEYSPAN_USA19HS_BAUDCLK,
323};
324
325static const struct keyspan_device_details usa28_device_details = {
326 .product_id = keyspan_usa28_product_id,
327 .msg_format = msg_usa28,
328 .num_ports = 2,
329 .indat_endp_flip = 1,
330 .outdat_endp_flip = 1,
331 .indat_endpoints = {0x81, 0x83},
332 .outdat_endpoints = {0x01, 0x03},
333 .inack_endpoints = {0x85, 0x86},
334 .outcont_endpoints = {0x05, 0x06},
335 .instat_endpoint = 0x87,
336 .indat_endpoint = -1,
337 .glocont_endpoint = 0x07,
338 .calculate_baud_rate = keyspan_usa28_calc_baud,
339 .baudclk = KEYSPAN_USA28_BAUDCLK,
340};
341
342static const struct keyspan_device_details usa28x_device_details = {
343 .product_id = keyspan_usa28x_product_id,
344 .msg_format = msg_usa26,
345 .num_ports = 2,
346 .indat_endp_flip = 0,
347 .outdat_endp_flip = 1,
348 .indat_endpoints = {0x81, 0x83},
349 .outdat_endpoints = {0x01, 0x03},
350 .inack_endpoints = {0x85, 0x86},
351 .outcont_endpoints = {0x05, 0x06},
352 .instat_endpoint = 0x87,
353 .indat_endpoint = -1,
354 .glocont_endpoint = 0x07,
355 .calculate_baud_rate = keyspan_usa19w_calc_baud,
356 .baudclk = KEYSPAN_USA28X_BAUDCLK,
357};
358
359static const struct keyspan_device_details usa28xa_device_details = {
360 .product_id = keyspan_usa28xa_product_id,
361 .msg_format = msg_usa26,
362 .num_ports = 2,
363 .indat_endp_flip = 0,
364 .outdat_endp_flip = 1,
365 .indat_endpoints = {0x81, 0x83},
366 .outdat_endpoints = {0x01, 0x03},
367 .inack_endpoints = {0x85, 0x86},
368 .outcont_endpoints = {0x05, 0x06},
369 .instat_endpoint = 0x87,
370 .indat_endpoint = -1,
371 .glocont_endpoint = 0x07,
372 .calculate_baud_rate = keyspan_usa19w_calc_baud,
373 .baudclk = KEYSPAN_USA28X_BAUDCLK,
374};
375
376static const struct keyspan_device_details usa28xg_device_details = {
377 .product_id = keyspan_usa28xg_product_id,
378 .msg_format = msg_usa67,
379 .num_ports = 2,
380 .indat_endp_flip = 0,
381 .outdat_endp_flip = 0,
382 .indat_endpoints = {0x84, 0x88},
383 .outdat_endpoints = {0x02, 0x06},
384 .inack_endpoints = {-1, -1},
385 .outcont_endpoints = {-1, -1},
386 .instat_endpoint = 0x81,
387 .indat_endpoint = -1,
388 .glocont_endpoint = 0x01,
389 .calculate_baud_rate = keyspan_usa19w_calc_baud,
390 .baudclk = KEYSPAN_USA28X_BAUDCLK,
391};
392/*
393 * We don't need a separate entry for the usa28xb as it appears as a 28x
394 * anyway.
395 */
396
397static const struct keyspan_device_details usa49w_device_details = {
398 .product_id = keyspan_usa49w_product_id,
399 .msg_format = msg_usa49,
400 .num_ports = 4,
401 .indat_endp_flip = 0,
402 .outdat_endp_flip = 0,
403 .indat_endpoints = {0x81, 0x82, 0x83, 0x84},
404 .outdat_endpoints = {0x01, 0x02, 0x03, 0x04},
405 .inack_endpoints = {-1, -1, -1, -1},
406 .outcont_endpoints = {-1, -1, -1, -1},
407 .instat_endpoint = 0x87,
408 .indat_endpoint = -1,
409 .glocont_endpoint = 0x07,
410 .calculate_baud_rate = keyspan_usa19w_calc_baud,
411 .baudclk = KEYSPAN_USA49W_BAUDCLK,
412};
413
414static const struct keyspan_device_details usa49wlc_device_details = {
415 .product_id = keyspan_usa49wlc_product_id,
416 .msg_format = msg_usa49,
417 .num_ports = 4,
418 .indat_endp_flip = 0,
419 .outdat_endp_flip = 0,
420 .indat_endpoints = {0x81, 0x82, 0x83, 0x84},
421 .outdat_endpoints = {0x01, 0x02, 0x03, 0x04},
422 .inack_endpoints = {-1, -1, -1, -1},
423 .outcont_endpoints = {-1, -1, -1, -1},
424 .instat_endpoint = 0x87,
425 .indat_endpoint = -1,
426 .glocont_endpoint = 0x07,
427 .calculate_baud_rate = keyspan_usa19w_calc_baud,
428 .baudclk = KEYSPAN_USA19W_BAUDCLK,
429};
430
431static const struct keyspan_device_details usa49wg_device_details = {
432 .product_id = keyspan_usa49wg_product_id,
433 .msg_format = msg_usa49,
434 .num_ports = 4,
435 .indat_endp_flip = 0,
436 .outdat_endp_flip = 0,
437 .indat_endpoints = {-1, -1, -1, -1}, /* single 'global' data in EP */
438 .outdat_endpoints = {0x01, 0x02, 0x04, 0x06},
439 .inack_endpoints = {-1, -1, -1, -1},
440 .outcont_endpoints = {-1, -1, -1, -1},
441 .instat_endpoint = 0x81,
442 .indat_endpoint = 0x88,
443 .glocont_endpoint = 0x00, /* uses control EP */
444 .calculate_baud_rate = keyspan_usa19w_calc_baud,
445 .baudclk = KEYSPAN_USA19W_BAUDCLK,
446};
447
448static const struct keyspan_device_details *keyspan_devices[] = {
449 &usa18x_device_details,
450 &usa19_device_details,
451 &usa19qi_device_details,
452 &mpr_device_details,
453 &usa19qw_device_details,
454 &usa19w_device_details,
455 &usa19hs_device_details,
456 &usa28_device_details,
457 &usa28x_device_details,
458 &usa28xa_device_details,
459 &usa28xg_device_details,
460 /* 28xb not required as it renumerates as a 28x */
461 &usa49w_device_details,
462 &usa49wlc_device_details,
463 &usa49wg_device_details,
464 NULL,
465};
466
467static const struct usb_device_id keyspan_ids_combined[] = {
468 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa18x_pre_product_id) },
469 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19_pre_product_id) },
470 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19w_pre_product_id) },
471 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qi_pre_product_id) },
472 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qw_pre_product_id) },
473 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_mpr_pre_product_id) },
474 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_pre_product_id) },
475 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_pre_product_id) },
476 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_pre_product_id) },
477 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_pre_product_id) },
478 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_pre_product_id) },
479 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_pre_product_id) },
480 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa18x_product_id) },
481 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19_product_id) },
482 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19w_product_id) },
483 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qi_product_id) },
484 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qw_product_id) },
485 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19hs_product_id) },
486 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_mpr_product_id) },
487 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
488 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
489 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) },
490 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xg_product_id) },
491 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id)},
492 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)},
493 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wg_product_id)},
494 { } /* Terminating entry */
495};
496
497MODULE_DEVICE_TABLE(usb, keyspan_ids_combined);
498
499/* usb_device_id table for the pre-firmware download keyspan devices */
500static const struct usb_device_id keyspan_pre_ids[] = {
501 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa18x_pre_product_id) },
502 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19_pre_product_id) },
503 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qi_pre_product_id) },
504 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qw_pre_product_id) },
505 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19w_pre_product_id) },
506 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_mpr_pre_product_id) },
507 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_pre_product_id) },
508 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_pre_product_id) },
509 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_pre_product_id) },
510 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_pre_product_id) },
511 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_pre_product_id) },
512 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_pre_product_id) },
513 { } /* Terminating entry */
514};
515
516static const struct usb_device_id keyspan_1port_ids[] = {
517 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa18x_product_id) },
518 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19_product_id) },
519 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qi_product_id) },
520 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qw_product_id) },
521 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19w_product_id) },
522 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19hs_product_id) },
523 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_mpr_product_id) },
524 { } /* Terminating entry */
525};
526
527static const struct usb_device_id keyspan_2port_ids[] = {
528 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
529 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
530 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) },
531 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xg_product_id) },
532 { } /* Terminating entry */
533};
534
535static const struct usb_device_id keyspan_4port_ids[] = {
536 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id) },
537 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)},
538 { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wg_product_id)},
539 { } /* Terminating entry */
540};
541
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542#define INSTAT_BUFLEN 32
543#define GLOCONT_BUFLEN 64
Lucy McCoy0ca12682007-05-18 12:10:41 -0700544#define INDAT49W_BUFLEN 512
Johan Hovoldbad41a52013-08-13 13:27:37 +0200545#define IN_BUFLEN 64
546#define OUT_BUFLEN 64
547#define INACK_BUFLEN 1
548#define OUTCONT_BUFLEN 64
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549
550 /* Per device and per port private data */
551struct keyspan_serial_private {
552 const struct keyspan_device_details *device_details;
553
554 struct urb *instat_urb;
Johan Hovold2fcd1c92013-08-13 13:27:36 +0200555 char *instat_buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556
Alan Coxdeb91682008-07-22 11:13:08 +0100557 /* added to support 49wg, where data from all 4 ports comes in
558 on 1 EP and high-speed supported */
Lucy McCoy0ca12682007-05-18 12:10:41 -0700559 struct urb *indat_urb;
Johan Hovold2fcd1c92013-08-13 13:27:36 +0200560 char *indat_buf;
Lucy McCoy0ca12682007-05-18 12:10:41 -0700561
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 /* XXX this one probably will need a lock */
563 struct urb *glocont_urb;
Johan Hovold2fcd1c92013-08-13 13:27:36 +0200564 char *glocont_buf;
565 char *ctrl_buf; /* for EP0 control message */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566};
567
568struct keyspan_port_private {
569 /* Keep track of which input & output endpoints to use */
570 int in_flip;
571 int out_flip;
572
573 /* Keep duplicate of device details in each port
574 structure as well - simplifies some of the
575 callback functions etc. */
576 const struct keyspan_device_details *device_details;
577
578 /* Input endpoints and buffer for this port */
579 struct urb *in_urbs[2];
Johan Hovoldbad41a52013-08-13 13:27:37 +0200580 char *in_buffer[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 /* Output endpoints and buffer for this port */
582 struct urb *out_urbs[2];
Johan Hovoldbad41a52013-08-13 13:27:37 +0200583 char *out_buffer[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584
585 /* Input ack endpoint */
586 struct urb *inack_urb;
Johan Hovoldbad41a52013-08-13 13:27:37 +0200587 char *inack_buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588
589 /* Output control endpoint */
590 struct urb *outcont_urb;
Johan Hovoldbad41a52013-08-13 13:27:37 +0200591 char *outcont_buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592
593 /* Settings for the port */
594 int baud;
595 int old_baud;
596 unsigned int cflag;
597 unsigned int old_cflag;
598 enum {flow_none, flow_cts, flow_xon} flow_control;
599 int rts_state; /* Handshaking pins (outputs) */
600 int dtr_state;
601 int cts_state; /* Handshaking pins (inputs) */
602 int dsr_state;
603 int dcd_state;
604 int ri_state;
605 int break_on;
606
607 unsigned long tx_start_time[2];
608 int resend_cont; /* need to resend control packet */
609};
610
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611/* Include Keyspan message headers. All current Keyspan Adapters
Lucy McCoy0ca12682007-05-18 12:10:41 -0700612 make use of one of five message formats which are referred
Alan Coxdeb91682008-07-22 11:13:08 +0100613 to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and
614 within this driver. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615#include "keyspan_usa26msg.h"
616#include "keyspan_usa28msg.h"
617#include "keyspan_usa49msg.h"
618#include "keyspan_usa90msg.h"
Lucy McCoy0ca12682007-05-18 12:10:41 -0700619#include "keyspan_usa67msg.h"
Alan Coxdeb91682008-07-22 11:13:08 +0100620
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621
Alan Cox95da3102008-07-22 11:09:07 +0100622static void keyspan_break_ctl(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623{
Alan Cox95da3102008-07-22 11:09:07 +0100624 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 struct keyspan_port_private *p_priv;
626
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 p_priv = usb_get_serial_port_data(port);
628
629 if (break_state == -1)
630 p_priv->break_on = 1;
631 else
632 p_priv->break_on = 0;
633
634 keyspan_send_setup(port, 0);
635}
636
637
Alan Coxdeb91682008-07-22 11:13:08 +0100638static void keyspan_set_termios(struct tty_struct *tty,
Alan Cox95da3102008-07-22 11:09:07 +0100639 struct usb_serial_port *port, struct ktermios *old_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640{
641 int baud_rate, device_port;
642 struct keyspan_port_private *p_priv;
643 const struct keyspan_device_details *d_details;
644 unsigned int cflag;
645
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 p_priv = usb_get_serial_port_data(port);
647 d_details = p_priv->device_details;
Alan Coxadc8d742012-07-14 15:31:47 +0100648 cflag = tty->termios.c_cflag;
Greg Kroah-Hartman11438322013-06-06 10:32:00 -0700649 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650
651 /* Baud rate calculation takes baud rate as an integer
652 so other rates can be generated if desired. */
Alan Cox74240b02007-10-18 01:24:20 -0700653 baud_rate = tty_get_baud_rate(tty);
Alan Coxdeb91682008-07-22 11:13:08 +0100654 /* If no match or invalid, don't change */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700655 if (d_details->calculate_baud_rate(port, baud_rate, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
657 /* FIXME - more to do here to ensure rate changes cleanly */
Rahul Bedarkarcd8c5052014-01-02 19:29:24 +0530658 /* FIXME - calculate exact rate from divisor ? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 p_priv->baud = baud_rate;
Alan Cox74240b02007-10-18 01:24:20 -0700660 } else
661 baud_rate = tty_termios_baud_rate(old_termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662
Alan Cox74240b02007-10-18 01:24:20 -0700663 tty_encode_baud_rate(tty, baud_rate, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 /* set CTS/RTS handshake etc. */
665 p_priv->cflag = cflag;
Ben Minerds2b982ab2012-07-12 00:10:16 +1000666 p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667
Alan Cox74240b02007-10-18 01:24:20 -0700668 /* Mark/Space not supported */
Alan Coxadc8d742012-07-14 15:31:47 +0100669 tty->termios.c_cflag &= ~CMSPAR;
Alan Cox74240b02007-10-18 01:24:20 -0700670
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 keyspan_send_setup(port, 0);
672}
673
Alan Cox60b33c12011-02-14 16:26:14 +0000674static int keyspan_tiocmget(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675{
Alan Cox95da3102008-07-22 11:09:07 +0100676 struct usb_serial_port *port = tty->driver_data;
677 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 unsigned int value;
Alan Coxdeb91682008-07-22 11:13:08 +0100679
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 value = ((p_priv->rts_state) ? TIOCM_RTS : 0) |
681 ((p_priv->dtr_state) ? TIOCM_DTR : 0) |
682 ((p_priv->cts_state) ? TIOCM_CTS : 0) |
683 ((p_priv->dsr_state) ? TIOCM_DSR : 0) |
684 ((p_priv->dcd_state) ? TIOCM_CAR : 0) |
Alan Coxdeb91682008-07-22 11:13:08 +0100685 ((p_priv->ri_state) ? TIOCM_RNG : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686
687 return value;
688}
689
Alan Cox20b9d172011-02-14 16:26:50 +0000690static int keyspan_tiocmset(struct tty_struct *tty,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 unsigned int set, unsigned int clear)
692{
Alan Cox95da3102008-07-22 11:09:07 +0100693 struct usb_serial_port *port = tty->driver_data;
694 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +0100695
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 if (set & TIOCM_RTS)
697 p_priv->rts_state = 1;
698 if (set & TIOCM_DTR)
699 p_priv->dtr_state = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 if (clear & TIOCM_RTS)
701 p_priv->rts_state = 0;
702 if (clear & TIOCM_DTR)
703 p_priv->dtr_state = 0;
704 keyspan_send_setup(port, 0);
705 return 0;
706}
707
Alan Cox95da3102008-07-22 11:09:07 +0100708/* Write function is similar for the four protocols used
709 with only a minor change for usa90 (usa19hs) required */
710static int keyspan_write(struct tty_struct *tty,
711 struct usb_serial_port *port, const unsigned char *buf, int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712{
713 struct keyspan_port_private *p_priv;
714 const struct keyspan_device_details *d_details;
715 int flip;
716 int left, todo;
717 struct urb *this_urb;
Alan Coxdeb91682008-07-22 11:13:08 +0100718 int err, maxDataLen, dataOffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719
720 p_priv = usb_get_serial_port_data(port);
721 d_details = p_priv->device_details;
722
723 if (d_details->msg_format == msg_usa90) {
Alan Coxdeb91682008-07-22 11:13:08 +0100724 maxDataLen = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 dataOffset = 0;
726 } else {
727 maxDataLen = 63;
728 dataOffset = 1;
729 }
Alan Coxdeb91682008-07-22 11:13:08 +0100730
Greg Kroah-Hartman11438322013-06-06 10:32:00 -0700731 dev_dbg(&port->dev, "%s - %d chars, flip=%d\n", __func__, count,
732 p_priv->out_flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733
734 for (left = count; left > 0; left -= todo) {
735 todo = left;
736 if (todo > maxDataLen)
737 todo = maxDataLen;
738
739 flip = p_priv->out_flip;
Alan Coxdeb91682008-07-22 11:13:08 +0100740
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 /* Check we have a valid urb/endpoint before we use it... */
Alan Coxdeb91682008-07-22 11:13:08 +0100742 this_urb = p_priv->out_urbs[flip];
743 if (this_urb == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 /* no bulk out, so return 0 bytes written */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700745 dev_dbg(&port->dev, "%s - no output urb :(\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 return count;
747 }
748
Johan Hovold0cd782b2016-05-08 20:08:00 +0200749 dev_dbg(&port->dev, "%s - endpoint %x flip %d\n",
Alan Coxdeb91682008-07-22 11:13:08 +0100750 __func__, usb_pipeendpoint(this_urb->pipe), flip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751
752 if (this_urb->status == -EINPROGRESS) {
Alan Coxdeb91682008-07-22 11:13:08 +0100753 if (time_before(jiffies,
754 p_priv->tx_start_time[flip] + 10 * HZ))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 usb_unlink_urb(this_urb);
757 break;
758 }
759
Alan Coxdeb91682008-07-22 11:13:08 +0100760 /* First byte in buffer is "last flag" (except for usa19hx)
761 - unused so for now so set to zero */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 ((char *)this_urb->transfer_buffer)[0] = 0;
763
Alan Coxdeb91682008-07-22 11:13:08 +0100764 memcpy(this_urb->transfer_buffer + dataOffset, buf, todo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 buf += todo;
766
767 /* send the data out the bulk port */
768 this_urb->transfer_buffer_length = todo + dataOffset;
769
Alan Coxdeb91682008-07-22 11:13:08 +0100770 err = usb_submit_urb(this_urb, GFP_ATOMIC);
771 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700772 dev_dbg(&port->dev, "usb_submit_urb(write bulk) failed (%d)\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 p_priv->tx_start_time[flip] = jiffies;
774
775 /* Flip for next time if usa26 or usa28 interface
776 (not used on usa49) */
777 p_priv->out_flip = (flip + 1) & d_details->outdat_endp_flip;
778 }
779
780 return count - left;
781}
782
David Howells7d12e782006-10-05 14:55:46 +0100783static void usa26_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784{
785 int i, err;
786 int endpoint;
787 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700789 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 endpoint = usb_pipeendpoint(urb->pipe);
792
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700793 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +0200794 dev_dbg(&urb->dev->dev, "%s - nonzero status %d on endpoint %x\n",
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700795 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 return;
797 }
798
Ming Leicdc97792008-02-24 18:41:47 +0800799 port = urb->context;
Jiri Slaby2e124b42013-01-03 15:53:06 +0100800 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 /* 0x80 bit is error flag */
802 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +0100803 /* no errors on individual bytes, only
804 possible overrun err */
Johan Hovold855515a2014-11-18 11:25:20 +0100805 if (data[0] & RXERROR_OVERRUN) {
806 tty_insert_flip_char(&port->port, 0,
807 TTY_OVERRUN);
808 }
Alan Coxdeb91682008-07-22 11:13:08 +0100809 for (i = 1; i < urb->actual_length ; ++i)
Johan Hovold855515a2014-11-18 11:25:20 +0100810 tty_insert_flip_char(&port->port, data[i],
811 TTY_NORMAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 } else {
813 /* some bytes had errors, every byte has status */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700814 dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 for (i = 0; i + 1 < urb->actual_length; i += 2) {
Johan Hovold5d1678a2014-11-18 11:25:19 +0100816 int stat = data[i];
817 int flag = TTY_NORMAL;
818
819 if (stat & RXERROR_OVERRUN) {
820 tty_insert_flip_char(&port->port, 0,
821 TTY_OVERRUN);
822 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 /* XXX should handle break (0x10) */
Johan Hovold5d1678a2014-11-18 11:25:19 +0100824 if (stat & RXERROR_PARITY)
825 flag = TTY_PARITY;
826 else if (stat & RXERROR_FRAMING)
827 flag = TTY_FRAME;
828
Jiri Slaby92a19f92013-01-03 15:53:03 +0100829 tty_insert_flip_char(&port->port, data[i+1],
830 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 }
832 }
Jiri Slaby2e124b42013-01-03 15:53:06 +0100833 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 }
Alan Coxdeb91682008-07-22 11:13:08 +0100835
836 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500837 err = usb_submit_urb(urb, GFP_ATOMIC);
838 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700839 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840}
841
Alan Coxdeb91682008-07-22 11:13:08 +0100842/* Outdat handling is common for all devices */
David Howells7d12e782006-10-05 14:55:46 +0100843static void usa2x_outdat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844{
845 struct usb_serial_port *port;
846 struct keyspan_port_private *p_priv;
847
Ming Leicdc97792008-02-24 18:41:47 +0800848 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 p_priv = usb_get_serial_port_data(port);
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700850 dev_dbg(&port->dev, "%s - urb %d\n", __func__, urb == p_priv->out_urbs[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851
Alan Stern1f871582010-02-17 10:05:47 -0500852 usb_serial_port_softint(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853}
854
David Howells7d12e782006-10-05 14:55:46 +0100855static void usa26_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857}
858
David Howells7d12e782006-10-05 14:55:46 +0100859static void usa26_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860{
861 struct usb_serial_port *port;
862 struct keyspan_port_private *p_priv;
863
Ming Leicdc97792008-02-24 18:41:47 +0800864 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 p_priv = usb_get_serial_port_data(port);
866
867 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700868 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100869 keyspan_usa26_send_setup(port->serial, port,
870 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 }
872}
873
David Howells7d12e782006-10-05 14:55:46 +0100874static void usa26_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875{
876 unsigned char *data = urb->transfer_buffer;
877 struct keyspan_usa26_portStatusMessage *msg;
878 struct usb_serial *serial;
879 struct usb_serial_port *port;
880 struct keyspan_port_private *p_priv;
881 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700882 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883
Ming Leicdc97792008-02-24 18:41:47 +0800884 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700886 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +0200887 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
888 __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 return;
890 }
891 if (urb->actual_length != 9) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700892 dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 goto exit;
894 }
895
896 msg = (struct keyspan_usa26_portStatusMessage *)data;
897
Alan Coxdeb91682008-07-22 11:13:08 +0100898 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700900 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 goto exit;
902 }
903 port = serial->port[msg->port];
904 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb5122232014-12-22 18:39:39 +0100905 if (!p_priv)
906 goto resubmit;
Alan Coxdeb91682008-07-22 11:13:08 +0100907
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 /* Update handshaking pin state information */
909 old_dcd_state = p_priv->dcd_state;
910 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
911 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
912 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
913 p_priv->ri_state = ((msg->ri) ? 1 : 0);
914
Jiri Slabyaa27a092013-03-07 13:12:30 +0100915 if (old_dcd_state != p_priv->dcd_state)
916 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb5122232014-12-22 18:39:39 +0100917resubmit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +0100919 err = usb_submit_urb(urb, GFP_ATOMIC);
920 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700921 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922exit: ;
923}
924
David Howells7d12e782006-10-05 14:55:46 +0100925static void usa26_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927}
928
929
David Howells7d12e782006-10-05 14:55:46 +0100930static void usa28_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931{
Alan Coxf035a8a2008-07-22 11:13:32 +0100932 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 unsigned char *data;
935 struct keyspan_port_private *p_priv;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700936 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937
Ming Leicdc97792008-02-24 18:41:47 +0800938 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 p_priv = usb_get_serial_port_data(port);
940 data = urb->transfer_buffer;
941
942 if (urb != p_priv->in_urbs[p_priv->in_flip])
943 return;
944
945 do {
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -0700946 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +0200947 dev_dbg(&urb->dev->dev, "%s - nonzero status %d on endpoint %x\n",
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700948 __func__, status, usb_pipeendpoint(urb->pipe));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 return;
950 }
951
Ming Leicdc97792008-02-24 18:41:47 +0800952 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 p_priv = usb_get_serial_port_data(port);
954 data = urb->transfer_buffer;
955
Jiri Slaby2e124b42013-01-03 15:53:06 +0100956 if (urb->actual_length) {
Jiri Slaby05c7cd32013-01-03 15:53:04 +0100957 tty_insert_flip_string(&port->port, data,
958 urb->actual_length);
Jiri Slaby2e124b42013-01-03 15:53:06 +0100959 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 }
961
962 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -0500963 err = usb_submit_urb(urb, GFP_ATOMIC);
964 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700965 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n",
Alan Stern1f871582010-02-17 10:05:47 -0500966 __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 p_priv->in_flip ^= 1;
968
969 urb = p_priv->in_urbs[p_priv->in_flip];
970 } while (urb->status != -EINPROGRESS);
971}
972
David Howells7d12e782006-10-05 14:55:46 +0100973static void usa28_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975}
976
David Howells7d12e782006-10-05 14:55:46 +0100977static void usa28_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978{
979 struct usb_serial_port *port;
980 struct keyspan_port_private *p_priv;
981
Ming Leicdc97792008-02-24 18:41:47 +0800982 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 p_priv = usb_get_serial_port_data(port);
984
985 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -0700986 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +0100987 keyspan_usa28_send_setup(port->serial, port,
988 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 }
990}
991
David Howells7d12e782006-10-05 14:55:46 +0100992static void usa28_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993{
994 int err;
995 unsigned char *data = urb->transfer_buffer;
996 struct keyspan_usa28_portStatusMessage *msg;
997 struct usb_serial *serial;
998 struct usb_serial_port *port;
999 struct keyspan_port_private *p_priv;
1000 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001001 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002
Ming Leicdc97792008-02-24 18:41:47 +08001003 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001005 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +02001006 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
1007 __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 return;
1009 }
1010
1011 if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001012 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 goto exit;
1014 }
1015
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 msg = (struct keyspan_usa28_portStatusMessage *)data;
1017
Alan Coxdeb91682008-07-22 11:13:08 +01001018 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001020 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 goto exit;
1022 }
1023 port = serial->port[msg->port];
1024 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb5122232014-12-22 18:39:39 +01001025 if (!p_priv)
1026 goto resubmit;
Alan Coxdeb91682008-07-22 11:13:08 +01001027
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 /* Update handshaking pin state information */
1029 old_dcd_state = p_priv->dcd_state;
1030 p_priv->cts_state = ((msg->cts) ? 1 : 0);
1031 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
1032 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
1033 p_priv->ri_state = ((msg->ri) ? 1 : 0);
1034
Jiri Slabyaa27a092013-03-07 13:12:30 +01001035 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
1036 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb5122232014-12-22 18:39:39 +01001037resubmit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +01001039 err = usb_submit_urb(urb, GFP_ATOMIC);
1040 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001041 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042exit: ;
1043}
1044
David Howells7d12e782006-10-05 14:55:46 +01001045static void usa28_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047}
1048
1049
David Howells7d12e782006-10-05 14:55:46 +01001050static void usa49_glocont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051{
1052 struct usb_serial *serial;
1053 struct usb_serial_port *port;
1054 struct keyspan_port_private *p_priv;
1055 int i;
1056
Ming Leicdc97792008-02-24 18:41:47 +08001057 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 for (i = 0; i < serial->num_ports; ++i) {
1059 port = serial->port[i];
1060 p_priv = usb_get_serial_port_data(port);
1061
1062 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001063 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +01001064 keyspan_usa49_send_setup(serial, port,
1065 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 break;
1067 }
1068 }
1069}
1070
1071 /* This is actually called glostat in the Keyspan
1072 doco */
David Howells7d12e782006-10-05 14:55:46 +01001073static void usa49_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074{
1075 int err;
1076 unsigned char *data = urb->transfer_buffer;
1077 struct keyspan_usa49_portStatusMessage *msg;
1078 struct usb_serial *serial;
1079 struct usb_serial_port *port;
1080 struct keyspan_port_private *p_priv;
1081 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001082 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083
Ming Leicdc97792008-02-24 18:41:47 +08001084 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001086 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +02001087 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
1088 __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 return;
1090 }
1091
Alan Coxdeb91682008-07-22 11:13:08 +01001092 if (urb->actual_length !=
1093 sizeof(struct keyspan_usa49_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001094 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 goto exit;
1096 }
1097
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 msg = (struct keyspan_usa49_portStatusMessage *)data;
1099
Alan Coxdeb91682008-07-22 11:13:08 +01001100 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 if (msg->portNumber >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001102 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
1103 __func__, msg->portNumber);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 goto exit;
1105 }
1106 port = serial->port[msg->portNumber];
1107 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb5122232014-12-22 18:39:39 +01001108 if (!p_priv)
1109 goto resubmit;
Alan Coxdeb91682008-07-22 11:13:08 +01001110
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 /* Update handshaking pin state information */
1112 old_dcd_state = p_priv->dcd_state;
1113 p_priv->cts_state = ((msg->cts) ? 1 : 0);
1114 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
1115 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
1116 p_priv->ri_state = ((msg->ri) ? 1 : 0);
1117
Jiri Slabyaa27a092013-03-07 13:12:30 +01001118 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
1119 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb5122232014-12-22 18:39:39 +01001120resubmit:
Alan Coxdeb91682008-07-22 11:13:08 +01001121 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +01001122 err = usb_submit_urb(urb, GFP_ATOMIC);
1123 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001124 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125exit: ;
1126}
1127
David Howells7d12e782006-10-05 14:55:46 +01001128static void usa49_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130}
1131
David Howells7d12e782006-10-05 14:55:46 +01001132static void usa49_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133{
1134 int i, err;
1135 int endpoint;
1136 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001138 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 endpoint = usb_pipeendpoint(urb->pipe);
1141
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001142 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +02001143 dev_dbg(&urb->dev->dev, "%s - nonzero status %d on endpoint %x\n",
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001144 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 return;
1146 }
1147
Ming Leicdc97792008-02-24 18:41:47 +08001148 port = urb->context;
Jiri Slaby2e124b42013-01-03 15:53:06 +01001149 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 /* 0x80 bit is error flag */
1151 if ((data[0] & 0x80) == 0) {
1152 /* no error on any byte */
Jiri Slaby05c7cd32013-01-03 15:53:04 +01001153 tty_insert_flip_string(&port->port, data + 1,
Alan Coxf035a8a2008-07-22 11:13:32 +01001154 urb->actual_length - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 } else {
1156 /* some bytes had errors, every byte has status */
1157 for (i = 0; i + 1 < urb->actual_length; i += 2) {
Johan Hovold5d1678a2014-11-18 11:25:19 +01001158 int stat = data[i];
1159 int flag = TTY_NORMAL;
1160
1161 if (stat & RXERROR_OVERRUN) {
1162 tty_insert_flip_char(&port->port, 0,
1163 TTY_OVERRUN);
1164 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 /* XXX should handle break (0x10) */
Johan Hovold5d1678a2014-11-18 11:25:19 +01001166 if (stat & RXERROR_PARITY)
1167 flag = TTY_PARITY;
1168 else if (stat & RXERROR_FRAMING)
1169 flag = TTY_FRAME;
1170
Jiri Slaby92a19f92013-01-03 15:53:03 +01001171 tty_insert_flip_char(&port->port, data[i+1],
1172 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 }
1174 }
Jiri Slaby2e124b42013-01-03 15:53:06 +01001175 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 }
Alan Coxdeb91682008-07-22 11:13:08 +01001177
1178 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -05001179 err = usb_submit_urb(urb, GFP_ATOMIC);
1180 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001181 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182}
1183
Lucy McCoy0ca12682007-05-18 12:10:41 -07001184static void usa49wg_indat_callback(struct urb *urb)
1185{
1186 int i, len, x, err;
1187 struct usb_serial *serial;
1188 struct usb_serial_port *port;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001189 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001190 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001191
Lucy McCoy0ca12682007-05-18 12:10:41 -07001192 serial = urb->context;
1193
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001194 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +02001195 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
1196 __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001197 return;
1198 }
1199
1200 /* inbound data is in the form P#, len, status, data */
1201 i = 0;
1202 len = 0;
1203
Dan Carpenter6a3ae842013-04-05 08:42:41 +03001204 while (i < urb->actual_length) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07001205
Dan Carpenter6a3ae842013-04-05 08:42:41 +03001206 /* Check port number from message */
1207 if (data[i] >= serial->num_ports) {
1208 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
1209 __func__, data[i]);
1210 return;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001211 }
Dan Carpenter6a3ae842013-04-05 08:42:41 +03001212 port = serial->port[data[i++]];
1213 len = data[i++];
1214
1215 /* 0x80 bit is error flag */
1216 if ((data[i] & 0x80) == 0) {
1217 /* no error on any byte */
1218 i++;
Dan Carpenter01a60e72013-04-05 08:43:20 +03001219 for (x = 1; x < len && i < urb->actual_length; ++x)
Dan Carpenter6a3ae842013-04-05 08:42:41 +03001220 tty_insert_flip_char(&port->port,
1221 data[i++], 0);
1222 } else {
1223 /*
1224 * some bytes had errors, every byte has status
1225 */
Dan Carpenter01a60e72013-04-05 08:43:20 +03001226 for (x = 0; x + 1 < len &&
1227 i + 1 < urb->actual_length; x += 2) {
Johan Hovold5d1678a2014-11-18 11:25:19 +01001228 int stat = data[i];
1229 int flag = TTY_NORMAL;
Dan Carpenter6a3ae842013-04-05 08:42:41 +03001230
Johan Hovold5d1678a2014-11-18 11:25:19 +01001231 if (stat & RXERROR_OVERRUN) {
1232 tty_insert_flip_char(&port->port, 0,
1233 TTY_OVERRUN);
1234 }
Dan Carpenter6a3ae842013-04-05 08:42:41 +03001235 /* XXX should handle break (0x10) */
Johan Hovold5d1678a2014-11-18 11:25:19 +01001236 if (stat & RXERROR_PARITY)
1237 flag = TTY_PARITY;
1238 else if (stat & RXERROR_FRAMING)
1239 flag = TTY_FRAME;
1240
Dan Carpenter6a3ae842013-04-05 08:42:41 +03001241 tty_insert_flip_char(&port->port, data[i+1],
1242 flag);
1243 i += 2;
1244 }
1245 }
1246 tty_flip_buffer_push(&port->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001247 }
1248
1249 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -07001250 err = usb_submit_urb(urb, GFP_ATOMIC);
1251 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001252 dev_dbg(&urb->dev->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001253}
1254
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255/* not used, usa-49 doesn't have per-port control endpoints */
Lucy McCoy0ca12682007-05-18 12:10:41 -07001256static void usa49_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258}
1259
Lucy McCoy0ca12682007-05-18 12:10:41 -07001260static void usa90_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261{
1262 int i, err;
1263 int endpoint;
1264 struct usb_serial_port *port;
1265 struct keyspan_port_private *p_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001267 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269 endpoint = usb_pipeendpoint(urb->pipe);
1270
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001271 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +02001272 dev_dbg(&urb->dev->dev, "%s - nonzero status %d on endpoint %x\n",
1273 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274 return;
1275 }
1276
Ming Leicdc97792008-02-24 18:41:47 +08001277 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 p_priv = usb_get_serial_port_data(port);
1279
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 /* if current mode is DMA, looks like usa28 format
Alan Coxdeb91682008-07-22 11:13:08 +01001282 otherwise looks like usa26 data format */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283
Alan Coxf035a8a2008-07-22 11:13:32 +01001284 if (p_priv->baud > 57600)
Jiri Slaby05c7cd32013-01-03 15:53:04 +01001285 tty_insert_flip_string(&port->port, data,
1286 urb->actual_length);
Alan Coxf035a8a2008-07-22 11:13:32 +01001287 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 /* 0x80 bit is error flag */
1289 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +01001290 /* no errors on individual bytes, only
1291 possible overrun err*/
Johan Hovold855515a2014-11-18 11:25:20 +01001292 if (data[0] & RXERROR_OVERRUN) {
1293 tty_insert_flip_char(&port->port, 0,
1294 TTY_OVERRUN);
1295 }
Alan Coxdeb91682008-07-22 11:13:08 +01001296 for (i = 1; i < urb->actual_length ; ++i)
Jiri Slaby92a19f92013-01-03 15:53:03 +01001297 tty_insert_flip_char(&port->port,
Johan Hovold855515a2014-11-18 11:25:20 +01001298 data[i], TTY_NORMAL);
Alan Coxdeb91682008-07-22 11:13:08 +01001299 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 /* some bytes had errors, every byte has status */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001301 dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 for (i = 0; i + 1 < urb->actual_length; i += 2) {
Johan Hovold5d1678a2014-11-18 11:25:19 +01001303 int stat = data[i];
1304 int flag = TTY_NORMAL;
1305
1306 if (stat & RXERROR_OVERRUN) {
1307 tty_insert_flip_char(
1308 &port->port, 0,
1309 TTY_OVERRUN);
1310 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 /* XXX should handle break (0x10) */
Johan Hovold5d1678a2014-11-18 11:25:19 +01001312 if (stat & RXERROR_PARITY)
1313 flag = TTY_PARITY;
1314 else if (stat & RXERROR_FRAMING)
1315 flag = TTY_FRAME;
1316
Jiri Slaby92a19f92013-01-03 15:53:03 +01001317 tty_insert_flip_char(&port->port,
1318 data[i+1], flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 }
1320 }
1321 }
Jiri Slaby2e124b42013-01-03 15:53:06 +01001322 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 }
Alan Coxdeb91682008-07-22 11:13:08 +01001324
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -05001326 err = usb_submit_urb(urb, GFP_ATOMIC);
1327 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001328 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329}
1330
1331
David Howells7d12e782006-10-05 14:55:46 +01001332static void usa90_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333{
1334 unsigned char *data = urb->transfer_buffer;
1335 struct keyspan_usa90_portStatusMessage *msg;
1336 struct usb_serial *serial;
1337 struct usb_serial_port *port;
1338 struct keyspan_port_private *p_priv;
1339 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001340 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341
Ming Leicdc97792008-02-24 18:41:47 +08001342 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001344 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +02001345 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
1346 __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 return;
1348 }
1349 if (urb->actual_length < 14) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001350 dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 goto exit;
1352 }
1353
1354 msg = (struct keyspan_usa90_portStatusMessage *)data;
1355
1356 /* Now do something useful with the data */
1357
1358 port = serial->port[0];
1359 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb5122232014-12-22 18:39:39 +01001360 if (!p_priv)
1361 goto resubmit;
Alan Coxdeb91682008-07-22 11:13:08 +01001362
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 /* Update handshaking pin state information */
1364 old_dcd_state = p_priv->dcd_state;
1365 p_priv->cts_state = ((msg->cts) ? 1 : 0);
1366 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
1367 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
1368 p_priv->ri_state = ((msg->ri) ? 1 : 0);
1369
Jiri Slabyaa27a092013-03-07 13:12:30 +01001370 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
1371 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb5122232014-12-22 18:39:39 +01001372resubmit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +01001374 err = usb_submit_urb(urb, GFP_ATOMIC);
1375 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001376 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377exit:
1378 ;
1379}
1380
David Howells7d12e782006-10-05 14:55:46 +01001381static void usa90_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382{
1383 struct usb_serial_port *port;
1384 struct keyspan_port_private *p_priv;
1385
Ming Leicdc97792008-02-24 18:41:47 +08001386 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 p_priv = usb_get_serial_port_data(port);
1388
1389 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001390 dev_dbg(&urb->dev->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +01001391 keyspan_usa90_send_setup(port->serial, port,
1392 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 }
1394}
1395
Lucy McCoy0ca12682007-05-18 12:10:41 -07001396/* Status messages from the 28xg */
1397static void usa67_instat_callback(struct urb *urb)
1398{
1399 int err;
1400 unsigned char *data = urb->transfer_buffer;
1401 struct keyspan_usa67_portStatusMessage *msg;
1402 struct usb_serial *serial;
1403 struct usb_serial_port *port;
1404 struct keyspan_port_private *p_priv;
1405 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001406 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001407
Lucy McCoy0ca12682007-05-18 12:10:41 -07001408 serial = urb->context;
1409
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001410 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +02001411 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
1412 __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001413 return;
1414 }
1415
Alan Coxdeb91682008-07-22 11:13:08 +01001416 if (urb->actual_length !=
1417 sizeof(struct keyspan_usa67_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001418 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001419 return;
1420 }
1421
1422
1423 /* Now do something useful with the data */
1424 msg = (struct keyspan_usa67_portStatusMessage *)data;
1425
1426 /* Check port number from message and retrieve private data */
1427 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001428 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001429 return;
1430 }
1431
1432 port = serial->port[msg->port];
1433 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb5122232014-12-22 18:39:39 +01001434 if (!p_priv)
1435 goto resubmit;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001436
1437 /* Update handshaking pin state information */
1438 old_dcd_state = p_priv->dcd_state;
1439 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
1440 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
1441
Jiri Slabyaa27a092013-03-07 13:12:30 +01001442 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
1443 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb5122232014-12-22 18:39:39 +01001444resubmit:
Lucy McCoy0ca12682007-05-18 12:10:41 -07001445 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -07001446 err = usb_submit_urb(urb, GFP_ATOMIC);
1447 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001448 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001449}
1450
1451static void usa67_glocont_callback(struct urb *urb)
1452{
1453 struct usb_serial *serial;
1454 struct usb_serial_port *port;
1455 struct keyspan_port_private *p_priv;
1456 int i;
1457
Lucy McCoy0ca12682007-05-18 12:10:41 -07001458 serial = urb->context;
1459 for (i = 0; i < serial->num_ports; ++i) {
1460 port = serial->port[i];
1461 p_priv = usb_get_serial_port_data(port);
1462
1463 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001464 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001465 keyspan_usa67_send_setup(serial, port,
1466 p_priv->resend_cont - 1);
1467 break;
1468 }
1469 }
1470}
1471
Alan Cox95da3102008-07-22 11:09:07 +01001472static int keyspan_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473{
Alan Cox95da3102008-07-22 11:09:07 +01001474 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475 struct keyspan_port_private *p_priv;
1476 const struct keyspan_device_details *d_details;
1477 int flip;
1478 int data_len;
1479 struct urb *this_urb;
1480
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 p_priv = usb_get_serial_port_data(port);
1482 d_details = p_priv->device_details;
1483
Alan Coxa5b6f602008-04-08 17:16:06 +01001484 /* FIXME: locking */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485 if (d_details->msg_format == msg_usa90)
Alan Coxdeb91682008-07-22 11:13:08 +01001486 data_len = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 else
1488 data_len = 63;
1489
1490 flip = p_priv->out_flip;
1491
1492 /* Check both endpoints to see if any are available. */
Alan Coxdeb91682008-07-22 11:13:08 +01001493 this_urb = p_priv->out_urbs[flip];
1494 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001496 return data_len;
1497 flip = (flip + 1) & d_details->outdat_endp_flip;
1498 this_urb = p_priv->out_urbs[flip];
1499 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001501 return data_len;
1502 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 }
Alan Coxa5b6f602008-04-08 17:16:06 +01001504 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505}
1506
1507
Alan Coxa509a7e2009-09-19 13:13:26 -07001508static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509{
Andrew Mortonf78ba152007-11-28 16:21:54 -08001510 struct keyspan_port_private *p_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 const struct keyspan_device_details *d_details;
1512 int i, err;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001513 int baud_rate, device_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 struct urb *urb;
Alan Cox95da3102008-07-22 11:09:07 +01001515 unsigned int cflag = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 p_priv = usb_get_serial_port_data(port);
1518 d_details = p_priv->device_details;
Borislav Petkov7eea4362007-11-14 17:00:39 -08001519
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520 /* Set some sane defaults */
1521 p_priv->rts_state = 1;
1522 p_priv->dtr_state = 1;
1523 p_priv->baud = 9600;
1524
1525 /* force baud and lcr to be set on open */
1526 p_priv->old_baud = 0;
1527 p_priv->old_cflag = 0;
1528
1529 p_priv->out_flip = 0;
1530 p_priv->in_flip = 0;
1531
1532 /* Reset low level data toggle and start reading from endpoints */
1533 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001534 urb = p_priv->in_urbs[i];
1535 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537
Alan Coxdeb91682008-07-22 11:13:08 +01001538 /* make sure endpoint data toggle is synchronized
1539 with the device */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 usb_clear_halt(urb->dev, urb->pipe);
Alan Coxdeb91682008-07-22 11:13:08 +01001541 err = usb_submit_urb(urb, GFP_KERNEL);
1542 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001543 dev_dbg(&port->dev, "%s - submit urb %d failed (%d)\n", __func__, i, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 }
1545
1546 /* Reset low level data toggle on out endpoints */
1547 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001548 urb = p_priv->out_urbs[i];
1549 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 continue;
Alan Coxdeb91682008-07-22 11:13:08 +01001551 /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
1552 usb_pipeout(urb->pipe), 0); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553 }
1554
Andrew Mortonf78ba152007-11-28 16:21:54 -08001555 /* get the terminal config for the setup message now so we don't
1556 * need to send 2 of them */
1557
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001558 device_port = port->port_number;
Alan Cox95da3102008-07-22 11:09:07 +01001559 if (tty) {
Alan Coxadc8d742012-07-14 15:31:47 +01001560 cflag = tty->termios.c_cflag;
Alan Cox95da3102008-07-22 11:09:07 +01001561 /* Baud rate calculation takes baud rate as an integer
1562 so other rates can be generated if desired. */
1563 baud_rate = tty_get_baud_rate(tty);
1564 /* If no match or invalid, leave as default */
1565 if (baud_rate >= 0
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001566 && d_details->calculate_baud_rate(port, baud_rate, d_details->baudclk,
Alan Cox95da3102008-07-22 11:09:07 +01001567 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
1568 p_priv->baud = baud_rate;
1569 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001570 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001571 /* set CTS/RTS handshake etc. */
1572 p_priv->cflag = cflag;
Ben Minerds2b982ab2012-07-12 00:10:16 +10001573 p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001574
1575 keyspan_send_setup(port, 1);
Alan Coxdeb91682008-07-22 11:13:08 +01001576 /* mdelay(100); */
1577 /* keyspan_set_termios(port, NULL); */
Andrew Mortonf78ba152007-11-28 16:21:54 -08001578
Alan Coxa5b6f602008-04-08 17:16:06 +01001579 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580}
1581
Alan Cox335f8512009-06-11 12:26:29 +01001582static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
1583{
1584 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
1585
1586 p_priv->rts_state = on;
1587 p_priv->dtr_state = on;
1588 keyspan_send_setup(port, 0);
1589}
1590
1591static void keyspan_close(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592{
1593 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 struct keyspan_port_private *p_priv;
1595
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +01001597
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598 p_priv->rts_state = 0;
1599 p_priv->dtr_state = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001600
Johan Hovold80dfe0c2013-03-21 12:36:32 +01001601 keyspan_send_setup(port, 2);
1602 /* pilot-xfer seems to work best with this delay */
1603 mdelay(100);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604
1605 p_priv->out_flip = 0;
1606 p_priv->in_flip = 0;
1607
Johan Hovold61924502016-05-08 20:07:59 +02001608 usb_kill_urb(p_priv->inack_urb);
Johan Hovold80dfe0c2013-03-21 12:36:32 +01001609 for (i = 0; i < 2; i++) {
Johan Hovold61924502016-05-08 20:07:59 +02001610 usb_kill_urb(p_priv->in_urbs[i]);
1611 usb_kill_urb(p_priv->out_urbs[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613}
1614
Alan Coxdeb91682008-07-22 11:13:08 +01001615/* download the firmware to a pre-renumeration device */
1616static int keyspan_fake_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617{
Rene Buergel8d733e22012-09-18 09:02:01 +02001618 char *fw_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001620 dev_dbg(&serial->dev->dev, "Keyspan startup version %04x product %04x\n",
1621 le16_to_cpu(serial->dev->descriptor.bcdDevice),
1622 le16_to_cpu(serial->dev->descriptor.idProduct));
Alan Coxdeb91682008-07-22 11:13:08 +01001623
1624 if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000)
1625 != 0x8000) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001626 dev_dbg(&serial->dev->dev, "Firmware already loaded. Quitting.\n");
Alan Coxdeb91682008-07-22 11:13:08 +01001627 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 }
1629
1630 /* Select firmware image on the basis of idProduct */
1631 switch (le16_to_cpu(serial->dev->descriptor.idProduct)) {
1632 case keyspan_usa28_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001633 fw_name = "keyspan/usa28.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 break;
1635
1636 case keyspan_usa28x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001637 fw_name = "keyspan/usa28x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 break;
1639
1640 case keyspan_usa28xa_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001641 fw_name = "keyspan/usa28xa.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642 break;
1643
1644 case keyspan_usa28xb_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001645 fw_name = "keyspan/usa28xb.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 break;
1647
1648 case keyspan_usa19_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001649 fw_name = "keyspan/usa19.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001651
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 case keyspan_usa19qi_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001653 fw_name = "keyspan/usa19qi.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_mpr_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001657 fw_name = "keyspan/mpr.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 break;
1659
1660 case keyspan_usa19qw_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001661 fw_name = "keyspan/usa19qw.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001663
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664 case keyspan_usa18x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001665 fw_name = "keyspan/usa18x.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_usa19w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001669 fw_name = "keyspan/usa19w.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_usa49w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001673 fw_name = "keyspan/usa49w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674 break;
1675
1676 case keyspan_usa49wlc_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001677 fw_name = "keyspan/usa49wlc.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 break;
1679
1680 default:
David Woodhouse2971c572008-05-30 14:04:03 +03001681 dev_err(&serial->dev->dev, "Unknown product ID (%04x)\n",
1682 le16_to_cpu(serial->dev->descriptor.idProduct));
1683 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 }
1685
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001686 dev_dbg(&serial->dev->dev, "Uploading Keyspan %s firmware.\n", fw_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687
Rene Buergel8d733e22012-09-18 09:02:01 +02001688 if (ezusb_fx1_ihex_firmware_download(serial->dev, fw_name) < 0) {
1689 dev_err(&serial->dev->dev, "failed to load firmware \"%s\"\n",
1690 fw_name);
1691 return -ENOENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692 }
1693
Rene Buergel8d733e22012-09-18 09:02:01 +02001694 /* after downloading firmware Renumeration will occur in a
1695 moment and the new device will bind to the real driver */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696
1697 /* we don't want this device to have a driver assigned to it. */
Alan Coxdeb91682008-07-22 11:13:08 +01001698 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699}
1700
1701/* Helper functions used by keyspan_setup_urbs */
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001702static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *serial,
1703 int endpoint)
1704{
1705 struct usb_host_interface *iface_desc;
1706 struct usb_endpoint_descriptor *ep;
1707 int i;
1708
1709 iface_desc = serial->interface->cur_altsetting;
1710 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1711 ep = &iface_desc->endpoint[i].desc;
1712 if (ep->bEndpointAddress == endpoint)
1713 return ep;
1714 }
Johan Hovold0cd782b2016-05-08 20:08:00 +02001715 dev_warn(&serial->interface->dev, "found no endpoint descriptor for endpoint %x\n",
1716 endpoint);
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001717 return NULL;
1718}
1719
Alan Coxdeb91682008-07-22 11:13:08 +01001720static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721 int dir, void *ctx, char *buf, int len,
David Howells7d12e782006-10-05 14:55:46 +01001722 void (*callback)(struct urb *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723{
1724 struct urb *urb;
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001725 struct usb_endpoint_descriptor const *ep_desc;
1726 char const *ep_type_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727
1728 if (endpoint == -1)
1729 return NULL; /* endpoint not needed */
1730
Johan Hovold0cd782b2016-05-08 20:08:00 +02001731 dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %x\n",
1732 __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
Johan Hovold10c642d2013-12-29 19:22:56 +01001734 if (!urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736
Lucy McCoy0ca12682007-05-18 12:10:41 -07001737 if (endpoint == 0) {
1738 /* control EP filled in when used */
1739 return urb;
1740 }
1741
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001742 ep_desc = find_ep(serial, endpoint);
1743 if (!ep_desc) {
Johan Hovold7d7e21f2019-10-03 15:49:58 +02001744 usb_free_urb(urb);
1745 return NULL;
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001746 }
1747 if (usb_endpoint_xfer_int(ep_desc)) {
1748 ep_type_name = "INT";
1749 usb_fill_int_urb(urb, serial->dev,
1750 usb_sndintpipe(serial->dev, endpoint) | dir,
1751 buf, len, callback, ctx,
1752 ep_desc->bInterval);
1753 } else if (usb_endpoint_xfer_bulk(ep_desc)) {
1754 ep_type_name = "BULK";
1755 usb_fill_bulk_urb(urb, serial->dev,
1756 usb_sndbulkpipe(serial->dev, endpoint) | dir,
1757 buf, len, callback, ctx);
1758 } else {
1759 dev_warn(&serial->interface->dev,
1760 "unsupported endpoint type %x\n",
Julia Lawall2e0fe702008-12-29 11:22:14 +01001761 usb_endpoint_type(ep_desc));
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001762 usb_free_urb(urb);
1763 return NULL;
1764 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001766 dev_dbg(&serial->interface->dev, "%s - using urb %p for %s endpoint %x\n",
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001767 __func__, urb, ep_type_name, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768 return urb;
1769}
1770
1771static struct callbacks {
David Howells7d12e782006-10-05 14:55:46 +01001772 void (*instat_callback)(struct urb *);
1773 void (*glocont_callback)(struct urb *);
1774 void (*indat_callback)(struct urb *);
1775 void (*outdat_callback)(struct urb *);
1776 void (*inack_callback)(struct urb *);
1777 void (*outcont_callback)(struct urb *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778} keyspan_callbacks[] = {
1779 {
1780 /* msg_usa26 callbacks */
1781 .instat_callback = usa26_instat_callback,
1782 .glocont_callback = usa26_glocont_callback,
1783 .indat_callback = usa26_indat_callback,
1784 .outdat_callback = usa2x_outdat_callback,
1785 .inack_callback = usa26_inack_callback,
1786 .outcont_callback = usa26_outcont_callback,
1787 }, {
1788 /* msg_usa28 callbacks */
1789 .instat_callback = usa28_instat_callback,
1790 .glocont_callback = usa28_glocont_callback,
1791 .indat_callback = usa28_indat_callback,
1792 .outdat_callback = usa2x_outdat_callback,
1793 .inack_callback = usa28_inack_callback,
1794 .outcont_callback = usa28_outcont_callback,
1795 }, {
1796 /* msg_usa49 callbacks */
1797 .instat_callback = usa49_instat_callback,
1798 .glocont_callback = usa49_glocont_callback,
1799 .indat_callback = usa49_indat_callback,
1800 .outdat_callback = usa2x_outdat_callback,
1801 .inack_callback = usa49_inack_callback,
1802 .outcont_callback = usa49_outcont_callback,
1803 }, {
1804 /* msg_usa90 callbacks */
1805 .instat_callback = usa90_instat_callback,
Alan Coxdeb91682008-07-22 11:13:08 +01001806 .glocont_callback = usa28_glocont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807 .indat_callback = usa90_indat_callback,
1808 .outdat_callback = usa2x_outdat_callback,
1809 .inack_callback = usa28_inack_callback,
1810 .outcont_callback = usa90_outcont_callback,
Lucy McCoy0ca12682007-05-18 12:10:41 -07001811 }, {
1812 /* msg_usa67 callbacks */
1813 .instat_callback = usa67_instat_callback,
1814 .glocont_callback = usa67_glocont_callback,
1815 .indat_callback = usa26_indat_callback,
1816 .outdat_callback = usa2x_outdat_callback,
1817 .inack_callback = usa26_inack_callback,
1818 .outcont_callback = usa26_outcont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819 }
1820};
1821
1822 /* Generic setup urbs function that uses
1823 data in device_details */
1824static void keyspan_setup_urbs(struct usb_serial *serial)
1825{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826 struct keyspan_serial_private *s_priv;
1827 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828 struct callbacks *cback;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 s_priv = usb_get_serial_data(serial);
1831 d_details = s_priv->device_details;
1832
Alan Coxdeb91682008-07-22 11:13:08 +01001833 /* Setup values for the various callback routines */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834 cback = &keyspan_callbacks[d_details->msg_format];
1835
Alan Coxdeb91682008-07-22 11:13:08 +01001836 /* Allocate and set up urbs for each one that is in use,
1837 starting with instat endpoints */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 s_priv->instat_urb = keyspan_setup_urb
1839 (serial, d_details->instat_endpoint, USB_DIR_IN,
1840 serial, s_priv->instat_buf, INSTAT_BUFLEN,
1841 cback->instat_callback);
1842
Lucy McCoy0ca12682007-05-18 12:10:41 -07001843 s_priv->indat_urb = keyspan_setup_urb
1844 (serial, d_details->indat_endpoint, USB_DIR_IN,
1845 serial, s_priv->indat_buf, INDAT49W_BUFLEN,
1846 usa49wg_indat_callback);
1847
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 s_priv->glocont_urb = keyspan_setup_urb
1849 (serial, d_details->glocont_endpoint, USB_DIR_OUT,
1850 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
1851 cback->glocont_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852}
1853
1854/* usa19 function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001855static int keyspan_usa19_calc_baud(struct usb_serial_port *port,
1856 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857 u8 *rate_low, u8 *prescaler, int portnum)
1858{
1859 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001860 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 cnt; /* inverse of divisor (programmed into 8051) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001863 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864
Alan Coxdeb91682008-07-22 11:13:08 +01001865 /* prevent divide by zero... */
1866 b16 = baud_rate * 16L;
1867 if (b16 == 0)
1868 return KEYSPAN_INVALID_BAUD_RATE;
1869 /* Any "standard" rate over 57k6 is marginal on the USA-19
1870 as we run out of divisor resolution. */
1871 if (baud_rate > 57600)
1872 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873
Alan Coxdeb91682008-07-22 11:13:08 +01001874 /* calculate the divisor and the counter (its inverse) */
1875 div = baudclk / b16;
1876 if (div == 0)
1877 return KEYSPAN_INVALID_BAUD_RATE;
1878 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880
Alan Coxdeb91682008-07-22 11:13:08 +01001881 if (div > 0xffff)
1882 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883
Alan Coxdeb91682008-07-22 11:13:08 +01001884 /* return the counter values if non-null */
1885 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001887 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001889 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001890 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001891 __func__, baud_rate, *rate_hi, *rate_low);
1892 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893}
1894
1895/* usa19hs function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001896static int keyspan_usa19hs_calc_baud(struct usb_serial_port *port,
1897 u32 baud_rate, u32 baudclk, u8 *rate_hi,
1898 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899{
1900 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001901 div; /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001903 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904
Alan Coxdeb91682008-07-22 11:13:08 +01001905 /* prevent divide by zero... */
1906 b16 = baud_rate * 16L;
1907 if (b16 == 0)
1908 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909
Alan Coxdeb91682008-07-22 11:13:08 +01001910 /* calculate the divisor */
1911 div = baudclk / b16;
1912 if (div == 0)
1913 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914
Alan Coxdeb91682008-07-22 11:13:08 +01001915 if (div > 0xffff)
1916 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917
Alan Coxdeb91682008-07-22 11:13:08 +01001918 /* return the counter values if non-null */
1919 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001921
1922 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 *rate_hi = (u8) ((div >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001924
1925 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001926 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001927 __func__, baud_rate, *rate_hi, *rate_low);
1928
1929 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930}
1931
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001932static int keyspan_usa19w_calc_baud(struct usb_serial_port *port,
1933 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934 u8 *rate_low, u8 *prescaler, int portnum)
1935{
1936 u32 b16, /* baud rate times 16 (actual rate used internally) */
1937 clk, /* clock with 13/8 prescaler */
Alan Coxdeb91682008-07-22 11:13:08 +01001938 div, /* divisor using 13/8 prescaler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 res, /* resulting baud rate using 13/8 prescaler */
1940 diff, /* error using 13/8 prescaler */
1941 smallest_diff;
1942 u8 best_prescaler;
1943 int i;
1944
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001945 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946
Alan Coxdeb91682008-07-22 11:13:08 +01001947 /* prevent divide by zero */
1948 b16 = baud_rate * 16L;
1949 if (b16 == 0)
1950 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951
Alan Coxdeb91682008-07-22 11:13:08 +01001952 /* Calculate prescaler by trying them all and looking
1953 for best fit */
1954
1955 /* start with largest possible difference */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 smallest_diff = 0xffffffff;
1957
1958 /* 0 is an invalid prescaler, used as a flag */
1959 best_prescaler = 0;
1960
Alan Coxdeb91682008-07-22 11:13:08 +01001961 for (i = 8; i <= 0xff; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001962 clk = (baudclk * 8) / (u32) i;
Alan Coxdeb91682008-07-22 11:13:08 +01001963
1964 div = clk / b16;
1965 if (div == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967
1968 res = clk / div;
Alan Coxdeb91682008-07-22 11:13:08 +01001969 diff = (res > b16) ? (res-b16) : (b16-res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970
Alan Coxdeb91682008-07-22 11:13:08 +01001971 if (diff < smallest_diff) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972 best_prescaler = i;
1973 smallest_diff = diff;
1974 }
1975 }
1976
Alan Coxdeb91682008-07-22 11:13:08 +01001977 if (best_prescaler == 0)
1978 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979
1980 clk = (baudclk * 8) / (u32) best_prescaler;
1981 div = clk / b16;
1982
Alan Coxdeb91682008-07-22 11:13:08 +01001983 /* return the divisor and prescaler if non-null */
1984 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001986 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987 *rate_hi = (u8) ((div >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988 if (prescaler) {
1989 *prescaler = best_prescaler;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001990 /* dev_dbg(&port->dev, "%s - %d %d\n", __func__, *prescaler, div); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991 }
Alan Coxdeb91682008-07-22 11:13:08 +01001992 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993}
1994
1995 /* USA-28 supports different maximum baud rates on each port */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001996static int keyspan_usa28_calc_baud(struct usb_serial_port *port,
1997 u32 baud_rate, u32 baudclk, u8 *rate_hi,
1998 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999{
2000 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01002001 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002 cnt; /* inverse of divisor (programmed into 8051) */
2003
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002004 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005
2006 /* prevent divide by zero */
Alan Coxdeb91682008-07-22 11:13:08 +01002007 b16 = baud_rate * 16L;
2008 if (b16 == 0)
2009 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010
Alan Coxdeb91682008-07-22 11:13:08 +01002011 /* calculate the divisor and the counter (its inverse) */
2012 div = KEYSPAN_USA28_BAUDCLK / b16;
2013 if (div == 0)
2014 return KEYSPAN_INVALID_BAUD_RATE;
2015 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017
Alan Coxdeb91682008-07-22 11:13:08 +01002018 /* check for out of range, based on portnum,
2019 and return result */
2020 if (portnum == 0) {
2021 if (div > 0xffff)
2022 return KEYSPAN_INVALID_BAUD_RATE;
2023 } else {
2024 if (portnum == 1) {
2025 if (div > 0xff)
2026 return KEYSPAN_INVALID_BAUD_RATE;
2027 } else
2028 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029 }
2030
2031 /* return the counter values if not NULL
2032 (port 1 will ignore retHi) */
Alan Coxdeb91682008-07-22 11:13:08 +01002033 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01002035 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002037 dev_dbg(&port->dev, "%s - %d OK.\n", __func__, baud_rate);
Alan Coxdeb91682008-07-22 11:13:08 +01002038 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039}
2040
2041static int keyspan_usa26_send_setup(struct usb_serial *serial,
2042 struct usb_serial_port *port,
2043 int reset_port)
2044{
Alan Coxdeb91682008-07-22 11:13:08 +01002045 struct keyspan_usa26_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046 struct keyspan_serial_private *s_priv;
2047 struct keyspan_port_private *p_priv;
2048 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049 struct urb *this_urb;
2050 int device_port, err;
2051
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002052 dev_dbg(&port->dev, "%s reset=%d\n", __func__, reset_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053
2054 s_priv = usb_get_serial_data(serial);
2055 p_priv = usb_get_serial_port_data(port);
2056 d_details = s_priv->device_details;
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002057 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 this_urb = p_priv->outcont_urb;
2060
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061 /* Make sure we have an urb then send the message */
2062 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002063 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 return -1;
2065 }
2066
Johan Hovold0cd782b2016-05-08 20:08:00 +02002067 dev_dbg(&port->dev, "%s - endpoint %x\n",
2068 __func__, usb_pipeendpoint(this_urb->pipe));
Rickard Strandqvistd5afce82014-05-16 17:39:13 +02002069
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07002071 Don't overwrite resend for open/close condition. */
2072 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073 p_priv->resend_cont = reset_port + 1;
2074 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002075 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002077 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078 }
2079
Alan Coxdeb91682008-07-22 11:13:08 +01002080 memset(&msg, 0, sizeof(struct keyspan_usa26_portControlMessage));
2081
2082 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083 if (p_priv->old_baud != p_priv->baud) {
2084 p_priv->old_baud = p_priv->baud;
2085 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002086 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2087 &msg.baudHi, &msg.baudLo, &msg.prescaler,
2088 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2089 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2090 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091 msg.baudLo = 0;
2092 msg.baudHi = 125; /* Values for 9600 baud */
2093 msg.prescaler = 10;
2094 }
2095 msg.setPrescaler = 0xff;
2096 }
2097
Ben Minerds2b982ab2012-07-12 00:10:16 +10002098 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099 switch (p_priv->cflag & CSIZE) {
2100 case CS5:
2101 msg.lcr |= USA_DATABITS_5;
2102 break;
2103 case CS6:
2104 msg.lcr |= USA_DATABITS_6;
2105 break;
2106 case CS7:
2107 msg.lcr |= USA_DATABITS_7;
2108 break;
2109 case CS8:
2110 msg.lcr |= USA_DATABITS_8;
2111 break;
2112 }
2113 if (p_priv->cflag & PARENB) {
2114 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002115 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002116 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117 }
2118 msg.setLcr = 0xff;
2119
2120 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2121 msg.xonFlowControl = 0;
2122 msg.setFlowControl = 0xff;
2123 msg.forwardingLength = 16;
2124 msg.xonChar = 17;
2125 msg.xoffChar = 19;
2126
2127 /* Opening port */
2128 if (reset_port == 1) {
2129 msg._txOn = 1;
2130 msg._txOff = 0;
2131 msg.txFlush = 0;
2132 msg.txBreak = 0;
2133 msg.rxOn = 1;
2134 msg.rxOff = 0;
2135 msg.rxFlush = 1;
2136 msg.rxForward = 0;
2137 msg.returnStatus = 0;
2138 msg.resetDataToggle = 0xff;
2139 }
2140
2141 /* Closing port */
2142 else if (reset_port == 2) {
2143 msg._txOn = 0;
2144 msg._txOff = 1;
2145 msg.txFlush = 0;
2146 msg.txBreak = 0;
2147 msg.rxOn = 0;
2148 msg.rxOff = 1;
2149 msg.rxFlush = 1;
2150 msg.rxForward = 0;
2151 msg.returnStatus = 0;
2152 msg.resetDataToggle = 0;
2153 }
2154
2155 /* Sending intermediate configs */
2156 else {
Alan Coxdeb91682008-07-22 11:13:08 +01002157 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 msg._txOff = 0;
2159 msg.txFlush = 0;
2160 msg.txBreak = (p_priv->break_on);
2161 msg.rxOn = 0;
2162 msg.rxOff = 0;
2163 msg.rxFlush = 0;
2164 msg.rxForward = 0;
2165 msg.returnStatus = 0;
2166 msg.resetDataToggle = 0x0;
2167 }
2168
Alan Coxdeb91682008-07-22 11:13:08 +01002169 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170 msg.setTxTriState_setRts = 0xff;
2171 msg.txTriState_rts = p_priv->rts_state;
2172
2173 msg.setHskoa_setDtr = 0xff;
2174 msg.hskoa_dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002175
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01002177 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2178
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 /* send the data out the device on control endpoint */
2180 this_urb->transfer_buffer_length = sizeof(msg);
2181
Alan Coxdeb91682008-07-22 11:13:08 +01002182 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2183 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002184 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002185 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186}
2187
2188static int keyspan_usa28_send_setup(struct usb_serial *serial,
2189 struct usb_serial_port *port,
2190 int reset_port)
2191{
Alan Coxdeb91682008-07-22 11:13:08 +01002192 struct keyspan_usa28_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 struct keyspan_serial_private *s_priv;
2194 struct keyspan_port_private *p_priv;
2195 const struct keyspan_device_details *d_details;
2196 struct urb *this_urb;
2197 int device_port, err;
2198
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199 s_priv = usb_get_serial_data(serial);
2200 p_priv = usb_get_serial_port_data(port);
2201 d_details = s_priv->device_details;
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002202 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203
2204 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01002205 this_urb = p_priv->outcont_urb;
2206 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002207 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 return -1;
2209 }
2210
2211 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07002212 Don't overwrite resend for open/close condition. */
2213 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 p_priv->resend_cont = reset_port + 1;
2215 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002216 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002218 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219 }
2220
Alan Coxdeb91682008-07-22 11:13:08 +01002221 memset(&msg, 0, sizeof(struct keyspan_usa28_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222
2223 msg.setBaudRate = 1;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002224 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2225 &msg.baudHi, &msg.baudLo, NULL,
2226 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2227 dev_dbg(&port->dev, "%s - Invalid baud rate requested %d.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01002228 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229 msg.baudLo = 0xff;
2230 msg.baudHi = 0xb2; /* Values for 9600 baud */
2231 }
2232
2233 /* If parity is enabled, we must calculate it ourselves. */
2234 msg.parity = 0; /* XXX for now */
2235
2236 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2237 msg.xonFlowControl = 0;
2238
Alan Coxdeb91682008-07-22 11:13:08 +01002239 /* Do handshaking outputs, DTR is inverted relative to RTS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240 msg.rts = p_priv->rts_state;
2241 msg.dtr = p_priv->dtr_state;
2242
2243 msg.forwardingLength = 16;
2244 msg.forwardMs = 10;
2245 msg.breakThreshold = 45;
2246 msg.xonChar = 17;
2247 msg.xoffChar = 19;
2248
2249 /*msg.returnStatus = 1;
2250 msg.resetDataToggle = 0xff;*/
2251 /* Opening port */
2252 if (reset_port == 1) {
2253 msg._txOn = 1;
2254 msg._txOff = 0;
2255 msg.txFlush = 0;
2256 msg.txForceXoff = 0;
2257 msg.txBreak = 0;
2258 msg.rxOn = 1;
2259 msg.rxOff = 0;
2260 msg.rxFlush = 1;
2261 msg.rxForward = 0;
2262 msg.returnStatus = 0;
2263 msg.resetDataToggle = 0xff;
2264 }
2265 /* Closing port */
2266 else if (reset_port == 2) {
2267 msg._txOn = 0;
2268 msg._txOff = 1;
2269 msg.txFlush = 0;
2270 msg.txForceXoff = 0;
2271 msg.txBreak = 0;
2272 msg.rxOn = 0;
2273 msg.rxOff = 1;
2274 msg.rxFlush = 1;
2275 msg.rxForward = 0;
2276 msg.returnStatus = 0;
2277 msg.resetDataToggle = 0;
2278 }
2279 /* Sending intermediate configs */
2280 else {
Alan Coxdeb91682008-07-22 11:13:08 +01002281 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282 msg._txOff = 0;
2283 msg.txFlush = 0;
2284 msg.txForceXoff = 0;
2285 msg.txBreak = (p_priv->break_on);
2286 msg.rxOn = 0;
2287 msg.rxOff = 0;
2288 msg.rxFlush = 0;
2289 msg.rxForward = 0;
2290 msg.returnStatus = 0;
2291 msg.resetDataToggle = 0x0;
2292 }
2293
2294 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01002295 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296
2297 /* send the data out the device on control endpoint */
2298 this_urb->transfer_buffer_length = sizeof(msg);
2299
Alan Coxdeb91682008-07-22 11:13:08 +01002300 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2301 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002302 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303
Alan Coxa5b6f602008-04-08 17:16:06 +01002304 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305}
2306
2307static int keyspan_usa49_send_setup(struct usb_serial *serial,
2308 struct usb_serial_port *port,
2309 int reset_port)
2310{
Lucy McCoy0ca12682007-05-18 12:10:41 -07002311 struct keyspan_usa49_portControlMessage msg;
2312 struct usb_ctrlrequest *dr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313 struct keyspan_serial_private *s_priv;
2314 struct keyspan_port_private *p_priv;
2315 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316 struct urb *this_urb;
2317 int err, device_port;
2318
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319 s_priv = usb_get_serial_data(serial);
2320 p_priv = usb_get_serial_port_data(port);
2321 d_details = s_priv->device_details;
2322
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323 this_urb = s_priv->glocont_urb;
2324
Lucy McCoy0ca12682007-05-18 12:10:41 -07002325 /* Work out which port within the device is being setup */
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002326 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05302328 /* Make sure we have an urb then send the message */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329 if (this_urb == NULL) {
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002330 dev_dbg(&port->dev, "%s - oops no urb for port.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331 return -1;
2332 }
2333
Johan Hovold0cd782b2016-05-08 20:08:00 +02002334 dev_dbg(&port->dev, "%s - endpoint %x (%d)\n",
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002335 __func__, usb_pipeendpoint(this_urb->pipe), device_port);
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05302336
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07002338 Don't overwrite resend for open/close condition. */
2339 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340 p_priv->resend_cont = reset_port + 1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002341
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002343 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002345 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346 }
2347
Alan Coxdeb91682008-07-22 11:13:08 +01002348 memset(&msg, 0, sizeof(struct keyspan_usa49_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 msg.portNumber = device_port;
Alan Coxdeb91682008-07-22 11:13:08 +01002351
2352 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353 if (p_priv->old_baud != p_priv->baud) {
2354 p_priv->old_baud = p_priv->baud;
2355 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002356 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2357 &msg.baudHi, &msg.baudLo, &msg.prescaler,
2358 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2359 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2360 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361 msg.baudLo = 0;
2362 msg.baudHi = 125; /* Values for 9600 baud */
2363 msg.prescaler = 10;
2364 }
Alan Coxdeb91682008-07-22 11:13:08 +01002365 /* msg.setPrescaler = 0xff; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366 }
2367
Ben Minerds2b982ab2012-07-12 00:10:16 +10002368 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369 switch (p_priv->cflag & CSIZE) {
2370 case CS5:
2371 msg.lcr |= USA_DATABITS_5;
2372 break;
2373 case CS6:
2374 msg.lcr |= USA_DATABITS_6;
2375 break;
2376 case CS7:
2377 msg.lcr |= USA_DATABITS_7;
2378 break;
2379 case CS8:
2380 msg.lcr |= USA_DATABITS_8;
2381 break;
2382 }
2383 if (p_priv->cflag & PARENB) {
2384 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002385 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002386 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 }
2388 msg.setLcr = 0xff;
2389
2390 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2391 msg.xonFlowControl = 0;
2392 msg.setFlowControl = 0xff;
Alan Coxdeb91682008-07-22 11:13:08 +01002393
Linus Torvalds1da177e2005-04-16 15:20:36 -07002394 msg.forwardingLength = 16;
2395 msg.xonChar = 17;
2396 msg.xoffChar = 19;
2397
Alan Coxdeb91682008-07-22 11:13:08 +01002398 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 if (reset_port == 1) {
2400 msg._txOn = 1;
2401 msg._txOff = 0;
2402 msg.txFlush = 0;
2403 msg.txBreak = 0;
2404 msg.rxOn = 1;
2405 msg.rxOff = 0;
2406 msg.rxFlush = 1;
2407 msg.rxForward = 0;
2408 msg.returnStatus = 0;
2409 msg.resetDataToggle = 0xff;
2410 msg.enablePort = 1;
2411 msg.disablePort = 0;
2412 }
2413 /* Closing port */
2414 else if (reset_port == 2) {
2415 msg._txOn = 0;
2416 msg._txOff = 1;
2417 msg.txFlush = 0;
2418 msg.txBreak = 0;
2419 msg.rxOn = 0;
2420 msg.rxOff = 1;
2421 msg.rxFlush = 1;
2422 msg.rxForward = 0;
2423 msg.returnStatus = 0;
2424 msg.resetDataToggle = 0;
2425 msg.enablePort = 0;
2426 msg.disablePort = 1;
2427 }
2428 /* Sending intermediate configs */
2429 else {
Alan Coxdeb91682008-07-22 11:13:08 +01002430 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431 msg._txOff = 0;
2432 msg.txFlush = 0;
2433 msg.txBreak = (p_priv->break_on);
2434 msg.rxOn = 0;
2435 msg.rxOff = 0;
2436 msg.rxFlush = 0;
2437 msg.rxForward = 0;
2438 msg.returnStatus = 0;
2439 msg.resetDataToggle = 0x0;
2440 msg.enablePort = 0;
2441 msg.disablePort = 0;
2442 }
2443
Alan Coxdeb91682008-07-22 11:13:08 +01002444 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445 msg.setRts = 0xff;
2446 msg.rts = p_priv->rts_state;
2447
2448 msg.setDtr = 0xff;
2449 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002450
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451 p_priv->resend_cont = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452
Alan Coxdeb91682008-07-22 11:13:08 +01002453 /* if the device is a 49wg, we send control message on usb
2454 control EP 0 */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002455
2456 if (d_details->product_id == keyspan_usa49wg_product_id) {
2457 dr = (void *)(s_priv->ctrl_buf);
2458 dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT;
Mathieu OTHACEHE64248392016-02-04 19:01:30 +01002459 dr->bRequest = 0xB0; /* 49wg control message */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002460 dr->wValue = 0;
2461 dr->wIndex = 0;
2462 dr->wLength = cpu_to_le16(sizeof(msg));
2463
Alan Coxdeb91682008-07-22 11:13:08 +01002464 memcpy(s_priv->glocont_buf, &msg, sizeof(msg));
Lucy McCoy0ca12682007-05-18 12:10:41 -07002465
Alan Coxdeb91682008-07-22 11:13:08 +01002466 usb_fill_control_urb(this_urb, serial->dev,
2467 usb_sndctrlpipe(serial->dev, 0),
2468 (unsigned char *)dr, s_priv->glocont_buf,
2469 sizeof(msg), usa49_glocont_callback, serial);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002470
2471 } else {
2472 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Alan Coxdeb91682008-07-22 11:13:08 +01002473
Lucy McCoy0ca12682007-05-18 12:10:41 -07002474 /* send the data out the device on control endpoint */
2475 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002476 }
Alan Coxdeb91682008-07-22 11:13:08 +01002477 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2478 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002479 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480
Alan Coxa5b6f602008-04-08 17:16:06 +01002481 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482}
2483
2484static int keyspan_usa90_send_setup(struct usb_serial *serial,
2485 struct usb_serial_port *port,
2486 int reset_port)
2487{
Alan Coxdeb91682008-07-22 11:13:08 +01002488 struct keyspan_usa90_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489 struct keyspan_serial_private *s_priv;
2490 struct keyspan_port_private *p_priv;
2491 const struct keyspan_device_details *d_details;
2492 struct urb *this_urb;
2493 int err;
2494 u8 prescaler;
2495
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496 s_priv = usb_get_serial_data(serial);
2497 p_priv = usb_get_serial_port_data(port);
2498 d_details = s_priv->device_details;
2499
2500 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01002501 this_urb = p_priv->outcont_urb;
2502 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002503 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504 return -1;
2505 }
2506
2507 /* Save reset port val for resend.
2508 Don't overwrite resend for open/close condition. */
2509 if ((reset_port + 1) > p_priv->resend_cont)
2510 p_priv->resend_cont = reset_port + 1;
2511 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002512 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002513 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002514 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515 }
2516
Alan Coxdeb91682008-07-22 11:13:08 +01002517 memset(&msg, 0, sizeof(struct keyspan_usa90_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002518
Alan Coxdeb91682008-07-22 11:13:08 +01002519 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520 if (p_priv->old_baud != p_priv->baud) {
2521 p_priv->old_baud = p_priv->baud;
2522 msg.setClocking = 0x01;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002523 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2524 &msg.baudHi, &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) {
2525 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2526 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527 p_priv->baud = 9600;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002528 d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529 &msg.baudHi, &msg.baudLo, &prescaler, 0);
2530 }
2531 msg.setRxMode = 1;
2532 msg.setTxMode = 1;
2533 }
2534
2535 /* modes must always be correctly specified */
Alan Coxdeb91682008-07-22 11:13:08 +01002536 if (p_priv->baud > 57600) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537 msg.rxMode = RXMODE_DMA;
2538 msg.txMode = TXMODE_DMA;
Alan Coxdeb91682008-07-22 11:13:08 +01002539 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540 msg.rxMode = RXMODE_BYHAND;
2541 msg.txMode = TXMODE_BYHAND;
2542 }
2543
Ben Minerds2b982ab2012-07-12 00:10:16 +10002544 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545 switch (p_priv->cflag & CSIZE) {
2546 case CS5:
2547 msg.lcr |= USA_DATABITS_5;
2548 break;
2549 case CS6:
2550 msg.lcr |= USA_DATABITS_6;
2551 break;
2552 case CS7:
2553 msg.lcr |= USA_DATABITS_7;
2554 break;
2555 case CS8:
2556 msg.lcr |= USA_DATABITS_8;
2557 break;
2558 }
2559 if (p_priv->cflag & PARENB) {
2560 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002561 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002562 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563 }
2564 if (p_priv->old_cflag != p_priv->cflag) {
2565 p_priv->old_cflag = p_priv->cflag;
2566 msg.setLcr = 0x01;
2567 }
2568
2569 if (p_priv->flow_control == flow_cts)
2570 msg.txFlowControl = TXFLOW_CTS;
2571 msg.setTxFlowControl = 0x01;
2572 msg.setRxFlowControl = 0x01;
Alan Coxdeb91682008-07-22 11:13:08 +01002573
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574 msg.rxForwardingLength = 16;
Alan Coxdeb91682008-07-22 11:13:08 +01002575 msg.rxForwardingTimeout = 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576 msg.txAckSetting = 0;
2577 msg.xonChar = 17;
2578 msg.xoffChar = 19;
2579
Alan Coxdeb91682008-07-22 11:13:08 +01002580 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581 if (reset_port == 1) {
2582 msg.portEnabled = 1;
2583 msg.rxFlush = 1;
2584 msg.txBreak = (p_priv->break_on);
2585 }
2586 /* Closing port */
Alan Coxdeb91682008-07-22 11:13:08 +01002587 else if (reset_port == 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588 msg.portEnabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589 /* Sending intermediate configs */
2590 else {
Alan Stern1f871582010-02-17 10:05:47 -05002591 msg.portEnabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592 msg.txBreak = (p_priv->break_on);
2593 }
2594
Alan Coxdeb91682008-07-22 11:13:08 +01002595 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596 msg.setRts = 0x01;
2597 msg.rts = p_priv->rts_state;
2598
2599 msg.setDtr = 0x01;
2600 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002601
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01002603 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2604
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605 /* send the data out the device on control endpoint */
2606 this_urb->transfer_buffer_length = sizeof(msg);
2607
Alan Coxdeb91682008-07-22 11:13:08 +01002608 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2609 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002610 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002611 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612}
2613
Lucy McCoy0ca12682007-05-18 12:10:41 -07002614static int keyspan_usa67_send_setup(struct usb_serial *serial,
2615 struct usb_serial_port *port,
2616 int reset_port)
2617{
2618 struct keyspan_usa67_portControlMessage msg;
2619 struct keyspan_serial_private *s_priv;
2620 struct keyspan_port_private *p_priv;
2621 const struct keyspan_device_details *d_details;
2622 struct urb *this_urb;
2623 int err, device_port;
2624
Lucy McCoy0ca12682007-05-18 12:10:41 -07002625 s_priv = usb_get_serial_data(serial);
2626 p_priv = usb_get_serial_port_data(port);
2627 d_details = s_priv->device_details;
2628
2629 this_urb = s_priv->glocont_urb;
2630
2631 /* Work out which port within the device is being setup */
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002632 device_port = port->port_number;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002633
2634 /* Make sure we have an urb then send the message */
2635 if (this_urb == NULL) {
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002636 dev_dbg(&port->dev, "%s - oops no urb for port.\n", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002637 return -1;
2638 }
2639
2640 /* Save reset port val for resend.
2641 Don't overwrite resend for open/close condition. */
2642 if ((reset_port + 1) > p_priv->resend_cont)
2643 p_priv->resend_cont = reset_port + 1;
2644 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002645 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002646 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002647 return -1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002648 }
2649
2650 memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
2651
2652 msg.port = device_port;
2653
2654 /* Only set baud rate if it's changed */
2655 if (p_priv->old_baud != p_priv->baud) {
2656 p_priv->old_baud = p_priv->baud;
2657 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002658 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2659 &msg.baudHi, &msg.baudLo, &msg.prescaler,
2660 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2661 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2662 __func__, p_priv->baud);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002663 msg.baudLo = 0;
2664 msg.baudHi = 125; /* Values for 9600 baud */
2665 msg.prescaler = 10;
2666 }
2667 msg.setPrescaler = 0xff;
2668 }
2669
2670 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
2671 switch (p_priv->cflag & CSIZE) {
2672 case CS5:
2673 msg.lcr |= USA_DATABITS_5;
2674 break;
2675 case CS6:
2676 msg.lcr |= USA_DATABITS_6;
2677 break;
2678 case CS7:
2679 msg.lcr |= USA_DATABITS_7;
2680 break;
2681 case CS8:
2682 msg.lcr |= USA_DATABITS_8;
2683 break;
2684 }
2685 if (p_priv->cflag & PARENB) {
2686 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002687 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002688 USA_PARITY_ODD : USA_PARITY_EVEN;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002689 }
2690 msg.setLcr = 0xff;
2691
2692 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2693 msg.xonFlowControl = 0;
2694 msg.setFlowControl = 0xff;
2695 msg.forwardingLength = 16;
2696 msg.xonChar = 17;
2697 msg.xoffChar = 19;
2698
2699 if (reset_port == 1) {
2700 /* Opening port */
2701 msg._txOn = 1;
2702 msg._txOff = 0;
2703 msg.txFlush = 0;
2704 msg.txBreak = 0;
2705 msg.rxOn = 1;
2706 msg.rxOff = 0;
2707 msg.rxFlush = 1;
2708 msg.rxForward = 0;
2709 msg.returnStatus = 0;
2710 msg.resetDataToggle = 0xff;
2711 } else if (reset_port == 2) {
2712 /* Closing port */
2713 msg._txOn = 0;
2714 msg._txOff = 1;
2715 msg.txFlush = 0;
2716 msg.txBreak = 0;
2717 msg.rxOn = 0;
2718 msg.rxOff = 1;
2719 msg.rxFlush = 1;
2720 msg.rxForward = 0;
2721 msg.returnStatus = 0;
2722 msg.resetDataToggle = 0;
2723 } else {
2724 /* Sending intermediate configs */
Alan Coxdeb91682008-07-22 11:13:08 +01002725 msg._txOn = (!p_priv->break_on);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002726 msg._txOff = 0;
2727 msg.txFlush = 0;
2728 msg.txBreak = (p_priv->break_on);
2729 msg.rxOn = 0;
2730 msg.rxOff = 0;
2731 msg.rxFlush = 0;
2732 msg.rxForward = 0;
2733 msg.returnStatus = 0;
2734 msg.resetDataToggle = 0x0;
2735 }
2736
2737 /* Do handshaking outputs */
2738 msg.setTxTriState_setRts = 0xff;
2739 msg.txTriState_rts = p_priv->rts_state;
2740
2741 msg.setHskoa_setDtr = 0xff;
2742 msg.hskoa_dtr = p_priv->dtr_state;
2743
2744 p_priv->resend_cont = 0;
2745
2746 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2747
2748 /* send the data out the device on control endpoint */
2749 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002750
2751 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2752 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002753 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002754 return 0;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002755}
2756
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
2758{
2759 struct usb_serial *serial = port->serial;
2760 struct keyspan_serial_private *s_priv;
2761 const struct keyspan_device_details *d_details;
2762
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763 s_priv = usb_get_serial_data(serial);
2764 d_details = s_priv->device_details;
2765
2766 switch (d_details->msg_format) {
2767 case msg_usa26:
2768 keyspan_usa26_send_setup(serial, port, reset_port);
2769 break;
2770 case msg_usa28:
2771 keyspan_usa28_send_setup(serial, port, reset_port);
2772 break;
2773 case msg_usa49:
2774 keyspan_usa49_send_setup(serial, port, reset_port);
2775 break;
2776 case msg_usa90:
2777 keyspan_usa90_send_setup(serial, port, reset_port);
2778 break;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002779 case msg_usa67:
2780 keyspan_usa67_send_setup(serial, port, reset_port);
2781 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002782 }
2783}
2784
2785
2786/* Gets called by the "real" driver (ie once firmware is loaded
2787 and renumeration has taken place. */
Alan Coxdeb91682008-07-22 11:13:08 +01002788static int keyspan_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789{
2790 int i, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792 const struct keyspan_device_details *d_details;
2793
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794 for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
Alan Coxdeb91682008-07-22 11:13:08 +01002795 if (d_details->product_id ==
2796 le16_to_cpu(serial->dev->descriptor.idProduct))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797 break;
2798 if (d_details == NULL) {
Alan Coxdeb91682008-07-22 11:13:08 +01002799 dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
2800 __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
Johan Hovoldff8a43c2013-08-13 13:27:35 +02002801 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802 }
2803
2804 /* Setup private data for serial driver */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01002805 s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
Johan Hovold10c642d2013-12-29 19:22:56 +01002806 if (!s_priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808
Johan Hovold2fcd1c92013-08-13 13:27:36 +02002809 s_priv->instat_buf = kzalloc(INSTAT_BUFLEN, GFP_KERNEL);
2810 if (!s_priv->instat_buf)
2811 goto err_instat_buf;
2812
2813 s_priv->indat_buf = kzalloc(INDAT49W_BUFLEN, GFP_KERNEL);
2814 if (!s_priv->indat_buf)
2815 goto err_indat_buf;
2816
2817 s_priv->glocont_buf = kzalloc(GLOCONT_BUFLEN, GFP_KERNEL);
2818 if (!s_priv->glocont_buf)
2819 goto err_glocont_buf;
2820
2821 s_priv->ctrl_buf = kzalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
2822 if (!s_priv->ctrl_buf)
2823 goto err_ctrl_buf;
2824
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825 s_priv->device_details = d_details;
2826 usb_set_serial_data(serial, s_priv);
2827
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828 keyspan_setup_urbs(serial);
2829
Lucy McCoy0ca12682007-05-18 12:10:41 -07002830 if (s_priv->instat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002831 err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
2832 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002833 dev_dbg(&serial->dev->dev, "%s - submit instat urb failed %d\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002834 }
2835 if (s_priv->indat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002836 err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
2837 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002838 dev_dbg(&serial->dev->dev, "%s - submit indat urb failed %d\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002839 }
Alan Coxdeb91682008-07-22 11:13:08 +01002840
Alan Coxa5b6f602008-04-08 17:16:06 +01002841 return 0;
Johan Hovold2fcd1c92013-08-13 13:27:36 +02002842
2843err_ctrl_buf:
2844 kfree(s_priv->glocont_buf);
2845err_glocont_buf:
2846 kfree(s_priv->indat_buf);
2847err_indat_buf:
2848 kfree(s_priv->instat_buf);
2849err_instat_buf:
2850 kfree(s_priv);
2851
2852 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002853}
2854
Alan Sternf9c99bb2009-06-02 11:53:55 -04002855static void keyspan_disconnect(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002856{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002857 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002858
Linus Torvalds1da177e2005-04-16 15:20:36 -07002859 s_priv = usb_get_serial_data(serial);
2860
Johan Hovold61924502016-05-08 20:07:59 +02002861 usb_kill_urb(s_priv->instat_urb);
2862 usb_kill_urb(s_priv->glocont_urb);
2863 usb_kill_urb(s_priv->indat_urb);
Alan Sternf9c99bb2009-06-02 11:53:55 -04002864}
2865
2866static void keyspan_release(struct usb_serial *serial)
2867{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002868 struct keyspan_serial_private *s_priv;
Alan Sternf9c99bb2009-06-02 11:53:55 -04002869
Alan Sternf9c99bb2009-06-02 11:53:55 -04002870 s_priv = usb_get_serial_data(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002871
Johan Hovold35be1a72016-05-08 20:07:58 +02002872 /* Make sure to unlink the URBs submitted in attach. */
2873 usb_kill_urb(s_priv->instat_urb);
2874 usb_kill_urb(s_priv->indat_urb);
2875
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002876 usb_free_urb(s_priv->instat_urb);
2877 usb_free_urb(s_priv->indat_urb);
2878 usb_free_urb(s_priv->glocont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879
Johan Hovold2fcd1c92013-08-13 13:27:36 +02002880 kfree(s_priv->ctrl_buf);
2881 kfree(s_priv->glocont_buf);
2882 kfree(s_priv->indat_buf);
2883 kfree(s_priv->instat_buf);
2884
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002885 kfree(s_priv);
2886}
2887
2888static int keyspan_port_probe(struct usb_serial_port *port)
2889{
2890 struct usb_serial *serial = port->serial;
Bjørn Morkf0e3e352012-11-10 10:13:42 +01002891 struct keyspan_serial_private *s_priv;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002892 struct keyspan_port_private *p_priv;
2893 const struct keyspan_device_details *d_details;
2894 struct callbacks *cback;
2895 int endp;
2896 int port_num;
2897 int i;
2898
2899 s_priv = usb_get_serial_data(serial);
2900 d_details = s_priv->device_details;
2901
2902 p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL);
2903 if (!p_priv)
2904 return -ENOMEM;
2905
Johan Hovoldbad41a52013-08-13 13:27:37 +02002906 for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i) {
2907 p_priv->in_buffer[i] = kzalloc(IN_BUFLEN, GFP_KERNEL);
2908 if (!p_priv->in_buffer[i])
2909 goto err_in_buffer;
2910 }
2911
2912 for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i) {
2913 p_priv->out_buffer[i] = kzalloc(OUT_BUFLEN, GFP_KERNEL);
2914 if (!p_priv->out_buffer[i])
2915 goto err_out_buffer;
2916 }
2917
2918 p_priv->inack_buffer = kzalloc(INACK_BUFLEN, GFP_KERNEL);
2919 if (!p_priv->inack_buffer)
2920 goto err_inack_buffer;
2921
2922 p_priv->outcont_buffer = kzalloc(OUTCONT_BUFLEN, GFP_KERNEL);
2923 if (!p_priv->outcont_buffer)
2924 goto err_outcont_buffer;
2925
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002926 p_priv->device_details = d_details;
2927
2928 /* Setup values for the various callback routines */
2929 cback = &keyspan_callbacks[d_details->msg_format];
2930
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002931 port_num = port->port_number;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002932
2933 /* Do indat endpoints first, once for each flip */
2934 endp = d_details->indat_endpoints[port_num];
2935 for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) {
2936 p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp,
2937 USB_DIR_IN, port,
Johan Hovoldbad41a52013-08-13 13:27:37 +02002938 p_priv->in_buffer[i],
2939 IN_BUFLEN,
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002940 cback->indat_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002941 }
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002942 /* outdat endpoints also have flip */
2943 endp = d_details->outdat_endpoints[port_num];
2944 for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) {
2945 p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp,
2946 USB_DIR_OUT, port,
Johan Hovoldbad41a52013-08-13 13:27:37 +02002947 p_priv->out_buffer[i],
2948 OUT_BUFLEN,
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002949 cback->outdat_callback);
2950 }
2951 /* inack endpoint */
2952 p_priv->inack_urb = keyspan_setup_urb(serial,
2953 d_details->inack_endpoints[port_num],
2954 USB_DIR_IN, port,
Johan Hovoldbad41a52013-08-13 13:27:37 +02002955 p_priv->inack_buffer,
2956 INACK_BUFLEN,
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002957 cback->inack_callback);
2958 /* outcont endpoint */
2959 p_priv->outcont_urb = keyspan_setup_urb(serial,
2960 d_details->outcont_endpoints[port_num],
2961 USB_DIR_OUT, port,
Johan Hovoldbad41a52013-08-13 13:27:37 +02002962 p_priv->outcont_buffer,
2963 OUTCONT_BUFLEN,
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002964 cback->outcont_callback);
2965
2966 usb_set_serial_port_data(port, p_priv);
2967
2968 return 0;
Johan Hovoldbad41a52013-08-13 13:27:37 +02002969
2970err_outcont_buffer:
2971 kfree(p_priv->inack_buffer);
2972err_inack_buffer:
2973 for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i)
2974 kfree(p_priv->out_buffer[i]);
2975err_out_buffer:
2976 for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i)
2977 kfree(p_priv->in_buffer[i]);
2978err_in_buffer:
2979 kfree(p_priv);
2980
2981 return -ENOMEM;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002982}
2983
2984static int keyspan_port_remove(struct usb_serial_port *port)
2985{
2986 struct keyspan_port_private *p_priv;
2987 int i;
2988
2989 p_priv = usb_get_serial_port_data(port);
2990
Johan Hovold61924502016-05-08 20:07:59 +02002991 usb_kill_urb(p_priv->inack_urb);
2992 usb_kill_urb(p_priv->outcont_urb);
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002993 for (i = 0; i < 2; i++) {
Johan Hovold61924502016-05-08 20:07:59 +02002994 usb_kill_urb(p_priv->in_urbs[i]);
2995 usb_kill_urb(p_priv->out_urbs[i]);
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002996 }
2997
2998 usb_free_urb(p_priv->inack_urb);
2999 usb_free_urb(p_priv->outcont_urb);
3000 for (i = 0; i < 2; i++) {
3001 usb_free_urb(p_priv->in_urbs[i]);
3002 usb_free_urb(p_priv->out_urbs[i]);
3003 }
3004
Johan Hovoldbad41a52013-08-13 13:27:37 +02003005 kfree(p_priv->outcont_buffer);
3006 kfree(p_priv->inack_buffer);
3007 for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i)
3008 kfree(p_priv->out_buffer[i]);
3009 for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i)
3010 kfree(p_priv->in_buffer[i]);
3011
Johan Hovoldf79b2d02012-10-25 10:29:15 +02003012 kfree(p_priv);
3013
3014 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015}
3016
Johan Hovoldbeabdc32017-02-15 11:09:51 +01003017/* Structs for the devices, pre and post renumeration. */
3018static struct usb_serial_driver keyspan_pre_device = {
3019 .driver = {
3020 .owner = THIS_MODULE,
3021 .name = "keyspan_no_firm",
3022 },
3023 .description = "Keyspan - (without firmware)",
3024 .id_table = keyspan_pre_ids,
3025 .num_ports = 1,
3026 .attach = keyspan_fake_startup,
3027};
3028
3029static struct usb_serial_driver keyspan_1port_device = {
3030 .driver = {
3031 .owner = THIS_MODULE,
3032 .name = "keyspan_1",
3033 },
3034 .description = "Keyspan 1 port adapter",
3035 .id_table = keyspan_1port_ids,
3036 .num_ports = 1,
3037 .open = keyspan_open,
3038 .close = keyspan_close,
3039 .dtr_rts = keyspan_dtr_rts,
3040 .write = keyspan_write,
3041 .write_room = keyspan_write_room,
3042 .set_termios = keyspan_set_termios,
3043 .break_ctl = keyspan_break_ctl,
3044 .tiocmget = keyspan_tiocmget,
3045 .tiocmset = keyspan_tiocmset,
3046 .attach = keyspan_startup,
3047 .disconnect = keyspan_disconnect,
3048 .release = keyspan_release,
3049 .port_probe = keyspan_port_probe,
3050 .port_remove = keyspan_port_remove,
3051};
3052
3053static struct usb_serial_driver keyspan_2port_device = {
3054 .driver = {
3055 .owner = THIS_MODULE,
3056 .name = "keyspan_2",
3057 },
3058 .description = "Keyspan 2 port adapter",
3059 .id_table = keyspan_2port_ids,
3060 .num_ports = 2,
3061 .open = keyspan_open,
3062 .close = keyspan_close,
3063 .dtr_rts = keyspan_dtr_rts,
3064 .write = keyspan_write,
3065 .write_room = keyspan_write_room,
3066 .set_termios = keyspan_set_termios,
3067 .break_ctl = keyspan_break_ctl,
3068 .tiocmget = keyspan_tiocmget,
3069 .tiocmset = keyspan_tiocmset,
3070 .attach = keyspan_startup,
3071 .disconnect = keyspan_disconnect,
3072 .release = keyspan_release,
3073 .port_probe = keyspan_port_probe,
3074 .port_remove = keyspan_port_remove,
3075};
3076
3077static struct usb_serial_driver keyspan_4port_device = {
3078 .driver = {
3079 .owner = THIS_MODULE,
3080 .name = "keyspan_4",
3081 },
3082 .description = "Keyspan 4 port adapter",
3083 .id_table = keyspan_4port_ids,
3084 .num_ports = 4,
3085 .open = keyspan_open,
3086 .close = keyspan_close,
3087 .dtr_rts = keyspan_dtr_rts,
3088 .write = keyspan_write,
3089 .write_room = keyspan_write_room,
3090 .set_termios = keyspan_set_termios,
3091 .break_ctl = keyspan_break_ctl,
3092 .tiocmget = keyspan_tiocmget,
3093 .tiocmset = keyspan_tiocmset,
3094 .attach = keyspan_startup,
3095 .disconnect = keyspan_disconnect,
3096 .release = keyspan_release,
3097 .port_probe = keyspan_port_probe,
3098 .port_remove = keyspan_port_remove,
3099};
3100
3101static struct usb_serial_driver * const serial_drivers[] = {
3102 &keyspan_pre_device, &keyspan_1port_device,
3103 &keyspan_2port_device, &keyspan_4port_device, NULL
3104};
3105
3106module_usb_serial_driver(serial_drivers, keyspan_ids_combined);
3107
Alan Coxdeb91682008-07-22 11:13:08 +01003108MODULE_AUTHOR(DRIVER_AUTHOR);
3109MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110MODULE_LICENSE("GPL");
3111
David Woodhouse2971c572008-05-30 14:04:03 +03003112MODULE_FIRMWARE("keyspan/usa28.fw");
3113MODULE_FIRMWARE("keyspan/usa28x.fw");
3114MODULE_FIRMWARE("keyspan/usa28xa.fw");
3115MODULE_FIRMWARE("keyspan/usa28xb.fw");
3116MODULE_FIRMWARE("keyspan/usa19.fw");
3117MODULE_FIRMWARE("keyspan/usa19qi.fw");
3118MODULE_FIRMWARE("keyspan/mpr.fw");
3119MODULE_FIRMWARE("keyspan/usa19qw.fw");
3120MODULE_FIRMWARE("keyspan/usa18x.fw");
3121MODULE_FIRMWARE("keyspan/usa19w.fw");
3122MODULE_FIRMWARE("keyspan/usa49w.fw");
3123MODULE_FIRMWARE("keyspan/usa49wlc.fw");