blob: 451759f38b57341da051d5faca57653ccab47ea2 [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);
Johan Hovold3018dd32020-01-17 10:50:25 +01001061 if (!p_priv)
1062 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063
1064 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001065 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +01001066 keyspan_usa49_send_setup(serial, port,
1067 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 break;
1069 }
1070 }
1071}
1072
1073 /* This is actually called glostat in the Keyspan
1074 doco */
David Howells7d12e782006-10-05 14:55:46 +01001075static void usa49_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076{
1077 int err;
1078 unsigned char *data = urb->transfer_buffer;
1079 struct keyspan_usa49_portStatusMessage *msg;
1080 struct usb_serial *serial;
1081 struct usb_serial_port *port;
1082 struct keyspan_port_private *p_priv;
1083 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001084 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085
Ming Leicdc97792008-02-24 18:41:47 +08001086 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001088 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +02001089 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
1090 __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 return;
1092 }
1093
Alan Coxdeb91682008-07-22 11:13:08 +01001094 if (urb->actual_length !=
1095 sizeof(struct keyspan_usa49_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001096 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 goto exit;
1098 }
1099
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 msg = (struct keyspan_usa49_portStatusMessage *)data;
1101
Alan Coxdeb91682008-07-22 11:13:08 +01001102 /* Check port number from message and retrieve private data */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 if (msg->portNumber >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001104 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
1105 __func__, msg->portNumber);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 goto exit;
1107 }
1108 port = serial->port[msg->portNumber];
1109 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb5122232014-12-22 18:39:39 +01001110 if (!p_priv)
1111 goto resubmit;
Alan Coxdeb91682008-07-22 11:13:08 +01001112
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 /* Update handshaking pin state information */
1114 old_dcd_state = p_priv->dcd_state;
1115 p_priv->cts_state = ((msg->cts) ? 1 : 0);
1116 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
1117 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
1118 p_priv->ri_state = ((msg->ri) ? 1 : 0);
1119
Jiri Slabyaa27a092013-03-07 13:12:30 +01001120 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
1121 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb5122232014-12-22 18:39:39 +01001122resubmit:
Alan Coxdeb91682008-07-22 11:13:08 +01001123 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +01001124 err = usb_submit_urb(urb, GFP_ATOMIC);
1125 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001126 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127exit: ;
1128}
1129
David Howells7d12e782006-10-05 14:55:46 +01001130static void usa49_inack_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132}
1133
David Howells7d12e782006-10-05 14:55:46 +01001134static void usa49_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135{
1136 int i, err;
1137 int endpoint;
1138 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001140 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142 endpoint = usb_pipeendpoint(urb->pipe);
1143
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001144 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +02001145 dev_dbg(&urb->dev->dev, "%s - nonzero status %d on endpoint %x\n",
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001146 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 return;
1148 }
1149
Ming Leicdc97792008-02-24 18:41:47 +08001150 port = urb->context;
Jiri Slaby2e124b42013-01-03 15:53:06 +01001151 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 /* 0x80 bit is error flag */
1153 if ((data[0] & 0x80) == 0) {
1154 /* no error on any byte */
Jiri Slaby05c7cd32013-01-03 15:53:04 +01001155 tty_insert_flip_string(&port->port, data + 1,
Alan Coxf035a8a2008-07-22 11:13:32 +01001156 urb->actual_length - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 } else {
1158 /* some bytes had errors, every byte has status */
1159 for (i = 0; i + 1 < urb->actual_length; i += 2) {
Johan Hovold5d1678a2014-11-18 11:25:19 +01001160 int stat = data[i];
1161 int flag = TTY_NORMAL;
1162
1163 if (stat & RXERROR_OVERRUN) {
1164 tty_insert_flip_char(&port->port, 0,
1165 TTY_OVERRUN);
1166 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 /* XXX should handle break (0x10) */
Johan Hovold5d1678a2014-11-18 11:25:19 +01001168 if (stat & RXERROR_PARITY)
1169 flag = TTY_PARITY;
1170 else if (stat & RXERROR_FRAMING)
1171 flag = TTY_FRAME;
1172
Jiri Slaby92a19f92013-01-03 15:53:03 +01001173 tty_insert_flip_char(&port->port, data[i+1],
1174 flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 }
1176 }
Jiri Slaby2e124b42013-01-03 15:53:06 +01001177 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 }
Alan Coxdeb91682008-07-22 11:13:08 +01001179
1180 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -05001181 err = usb_submit_urb(urb, GFP_ATOMIC);
1182 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001183 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184}
1185
Lucy McCoy0ca12682007-05-18 12:10:41 -07001186static void usa49wg_indat_callback(struct urb *urb)
1187{
1188 int i, len, x, err;
1189 struct usb_serial *serial;
1190 struct usb_serial_port *port;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001191 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001192 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001193
Lucy McCoy0ca12682007-05-18 12:10:41 -07001194 serial = urb->context;
1195
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001196 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +02001197 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
1198 __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001199 return;
1200 }
1201
1202 /* inbound data is in the form P#, len, status, data */
1203 i = 0;
1204 len = 0;
1205
Dan Carpenter6a3ae842013-04-05 08:42:41 +03001206 while (i < urb->actual_length) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07001207
Dan Carpenter6a3ae842013-04-05 08:42:41 +03001208 /* Check port number from message */
1209 if (data[i] >= serial->num_ports) {
1210 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
1211 __func__, data[i]);
1212 return;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001213 }
Dan Carpenter6a3ae842013-04-05 08:42:41 +03001214 port = serial->port[data[i++]];
1215 len = data[i++];
1216
1217 /* 0x80 bit is error flag */
1218 if ((data[i] & 0x80) == 0) {
1219 /* no error on any byte */
1220 i++;
Dan Carpenter01a60e72013-04-05 08:43:20 +03001221 for (x = 1; x < len && i < urb->actual_length; ++x)
Dan Carpenter6a3ae842013-04-05 08:42:41 +03001222 tty_insert_flip_char(&port->port,
1223 data[i++], 0);
1224 } else {
1225 /*
1226 * some bytes had errors, every byte has status
1227 */
Dan Carpenter01a60e72013-04-05 08:43:20 +03001228 for (x = 0; x + 1 < len &&
1229 i + 1 < urb->actual_length; x += 2) {
Johan Hovold5d1678a2014-11-18 11:25:19 +01001230 int stat = data[i];
1231 int flag = TTY_NORMAL;
Dan Carpenter6a3ae842013-04-05 08:42:41 +03001232
Johan Hovold5d1678a2014-11-18 11:25:19 +01001233 if (stat & RXERROR_OVERRUN) {
1234 tty_insert_flip_char(&port->port, 0,
1235 TTY_OVERRUN);
1236 }
Dan Carpenter6a3ae842013-04-05 08:42:41 +03001237 /* XXX should handle break (0x10) */
Johan Hovold5d1678a2014-11-18 11:25:19 +01001238 if (stat & RXERROR_PARITY)
1239 flag = TTY_PARITY;
1240 else if (stat & RXERROR_FRAMING)
1241 flag = TTY_FRAME;
1242
Dan Carpenter6a3ae842013-04-05 08:42:41 +03001243 tty_insert_flip_char(&port->port, data[i+1],
1244 flag);
1245 i += 2;
1246 }
1247 }
1248 tty_flip_buffer_push(&port->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001249 }
1250
1251 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -07001252 err = usb_submit_urb(urb, GFP_ATOMIC);
1253 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001254 dev_dbg(&urb->dev->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001255}
1256
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257/* not used, usa-49 doesn't have per-port control endpoints */
Lucy McCoy0ca12682007-05-18 12:10:41 -07001258static void usa49_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260}
1261
Lucy McCoy0ca12682007-05-18 12:10:41 -07001262static void usa90_indat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263{
1264 int i, err;
1265 int endpoint;
1266 struct usb_serial_port *port;
1267 struct keyspan_port_private *p_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 unsigned char *data = urb->transfer_buffer;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001269 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 endpoint = usb_pipeendpoint(urb->pipe);
1272
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001273 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +02001274 dev_dbg(&urb->dev->dev, "%s - nonzero status %d on endpoint %x\n",
1275 __func__, status, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 return;
1277 }
1278
Ming Leicdc97792008-02-24 18:41:47 +08001279 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 p_priv = usb_get_serial_port_data(port);
1281
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 if (urb->actual_length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283 /* if current mode is DMA, looks like usa28 format
Alan Coxdeb91682008-07-22 11:13:08 +01001284 otherwise looks like usa26 data format */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285
Alan Coxf035a8a2008-07-22 11:13:32 +01001286 if (p_priv->baud > 57600)
Jiri Slaby05c7cd32013-01-03 15:53:04 +01001287 tty_insert_flip_string(&port->port, data,
1288 urb->actual_length);
Alan Coxf035a8a2008-07-22 11:13:32 +01001289 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 /* 0x80 bit is error flag */
1291 if ((data[0] & 0x80) == 0) {
Alan Coxdeb91682008-07-22 11:13:08 +01001292 /* no errors on individual bytes, only
1293 possible overrun err*/
Johan Hovold855515a2014-11-18 11:25:20 +01001294 if (data[0] & RXERROR_OVERRUN) {
1295 tty_insert_flip_char(&port->port, 0,
1296 TTY_OVERRUN);
1297 }
Alan Coxdeb91682008-07-22 11:13:08 +01001298 for (i = 1; i < urb->actual_length ; ++i)
Jiri Slaby92a19f92013-01-03 15:53:03 +01001299 tty_insert_flip_char(&port->port,
Johan Hovold855515a2014-11-18 11:25:20 +01001300 data[i], TTY_NORMAL);
Alan Coxdeb91682008-07-22 11:13:08 +01001301 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 /* some bytes had errors, every byte has status */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001303 dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 for (i = 0; i + 1 < urb->actual_length; i += 2) {
Johan Hovold5d1678a2014-11-18 11:25:19 +01001305 int stat = data[i];
1306 int flag = TTY_NORMAL;
1307
1308 if (stat & RXERROR_OVERRUN) {
1309 tty_insert_flip_char(
1310 &port->port, 0,
1311 TTY_OVERRUN);
1312 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313 /* XXX should handle break (0x10) */
Johan Hovold5d1678a2014-11-18 11:25:19 +01001314 if (stat & RXERROR_PARITY)
1315 flag = TTY_PARITY;
1316 else if (stat & RXERROR_FRAMING)
1317 flag = TTY_FRAME;
1318
Jiri Slaby92a19f92013-01-03 15:53:03 +01001319 tty_insert_flip_char(&port->port,
1320 data[i+1], flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 }
1322 }
1323 }
Jiri Slaby2e124b42013-01-03 15:53:06 +01001324 tty_flip_buffer_push(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 }
Alan Coxdeb91682008-07-22 11:13:08 +01001326
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 /* Resubmit urb so we continue receiving */
Alan Stern1f871582010-02-17 10:05:47 -05001328 err = usb_submit_urb(urb, GFP_ATOMIC);
1329 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001330 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331}
1332
1333
David Howells7d12e782006-10-05 14:55:46 +01001334static void usa90_instat_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335{
1336 unsigned char *data = urb->transfer_buffer;
1337 struct keyspan_usa90_portStatusMessage *msg;
1338 struct usb_serial *serial;
1339 struct usb_serial_port *port;
1340 struct keyspan_port_private *p_priv;
1341 int old_dcd_state, err;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001342 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343
Ming Leicdc97792008-02-24 18:41:47 +08001344 serial = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001346 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +02001347 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
1348 __func__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 return;
1350 }
1351 if (urb->actual_length < 14) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001352 dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 goto exit;
1354 }
1355
1356 msg = (struct keyspan_usa90_portStatusMessage *)data;
1357
1358 /* Now do something useful with the data */
1359
1360 port = serial->port[0];
1361 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb5122232014-12-22 18:39:39 +01001362 if (!p_priv)
1363 goto resubmit;
Alan Coxdeb91682008-07-22 11:13:08 +01001364
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 /* Update handshaking pin state information */
1366 old_dcd_state = p_priv->dcd_state;
1367 p_priv->cts_state = ((msg->cts) ? 1 : 0);
1368 p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
1369 p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
1370 p_priv->ri_state = ((msg->ri) ? 1 : 0);
1371
Jiri Slabyaa27a092013-03-07 13:12:30 +01001372 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
1373 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb5122232014-12-22 18:39:39 +01001374resubmit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 /* Resubmit urb so we continue receiving */
Alan Coxdeb91682008-07-22 11:13:08 +01001376 err = usb_submit_urb(urb, GFP_ATOMIC);
1377 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001378 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379exit:
1380 ;
1381}
1382
David Howells7d12e782006-10-05 14:55:46 +01001383static void usa90_outcont_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384{
1385 struct usb_serial_port *port;
1386 struct keyspan_port_private *p_priv;
1387
Ming Leicdc97792008-02-24 18:41:47 +08001388 port = urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 p_priv = usb_get_serial_port_data(port);
1390
1391 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001392 dev_dbg(&urb->dev->dev, "%s - sending setup\n", __func__);
Alan Coxdeb91682008-07-22 11:13:08 +01001393 keyspan_usa90_send_setup(port->serial, port,
1394 p_priv->resend_cont - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 }
1396}
1397
Lucy McCoy0ca12682007-05-18 12:10:41 -07001398/* Status messages from the 28xg */
1399static void usa67_instat_callback(struct urb *urb)
1400{
1401 int err;
1402 unsigned char *data = urb->transfer_buffer;
1403 struct keyspan_usa67_portStatusMessage *msg;
1404 struct usb_serial *serial;
1405 struct usb_serial_port *port;
1406 struct keyspan_port_private *p_priv;
1407 int old_dcd_state;
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001408 int status = urb->status;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001409
Lucy McCoy0ca12682007-05-18 12:10:41 -07001410 serial = urb->context;
1411
Greg Kroah-Hartman95b93452007-06-15 15:44:13 -07001412 if (status) {
Johan Hovold0cd782b2016-05-08 20:08:00 +02001413 dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
1414 __func__, status);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001415 return;
1416 }
1417
Alan Coxdeb91682008-07-22 11:13:08 +01001418 if (urb->actual_length !=
1419 sizeof(struct keyspan_usa67_portStatusMessage)) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001420 dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001421 return;
1422 }
1423
1424
1425 /* Now do something useful with the data */
1426 msg = (struct keyspan_usa67_portStatusMessage *)data;
1427
1428 /* Check port number from message and retrieve private data */
1429 if (msg->port >= serial->num_ports) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001430 dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001431 return;
1432 }
1433
1434 port = serial->port[msg->port];
1435 p_priv = usb_get_serial_port_data(port);
Johan Hovoldb5122232014-12-22 18:39:39 +01001436 if (!p_priv)
1437 goto resubmit;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001438
1439 /* Update handshaking pin state information */
1440 old_dcd_state = p_priv->dcd_state;
1441 p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
1442 p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
1443
Jiri Slabyaa27a092013-03-07 13:12:30 +01001444 if (old_dcd_state != p_priv->dcd_state && old_dcd_state)
1445 tty_port_tty_hangup(&port->port, true);
Johan Hovoldb5122232014-12-22 18:39:39 +01001446resubmit:
Lucy McCoy0ca12682007-05-18 12:10:41 -07001447 /* Resubmit urb so we continue receiving */
Lucy McCoy0ca12682007-05-18 12:10:41 -07001448 err = usb_submit_urb(urb, GFP_ATOMIC);
1449 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001450 dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001451}
1452
1453static void usa67_glocont_callback(struct urb *urb)
1454{
1455 struct usb_serial *serial;
1456 struct usb_serial_port *port;
1457 struct keyspan_port_private *p_priv;
1458 int i;
1459
Lucy McCoy0ca12682007-05-18 12:10:41 -07001460 serial = urb->context;
1461 for (i = 0; i < serial->num_ports; ++i) {
1462 port = serial->port[i];
1463 p_priv = usb_get_serial_port_data(port);
Johan Hovold3018dd32020-01-17 10:50:25 +01001464 if (!p_priv)
1465 continue;
Lucy McCoy0ca12682007-05-18 12:10:41 -07001466
1467 if (p_priv->resend_cont) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001468 dev_dbg(&port->dev, "%s - sending setup\n", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07001469 keyspan_usa67_send_setup(serial, port,
1470 p_priv->resend_cont - 1);
1471 break;
1472 }
1473 }
1474}
1475
Alan Cox95da3102008-07-22 11:09:07 +01001476static int keyspan_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477{
Alan Cox95da3102008-07-22 11:09:07 +01001478 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 struct keyspan_port_private *p_priv;
1480 const struct keyspan_device_details *d_details;
1481 int flip;
1482 int data_len;
1483 struct urb *this_urb;
1484
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485 p_priv = usb_get_serial_port_data(port);
1486 d_details = p_priv->device_details;
1487
Alan Coxa5b6f602008-04-08 17:16:06 +01001488 /* FIXME: locking */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 if (d_details->msg_format == msg_usa90)
Alan Coxdeb91682008-07-22 11:13:08 +01001490 data_len = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 else
1492 data_len = 63;
1493
1494 flip = p_priv->out_flip;
1495
1496 /* Check both endpoints to see if any are available. */
Alan Coxdeb91682008-07-22 11:13:08 +01001497 this_urb = p_priv->out_urbs[flip];
1498 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001500 return data_len;
1501 flip = (flip + 1) & d_details->outdat_endp_flip;
1502 this_urb = p_priv->out_urbs[flip];
1503 if (this_urb != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 if (this_urb->status != -EINPROGRESS)
Alan Coxdeb91682008-07-22 11:13:08 +01001505 return data_len;
1506 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 }
Alan Coxa5b6f602008-04-08 17:16:06 +01001508 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509}
1510
1511
Alan Coxa509a7e2009-09-19 13:13:26 -07001512static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513{
Andrew Mortonf78ba152007-11-28 16:21:54 -08001514 struct keyspan_port_private *p_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 const struct keyspan_device_details *d_details;
1516 int i, err;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001517 int baud_rate, device_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 struct urb *urb;
Alan Cox95da3102008-07-22 11:09:07 +01001519 unsigned int cflag = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 p_priv = usb_get_serial_port_data(port);
1522 d_details = p_priv->device_details;
Borislav Petkov7eea4362007-11-14 17:00:39 -08001523
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 /* Set some sane defaults */
1525 p_priv->rts_state = 1;
1526 p_priv->dtr_state = 1;
1527 p_priv->baud = 9600;
1528
1529 /* force baud and lcr to be set on open */
1530 p_priv->old_baud = 0;
1531 p_priv->old_cflag = 0;
1532
1533 p_priv->out_flip = 0;
1534 p_priv->in_flip = 0;
1535
1536 /* Reset low level data toggle and start reading from endpoints */
1537 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001538 urb = p_priv->in_urbs[i];
1539 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541
Alan Coxdeb91682008-07-22 11:13:08 +01001542 /* make sure endpoint data toggle is synchronized
1543 with the device */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 usb_clear_halt(urb->dev, urb->pipe);
Alan Coxdeb91682008-07-22 11:13:08 +01001545 err = usb_submit_urb(urb, GFP_KERNEL);
1546 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001547 dev_dbg(&port->dev, "%s - submit urb %d failed (%d)\n", __func__, i, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 }
1549
1550 /* Reset low level data toggle on out endpoints */
1551 for (i = 0; i < 2; i++) {
Alan Coxdeb91682008-07-22 11:13:08 +01001552 urb = p_priv->out_urbs[i];
1553 if (urb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554 continue;
Alan Coxdeb91682008-07-22 11:13:08 +01001555 /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
1556 usb_pipeout(urb->pipe), 0); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 }
1558
Andrew Mortonf78ba152007-11-28 16:21:54 -08001559 /* get the terminal config for the setup message now so we don't
1560 * need to send 2 of them */
1561
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001562 device_port = port->port_number;
Alan Cox95da3102008-07-22 11:09:07 +01001563 if (tty) {
Alan Coxadc8d742012-07-14 15:31:47 +01001564 cflag = tty->termios.c_cflag;
Alan Cox95da3102008-07-22 11:09:07 +01001565 /* Baud rate calculation takes baud rate as an integer
1566 so other rates can be generated if desired. */
1567 baud_rate = tty_get_baud_rate(tty);
1568 /* If no match or invalid, leave as default */
1569 if (baud_rate >= 0
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001570 && d_details->calculate_baud_rate(port, baud_rate, d_details->baudclk,
Alan Cox95da3102008-07-22 11:09:07 +01001571 NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
1572 p_priv->baud = baud_rate;
1573 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001574 }
Andrew Mortonf78ba152007-11-28 16:21:54 -08001575 /* set CTS/RTS handshake etc. */
1576 p_priv->cflag = cflag;
Ben Minerds2b982ab2012-07-12 00:10:16 +10001577 p_priv->flow_control = (cflag & CRTSCTS) ? flow_cts : flow_none;
Andrew Mortonf78ba152007-11-28 16:21:54 -08001578
1579 keyspan_send_setup(port, 1);
Alan Coxdeb91682008-07-22 11:13:08 +01001580 /* mdelay(100); */
1581 /* keyspan_set_termios(port, NULL); */
Andrew Mortonf78ba152007-11-28 16:21:54 -08001582
Alan Coxa5b6f602008-04-08 17:16:06 +01001583 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584}
1585
Alan Cox335f8512009-06-11 12:26:29 +01001586static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
1587{
1588 struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
1589
1590 p_priv->rts_state = on;
1591 p_priv->dtr_state = on;
1592 keyspan_send_setup(port, 0);
1593}
1594
1595static void keyspan_close(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596{
1597 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598 struct keyspan_port_private *p_priv;
1599
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600 p_priv = usb_get_serial_port_data(port);
Alan Coxdeb91682008-07-22 11:13:08 +01001601
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602 p_priv->rts_state = 0;
1603 p_priv->dtr_state = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01001604
Johan Hovold80dfe0c2013-03-21 12:36:32 +01001605 keyspan_send_setup(port, 2);
1606 /* pilot-xfer seems to work best with this delay */
1607 mdelay(100);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608
1609 p_priv->out_flip = 0;
1610 p_priv->in_flip = 0;
1611
Johan Hovold61924502016-05-08 20:07:59 +02001612 usb_kill_urb(p_priv->inack_urb);
Johan Hovold80dfe0c2013-03-21 12:36:32 +01001613 for (i = 0; i < 2; i++) {
Johan Hovold61924502016-05-08 20:07:59 +02001614 usb_kill_urb(p_priv->in_urbs[i]);
1615 usb_kill_urb(p_priv->out_urbs[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617}
1618
Alan Coxdeb91682008-07-22 11:13:08 +01001619/* download the firmware to a pre-renumeration device */
1620static int keyspan_fake_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621{
Rene Buergel8d733e22012-09-18 09:02:01 +02001622 char *fw_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001624 dev_dbg(&serial->dev->dev, "Keyspan startup version %04x product %04x\n",
1625 le16_to_cpu(serial->dev->descriptor.bcdDevice),
1626 le16_to_cpu(serial->dev->descriptor.idProduct));
Alan Coxdeb91682008-07-22 11:13:08 +01001627
1628 if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000)
1629 != 0x8000) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001630 dev_dbg(&serial->dev->dev, "Firmware already loaded. Quitting.\n");
Alan Coxdeb91682008-07-22 11:13:08 +01001631 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632 }
1633
1634 /* Select firmware image on the basis of idProduct */
1635 switch (le16_to_cpu(serial->dev->descriptor.idProduct)) {
1636 case keyspan_usa28_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001637 fw_name = "keyspan/usa28.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 break;
1639
1640 case keyspan_usa28x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001641 fw_name = "keyspan/usa28x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642 break;
1643
1644 case keyspan_usa28xa_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001645 fw_name = "keyspan/usa28xa.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 break;
1647
1648 case keyspan_usa28xb_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001649 fw_name = "keyspan/usa28xb.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650 break;
1651
1652 case keyspan_usa19_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001653 fw_name = "keyspan/usa19.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001655
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656 case keyspan_usa19qi_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001657 fw_name = "keyspan/usa19qi.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001659
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 case keyspan_mpr_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001661 fw_name = "keyspan/mpr.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 break;
1663
1664 case keyspan_usa19qw_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001665 fw_name = "keyspan/usa19qw.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001667
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 case keyspan_usa18x_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001669 fw_name = "keyspan/usa18x.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001671
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 case keyspan_usa19w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001673 fw_name = "keyspan/usa19w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674 break;
Alan Coxdeb91682008-07-22 11:13:08 +01001675
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676 case keyspan_usa49w_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001677 fw_name = "keyspan/usa49w.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 break;
1679
1680 case keyspan_usa49wlc_pre_product_id:
David Woodhouse2971c572008-05-30 14:04:03 +03001681 fw_name = "keyspan/usa49wlc.fw";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 break;
1683
1684 default:
David Woodhouse2971c572008-05-30 14:04:03 +03001685 dev_err(&serial->dev->dev, "Unknown product ID (%04x)\n",
1686 le16_to_cpu(serial->dev->descriptor.idProduct));
1687 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688 }
1689
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001690 dev_dbg(&serial->dev->dev, "Uploading Keyspan %s firmware.\n", fw_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691
Rene Buergel8d733e22012-09-18 09:02:01 +02001692 if (ezusb_fx1_ihex_firmware_download(serial->dev, fw_name) < 0) {
1693 dev_err(&serial->dev->dev, "failed to load firmware \"%s\"\n",
1694 fw_name);
1695 return -ENOENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 }
1697
Rene Buergel8d733e22012-09-18 09:02:01 +02001698 /* after downloading firmware Renumeration will occur in a
1699 moment and the new device will bind to the real driver */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700
1701 /* we don't want this device to have a driver assigned to it. */
Alan Coxdeb91682008-07-22 11:13:08 +01001702 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703}
1704
1705/* Helper functions used by keyspan_setup_urbs */
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001706static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *serial,
1707 int endpoint)
1708{
1709 struct usb_host_interface *iface_desc;
1710 struct usb_endpoint_descriptor *ep;
1711 int i;
1712
1713 iface_desc = serial->interface->cur_altsetting;
1714 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
1715 ep = &iface_desc->endpoint[i].desc;
1716 if (ep->bEndpointAddress == endpoint)
1717 return ep;
1718 }
Johan Hovold0cd782b2016-05-08 20:08:00 +02001719 dev_warn(&serial->interface->dev, "found no endpoint descriptor for endpoint %x\n",
1720 endpoint);
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001721 return NULL;
1722}
1723
Alan Coxdeb91682008-07-22 11:13:08 +01001724static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725 int dir, void *ctx, char *buf, int len,
David Howells7d12e782006-10-05 14:55:46 +01001726 void (*callback)(struct urb *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727{
1728 struct urb *urb;
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001729 struct usb_endpoint_descriptor const *ep_desc;
1730 char const *ep_type_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731
1732 if (endpoint == -1)
1733 return NULL; /* endpoint not needed */
1734
Johan Hovold0cd782b2016-05-08 20:08:00 +02001735 dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %x\n",
1736 __func__, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737 urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
Johan Hovold10c642d2013-12-29 19:22:56 +01001738 if (!urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740
Lucy McCoy0ca12682007-05-18 12:10:41 -07001741 if (endpoint == 0) {
1742 /* control EP filled in when used */
1743 return urb;
1744 }
1745
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001746 ep_desc = find_ep(serial, endpoint);
1747 if (!ep_desc) {
Johan Hovold7d7e21f2019-10-03 15:49:58 +02001748 usb_free_urb(urb);
1749 return NULL;
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001750 }
1751 if (usb_endpoint_xfer_int(ep_desc)) {
1752 ep_type_name = "INT";
1753 usb_fill_int_urb(urb, serial->dev,
1754 usb_sndintpipe(serial->dev, endpoint) | dir,
1755 buf, len, callback, ctx,
1756 ep_desc->bInterval);
1757 } else if (usb_endpoint_xfer_bulk(ep_desc)) {
1758 ep_type_name = "BULK";
1759 usb_fill_bulk_urb(urb, serial->dev,
1760 usb_sndbulkpipe(serial->dev, endpoint) | dir,
1761 buf, len, callback, ctx);
1762 } else {
1763 dev_warn(&serial->interface->dev,
1764 "unsupported endpoint type %x\n",
Julia Lawall2e0fe702008-12-29 11:22:14 +01001765 usb_endpoint_type(ep_desc));
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001766 usb_free_urb(urb);
1767 return NULL;
1768 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001770 dev_dbg(&serial->interface->dev, "%s - using urb %p for %s endpoint %x\n",
Rainer Weikusatfdcba532007-01-03 15:36:25 +01001771 __func__, urb, ep_type_name, endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772 return urb;
1773}
1774
1775static struct callbacks {
David Howells7d12e782006-10-05 14:55:46 +01001776 void (*instat_callback)(struct urb *);
1777 void (*glocont_callback)(struct urb *);
1778 void (*indat_callback)(struct urb *);
1779 void (*outdat_callback)(struct urb *);
1780 void (*inack_callback)(struct urb *);
1781 void (*outcont_callback)(struct urb *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782} keyspan_callbacks[] = {
1783 {
1784 /* msg_usa26 callbacks */
1785 .instat_callback = usa26_instat_callback,
1786 .glocont_callback = usa26_glocont_callback,
1787 .indat_callback = usa26_indat_callback,
1788 .outdat_callback = usa2x_outdat_callback,
1789 .inack_callback = usa26_inack_callback,
1790 .outcont_callback = usa26_outcont_callback,
1791 }, {
1792 /* msg_usa28 callbacks */
1793 .instat_callback = usa28_instat_callback,
1794 .glocont_callback = usa28_glocont_callback,
1795 .indat_callback = usa28_indat_callback,
1796 .outdat_callback = usa2x_outdat_callback,
1797 .inack_callback = usa28_inack_callback,
1798 .outcont_callback = usa28_outcont_callback,
1799 }, {
1800 /* msg_usa49 callbacks */
1801 .instat_callback = usa49_instat_callback,
1802 .glocont_callback = usa49_glocont_callback,
1803 .indat_callback = usa49_indat_callback,
1804 .outdat_callback = usa2x_outdat_callback,
1805 .inack_callback = usa49_inack_callback,
1806 .outcont_callback = usa49_outcont_callback,
1807 }, {
1808 /* msg_usa90 callbacks */
1809 .instat_callback = usa90_instat_callback,
Alan Coxdeb91682008-07-22 11:13:08 +01001810 .glocont_callback = usa28_glocont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811 .indat_callback = usa90_indat_callback,
1812 .outdat_callback = usa2x_outdat_callback,
1813 .inack_callback = usa28_inack_callback,
1814 .outcont_callback = usa90_outcont_callback,
Lucy McCoy0ca12682007-05-18 12:10:41 -07001815 }, {
1816 /* msg_usa67 callbacks */
1817 .instat_callback = usa67_instat_callback,
1818 .glocont_callback = usa67_glocont_callback,
1819 .indat_callback = usa26_indat_callback,
1820 .outdat_callback = usa2x_outdat_callback,
1821 .inack_callback = usa26_inack_callback,
1822 .outcont_callback = usa26_outcont_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823 }
1824};
1825
1826 /* Generic setup urbs function that uses
1827 data in device_details */
1828static void keyspan_setup_urbs(struct usb_serial *serial)
1829{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 struct keyspan_serial_private *s_priv;
1831 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 struct callbacks *cback;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834 s_priv = usb_get_serial_data(serial);
1835 d_details = s_priv->device_details;
1836
Alan Coxdeb91682008-07-22 11:13:08 +01001837 /* Setup values for the various callback routines */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 cback = &keyspan_callbacks[d_details->msg_format];
1839
Alan Coxdeb91682008-07-22 11:13:08 +01001840 /* Allocate and set up urbs for each one that is in use,
1841 starting with instat endpoints */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 s_priv->instat_urb = keyspan_setup_urb
1843 (serial, d_details->instat_endpoint, USB_DIR_IN,
1844 serial, s_priv->instat_buf, INSTAT_BUFLEN,
1845 cback->instat_callback);
1846
Lucy McCoy0ca12682007-05-18 12:10:41 -07001847 s_priv->indat_urb = keyspan_setup_urb
1848 (serial, d_details->indat_endpoint, USB_DIR_IN,
1849 serial, s_priv->indat_buf, INDAT49W_BUFLEN,
1850 usa49wg_indat_callback);
1851
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 s_priv->glocont_urb = keyspan_setup_urb
1853 (serial, d_details->glocont_endpoint, USB_DIR_OUT,
1854 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
1855 cback->glocont_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856}
1857
1858/* usa19 function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001859static int keyspan_usa19_calc_baud(struct usb_serial_port *port,
1860 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 u8 *rate_low, u8 *prescaler, int portnum)
1862{
1863 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001864 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865 cnt; /* inverse of divisor (programmed into 8051) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001867 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868
Alan Coxdeb91682008-07-22 11:13:08 +01001869 /* prevent divide by zero... */
1870 b16 = baud_rate * 16L;
1871 if (b16 == 0)
1872 return KEYSPAN_INVALID_BAUD_RATE;
1873 /* Any "standard" rate over 57k6 is marginal on the USA-19
1874 as we run out of divisor resolution. */
1875 if (baud_rate > 57600)
1876 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877
Alan Coxdeb91682008-07-22 11:13:08 +01001878 /* calculate the divisor and the counter (its inverse) */
1879 div = baudclk / b16;
1880 if (div == 0)
1881 return KEYSPAN_INVALID_BAUD_RATE;
1882 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884
Alan Coxdeb91682008-07-22 11:13:08 +01001885 if (div > 0xffff)
1886 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887
Alan Coxdeb91682008-07-22 11:13:08 +01001888 /* return the counter values if non-null */
1889 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001891 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001893 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001894 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001895 __func__, baud_rate, *rate_hi, *rate_low);
1896 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897}
1898
1899/* usa19hs function doesn't require prescaler */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001900static int keyspan_usa19hs_calc_baud(struct usb_serial_port *port,
1901 u32 baud_rate, u32 baudclk, u8 *rate_hi,
1902 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903{
1904 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01001905 div; /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001907 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908
Alan Coxdeb91682008-07-22 11:13:08 +01001909 /* prevent divide by zero... */
1910 b16 = baud_rate * 16L;
1911 if (b16 == 0)
1912 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913
Alan Coxdeb91682008-07-22 11:13:08 +01001914 /* calculate the divisor */
1915 div = baudclk / b16;
1916 if (div == 0)
1917 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918
Alan Coxdeb91682008-07-22 11:13:08 +01001919 if (div > 0xffff)
1920 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921
Alan Coxdeb91682008-07-22 11:13:08 +01001922 /* return the counter values if non-null */
1923 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001925
1926 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927 *rate_hi = (u8) ((div >> 8) & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001928
1929 if (rate_low && rate_hi)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001930 dev_dbg(&port->dev, "%s - %d %02x %02x.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01001931 __func__, baud_rate, *rate_hi, *rate_low);
1932
1933 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934}
1935
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001936static int keyspan_usa19w_calc_baud(struct usb_serial_port *port,
1937 u32 baud_rate, u32 baudclk, u8 *rate_hi,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 u8 *rate_low, u8 *prescaler, int portnum)
1939{
1940 u32 b16, /* baud rate times 16 (actual rate used internally) */
1941 clk, /* clock with 13/8 prescaler */
Alan Coxdeb91682008-07-22 11:13:08 +01001942 div, /* divisor using 13/8 prescaler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943 res, /* resulting baud rate using 13/8 prescaler */
1944 diff, /* error using 13/8 prescaler */
1945 smallest_diff;
1946 u8 best_prescaler;
1947 int i;
1948
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001949 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950
Alan Coxdeb91682008-07-22 11:13:08 +01001951 /* prevent divide by zero */
1952 b16 = baud_rate * 16L;
1953 if (b16 == 0)
1954 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955
Alan Coxdeb91682008-07-22 11:13:08 +01001956 /* Calculate prescaler by trying them all and looking
1957 for best fit */
1958
1959 /* start with largest possible difference */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960 smallest_diff = 0xffffffff;
1961
1962 /* 0 is an invalid prescaler, used as a flag */
1963 best_prescaler = 0;
1964
Alan Coxdeb91682008-07-22 11:13:08 +01001965 for (i = 8; i <= 0xff; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966 clk = (baudclk * 8) / (u32) i;
Alan Coxdeb91682008-07-22 11:13:08 +01001967
1968 div = clk / b16;
1969 if (div == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971
1972 res = clk / div;
Alan Coxdeb91682008-07-22 11:13:08 +01001973 diff = (res > b16) ? (res-b16) : (b16-res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974
Alan Coxdeb91682008-07-22 11:13:08 +01001975 if (diff < smallest_diff) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 best_prescaler = i;
1977 smallest_diff = diff;
1978 }
1979 }
1980
Alan Coxdeb91682008-07-22 11:13:08 +01001981 if (best_prescaler == 0)
1982 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983
1984 clk = (baudclk * 8) / (u32) best_prescaler;
1985 div = clk / b16;
1986
Alan Coxdeb91682008-07-22 11:13:08 +01001987 /* return the divisor and prescaler if non-null */
1988 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 *rate_low = (u8) (div & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01001990 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991 *rate_hi = (u8) ((div >> 8) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 if (prescaler) {
1993 *prescaler = best_prescaler;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07001994 /* dev_dbg(&port->dev, "%s - %d %d\n", __func__, *prescaler, div); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995 }
Alan Coxdeb91682008-07-22 11:13:08 +01001996 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997}
1998
1999 /* USA-28 supports different maximum baud rates on each port */
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002000static int keyspan_usa28_calc_baud(struct usb_serial_port *port,
2001 u32 baud_rate, u32 baudclk, u8 *rate_hi,
2002 u8 *rate_low, u8 *prescaler, int portnum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003{
2004 u32 b16, /* baud rate times 16 (actual rate used internally) */
Alan Coxdeb91682008-07-22 11:13:08 +01002005 div, /* divisor */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006 cnt; /* inverse of divisor (programmed into 8051) */
2007
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002008 dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009
2010 /* prevent divide by zero */
Alan Coxdeb91682008-07-22 11:13:08 +01002011 b16 = baud_rate * 16L;
2012 if (b16 == 0)
2013 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014
Alan Coxdeb91682008-07-22 11:13:08 +01002015 /* calculate the divisor and the counter (its inverse) */
2016 div = KEYSPAN_USA28_BAUDCLK / b16;
2017 if (div == 0)
2018 return KEYSPAN_INVALID_BAUD_RATE;
2019 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 cnt = 0 - div;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021
Alan Coxdeb91682008-07-22 11:13:08 +01002022 /* check for out of range, based on portnum,
2023 and return result */
2024 if (portnum == 0) {
2025 if (div > 0xffff)
2026 return KEYSPAN_INVALID_BAUD_RATE;
2027 } else {
2028 if (portnum == 1) {
2029 if (div > 0xff)
2030 return KEYSPAN_INVALID_BAUD_RATE;
2031 } else
2032 return KEYSPAN_INVALID_BAUD_RATE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 }
2034
2035 /* return the counter values if not NULL
2036 (port 1 will ignore retHi) */
Alan Coxdeb91682008-07-22 11:13:08 +01002037 if (rate_low)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038 *rate_low = (u8) (cnt & 0xff);
Alan Coxdeb91682008-07-22 11:13:08 +01002039 if (rate_hi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 *rate_hi = (u8) ((cnt >> 8) & 0xff);
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002041 dev_dbg(&port->dev, "%s - %d OK.\n", __func__, baud_rate);
Alan Coxdeb91682008-07-22 11:13:08 +01002042 return KEYSPAN_BAUD_RATE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043}
2044
2045static int keyspan_usa26_send_setup(struct usb_serial *serial,
2046 struct usb_serial_port *port,
2047 int reset_port)
2048{
Alan Coxdeb91682008-07-22 11:13:08 +01002049 struct keyspan_usa26_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050 struct keyspan_serial_private *s_priv;
2051 struct keyspan_port_private *p_priv;
2052 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 struct urb *this_urb;
2054 int device_port, err;
2055
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002056 dev_dbg(&port->dev, "%s reset=%d\n", __func__, reset_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057
2058 s_priv = usb_get_serial_data(serial);
2059 p_priv = usb_get_serial_port_data(port);
2060 d_details = s_priv->device_details;
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002061 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 this_urb = p_priv->outcont_urb;
2064
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 /* Make sure we have an urb then send the message */
2066 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002067 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068 return -1;
2069 }
2070
Johan Hovold0cd782b2016-05-08 20:08:00 +02002071 dev_dbg(&port->dev, "%s - endpoint %x\n",
2072 __func__, usb_pipeendpoint(this_urb->pipe));
Rickard Strandqvistd5afce82014-05-16 17:39:13 +02002073
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07002075 Don't overwrite resend for open/close condition. */
2076 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077 p_priv->resend_cont = reset_port + 1;
2078 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002079 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002081 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082 }
2083
Alan Coxdeb91682008-07-22 11:13:08 +01002084 memset(&msg, 0, sizeof(struct keyspan_usa26_portControlMessage));
2085
2086 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 if (p_priv->old_baud != p_priv->baud) {
2088 p_priv->old_baud = p_priv->baud;
2089 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002090 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2091 &msg.baudHi, &msg.baudLo, &msg.prescaler,
2092 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2093 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2094 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095 msg.baudLo = 0;
2096 msg.baudHi = 125; /* Values for 9600 baud */
2097 msg.prescaler = 10;
2098 }
2099 msg.setPrescaler = 0xff;
2100 }
2101
Ben Minerds2b982ab2012-07-12 00:10:16 +10002102 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 switch (p_priv->cflag & CSIZE) {
2104 case CS5:
2105 msg.lcr |= USA_DATABITS_5;
2106 break;
2107 case CS6:
2108 msg.lcr |= USA_DATABITS_6;
2109 break;
2110 case CS7:
2111 msg.lcr |= USA_DATABITS_7;
2112 break;
2113 case CS8:
2114 msg.lcr |= USA_DATABITS_8;
2115 break;
2116 }
2117 if (p_priv->cflag & PARENB) {
2118 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002119 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002120 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 }
2122 msg.setLcr = 0xff;
2123
2124 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2125 msg.xonFlowControl = 0;
2126 msg.setFlowControl = 0xff;
2127 msg.forwardingLength = 16;
2128 msg.xonChar = 17;
2129 msg.xoffChar = 19;
2130
2131 /* Opening port */
2132 if (reset_port == 1) {
2133 msg._txOn = 1;
2134 msg._txOff = 0;
2135 msg.txFlush = 0;
2136 msg.txBreak = 0;
2137 msg.rxOn = 1;
2138 msg.rxOff = 0;
2139 msg.rxFlush = 1;
2140 msg.rxForward = 0;
2141 msg.returnStatus = 0;
2142 msg.resetDataToggle = 0xff;
2143 }
2144
2145 /* Closing port */
2146 else if (reset_port == 2) {
2147 msg._txOn = 0;
2148 msg._txOff = 1;
2149 msg.txFlush = 0;
2150 msg.txBreak = 0;
2151 msg.rxOn = 0;
2152 msg.rxOff = 1;
2153 msg.rxFlush = 1;
2154 msg.rxForward = 0;
2155 msg.returnStatus = 0;
2156 msg.resetDataToggle = 0;
2157 }
2158
2159 /* Sending intermediate configs */
2160 else {
Alan Coxdeb91682008-07-22 11:13:08 +01002161 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 msg._txOff = 0;
2163 msg.txFlush = 0;
2164 msg.txBreak = (p_priv->break_on);
2165 msg.rxOn = 0;
2166 msg.rxOff = 0;
2167 msg.rxFlush = 0;
2168 msg.rxForward = 0;
2169 msg.returnStatus = 0;
2170 msg.resetDataToggle = 0x0;
2171 }
2172
Alan Coxdeb91682008-07-22 11:13:08 +01002173 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174 msg.setTxTriState_setRts = 0xff;
2175 msg.txTriState_rts = p_priv->rts_state;
2176
2177 msg.setHskoa_setDtr = 0xff;
2178 msg.hskoa_dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002179
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01002181 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2182
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183 /* send the data out the device on control endpoint */
2184 this_urb->transfer_buffer_length = sizeof(msg);
2185
Alan Coxdeb91682008-07-22 11:13:08 +01002186 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2187 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002188 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002189 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190}
2191
2192static int keyspan_usa28_send_setup(struct usb_serial *serial,
2193 struct usb_serial_port *port,
2194 int reset_port)
2195{
Alan Coxdeb91682008-07-22 11:13:08 +01002196 struct keyspan_usa28_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197 struct keyspan_serial_private *s_priv;
2198 struct keyspan_port_private *p_priv;
2199 const struct keyspan_device_details *d_details;
2200 struct urb *this_urb;
2201 int device_port, err;
2202
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203 s_priv = usb_get_serial_data(serial);
2204 p_priv = usb_get_serial_port_data(port);
2205 d_details = s_priv->device_details;
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002206 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207
2208 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01002209 this_urb = p_priv->outcont_urb;
2210 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002211 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212 return -1;
2213 }
2214
2215 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07002216 Don't overwrite resend for open/close condition. */
2217 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218 p_priv->resend_cont = reset_port + 1;
2219 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002220 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002222 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223 }
2224
Alan Coxdeb91682008-07-22 11:13:08 +01002225 memset(&msg, 0, sizeof(struct keyspan_usa28_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226
2227 msg.setBaudRate = 1;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002228 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2229 &msg.baudHi, &msg.baudLo, NULL,
2230 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2231 dev_dbg(&port->dev, "%s - Invalid baud rate requested %d.\n",
Alan Coxdeb91682008-07-22 11:13:08 +01002232 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233 msg.baudLo = 0xff;
2234 msg.baudHi = 0xb2; /* Values for 9600 baud */
2235 }
2236
2237 /* If parity is enabled, we must calculate it ourselves. */
2238 msg.parity = 0; /* XXX for now */
2239
2240 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2241 msg.xonFlowControl = 0;
2242
Alan Coxdeb91682008-07-22 11:13:08 +01002243 /* Do handshaking outputs, DTR is inverted relative to RTS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244 msg.rts = p_priv->rts_state;
2245 msg.dtr = p_priv->dtr_state;
2246
2247 msg.forwardingLength = 16;
2248 msg.forwardMs = 10;
2249 msg.breakThreshold = 45;
2250 msg.xonChar = 17;
2251 msg.xoffChar = 19;
2252
2253 /*msg.returnStatus = 1;
2254 msg.resetDataToggle = 0xff;*/
2255 /* Opening port */
2256 if (reset_port == 1) {
2257 msg._txOn = 1;
2258 msg._txOff = 0;
2259 msg.txFlush = 0;
2260 msg.txForceXoff = 0;
2261 msg.txBreak = 0;
2262 msg.rxOn = 1;
2263 msg.rxOff = 0;
2264 msg.rxFlush = 1;
2265 msg.rxForward = 0;
2266 msg.returnStatus = 0;
2267 msg.resetDataToggle = 0xff;
2268 }
2269 /* Closing port */
2270 else if (reset_port == 2) {
2271 msg._txOn = 0;
2272 msg._txOff = 1;
2273 msg.txFlush = 0;
2274 msg.txForceXoff = 0;
2275 msg.txBreak = 0;
2276 msg.rxOn = 0;
2277 msg.rxOff = 1;
2278 msg.rxFlush = 1;
2279 msg.rxForward = 0;
2280 msg.returnStatus = 0;
2281 msg.resetDataToggle = 0;
2282 }
2283 /* Sending intermediate configs */
2284 else {
Alan Coxdeb91682008-07-22 11:13:08 +01002285 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286 msg._txOff = 0;
2287 msg.txFlush = 0;
2288 msg.txForceXoff = 0;
2289 msg.txBreak = (p_priv->break_on);
2290 msg.rxOn = 0;
2291 msg.rxOff = 0;
2292 msg.rxFlush = 0;
2293 msg.rxForward = 0;
2294 msg.returnStatus = 0;
2295 msg.resetDataToggle = 0x0;
2296 }
2297
2298 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01002299 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300
2301 /* send the data out the device on control endpoint */
2302 this_urb->transfer_buffer_length = sizeof(msg);
2303
Alan Coxdeb91682008-07-22 11:13:08 +01002304 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2305 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002306 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307
Alan Coxa5b6f602008-04-08 17:16:06 +01002308 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309}
2310
2311static int keyspan_usa49_send_setup(struct usb_serial *serial,
2312 struct usb_serial_port *port,
2313 int reset_port)
2314{
Lucy McCoy0ca12682007-05-18 12:10:41 -07002315 struct keyspan_usa49_portControlMessage msg;
2316 struct usb_ctrlrequest *dr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 struct keyspan_serial_private *s_priv;
2318 struct keyspan_port_private *p_priv;
2319 const struct keyspan_device_details *d_details;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 struct urb *this_urb;
2321 int err, device_port;
2322
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323 s_priv = usb_get_serial_data(serial);
2324 p_priv = usb_get_serial_port_data(port);
2325 d_details = s_priv->device_details;
2326
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327 this_urb = s_priv->glocont_urb;
2328
Lucy McCoy0ca12682007-05-18 12:10:41 -07002329 /* Work out which port within the device is being setup */
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002330 device_port = port->port_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05302332 /* Make sure we have an urb then send the message */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333 if (this_urb == NULL) {
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002334 dev_dbg(&port->dev, "%s - oops no urb for port.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 return -1;
2336 }
2337
Johan Hovold0cd782b2016-05-08 20:08:00 +02002338 dev_dbg(&port->dev, "%s - endpoint %x (%d)\n",
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002339 __func__, usb_pipeendpoint(this_urb->pipe), device_port);
Huzaifa Sidhpurwalad8661502011-02-21 12:58:44 +05302340
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341 /* Save reset port val for resend.
Lucy McCoy0ca12682007-05-18 12:10:41 -07002342 Don't overwrite resend for open/close condition. */
2343 if ((reset_port + 1) > p_priv->resend_cont)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344 p_priv->resend_cont = reset_port + 1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002345
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002347 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002349 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 }
2351
Alan Coxdeb91682008-07-22 11:13:08 +01002352 memset(&msg, 0, sizeof(struct keyspan_usa49_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 msg.portNumber = device_port;
Alan Coxdeb91682008-07-22 11:13:08 +01002355
2356 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 if (p_priv->old_baud != p_priv->baud) {
2358 p_priv->old_baud = p_priv->baud;
2359 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002360 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2361 &msg.baudHi, &msg.baudLo, &msg.prescaler,
2362 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2363 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2364 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 msg.baudLo = 0;
2366 msg.baudHi = 125; /* Values for 9600 baud */
2367 msg.prescaler = 10;
2368 }
Alan Coxdeb91682008-07-22 11:13:08 +01002369 /* msg.setPrescaler = 0xff; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370 }
2371
Ben Minerds2b982ab2012-07-12 00:10:16 +10002372 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373 switch (p_priv->cflag & CSIZE) {
2374 case CS5:
2375 msg.lcr |= USA_DATABITS_5;
2376 break;
2377 case CS6:
2378 msg.lcr |= USA_DATABITS_6;
2379 break;
2380 case CS7:
2381 msg.lcr |= USA_DATABITS_7;
2382 break;
2383 case CS8:
2384 msg.lcr |= USA_DATABITS_8;
2385 break;
2386 }
2387 if (p_priv->cflag & PARENB) {
2388 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002389 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002390 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 }
2392 msg.setLcr = 0xff;
2393
2394 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2395 msg.xonFlowControl = 0;
2396 msg.setFlowControl = 0xff;
Alan Coxdeb91682008-07-22 11:13:08 +01002397
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 msg.forwardingLength = 16;
2399 msg.xonChar = 17;
2400 msg.xoffChar = 19;
2401
Alan Coxdeb91682008-07-22 11:13:08 +01002402 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403 if (reset_port == 1) {
2404 msg._txOn = 1;
2405 msg._txOff = 0;
2406 msg.txFlush = 0;
2407 msg.txBreak = 0;
2408 msg.rxOn = 1;
2409 msg.rxOff = 0;
2410 msg.rxFlush = 1;
2411 msg.rxForward = 0;
2412 msg.returnStatus = 0;
2413 msg.resetDataToggle = 0xff;
2414 msg.enablePort = 1;
2415 msg.disablePort = 0;
2416 }
2417 /* Closing port */
2418 else if (reset_port == 2) {
2419 msg._txOn = 0;
2420 msg._txOff = 1;
2421 msg.txFlush = 0;
2422 msg.txBreak = 0;
2423 msg.rxOn = 0;
2424 msg.rxOff = 1;
2425 msg.rxFlush = 1;
2426 msg.rxForward = 0;
2427 msg.returnStatus = 0;
2428 msg.resetDataToggle = 0;
2429 msg.enablePort = 0;
2430 msg.disablePort = 1;
2431 }
2432 /* Sending intermediate configs */
2433 else {
Alan Coxdeb91682008-07-22 11:13:08 +01002434 msg._txOn = (!p_priv->break_on);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435 msg._txOff = 0;
2436 msg.txFlush = 0;
2437 msg.txBreak = (p_priv->break_on);
2438 msg.rxOn = 0;
2439 msg.rxOff = 0;
2440 msg.rxFlush = 0;
2441 msg.rxForward = 0;
2442 msg.returnStatus = 0;
2443 msg.resetDataToggle = 0x0;
2444 msg.enablePort = 0;
2445 msg.disablePort = 0;
2446 }
2447
Alan Coxdeb91682008-07-22 11:13:08 +01002448 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002449 msg.setRts = 0xff;
2450 msg.rts = p_priv->rts_state;
2451
2452 msg.setDtr = 0xff;
2453 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002454
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 p_priv->resend_cont = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456
Alan Coxdeb91682008-07-22 11:13:08 +01002457 /* if the device is a 49wg, we send control message on usb
2458 control EP 0 */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002459
2460 if (d_details->product_id == keyspan_usa49wg_product_id) {
2461 dr = (void *)(s_priv->ctrl_buf);
2462 dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT;
Mathieu OTHACEHE64248392016-02-04 19:01:30 +01002463 dr->bRequest = 0xB0; /* 49wg control message */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002464 dr->wValue = 0;
2465 dr->wIndex = 0;
2466 dr->wLength = cpu_to_le16(sizeof(msg));
2467
Alan Coxdeb91682008-07-22 11:13:08 +01002468 memcpy(s_priv->glocont_buf, &msg, sizeof(msg));
Lucy McCoy0ca12682007-05-18 12:10:41 -07002469
Alan Coxdeb91682008-07-22 11:13:08 +01002470 usb_fill_control_urb(this_urb, serial->dev,
2471 usb_sndctrlpipe(serial->dev, 0),
2472 (unsigned char *)dr, s_priv->glocont_buf,
2473 sizeof(msg), usa49_glocont_callback, serial);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002474
2475 } else {
2476 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
Alan Coxdeb91682008-07-22 11:13:08 +01002477
Lucy McCoy0ca12682007-05-18 12:10:41 -07002478 /* send the data out the device on control endpoint */
2479 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002480 }
Alan Coxdeb91682008-07-22 11:13:08 +01002481 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2482 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002483 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484
Alan Coxa5b6f602008-04-08 17:16:06 +01002485 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486}
2487
2488static int keyspan_usa90_send_setup(struct usb_serial *serial,
2489 struct usb_serial_port *port,
2490 int reset_port)
2491{
Alan Coxdeb91682008-07-22 11:13:08 +01002492 struct keyspan_usa90_portControlMessage msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493 struct keyspan_serial_private *s_priv;
2494 struct keyspan_port_private *p_priv;
2495 const struct keyspan_device_details *d_details;
2496 struct urb *this_urb;
2497 int err;
2498 u8 prescaler;
2499
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500 s_priv = usb_get_serial_data(serial);
2501 p_priv = usb_get_serial_port_data(port);
2502 d_details = s_priv->device_details;
2503
2504 /* only do something if we have a bulk out endpoint */
Alan Coxdeb91682008-07-22 11:13:08 +01002505 this_urb = p_priv->outcont_urb;
2506 if (this_urb == NULL) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002507 dev_dbg(&port->dev, "%s - oops no urb.\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508 return -1;
2509 }
2510
2511 /* Save reset port val for resend.
2512 Don't overwrite resend for open/close condition. */
2513 if ((reset_port + 1) > p_priv->resend_cont)
2514 p_priv->resend_cont = reset_port + 1;
2515 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002516 dev_dbg(&port->dev, "%s already writing\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002518 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519 }
2520
Alan Coxdeb91682008-07-22 11:13:08 +01002521 memset(&msg, 0, sizeof(struct keyspan_usa90_portControlMessage));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522
Alan Coxdeb91682008-07-22 11:13:08 +01002523 /* Only set baud rate if it's changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524 if (p_priv->old_baud != p_priv->baud) {
2525 p_priv->old_baud = p_priv->baud;
2526 msg.setClocking = 0x01;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002527 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2528 &msg.baudHi, &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) {
2529 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2530 __func__, p_priv->baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531 p_priv->baud = 9600;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002532 d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533 &msg.baudHi, &msg.baudLo, &prescaler, 0);
2534 }
2535 msg.setRxMode = 1;
2536 msg.setTxMode = 1;
2537 }
2538
2539 /* modes must always be correctly specified */
Alan Coxdeb91682008-07-22 11:13:08 +01002540 if (p_priv->baud > 57600) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541 msg.rxMode = RXMODE_DMA;
2542 msg.txMode = TXMODE_DMA;
Alan Coxdeb91682008-07-22 11:13:08 +01002543 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544 msg.rxMode = RXMODE_BYHAND;
2545 msg.txMode = TXMODE_BYHAND;
2546 }
2547
Ben Minerds2b982ab2012-07-12 00:10:16 +10002548 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549 switch (p_priv->cflag & CSIZE) {
2550 case CS5:
2551 msg.lcr |= USA_DATABITS_5;
2552 break;
2553 case CS6:
2554 msg.lcr |= USA_DATABITS_6;
2555 break;
2556 case CS7:
2557 msg.lcr |= USA_DATABITS_7;
2558 break;
2559 case CS8:
2560 msg.lcr |= USA_DATABITS_8;
2561 break;
2562 }
2563 if (p_priv->cflag & PARENB) {
2564 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002565 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002566 USA_PARITY_ODD : USA_PARITY_EVEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567 }
2568 if (p_priv->old_cflag != p_priv->cflag) {
2569 p_priv->old_cflag = p_priv->cflag;
2570 msg.setLcr = 0x01;
2571 }
2572
2573 if (p_priv->flow_control == flow_cts)
2574 msg.txFlowControl = TXFLOW_CTS;
2575 msg.setTxFlowControl = 0x01;
2576 msg.setRxFlowControl = 0x01;
Alan Coxdeb91682008-07-22 11:13:08 +01002577
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578 msg.rxForwardingLength = 16;
Alan Coxdeb91682008-07-22 11:13:08 +01002579 msg.rxForwardingTimeout = 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 msg.txAckSetting = 0;
2581 msg.xonChar = 17;
2582 msg.xoffChar = 19;
2583
Alan Coxdeb91682008-07-22 11:13:08 +01002584 /* Opening port */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585 if (reset_port == 1) {
2586 msg.portEnabled = 1;
2587 msg.rxFlush = 1;
2588 msg.txBreak = (p_priv->break_on);
2589 }
2590 /* Closing port */
Alan Coxdeb91682008-07-22 11:13:08 +01002591 else if (reset_port == 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592 msg.portEnabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593 /* Sending intermediate configs */
2594 else {
Alan Stern1f871582010-02-17 10:05:47 -05002595 msg.portEnabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596 msg.txBreak = (p_priv->break_on);
2597 }
2598
Alan Coxdeb91682008-07-22 11:13:08 +01002599 /* Do handshaking outputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600 msg.setRts = 0x01;
2601 msg.rts = p_priv->rts_state;
2602
2603 msg.setDtr = 0x01;
2604 msg.dtr = p_priv->dtr_state;
Alan Coxdeb91682008-07-22 11:13:08 +01002605
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606 p_priv->resend_cont = 0;
Alan Coxdeb91682008-07-22 11:13:08 +01002607 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2608
Linus Torvalds1da177e2005-04-16 15:20:36 -07002609 /* send the data out the device on control endpoint */
2610 this_urb->transfer_buffer_length = sizeof(msg);
2611
Alan Coxdeb91682008-07-22 11:13:08 +01002612 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2613 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002614 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002615 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616}
2617
Lucy McCoy0ca12682007-05-18 12:10:41 -07002618static int keyspan_usa67_send_setup(struct usb_serial *serial,
2619 struct usb_serial_port *port,
2620 int reset_port)
2621{
2622 struct keyspan_usa67_portControlMessage msg;
2623 struct keyspan_serial_private *s_priv;
2624 struct keyspan_port_private *p_priv;
2625 const struct keyspan_device_details *d_details;
2626 struct urb *this_urb;
2627 int err, device_port;
2628
Lucy McCoy0ca12682007-05-18 12:10:41 -07002629 s_priv = usb_get_serial_data(serial);
2630 p_priv = usb_get_serial_port_data(port);
2631 d_details = s_priv->device_details;
2632
2633 this_urb = s_priv->glocont_urb;
2634
2635 /* Work out which port within the device is being setup */
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002636 device_port = port->port_number;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002637
2638 /* Make sure we have an urb then send the message */
2639 if (this_urb == NULL) {
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002640 dev_dbg(&port->dev, "%s - oops no urb for port.\n", __func__);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002641 return -1;
2642 }
2643
2644 /* Save reset port val for resend.
2645 Don't overwrite resend for open/close condition. */
2646 if ((reset_port + 1) > p_priv->resend_cont)
2647 p_priv->resend_cont = reset_port + 1;
2648 if (this_urb->status == -EINPROGRESS) {
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002649 /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */
Lucy McCoy0ca12682007-05-18 12:10:41 -07002650 mdelay(5);
Alan Coxdeb91682008-07-22 11:13:08 +01002651 return -1;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002652 }
2653
2654 memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
2655
2656 msg.port = device_port;
2657
2658 /* Only set baud rate if it's changed */
2659 if (p_priv->old_baud != p_priv->baud) {
2660 p_priv->old_baud = p_priv->baud;
2661 msg.setClocking = 0xff;
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002662 if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk,
2663 &msg.baudHi, &msg.baudLo, &msg.prescaler,
2664 device_port) == KEYSPAN_INVALID_BAUD_RATE) {
2665 dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n",
2666 __func__, p_priv->baud);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002667 msg.baudLo = 0;
2668 msg.baudHi = 125; /* Values for 9600 baud */
2669 msg.prescaler = 10;
2670 }
2671 msg.setPrescaler = 0xff;
2672 }
2673
2674 msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
2675 switch (p_priv->cflag & CSIZE) {
2676 case CS5:
2677 msg.lcr |= USA_DATABITS_5;
2678 break;
2679 case CS6:
2680 msg.lcr |= USA_DATABITS_6;
2681 break;
2682 case CS7:
2683 msg.lcr |= USA_DATABITS_7;
2684 break;
2685 case CS8:
2686 msg.lcr |= USA_DATABITS_8;
2687 break;
2688 }
2689 if (p_priv->cflag & PARENB) {
2690 /* note USA_PARITY_NONE == 0 */
Ben Minerds2b982ab2012-07-12 00:10:16 +10002691 msg.lcr |= (p_priv->cflag & PARODD) ?
Alan Coxdeb91682008-07-22 11:13:08 +01002692 USA_PARITY_ODD : USA_PARITY_EVEN;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002693 }
2694 msg.setLcr = 0xff;
2695
2696 msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
2697 msg.xonFlowControl = 0;
2698 msg.setFlowControl = 0xff;
2699 msg.forwardingLength = 16;
2700 msg.xonChar = 17;
2701 msg.xoffChar = 19;
2702
2703 if (reset_port == 1) {
2704 /* Opening port */
2705 msg._txOn = 1;
2706 msg._txOff = 0;
2707 msg.txFlush = 0;
2708 msg.txBreak = 0;
2709 msg.rxOn = 1;
2710 msg.rxOff = 0;
2711 msg.rxFlush = 1;
2712 msg.rxForward = 0;
2713 msg.returnStatus = 0;
2714 msg.resetDataToggle = 0xff;
2715 } else if (reset_port == 2) {
2716 /* Closing port */
2717 msg._txOn = 0;
2718 msg._txOff = 1;
2719 msg.txFlush = 0;
2720 msg.txBreak = 0;
2721 msg.rxOn = 0;
2722 msg.rxOff = 1;
2723 msg.rxFlush = 1;
2724 msg.rxForward = 0;
2725 msg.returnStatus = 0;
2726 msg.resetDataToggle = 0;
2727 } else {
2728 /* Sending intermediate configs */
Alan Coxdeb91682008-07-22 11:13:08 +01002729 msg._txOn = (!p_priv->break_on);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002730 msg._txOff = 0;
2731 msg.txFlush = 0;
2732 msg.txBreak = (p_priv->break_on);
2733 msg.rxOn = 0;
2734 msg.rxOff = 0;
2735 msg.rxFlush = 0;
2736 msg.rxForward = 0;
2737 msg.returnStatus = 0;
2738 msg.resetDataToggle = 0x0;
2739 }
2740
2741 /* Do handshaking outputs */
2742 msg.setTxTriState_setRts = 0xff;
2743 msg.txTriState_rts = p_priv->rts_state;
2744
2745 msg.setHskoa_setDtr = 0xff;
2746 msg.hskoa_dtr = p_priv->dtr_state;
2747
2748 p_priv->resend_cont = 0;
2749
2750 memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
2751
2752 /* send the data out the device on control endpoint */
2753 this_urb->transfer_buffer_length = sizeof(msg);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002754
2755 err = usb_submit_urb(this_urb, GFP_ATOMIC);
2756 if (err != 0)
Greg Kroah-Hartman049c6b42012-09-14 16:30:23 -07002757 dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err);
Alan Coxa5b6f602008-04-08 17:16:06 +01002758 return 0;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002759}
2760
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
2762{
2763 struct usb_serial *serial = port->serial;
2764 struct keyspan_serial_private *s_priv;
2765 const struct keyspan_device_details *d_details;
2766
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 s_priv = usb_get_serial_data(serial);
2768 d_details = s_priv->device_details;
2769
2770 switch (d_details->msg_format) {
2771 case msg_usa26:
2772 keyspan_usa26_send_setup(serial, port, reset_port);
2773 break;
2774 case msg_usa28:
2775 keyspan_usa28_send_setup(serial, port, reset_port);
2776 break;
2777 case msg_usa49:
2778 keyspan_usa49_send_setup(serial, port, reset_port);
2779 break;
2780 case msg_usa90:
2781 keyspan_usa90_send_setup(serial, port, reset_port);
2782 break;
Lucy McCoy0ca12682007-05-18 12:10:41 -07002783 case msg_usa67:
2784 keyspan_usa67_send_setup(serial, port, reset_port);
2785 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002786 }
2787}
2788
2789
2790/* Gets called by the "real" driver (ie once firmware is loaded
2791 and renumeration has taken place. */
Alan Coxdeb91682008-07-22 11:13:08 +01002792static int keyspan_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793{
2794 int i, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796 const struct keyspan_device_details *d_details;
2797
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798 for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
Alan Coxdeb91682008-07-22 11:13:08 +01002799 if (d_details->product_id ==
2800 le16_to_cpu(serial->dev->descriptor.idProduct))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801 break;
2802 if (d_details == NULL) {
Alan Coxdeb91682008-07-22 11:13:08 +01002803 dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
2804 __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
Johan Hovoldff8a43c2013-08-13 13:27:35 +02002805 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002806 }
2807
2808 /* Setup private data for serial driver */
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +01002809 s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
Johan Hovold10c642d2013-12-29 19:22:56 +01002810 if (!s_priv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812
Johan Hovold2fcd1c92013-08-13 13:27:36 +02002813 s_priv->instat_buf = kzalloc(INSTAT_BUFLEN, GFP_KERNEL);
2814 if (!s_priv->instat_buf)
2815 goto err_instat_buf;
2816
2817 s_priv->indat_buf = kzalloc(INDAT49W_BUFLEN, GFP_KERNEL);
2818 if (!s_priv->indat_buf)
2819 goto err_indat_buf;
2820
2821 s_priv->glocont_buf = kzalloc(GLOCONT_BUFLEN, GFP_KERNEL);
2822 if (!s_priv->glocont_buf)
2823 goto err_glocont_buf;
2824
2825 s_priv->ctrl_buf = kzalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
2826 if (!s_priv->ctrl_buf)
2827 goto err_ctrl_buf;
2828
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829 s_priv->device_details = d_details;
2830 usb_set_serial_data(serial, s_priv);
2831
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832 keyspan_setup_urbs(serial);
2833
Lucy McCoy0ca12682007-05-18 12:10:41 -07002834 if (s_priv->instat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002835 err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
2836 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002837 dev_dbg(&serial->dev->dev, "%s - submit instat urb failed %d\n", __func__, err);
Lucy McCoy0ca12682007-05-18 12:10:41 -07002838 }
2839 if (s_priv->indat_urb != NULL) {
Lucy McCoy0ca12682007-05-18 12:10:41 -07002840 err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
2841 if (err != 0)
Greg Kroah-Hartman7ebcb332012-09-14 16:34:21 -07002842 dev_dbg(&serial->dev->dev, "%s - submit indat urb failed %d\n", __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843 }
Alan Coxdeb91682008-07-22 11:13:08 +01002844
Alan Coxa5b6f602008-04-08 17:16:06 +01002845 return 0;
Johan Hovold2fcd1c92013-08-13 13:27:36 +02002846
2847err_ctrl_buf:
2848 kfree(s_priv->glocont_buf);
2849err_glocont_buf:
2850 kfree(s_priv->indat_buf);
2851err_indat_buf:
2852 kfree(s_priv->instat_buf);
2853err_instat_buf:
2854 kfree(s_priv);
2855
2856 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002857}
2858
Alan Sternf9c99bb2009-06-02 11:53:55 -04002859static void keyspan_disconnect(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002861 struct keyspan_serial_private *s_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862
Linus Torvalds1da177e2005-04-16 15:20:36 -07002863 s_priv = usb_get_serial_data(serial);
2864
Johan Hovold61924502016-05-08 20:07:59 +02002865 usb_kill_urb(s_priv->instat_urb);
2866 usb_kill_urb(s_priv->glocont_urb);
2867 usb_kill_urb(s_priv->indat_urb);
Alan Sternf9c99bb2009-06-02 11:53:55 -04002868}
2869
2870static void keyspan_release(struct usb_serial *serial)
2871{
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002872 struct keyspan_serial_private *s_priv;
Alan Sternf9c99bb2009-06-02 11:53:55 -04002873
Alan Sternf9c99bb2009-06-02 11:53:55 -04002874 s_priv = usb_get_serial_data(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002875
Johan Hovold35be1a72016-05-08 20:07:58 +02002876 /* Make sure to unlink the URBs submitted in attach. */
2877 usb_kill_urb(s_priv->instat_urb);
2878 usb_kill_urb(s_priv->indat_urb);
2879
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002880 usb_free_urb(s_priv->instat_urb);
2881 usb_free_urb(s_priv->indat_urb);
2882 usb_free_urb(s_priv->glocont_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883
Johan Hovold2fcd1c92013-08-13 13:27:36 +02002884 kfree(s_priv->ctrl_buf);
2885 kfree(s_priv->glocont_buf);
2886 kfree(s_priv->indat_buf);
2887 kfree(s_priv->instat_buf);
2888
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002889 kfree(s_priv);
2890}
2891
2892static int keyspan_port_probe(struct usb_serial_port *port)
2893{
2894 struct usb_serial *serial = port->serial;
Bjørn Morkf0e3e352012-11-10 10:13:42 +01002895 struct keyspan_serial_private *s_priv;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002896 struct keyspan_port_private *p_priv;
2897 const struct keyspan_device_details *d_details;
2898 struct callbacks *cback;
2899 int endp;
2900 int port_num;
2901 int i;
2902
2903 s_priv = usb_get_serial_data(serial);
2904 d_details = s_priv->device_details;
2905
2906 p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL);
2907 if (!p_priv)
2908 return -ENOMEM;
2909
Johan Hovoldbad41a52013-08-13 13:27:37 +02002910 for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i) {
2911 p_priv->in_buffer[i] = kzalloc(IN_BUFLEN, GFP_KERNEL);
2912 if (!p_priv->in_buffer[i])
Wang Hai5f31af42021-10-15 16:55:43 +08002913 goto err_free_in_buffer;
Johan Hovoldbad41a52013-08-13 13:27:37 +02002914 }
2915
2916 for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i) {
2917 p_priv->out_buffer[i] = kzalloc(OUT_BUFLEN, GFP_KERNEL);
2918 if (!p_priv->out_buffer[i])
Wang Hai5f31af42021-10-15 16:55:43 +08002919 goto err_free_out_buffer;
Johan Hovoldbad41a52013-08-13 13:27:37 +02002920 }
2921
2922 p_priv->inack_buffer = kzalloc(INACK_BUFLEN, GFP_KERNEL);
2923 if (!p_priv->inack_buffer)
Wang Hai5f31af42021-10-15 16:55:43 +08002924 goto err_free_out_buffer;
Johan Hovoldbad41a52013-08-13 13:27:37 +02002925
2926 p_priv->outcont_buffer = kzalloc(OUTCONT_BUFLEN, GFP_KERNEL);
2927 if (!p_priv->outcont_buffer)
Wang Hai5f31af42021-10-15 16:55:43 +08002928 goto err_free_inack_buffer;
Johan Hovoldbad41a52013-08-13 13:27:37 +02002929
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002930 p_priv->device_details = d_details;
2931
2932 /* Setup values for the various callback routines */
2933 cback = &keyspan_callbacks[d_details->msg_format];
2934
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07002935 port_num = port->port_number;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002936
2937 /* Do indat endpoints first, once for each flip */
2938 endp = d_details->indat_endpoints[port_num];
2939 for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) {
2940 p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp,
2941 USB_DIR_IN, port,
Johan Hovoldbad41a52013-08-13 13:27:37 +02002942 p_priv->in_buffer[i],
2943 IN_BUFLEN,
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002944 cback->indat_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002945 }
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002946 /* outdat endpoints also have flip */
2947 endp = d_details->outdat_endpoints[port_num];
2948 for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) {
2949 p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp,
2950 USB_DIR_OUT, port,
Johan Hovoldbad41a52013-08-13 13:27:37 +02002951 p_priv->out_buffer[i],
2952 OUT_BUFLEN,
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002953 cback->outdat_callback);
2954 }
2955 /* inack endpoint */
2956 p_priv->inack_urb = keyspan_setup_urb(serial,
2957 d_details->inack_endpoints[port_num],
2958 USB_DIR_IN, port,
Johan Hovoldbad41a52013-08-13 13:27:37 +02002959 p_priv->inack_buffer,
2960 INACK_BUFLEN,
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002961 cback->inack_callback);
2962 /* outcont endpoint */
2963 p_priv->outcont_urb = keyspan_setup_urb(serial,
2964 d_details->outcont_endpoints[port_num],
2965 USB_DIR_OUT, port,
Johan Hovoldbad41a52013-08-13 13:27:37 +02002966 p_priv->outcont_buffer,
2967 OUTCONT_BUFLEN,
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002968 cback->outcont_callback);
2969
2970 usb_set_serial_port_data(port, p_priv);
2971
2972 return 0;
Johan Hovoldbad41a52013-08-13 13:27:37 +02002973
Wang Hai5f31af42021-10-15 16:55:43 +08002974err_free_inack_buffer:
Johan Hovoldbad41a52013-08-13 13:27:37 +02002975 kfree(p_priv->inack_buffer);
Wang Hai5f31af42021-10-15 16:55:43 +08002976err_free_out_buffer:
Johan Hovoldbad41a52013-08-13 13:27:37 +02002977 for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i)
2978 kfree(p_priv->out_buffer[i]);
Wang Hai5f31af42021-10-15 16:55:43 +08002979err_free_in_buffer:
Johan Hovoldbad41a52013-08-13 13:27:37 +02002980 for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i)
2981 kfree(p_priv->in_buffer[i]);
Johan Hovoldbad41a52013-08-13 13:27:37 +02002982 kfree(p_priv);
2983
2984 return -ENOMEM;
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002985}
2986
2987static int keyspan_port_remove(struct usb_serial_port *port)
2988{
2989 struct keyspan_port_private *p_priv;
2990 int i;
2991
2992 p_priv = usb_get_serial_port_data(port);
2993
Johan Hovold61924502016-05-08 20:07:59 +02002994 usb_kill_urb(p_priv->inack_urb);
2995 usb_kill_urb(p_priv->outcont_urb);
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002996 for (i = 0; i < 2; i++) {
Johan Hovold61924502016-05-08 20:07:59 +02002997 usb_kill_urb(p_priv->in_urbs[i]);
2998 usb_kill_urb(p_priv->out_urbs[i]);
Johan Hovoldf79b2d02012-10-25 10:29:15 +02002999 }
3000
3001 usb_free_urb(p_priv->inack_urb);
3002 usb_free_urb(p_priv->outcont_urb);
3003 for (i = 0; i < 2; i++) {
3004 usb_free_urb(p_priv->in_urbs[i]);
3005 usb_free_urb(p_priv->out_urbs[i]);
3006 }
3007
Johan Hovoldbad41a52013-08-13 13:27:37 +02003008 kfree(p_priv->outcont_buffer);
3009 kfree(p_priv->inack_buffer);
3010 for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i)
3011 kfree(p_priv->out_buffer[i]);
3012 for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i)
3013 kfree(p_priv->in_buffer[i]);
3014
Johan Hovoldf79b2d02012-10-25 10:29:15 +02003015 kfree(p_priv);
3016
3017 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003018}
3019
Johan Hovoldbeabdc32017-02-15 11:09:51 +01003020/* Structs for the devices, pre and post renumeration. */
3021static struct usb_serial_driver keyspan_pre_device = {
3022 .driver = {
3023 .owner = THIS_MODULE,
3024 .name = "keyspan_no_firm",
3025 },
3026 .description = "Keyspan - (without firmware)",
3027 .id_table = keyspan_pre_ids,
3028 .num_ports = 1,
3029 .attach = keyspan_fake_startup,
3030};
3031
3032static struct usb_serial_driver keyspan_1port_device = {
3033 .driver = {
3034 .owner = THIS_MODULE,
3035 .name = "keyspan_1",
3036 },
3037 .description = "Keyspan 1 port adapter",
3038 .id_table = keyspan_1port_ids,
3039 .num_ports = 1,
3040 .open = keyspan_open,
3041 .close = keyspan_close,
3042 .dtr_rts = keyspan_dtr_rts,
3043 .write = keyspan_write,
3044 .write_room = keyspan_write_room,
3045 .set_termios = keyspan_set_termios,
3046 .break_ctl = keyspan_break_ctl,
3047 .tiocmget = keyspan_tiocmget,
3048 .tiocmset = keyspan_tiocmset,
3049 .attach = keyspan_startup,
3050 .disconnect = keyspan_disconnect,
3051 .release = keyspan_release,
3052 .port_probe = keyspan_port_probe,
3053 .port_remove = keyspan_port_remove,
3054};
3055
3056static struct usb_serial_driver keyspan_2port_device = {
3057 .driver = {
3058 .owner = THIS_MODULE,
3059 .name = "keyspan_2",
3060 },
3061 .description = "Keyspan 2 port adapter",
3062 .id_table = keyspan_2port_ids,
3063 .num_ports = 2,
3064 .open = keyspan_open,
3065 .close = keyspan_close,
3066 .dtr_rts = keyspan_dtr_rts,
3067 .write = keyspan_write,
3068 .write_room = keyspan_write_room,
3069 .set_termios = keyspan_set_termios,
3070 .break_ctl = keyspan_break_ctl,
3071 .tiocmget = keyspan_tiocmget,
3072 .tiocmset = keyspan_tiocmset,
3073 .attach = keyspan_startup,
3074 .disconnect = keyspan_disconnect,
3075 .release = keyspan_release,
3076 .port_probe = keyspan_port_probe,
3077 .port_remove = keyspan_port_remove,
3078};
3079
3080static struct usb_serial_driver keyspan_4port_device = {
3081 .driver = {
3082 .owner = THIS_MODULE,
3083 .name = "keyspan_4",
3084 },
3085 .description = "Keyspan 4 port adapter",
3086 .id_table = keyspan_4port_ids,
3087 .num_ports = 4,
3088 .open = keyspan_open,
3089 .close = keyspan_close,
3090 .dtr_rts = keyspan_dtr_rts,
3091 .write = keyspan_write,
3092 .write_room = keyspan_write_room,
3093 .set_termios = keyspan_set_termios,
3094 .break_ctl = keyspan_break_ctl,
3095 .tiocmget = keyspan_tiocmget,
3096 .tiocmset = keyspan_tiocmset,
3097 .attach = keyspan_startup,
3098 .disconnect = keyspan_disconnect,
3099 .release = keyspan_release,
3100 .port_probe = keyspan_port_probe,
3101 .port_remove = keyspan_port_remove,
3102};
3103
3104static struct usb_serial_driver * const serial_drivers[] = {
3105 &keyspan_pre_device, &keyspan_1port_device,
3106 &keyspan_2port_device, &keyspan_4port_device, NULL
3107};
3108
3109module_usb_serial_driver(serial_drivers, keyspan_ids_combined);
3110
Alan Coxdeb91682008-07-22 11:13:08 +01003111MODULE_AUTHOR(DRIVER_AUTHOR);
3112MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113MODULE_LICENSE("GPL");
3114
David Woodhouse2971c572008-05-30 14:04:03 +03003115MODULE_FIRMWARE("keyspan/usa28.fw");
3116MODULE_FIRMWARE("keyspan/usa28x.fw");
3117MODULE_FIRMWARE("keyspan/usa28xa.fw");
3118MODULE_FIRMWARE("keyspan/usa28xb.fw");
3119MODULE_FIRMWARE("keyspan/usa19.fw");
3120MODULE_FIRMWARE("keyspan/usa19qi.fw");
3121MODULE_FIRMWARE("keyspan/mpr.fw");
3122MODULE_FIRMWARE("keyspan/usa19qw.fw");
3123MODULE_FIRMWARE("keyspan/usa18x.fw");
3124MODULE_FIRMWARE("keyspan/usa19w.fw");
3125MODULE_FIRMWARE("keyspan/usa49w.fw");
3126MODULE_FIRMWARE("keyspan/usa49wlc.fw");