Commit | Line | Data |
---|---|---|
d75662e1 BP |
1 | /* |
2 | * This code was developed for the Quatech USB line for linux, it used | |
3 | * much of the code developed by Greg Kroah-Hartman for USB serial devices | |
4 | * | |
5 | */ | |
6 | ||
7 | #include <linux/errno.h> | |
8 | #include <linux/init.h> | |
9 | #include <linux/slab.h> | |
10 | #include <linux/tty.h> | |
11 | #include <linux/tty_driver.h> | |
12 | #include <linux/tty_flip.h> | |
13 | #include <linux/module.h> | |
14 | #include <linux/serial.h> | |
15 | #include <linux/usb.h> | |
16 | #include <linux/usb/serial.h> | |
17 | #include <linux/uaccess.h> | |
18 | ||
d75662e1 BP |
19 | /* Version Information */ |
20 | #define DRIVER_VERSION "v2.14" | |
21 | #define DRIVER_AUTHOR "Tim Gobeli, Quatech, Inc" | |
22 | #define DRIVER_DESC "Quatech USB to Serial Driver" | |
23 | ||
24 | #define USB_VENDOR_ID_QUATECH 0x061d /* Quatech VID */ | |
d75662e1 BP |
25 | #define QUATECH_SSU200 0xC030 /* SSU200 */ |
26 | #define QUATECH_DSU100 0xC040 /* DSU100 */ | |
27 | #define QUATECH_DSU200 0xC050 /* DSU200 */ | |
28 | #define QUATECH_QSU100 0xC060 /* QSU100 */ | |
29 | #define QUATECH_QSU200 0xC070 /* QSU200 */ | |
30 | #define QUATECH_ESU100A 0xC080 /* ESU100A */ | |
31 | #define QUATECH_ESU100B 0xC081 /* ESU100B */ | |
32 | #define QUATECH_ESU200A 0xC0A0 /* ESU200A */ | |
33 | #define QUATECH_ESU200B 0xC0A1 /* ESU200B */ | |
34 | #define QUATECH_HSU100A 0xC090 /* HSU100A */ | |
35 | #define QUATECH_HSU100B 0xC091 /* HSU100B */ | |
36 | #define QUATECH_HSU100C 0xC092 /* HSU100C */ | |
37 | #define QUATECH_HSU100D 0xC093 /* HSU100D */ | |
38 | #define QUATECH_HSU200A 0xC0B0 /* HSU200A */ | |
39 | #define QUATECH_HSU200B 0xC0B1 /* HSU200B */ | |
40 | #define QUATECH_HSU200C 0xC0B2 /* HSU200C */ | |
41 | #define QUATECH_HSU200D 0xC0B3 /* HSU200D */ | |
d75662e1 BP |
42 | |
43 | #define QT_SET_GET_DEVICE 0xc2 | |
44 | #define QT_OPEN_CLOSE_CHANNEL 0xca | |
45 | #define QT_GET_SET_PREBUF_TRIG_LVL 0xcc | |
46 | #define QT_SET_ATF 0xcd | |
47 | #define QT_GET_SET_REGISTER 0xc0 | |
48 | #define QT_GET_SET_UART 0xc1 | |
49 | #define QT_HW_FLOW_CONTROL_MASK 0xc5 | |
50 | #define QT_SW_FLOW_CONTROL_MASK 0xc6 | |
51 | #define QT_SW_FLOW_CONTROL_DISABLE 0xc7 | |
52 | #define QT_BREAK_CONTROL 0xc8 | |
53 | ||
54 | #define USBD_TRANSFER_DIRECTION_IN 0xc0 | |
55 | #define USBD_TRANSFER_DIRECTION_OUT 0x40 | |
56 | ||
57 | #define MAX_BAUD_RATE 460800 | |
58 | #define MAX_BAUD_REMAINDER 4608 | |
59 | ||
60 | #define DIV_LATCH_LS 0x00 | |
61 | #define XMT_HOLD_REGISTER 0x00 | |
62 | #define XVR_BUFFER_REGISTER 0x00 | |
63 | #define DIV_LATCH_MS 0x01 | |
64 | #define FIFO_CONTROL_REGISTER 0x02 | |
65 | #define LINE_CONTROL_REGISTER 0x03 | |
66 | #define MODEM_CONTROL_REGISTER 0x04 | |
67 | #define LINE_STATUS_REGISTER 0x05 | |
68 | #define MODEM_STATUS_REGISTER 0x06 | |
69 | ||
70 | #define SERIAL_MCR_DTR 0x01 | |
71 | #define SERIAL_MCR_RTS 0x02 | |
72 | #define SERIAL_MCR_LOOP 0x10 | |
73 | ||
74 | #define SERIAL_MSR_CTS 0x10 | |
75 | #define SERIAL_MSR_CD 0x80 | |
76 | #define SERIAL_MSR_RI 0x40 | |
77 | #define SERIAL_MSR_DSR 0x20 | |
78 | #define SERIAL_MSR_MASK 0xf0 | |
79 | ||
80 | #define SERIAL_8_DATA 0x03 | |
81 | #define SERIAL_7_DATA 0x02 | |
82 | #define SERIAL_6_DATA 0x01 | |
83 | #define SERIAL_5_DATA 0x00 | |
84 | ||
85 | #define SERIAL_ODD_PARITY 0X08 | |
86 | #define SERIAL_EVEN_PARITY 0X18 | |
87 | #define SERIAL_TWO_STOPB 0x04 | |
88 | #define SERIAL_ONE_STOPB 0x00 | |
89 | ||
90 | #define DEFAULT_DIVISOR 0x30 /* gives 9600 baud rate */ | |
91 | #define DEFAULT_LCR SERIAL_8_DATA /* 8, none , 1 */ | |
92 | ||
93 | #define FULLPWRBIT 0x00000080 | |
94 | #define NEXT_BOARD_POWER_BIT 0x00000004 | |
95 | ||
96 | #define SERIAL_LSR_OE 0x02 | |
97 | #define SERIAL_LSR_PE 0x04 | |
98 | #define SERIAL_LSR_FE 0x08 | |
99 | #define SERIAL_LSR_BI 0x10 | |
100 | ||
101 | #define SERIAL_MSR_CTS 0x10 | |
102 | #define SERIAL_MSR_CD 0x80 | |
103 | #define SERIAL_MSR_RI 0x40 | |
104 | #define SERIAL_MSR_DSR 0x20 | |
105 | #define SERIAL_MSR_MASK 0xf0 | |
106 | ||
107 | #define PREFUFF_LEVEL_CONSERVATIVE 128 | |
108 | #define ATC_DISABLED 0x0 | |
109 | ||
110 | #define RR_BITS 0x03 /* for clearing clock bits */ | |
111 | #define DUPMODE_BITS 0xc0 | |
112 | #define CLKS_X4 0x02 | |
113 | ||
114 | #define LOOPMODE_BITS 0x41 /* LOOP1 = b6, LOOP0 = b0 (PORT B) */ | |
115 | #define ALL_LOOPBACK 0x01 | |
116 | #define MODEM_CTRL 0x40 | |
117 | #define RS232_MODE 0x00 | |
118 | ||
68e24113 | 119 | static const struct usb_device_id id_table[] = { |
d75662e1 BP |
120 | {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU200)}, |
121 | {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU100)}, | |
122 | {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU200)}, | |
123 | {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU100)}, | |
124 | {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU200)}, | |
125 | {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU100A)}, | |
126 | {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU100B)}, | |
127 | {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU200A)}, | |
128 | {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU200B)}, | |
129 | {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU100A)}, | |
130 | {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU100B)}, | |
131 | {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU100C)}, | |
132 | {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU100D)}, | |
133 | {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU200A)}, | |
134 | {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU200B)}, | |
135 | {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU200C)}, | |
136 | {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU200D)}, | |
d75662e1 BP |
137 | {} /* Terminating entry */ |
138 | }; | |
68e24113 | 139 | MODULE_DEVICE_TABLE(usb, id_table); |
d75662e1 BP |
140 | |
141 | struct qt_get_device_data { | |
142 | __u8 porta; | |
143 | __u8 portb; | |
144 | __u8 portc; | |
145 | }; | |
146 | ||
147 | struct qt_open_channel_data { | |
148 | __u8 line_status; | |
149 | __u8 modem_status; | |
150 | }; | |
151 | ||
152 | struct quatech_port { | |
153 | int port_num; /* number of the port */ | |
154 | struct urb *write_urb; /* write URB for this port */ | |
155 | struct urb *read_urb; /* read URB for this port */ | |
156 | struct urb *int_urb; | |
157 | ||
158 | __u8 shadowLCR; /* last LCR value received */ | |
159 | __u8 shadowMCR; /* last MCR value received */ | |
160 | __u8 shadowMSR; /* last MSR value received */ | |
161 | __u8 shadowLSR; /* last LSR value received */ | |
162 | char open_ports; | |
163 | ||
164 | /* Used for TIOCMIWAIT */ | |
165 | wait_queue_head_t msr_wait; | |
166 | char prev_status, diff_status; | |
167 | ||
168 | wait_queue_head_t wait; | |
169 | ||
170 | struct async_icount icount; | |
171 | ||
172 | struct usb_serial_port *port; /* owner of this object */ | |
173 | struct qt_get_device_data DeviceData; | |
fa2d8bbb | 174 | struct mutex lock; |
d75662e1 BP |
175 | bool read_urb_busy; |
176 | int RxHolding; | |
177 | int ReadBulkStopped; | |
178 | char closePending; | |
179 | }; | |
180 | ||
d75662e1 BP |
181 | static int port_paranoia_check(struct usb_serial_port *port, |
182 | const char *function) | |
183 | { | |
184 | if (!port) { | |
e8656b02 | 185 | pr_debug("%s - port == NULL", function); |
d75662e1 BP |
186 | return -1; |
187 | } | |
188 | if (!port->serial) { | |
e8656b02 | 189 | pr_debug("%s - port->serial == NULL\n", function); |
d75662e1 BP |
190 | return -1; |
191 | } | |
192 | ||
193 | return 0; | |
194 | } | |
195 | ||
196 | static int serial_paranoia_check(struct usb_serial *serial, | |
197 | const char *function) | |
198 | { | |
199 | if (!serial) { | |
e8656b02 | 200 | pr_debug("%s - serial == NULL\n", function); |
d75662e1 BP |
201 | return -1; |
202 | } | |
203 | ||
204 | if (!serial->type) { | |
e8656b02 | 205 | pr_debug("%s - serial->type == NULL!", function); |
d75662e1 BP |
206 | return -1; |
207 | } | |
208 | ||
209 | return 0; | |
210 | } | |
211 | ||
212 | static inline struct quatech_port *qt_get_port_private(struct usb_serial_port | |
213 | *port) | |
214 | { | |
215 | return (struct quatech_port *)usb_get_serial_port_data(port); | |
216 | } | |
217 | ||
218 | static inline void qt_set_port_private(struct usb_serial_port *port, | |
219 | struct quatech_port *data) | |
220 | { | |
221 | usb_set_serial_port_data(port, (void *)data); | |
222 | } | |
223 | ||
224 | static struct usb_serial *get_usb_serial(struct usb_serial_port *port, | |
225 | const char *function) | |
226 | { | |
227 | /* if no port was specified, or it fails a paranoia check */ | |
228 | if (!port || | |
229 | port_paranoia_check(port, function) || | |
230 | serial_paranoia_check(port->serial, function)) { | |
231 | /* | |
232 | * then say that we dont have a valid usb_serial thing, | |
233 | * which will end up genrating -ENODEV return values | |
234 | */ | |
235 | return NULL; | |
236 | } | |
237 | ||
238 | return port->serial; | |
239 | } | |
240 | ||
241 | static void ProcessLineStatus(struct quatech_port *qt_port, | |
242 | unsigned char line_status) | |
243 | { | |
244 | ||
245 | qt_port->shadowLSR = | |
246 | line_status & (SERIAL_LSR_OE | SERIAL_LSR_PE | SERIAL_LSR_FE | | |
247 | SERIAL_LSR_BI); | |
d75662e1 BP |
248 | } |
249 | ||
250 | static void ProcessModemStatus(struct quatech_port *qt_port, | |
251 | unsigned char modem_status) | |
252 | { | |
253 | ||
254 | qt_port->shadowMSR = modem_status; | |
255 | wake_up_interruptible(&qt_port->wait); | |
d75662e1 BP |
256 | } |
257 | ||
92a19f9c | 258 | static void ProcessRxChar(struct usb_serial_port *port, unsigned char data) |
d75662e1 | 259 | { |
d75662e1 | 260 | struct urb *urb = port->read_urb; |
94362fd7 | 261 | if (urb->actual_length) |
92a19f9c | 262 | tty_insert_flip_char(&port->port, data, TTY_NORMAL); |
d75662e1 BP |
263 | } |
264 | ||
265 | static void qt_write_bulk_callback(struct urb *urb) | |
266 | { | |
267 | struct tty_struct *tty; | |
268 | int status; | |
269 | struct quatech_port *quatech_port; | |
270 | ||
271 | status = urb->status; | |
272 | ||
273 | if (status) { | |
01295448 YT |
274 | dev_dbg(&urb->dev->dev, |
275 | "nonzero write bulk status received:%d\n", status); | |
d75662e1 BP |
276 | return; |
277 | } | |
278 | ||
279 | quatech_port = urb->context; | |
280 | ||
d75662e1 BP |
281 | tty = tty_port_tty_get(&quatech_port->port->port); |
282 | ||
283 | if (tty) | |
284 | tty_wakeup(tty); | |
285 | tty_kref_put(tty); | |
286 | } | |
287 | ||
288 | static void qt_interrupt_callback(struct urb *urb) | |
289 | { | |
290 | /* FIXME */ | |
291 | } | |
292 | ||
2e124b4a | 293 | static void qt_status_change_check(struct urb *urb, |
bbbd527b YT |
294 | struct quatech_port *qt_port, |
295 | struct usb_serial_port *port) | |
296 | { | |
297 | int flag, i; | |
298 | unsigned char *data = urb->transfer_buffer; | |
299 | unsigned int RxCount = urb->actual_length; | |
300 | ||
301 | for (i = 0; i < RxCount; ++i) { | |
302 | /* Look ahead code here */ | |
303 | if ((i <= (RxCount - 3)) && (data[i] == 0x1b) | |
304 | && (data[i + 1] == 0x1b)) { | |
305 | flag = 0; | |
306 | switch (data[i + 2]) { | |
307 | case 0x00: | |
9d36976f YT |
308 | if (i > (RxCount - 4)) { |
309 | dev_dbg(&port->dev, | |
310 | "Illegal escape seuences in received data\n"); | |
311 | break; | |
312 | } | |
313 | ||
314 | ProcessLineStatus(qt_port, data[i + 3]); | |
315 | ||
316 | i += 3; | |
317 | flag = 1; | |
318 | break; | |
319 | ||
bbbd527b | 320 | case 0x01: |
9d36976f YT |
321 | if (i > (RxCount - 4)) { |
322 | dev_dbg(&port->dev, | |
323 | "Illegal escape seuences in received data\n"); | |
324 | break; | |
325 | } | |
326 | ||
327 | ProcessModemStatus(qt_port, data[i + 3]); | |
328 | ||
329 | i += 3; | |
330 | flag = 1; | |
bbbd527b YT |
331 | break; |
332 | ||
333 | case 0xff: | |
334 | dev_dbg(&port->dev, "No status sequence.\n"); | |
335 | ||
92a19f9c JS |
336 | ProcessRxChar(port, data[i]); |
337 | ProcessRxChar(port, data[i + 1]); | |
bbbd527b YT |
338 | |
339 | i += 2; | |
340 | break; | |
341 | } | |
342 | if (flag == 1) | |
343 | continue; | |
344 | } | |
345 | ||
92a19f9c JS |
346 | if (urb->actual_length) |
347 | tty_insert_flip_char(&port->port, data[i], TTY_NORMAL); | |
bbbd527b YT |
348 | |
349 | } | |
2e124b4a | 350 | tty_flip_buffer_push(&port->port); |
bbbd527b YT |
351 | } |
352 | ||
d75662e1 BP |
353 | static void qt_read_bulk_callback(struct urb *urb) |
354 | { | |
355 | ||
356 | struct usb_serial_port *port = urb->context; | |
357 | struct usb_serial *serial = get_usb_serial(port, __func__); | |
358 | struct quatech_port *qt_port = qt_get_port_private(port); | |
bbbd527b | 359 | int result; |
d75662e1 BP |
360 | |
361 | if (urb->status) { | |
362 | qt_port->ReadBulkStopped = 1; | |
bbbd527b YT |
363 | dev_dbg(&urb->dev->dev, |
364 | "%s - nonzero write bulk status received: %d\n", | |
e8656b02 | 365 | __func__, urb->status); |
d75662e1 BP |
366 | return; |
367 | } | |
368 | ||
01295448 YT |
369 | dev_dbg(&port->dev, |
370 | "%s - port->RxHolding = %d\n", __func__, qt_port->RxHolding); | |
d75662e1 BP |
371 | |
372 | if (port_paranoia_check(port, __func__) != 0) { | |
d75662e1 | 373 | qt_port->ReadBulkStopped = 1; |
6732c8bb | 374 | return; |
d75662e1 BP |
375 | } |
376 | ||
e8656b02 | 377 | if (!serial) |
6732c8bb | 378 | return; |
e8656b02 | 379 | |
d75662e1 BP |
380 | if (qt_port->closePending == 1) { |
381 | /* Were closing , stop reading */ | |
01295448 YT |
382 | dev_dbg(&port->dev, |
383 | "%s - (qt_port->closepending == 1\n", __func__); | |
d75662e1 | 384 | qt_port->ReadBulkStopped = 1; |
6732c8bb | 385 | return; |
d75662e1 BP |
386 | } |
387 | ||
388 | /* | |
389 | * RxHolding is asserted by throttle, if we assert it, we're not | |
390 | * receiving any more characters and let the box handle the flow | |
391 | * control | |
392 | */ | |
393 | if (qt_port->RxHolding == 1) { | |
394 | qt_port->ReadBulkStopped = 1; | |
6732c8bb | 395 | return; |
d75662e1 BP |
396 | } |
397 | ||
398 | if (urb->status) { | |
399 | qt_port->ReadBulkStopped = 1; | |
400 | ||
bbbd527b YT |
401 | dev_dbg(&port->dev, |
402 | "%s - nonzero read bulk status received: %d\n", | |
e8656b02 | 403 | __func__, urb->status); |
6732c8bb | 404 | return; |
d75662e1 BP |
405 | } |
406 | ||
bbbd527b | 407 | if (urb->actual_length) |
2e124b4a | 408 | qt_status_change_check(urb, qt_port, port); |
d75662e1 BP |
409 | |
410 | /* Continue trying to always read */ | |
411 | usb_fill_bulk_urb(port->read_urb, serial->dev, | |
412 | usb_rcvbulkpipe(serial->dev, | |
413 | port->bulk_in_endpointAddress), | |
414 | port->read_urb->transfer_buffer, | |
415 | port->read_urb->transfer_buffer_length, | |
416 | qt_read_bulk_callback, port); | |
417 | result = usb_submit_urb(port->read_urb, GFP_ATOMIC); | |
418 | if (result) | |
bbbd527b YT |
419 | dev_dbg(&port->dev, |
420 | "%s - failed resubmitting read urb, error %d", | |
e8656b02 | 421 | __func__, result); |
d75662e1 | 422 | else { |
bbbd527b | 423 | if (urb->actual_length) { |
2e124b4a | 424 | tty_flip_buffer_push(&port->port); |
6732c8bb | 425 | tty_schedule_flip(&port->port); |
d75662e1 BP |
426 | } |
427 | } | |
428 | ||
429 | schedule_work(&port->work); | |
430 | } | |
431 | ||
432 | /* | |
433 | * qt_get_device | |
434 | * Issue a GET_DEVICE vendor-specific request on the default control pipe If | |
435 | * successful, fills in the qt_get_device_data structure pointed to by | |
436 | * device_data, otherwise return a negative error number of the problem. | |
437 | */ | |
438 | ||
439 | static int qt_get_device(struct usb_serial *serial, | |
440 | struct qt_get_device_data *device_data) | |
441 | { | |
442 | int result; | |
443 | unsigned char *transfer_buffer; | |
444 | ||
445 | transfer_buffer = | |
446 | kmalloc(sizeof(struct qt_get_device_data), GFP_KERNEL); | |
447 | if (!transfer_buffer) | |
448 | return -ENOMEM; | |
449 | ||
450 | result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | |
451 | QT_SET_GET_DEVICE, 0xc0, 0, 0, | |
452 | transfer_buffer, | |
453 | sizeof(struct qt_get_device_data), 300); | |
454 | if (result > 0) | |
455 | memcpy(device_data, transfer_buffer, | |
456 | sizeof(struct qt_get_device_data)); | |
457 | kfree(transfer_buffer); | |
458 | ||
459 | return result; | |
460 | } | |
461 | ||
462 | /**************************************************************************** | |
463 | * BoxSetPrebufferLevel | |
464 | TELLS BOX WHEN TO ASSERT FLOW CONTROL | |
465 | ****************************************************************************/ | |
466 | static int BoxSetPrebufferLevel(struct usb_serial *serial) | |
467 | { | |
468 | int result; | |
469 | __u16 buffer_length; | |
470 | ||
471 | buffer_length = PREFUFF_LEVEL_CONSERVATIVE; | |
472 | result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | |
473 | QT_GET_SET_PREBUF_TRIG_LVL, 0x40, | |
474 | buffer_length, 0, NULL, 0, 300); | |
475 | return result; | |
476 | } | |
477 | ||
478 | /**************************************************************************** | |
479 | * BoxSetATC | |
480 | TELLS BOX WHEN TO ASSERT automatic transmitter control | |
481 | ****************************************************************************/ | |
482 | static int BoxSetATC(struct usb_serial *serial, __u16 n_Mode) | |
483 | { | |
484 | int result; | |
485 | __u16 buffer_length; | |
486 | ||
487 | buffer_length = PREFUFF_LEVEL_CONSERVATIVE; | |
488 | ||
489 | result = | |
490 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | |
491 | QT_SET_ATF, 0x40, n_Mode, 0, NULL, 0, 300); | |
492 | ||
493 | return result; | |
494 | } | |
495 | ||
496 | /** | |
497 | * qt_set_device | |
498 | * Issue a SET_DEVICE vendor-specific request on the default control pipe If | |
499 | * successful returns the number of bytes written, otherwise it returns a | |
500 | * negative error number of the problem. | |
501 | */ | |
502 | static int qt_set_device(struct usb_serial *serial, | |
503 | struct qt_get_device_data *device_data) | |
504 | { | |
505 | int result; | |
506 | __u16 length; | |
507 | __u16 PortSettings; | |
508 | ||
509 | PortSettings = ((__u16) (device_data->portb)); | |
510 | PortSettings = (PortSettings << 8); | |
511 | PortSettings += ((__u16) (device_data->porta)); | |
512 | ||
513 | length = sizeof(struct qt_get_device_data); | |
d75662e1 BP |
514 | |
515 | result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | |
516 | QT_SET_GET_DEVICE, 0x40, PortSettings, | |
517 | 0, NULL, 0, 300); | |
518 | return result; | |
519 | } | |
520 | ||
521 | static int qt_open_channel(struct usb_serial *serial, __u16 Uart_Number, | |
522 | struct qt_open_channel_data *pDeviceData) | |
523 | { | |
524 | int result; | |
525 | ||
526 | result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | |
527 | QT_OPEN_CLOSE_CHANNEL, | |
528 | USBD_TRANSFER_DIRECTION_IN, 1, Uart_Number, | |
529 | pDeviceData, | |
530 | sizeof(struct qt_open_channel_data), 300); | |
531 | ||
532 | return result; | |
533 | ||
534 | } | |
535 | ||
536 | static int qt_close_channel(struct usb_serial *serial, __u16 Uart_Number) | |
537 | { | |
538 | int result; | |
539 | ||
540 | result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | |
541 | QT_OPEN_CLOSE_CHANNEL, | |
542 | USBD_TRANSFER_DIRECTION_OUT, 0, Uart_Number, | |
543 | NULL, 0, 300); | |
544 | ||
545 | return result; | |
546 | ||
547 | } | |
548 | ||
549 | /**************************************************************************** | |
550 | * BoxGetRegister | |
551 | * issuse a GET_REGISTER vendor-spcific request on the default control pipe | |
552 | * If successful, fills in the pValue with the register value asked for | |
553 | ****************************************************************************/ | |
554 | static int BoxGetRegister(struct usb_serial *serial, unsigned short Uart_Number, | |
555 | unsigned short Register_Num, __u8 *pValue) | |
556 | { | |
557 | int result; | |
558 | __u16 current_length; | |
559 | ||
560 | current_length = sizeof(struct qt_get_device_data); | |
561 | ||
562 | result = | |
563 | usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | |
564 | QT_GET_SET_REGISTER, 0xC0, Register_Num, | |
565 | Uart_Number, (void *)pValue, sizeof(*pValue), 300); | |
566 | ||
567 | return result; | |
568 | } | |
569 | ||
570 | /**************************************************************************** | |
571 | * BoxSetRegister | |
572 | * issuse a GET_REGISTER vendor-spcific request on the default control pipe | |
573 | * If successful, fills in the pValue with the register value asked for | |
574 | ****************************************************************************/ | |
575 | static int BoxSetRegister(struct usb_serial *serial, unsigned short Uart_Number, | |
576 | unsigned short Register_Num, unsigned short Value) | |
577 | { | |
578 | int result; | |
579 | unsigned short RegAndByte; | |
580 | ||
581 | RegAndByte = Value; | |
582 | RegAndByte = RegAndByte << 8; | |
583 | RegAndByte = RegAndByte + Register_Num; | |
584 | ||
585 | /* | |
586 | result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | |
587 | QT_GET_SET_REGISTER, 0xC0, Register_Num, | |
588 | Uart_Number, NULL, 0, 300); | |
589 | */ | |
590 | ||
591 | result = | |
592 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | |
593 | QT_GET_SET_REGISTER, 0x40, RegAndByte, Uart_Number, | |
594 | NULL, 0, 300); | |
595 | ||
596 | return result; | |
597 | } | |
598 | ||
599 | /* | |
600 | * qt_setuart | |
1351acce | 601 | * issues a SET_UART vendor-specific request on the default control pipe |
d75662e1 BP |
602 | * If successful sets baud rate divisor and LCR value |
603 | */ | |
604 | static int qt_setuart(struct usb_serial *serial, unsigned short Uart_Number, | |
605 | unsigned short default_divisor, unsigned char default_LCR) | |
606 | { | |
607 | int result; | |
608 | unsigned short UartNumandLCR; | |
609 | ||
610 | UartNumandLCR = (default_LCR << 8) + Uart_Number; | |
611 | ||
612 | result = | |
613 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | |
614 | QT_GET_SET_UART, 0x40, default_divisor, | |
615 | UartNumandLCR, NULL, 0, 300); | |
616 | ||
617 | return result; | |
618 | } | |
619 | ||
620 | static int BoxSetHW_FlowCtrl(struct usb_serial *serial, unsigned int index, | |
621 | int bSet) | |
622 | { | |
623 | __u8 mcr = 0; | |
624 | __u8 msr = 0, MOUT_Value = 0; | |
625 | unsigned int status; | |
626 | ||
627 | if (bSet == 1) { | |
628 | /* flow control, box will clear RTS line to prevent remote */ | |
629 | mcr = SERIAL_MCR_RTS; | |
630 | } /* device from xmitting more chars */ | |
631 | else { | |
632 | /* no flow control to remote device */ | |
633 | mcr = 0; | |
634 | ||
635 | } | |
636 | MOUT_Value = mcr << 8; | |
637 | ||
638 | if (bSet == 1) { | |
639 | /* flow control, box will inhibit xmit data if CTS line is | |
640 | * asserted */ | |
641 | msr = SERIAL_MSR_CTS; | |
642 | } else { | |
643 | /* Box will not inhimbe xmit data due to CTS line */ | |
644 | msr = 0; | |
645 | } | |
646 | MOUT_Value |= msr; | |
647 | ||
648 | status = | |
649 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | |
650 | QT_HW_FLOW_CONTROL_MASK, 0x40, MOUT_Value, | |
651 | index, NULL, 0, 300); | |
652 | return status; | |
653 | ||
654 | } | |
655 | ||
656 | static int BoxSetSW_FlowCtrl(struct usb_serial *serial, __u16 index, | |
657 | unsigned char stop_char, unsigned char start_char) | |
658 | { | |
659 | __u16 nSWflowout; | |
660 | int result; | |
661 | ||
662 | nSWflowout = start_char << 8; | |
663 | nSWflowout = (unsigned short)stop_char; | |
664 | ||
665 | result = | |
666 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | |
667 | QT_SW_FLOW_CONTROL_MASK, 0x40, nSWflowout, | |
668 | index, NULL, 0, 300); | |
669 | return result; | |
670 | ||
671 | } | |
672 | ||
673 | static int BoxDisable_SW_FlowCtrl(struct usb_serial *serial, __u16 index) | |
674 | { | |
675 | int result; | |
676 | ||
677 | result = | |
678 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | |
679 | QT_SW_FLOW_CONTROL_DISABLE, 0x40, 0, index, | |
680 | NULL, 0, 300); | |
681 | return result; | |
682 | ||
683 | } | |
684 | ||
685 | static int qt_startup(struct usb_serial *serial) | |
686 | { | |
e8656b02 | 687 | struct device *dev = &serial->dev->dev; |
d75662e1 BP |
688 | struct usb_serial_port *port; |
689 | struct quatech_port *qt_port; | |
690 | struct qt_get_device_data DeviceData; | |
691 | int i; | |
692 | int status; | |
693 | ||
d75662e1 BP |
694 | /* Now setup per port private data */ |
695 | for (i = 0; i < serial->num_ports; i++) { | |
696 | port = serial->port[i]; | |
697 | qt_port = kzalloc(sizeof(*qt_port), GFP_KERNEL); | |
698 | if (!qt_port) { | |
1695eb36 | 699 | for (--i; i >= 0; i--) { |
de8f8bd6 ON |
700 | port = serial->port[i]; |
701 | kfree(usb_get_serial_port_data(port)); | |
702 | usb_set_serial_port_data(port, NULL); | |
703 | } | |
d75662e1 BP |
704 | return -ENOMEM; |
705 | } | |
fa2d8bbb | 706 | mutex_init(&qt_port->lock); |
d75662e1 BP |
707 | |
708 | usb_set_serial_port_data(port, qt_port); | |
709 | ||
710 | } | |
711 | ||
712 | status = qt_get_device(serial, &DeviceData); | |
e8656b02 | 713 | if (status < 0) |
d75662e1 | 714 | goto startup_error; |
d75662e1 | 715 | |
e8656b02 | 716 | dev_dbg(dev, "DeviceData.portb = 0x%x\n", DeviceData.portb); |
d75662e1 BP |
717 | |
718 | DeviceData.portb &= ~FULLPWRBIT; | |
e8656b02 | 719 | dev_dbg(dev, "Changing DeviceData.portb to 0x%x\n", DeviceData.portb); |
d75662e1 BP |
720 | |
721 | status = qt_set_device(serial, &DeviceData); | |
722 | if (status < 0) { | |
e8656b02 | 723 | dev_dbg(dev, "qt_set_device failed\n"); |
d75662e1 BP |
724 | goto startup_error; |
725 | } | |
726 | ||
727 | status = qt_get_device(serial, &DeviceData); | |
728 | if (status < 0) { | |
e8656b02 | 729 | dev_dbg(dev, "qt_get_device failed\n"); |
d75662e1 BP |
730 | goto startup_error; |
731 | } | |
732 | ||
733 | switch (serial->dev->descriptor.idProduct) { | |
d75662e1 BP |
734 | case QUATECH_DSU100: |
735 | case QUATECH_QSU100: | |
736 | case QUATECH_ESU100A: | |
737 | case QUATECH_ESU100B: | |
738 | case QUATECH_HSU100A: | |
739 | case QUATECH_HSU100B: | |
740 | case QUATECH_HSU100C: | |
741 | case QUATECH_HSU100D: | |
742 | DeviceData.porta &= ~(RR_BITS | DUPMODE_BITS); | |
743 | DeviceData.porta |= CLKS_X4; | |
744 | DeviceData.portb &= ~(LOOPMODE_BITS); | |
745 | DeviceData.portb |= RS232_MODE; | |
746 | break; | |
747 | ||
748 | case QUATECH_SSU200: | |
749 | case QUATECH_DSU200: | |
750 | case QUATECH_QSU200: | |
751 | case QUATECH_ESU200A: | |
752 | case QUATECH_ESU200B: | |
753 | case QUATECH_HSU200A: | |
754 | case QUATECH_HSU200B: | |
755 | case QUATECH_HSU200C: | |
756 | case QUATECH_HSU200D: | |
757 | DeviceData.porta &= ~(RR_BITS | DUPMODE_BITS); | |
758 | DeviceData.porta |= CLKS_X4; | |
759 | DeviceData.portb &= ~(LOOPMODE_BITS); | |
760 | DeviceData.portb |= ALL_LOOPBACK; | |
761 | break; | |
762 | default: | |
763 | DeviceData.porta &= ~(RR_BITS | DUPMODE_BITS); | |
764 | DeviceData.porta |= CLKS_X4; | |
765 | DeviceData.portb &= ~(LOOPMODE_BITS); | |
766 | DeviceData.portb |= RS232_MODE; | |
767 | break; | |
768 | ||
769 | } | |
770 | ||
771 | status = BoxSetPrebufferLevel(serial); /* sets to default value */ | |
772 | if (status < 0) { | |
e8656b02 | 773 | dev_dbg(dev, "BoxSetPrebufferLevel failed\n"); |
d75662e1 BP |
774 | goto startup_error; |
775 | } | |
776 | ||
777 | status = BoxSetATC(serial, ATC_DISABLED); | |
778 | if (status < 0) { | |
e8656b02 | 779 | dev_dbg(dev, "BoxSetATC failed\n"); |
d75662e1 BP |
780 | goto startup_error; |
781 | } | |
782 | ||
e8656b02 | 783 | dev_dbg(dev, "DeviceData.portb = 0x%x\n", DeviceData.portb); |
d75662e1 BP |
784 | |
785 | DeviceData.portb |= NEXT_BOARD_POWER_BIT; | |
e8656b02 | 786 | dev_dbg(dev, "Changing DeviceData.portb to 0x%x\n", DeviceData.portb); |
d75662e1 BP |
787 | |
788 | status = qt_set_device(serial, &DeviceData); | |
789 | if (status < 0) { | |
e8656b02 | 790 | dev_dbg(dev, "qt_set_device failed\n"); |
d75662e1 BP |
791 | goto startup_error; |
792 | } | |
793 | ||
d75662e1 BP |
794 | return 0; |
795 | ||
796 | startup_error: | |
797 | for (i = 0; i < serial->num_ports; i++) { | |
798 | port = serial->port[i]; | |
799 | qt_port = qt_get_port_private(port); | |
800 | kfree(qt_port); | |
801 | usb_set_serial_port_data(port, NULL); | |
802 | } | |
803 | ||
d75662e1 BP |
804 | return -EIO; |
805 | } | |
806 | ||
807 | static void qt_release(struct usb_serial *serial) | |
808 | { | |
809 | struct usb_serial_port *port; | |
810 | struct quatech_port *qt_port; | |
811 | int i; | |
812 | ||
d75662e1 BP |
813 | for (i = 0; i < serial->num_ports; i++) { |
814 | port = serial->port[i]; | |
815 | if (!port) | |
816 | continue; | |
817 | ||
818 | qt_port = usb_get_serial_port_data(port); | |
819 | kfree(qt_port); | |
820 | usb_set_serial_port_data(port, NULL); | |
821 | } | |
822 | ||
823 | } | |
824 | ||
04e9d11b YT |
825 | static void qt_submit_urb_from_open(struct usb_serial *serial, |
826 | struct usb_serial_port *port) | |
827 | { | |
828 | int result; | |
829 | struct usb_serial_port *port0 = serial->port[0]; | |
830 | ||
831 | /* set up interrupt urb */ | |
832 | usb_fill_int_urb(port0->interrupt_in_urb, | |
833 | serial->dev, | |
834 | usb_rcvintpipe(serial->dev, | |
835 | port0->interrupt_in_endpointAddress), | |
836 | port0->interrupt_in_buffer, | |
837 | port0->interrupt_in_urb->transfer_buffer_length, | |
838 | qt_interrupt_callback, serial, | |
839 | port0->interrupt_in_urb->interval); | |
840 | ||
841 | result = usb_submit_urb(port0->interrupt_in_urb, | |
842 | GFP_KERNEL); | |
843 | if (result) { | |
844 | dev_err(&port->dev, | |
845 | "%s - Error %d submitting interrupt urb\n", | |
846 | __func__, result); | |
847 | } | |
848 | } | |
849 | ||
35e2bed5 | 850 | static int qt_open(struct tty_struct *tty, |
2386b331 | 851 | struct usb_serial_port *port) |
d75662e1 BP |
852 | { |
853 | struct usb_serial *serial; | |
854 | struct quatech_port *quatech_port; | |
855 | struct quatech_port *port0; | |
856 | struct qt_open_channel_data ChannelData; | |
857 | ||
858 | int result; | |
859 | ||
860 | if (port_paranoia_check(port, __func__)) | |
861 | return -ENODEV; | |
862 | ||
d75662e1 BP |
863 | serial = port->serial; |
864 | ||
865 | if (serial_paranoia_check(serial, __func__)) | |
866 | return -ENODEV; | |
867 | ||
868 | quatech_port = qt_get_port_private(port); | |
869 | port0 = qt_get_port_private(serial->port[0]); | |
870 | ||
871 | if (quatech_port == NULL || port0 == NULL) | |
872 | return -ENODEV; | |
873 | ||
874 | usb_clear_halt(serial->dev, port->write_urb->pipe); | |
875 | usb_clear_halt(serial->dev, port->read_urb->pipe); | |
876 | port0->open_ports++; | |
877 | ||
878 | result = qt_get_device(serial, &port0->DeviceData); | |
879 | ||
880 | /* Port specific setups */ | |
881 | result = qt_open_channel(serial, port->number, &ChannelData); | |
882 | if (result < 0) { | |
e8656b02 | 883 | dev_dbg(&port->dev, "qt_open_channel failed\n"); |
d75662e1 BP |
884 | return result; |
885 | } | |
e8656b02 | 886 | dev_dbg(&port->dev, "qt_open_channel completed.\n"); |
d75662e1 BP |
887 | |
888 | /* FIXME: are these needed? Does it even do anything useful? */ | |
889 | quatech_port->shadowLSR = ChannelData.line_status & | |
890 | (SERIAL_LSR_OE | SERIAL_LSR_PE | SERIAL_LSR_FE | SERIAL_LSR_BI); | |
891 | ||
892 | quatech_port->shadowMSR = ChannelData.modem_status & | |
893 | (SERIAL_MSR_CTS | SERIAL_MSR_DSR | SERIAL_MSR_RI | SERIAL_MSR_CD); | |
894 | ||
895 | /* Set Baud rate to default and turn off (default)flow control here */ | |
896 | result = qt_setuart(serial, port->number, DEFAULT_DIVISOR, DEFAULT_LCR); | |
897 | if (result < 0) { | |
e8656b02 | 898 | dev_dbg(&port->dev, "qt_setuart failed\n"); |
d75662e1 BP |
899 | return result; |
900 | } | |
e8656b02 | 901 | dev_dbg(&port->dev, "qt_setuart completed.\n"); |
d75662e1 BP |
902 | |
903 | /* | |
bbc9a991 | 904 | * Put this here to make it responsive to stty and defaults set by |
d75662e1 BP |
905 | * the tty layer |
906 | */ | |
d75662e1 BP |
907 | |
908 | /* Check to see if we've set up our endpoint info yet */ | |
909 | if (port0->open_ports == 1) { | |
04e9d11b YT |
910 | if (serial->port[0]->interrupt_in_buffer == NULL) |
911 | qt_submit_urb_from_open(serial, port); | |
d75662e1 BP |
912 | } |
913 | ||
e8656b02 GKH |
914 | dev_dbg(&port->dev, "port number is %d\n", port->number); |
915 | dev_dbg(&port->dev, "serial number is %d\n", port->serial->minor); | |
01295448 YT |
916 | dev_dbg(&port->dev, |
917 | "Bulkin endpoint is %d\n", port->bulk_in_endpointAddress); | |
918 | dev_dbg(&port->dev, | |
919 | "BulkOut endpoint is %d\n", port->bulk_out_endpointAddress); | |
920 | dev_dbg(&port->dev, "Interrupt endpoint is %d\n", | |
921 | port->interrupt_in_endpointAddress); | |
922 | dev_dbg(&port->dev, "port's number in the device is %d\n", | |
923 | quatech_port->port_num); | |
d75662e1 BP |
924 | quatech_port->read_urb = port->read_urb; |
925 | ||
926 | /* set up our bulk in urb */ | |
927 | ||
928 | usb_fill_bulk_urb(quatech_port->read_urb, | |
929 | serial->dev, | |
930 | usb_rcvbulkpipe(serial->dev, | |
931 | port->bulk_in_endpointAddress), | |
932 | port->bulk_in_buffer, | |
933 | quatech_port->read_urb->transfer_buffer_length, | |
934 | qt_read_bulk_callback, quatech_port); | |
935 | ||
01295448 YT |
936 | dev_dbg(&port->dev, "qt_open: bulkin endpoint is %d\n", |
937 | port->bulk_in_endpointAddress); | |
d75662e1 BP |
938 | quatech_port->read_urb_busy = true; |
939 | result = usb_submit_urb(quatech_port->read_urb, GFP_KERNEL); | |
940 | if (result) { | |
941 | dev_err(&port->dev, | |
942 | "%s - Error %d submitting control urb\n", | |
943 | __func__, result); | |
944 | quatech_port->read_urb_busy = false; | |
945 | } | |
946 | ||
947 | /* initialize our wait queues */ | |
948 | init_waitqueue_head(&quatech_port->wait); | |
949 | init_waitqueue_head(&quatech_port->msr_wait); | |
950 | ||
951 | /* initialize our icount structure */ | |
952 | memset(&(quatech_port->icount), 0x00, sizeof(quatech_port->icount)); | |
953 | ||
954 | return 0; | |
955 | ||
956 | } | |
957 | ||
958 | static int qt_chars_in_buffer(struct tty_struct *tty) | |
959 | { | |
960 | struct usb_serial_port *port = tty->driver_data; | |
961 | struct usb_serial *serial; | |
962 | int chars = 0; | |
963 | ||
964 | serial = get_usb_serial(port, __func__); | |
965 | ||
d75662e1 BP |
966 | if (serial->num_bulk_out) { |
967 | if (port->write_urb->status == -EINPROGRESS) | |
968 | chars = port->write_urb->transfer_buffer_length; | |
969 | } | |
970 | ||
d75662e1 BP |
971 | return chars; |
972 | } | |
973 | ||
974 | static void qt_block_until_empty(struct tty_struct *tty, | |
975 | struct quatech_port *qt_port) | |
976 | { | |
977 | int timeout = HZ / 10; | |
978 | int wait = 30; | |
979 | int count; | |
980 | ||
981 | while (1) { | |
982 | ||
983 | count = qt_chars_in_buffer(tty); | |
984 | ||
985 | if (count <= 0) | |
986 | return; | |
987 | ||
988 | interruptible_sleep_on_timeout(&qt_port->wait, timeout); | |
989 | ||
990 | wait--; | |
991 | if (wait == 0) { | |
e8656b02 | 992 | dev_dbg(&qt_port->port->dev, "%s - TIMEOUT", __func__); |
d75662e1 BP |
993 | return; |
994 | } else { | |
995 | wait = 30; | |
996 | } | |
997 | } | |
998 | } | |
999 | ||
f3a75688 | 1000 | static void qt_close(struct usb_serial_port *port) |
d75662e1 BP |
1001 | { |
1002 | struct usb_serial *serial = port->serial; | |
1003 | struct quatech_port *qt_port; | |
1004 | struct quatech_port *port0; | |
d9dea3c1 | 1005 | struct tty_struct *tty; |
d75662e1 BP |
1006 | int status; |
1007 | unsigned int index; | |
1008 | status = 0; | |
1009 | ||
d9dea3c1 | 1010 | tty = tty_port_tty_get(&port->port); |
d75662e1 BP |
1011 | index = tty->index - serial->minor; |
1012 | ||
1013 | qt_port = qt_get_port_private(port); | |
1014 | port0 = qt_get_port_private(serial->port[0]); | |
1015 | ||
1016 | /* shutdown any bulk reads that might be going on */ | |
1017 | if (serial->num_bulk_out) | |
1018 | usb_unlink_urb(port->write_urb); | |
1019 | if (serial->num_bulk_in) | |
1020 | usb_unlink_urb(port->read_urb); | |
1021 | ||
1022 | /* wait up to for transmitter to empty */ | |
1023 | if (serial->dev) | |
1024 | qt_block_until_empty(tty, qt_port); | |
f3a75688 | 1025 | tty_kref_put(tty); |
d75662e1 BP |
1026 | |
1027 | /* Close uart channel */ | |
1028 | status = qt_close_channel(serial, index); | |
1029 | if (status < 0) | |
01295448 YT |
1030 | dev_dbg(&port->dev, |
1031 | "%s - port %d qt_close_channel failed.\n", | |
1032 | __func__, port->number); | |
d75662e1 BP |
1033 | |
1034 | port0->open_ports--; | |
1035 | ||
01295448 YT |
1036 | dev_dbg(&port->dev, "qt_num_open_ports in close%d:in port%d\n", |
1037 | port0->open_ports, port->number); | |
d75662e1 BP |
1038 | |
1039 | if (port0->open_ports == 0) { | |
1040 | if (serial->port[0]->interrupt_in_urb) { | |
01295448 | 1041 | dev_dbg(&port->dev, "Shutdown interrupt_in_urb\n"); |
d75662e1 BP |
1042 | usb_kill_urb(serial->port[0]->interrupt_in_urb); |
1043 | } | |
1044 | ||
1045 | } | |
1046 | ||
1047 | if (qt_port->write_urb) { | |
1048 | /* if this urb had a transfer buffer already (old tx) free it */ | |
ef055f10 | 1049 | kfree(qt_port->write_urb->transfer_buffer); |
d75662e1 BP |
1050 | usb_free_urb(qt_port->write_urb); |
1051 | } | |
1052 | ||
1053 | } | |
1054 | ||
1055 | static int qt_write(struct tty_struct *tty, struct usb_serial_port *port, | |
1056 | const unsigned char *buf, int count) | |
1057 | { | |
1058 | int result; | |
1059 | struct usb_serial *serial = get_usb_serial(port, __func__); | |
1060 | ||
1061 | if (serial == NULL) | |
1062 | return -ENODEV; | |
1063 | ||
d75662e1 | 1064 | if (count == 0) { |
01295448 YT |
1065 | dev_dbg(&port->dev, |
1066 | "%s - write request of 0 bytes\n", __func__); | |
d75662e1 BP |
1067 | return 0; |
1068 | } | |
1069 | ||
1070 | /* only do something if we have a bulk out endpoint */ | |
1071 | if (serial->num_bulk_out) { | |
1072 | if (port->write_urb->status == -EINPROGRESS) { | |
e8656b02 | 1073 | dev_dbg(&port->dev, "%s - already writing\n", __func__); |
d75662e1 BP |
1074 | return 0; |
1075 | } | |
1076 | ||
1077 | count = | |
1078 | (count > port->bulk_out_size) ? port->bulk_out_size : count; | |
1079 | memcpy(port->write_urb->transfer_buffer, buf, count); | |
1080 | ||
1081 | /* set up our urb */ | |
1082 | ||
1083 | usb_fill_bulk_urb(port->write_urb, serial->dev, | |
1084 | usb_sndbulkpipe(serial->dev, | |
1085 | port-> | |
1086 | bulk_out_endpointAddress), | |
1087 | port->write_urb->transfer_buffer, count, | |
1088 | qt_write_bulk_callback, port); | |
1089 | ||
1090 | /* send the data out the bulk port */ | |
1091 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | |
1092 | if (result) | |
01295448 YT |
1093 | dev_dbg(&port->dev, |
1094 | "%s - failed submitting write urb, error %d\n", | |
e8656b02 | 1095 | __func__, result); |
d75662e1 BP |
1096 | else |
1097 | result = count; | |
1098 | ||
1099 | return result; | |
1100 | } | |
1101 | ||
1102 | /* no bulk out, so return 0 bytes written */ | |
1103 | return 0; | |
1104 | } | |
1105 | ||
1106 | static int qt_write_room(struct tty_struct *tty) | |
1107 | { | |
1108 | struct usb_serial_port *port = tty->driver_data; | |
1109 | struct usb_serial *serial; | |
1110 | struct quatech_port *qt_port; | |
d75662e1 BP |
1111 | |
1112 | int retval = -EINVAL; | |
1113 | ||
e8656b02 | 1114 | if (port_paranoia_check(port, __func__)) |
d75662e1 | 1115 | return -1; |
d75662e1 BP |
1116 | |
1117 | serial = get_usb_serial(port, __func__); | |
1118 | ||
1119 | if (!serial) | |
1120 | return -ENODEV; | |
1121 | ||
1122 | qt_port = qt_get_port_private(port); | |
1123 | ||
fa2d8bbb | 1124 | mutex_lock(&qt_port->lock); |
d75662e1 | 1125 | |
d75662e1 BP |
1126 | if (serial->num_bulk_out) { |
1127 | if (port->write_urb->status != -EINPROGRESS) | |
1128 | retval = port->bulk_out_size; | |
1129 | } | |
1130 | ||
fa2d8bbb | 1131 | mutex_unlock(&qt_port->lock); |
d75662e1 BP |
1132 | return retval; |
1133 | ||
1134 | } | |
1135 | ||
00a0d0d6 | 1136 | static int qt_ioctl(struct tty_struct *tty, |
d75662e1 BP |
1137 | unsigned int cmd, unsigned long arg) |
1138 | { | |
1139 | struct usb_serial_port *port = tty->driver_data; | |
1140 | struct quatech_port *qt_port = qt_get_port_private(port); | |
1141 | struct usb_serial *serial = get_usb_serial(port, __func__); | |
1142 | unsigned int index; | |
1143 | ||
e8656b02 | 1144 | dev_dbg(&port->dev, "%s cmd 0x%04x\n", __func__, cmd); |
d75662e1 BP |
1145 | |
1146 | index = tty->index - serial->minor; | |
1147 | ||
1148 | if (cmd == TIOCMIWAIT) { | |
1149 | while (qt_port != NULL) { | |
1150 | interruptible_sleep_on(&qt_port->msr_wait); | |
1151 | if (signal_pending(current)) | |
1152 | return -ERESTARTSYS; | |
1153 | else { | |
1154 | char diff = qt_port->diff_status; | |
1155 | ||
1156 | if (diff == 0) | |
1157 | return -EIO; /* no change => error */ | |
1158 | ||
1159 | /* Consume all events */ | |
1160 | qt_port->diff_status = 0; | |
1161 | ||
1162 | if (((arg & TIOCM_RNG) | |
1163 | && (diff & SERIAL_MSR_RI)) | |
1164 | || ((arg & TIOCM_DSR) | |
1165 | && (diff & SERIAL_MSR_DSR)) | |
1166 | || ((arg & TIOCM_CD) | |
1167 | && (diff & SERIAL_MSR_CD)) | |
1168 | || ((arg & TIOCM_CTS) | |
1169 | && (diff & SERIAL_MSR_CTS))) { | |
1170 | return 0; | |
1171 | } | |
1172 | } | |
1173 | } | |
1174 | return 0; | |
1175 | } | |
1176 | ||
01295448 YT |
1177 | dev_dbg(&port->dev, "%s -No ioctl for that one. port = %d\n", |
1178 | __func__, port->number); | |
d75662e1 BP |
1179 | return -ENOIOCTLCMD; |
1180 | } | |
1181 | ||
1182 | static void qt_set_termios(struct tty_struct *tty, | |
1183 | struct usb_serial_port *port, | |
1184 | struct ktermios *old_termios) | |
1185 | { | |
9b12daf7 | 1186 | struct ktermios *termios = &tty->termios; |
d75662e1 BP |
1187 | unsigned char new_LCR = 0; |
1188 | unsigned int cflag = termios->c_cflag; | |
1189 | unsigned int index; | |
1190 | int baud, divisor, remainder; | |
1191 | int status; | |
1192 | ||
d75662e1 BP |
1193 | index = tty->index - port->serial->minor; |
1194 | ||
9b12daf7 | 1195 | switch (cflag & CSIZE) { |
d75662e1 BP |
1196 | case CS5: |
1197 | new_LCR |= SERIAL_5_DATA; | |
1198 | break; | |
1199 | case CS6: | |
1200 | new_LCR |= SERIAL_6_DATA; | |
1201 | break; | |
1202 | case CS7: | |
1203 | new_LCR |= SERIAL_7_DATA; | |
1204 | break; | |
1205 | default: | |
9b12daf7 AC |
1206 | termios->c_cflag &= ~CSIZE; |
1207 | termios->c_cflag |= CS8; | |
d75662e1 BP |
1208 | case CS8: |
1209 | new_LCR |= SERIAL_8_DATA; | |
1210 | break; | |
1211 | } | |
1212 | ||
1213 | /* Parity stuff */ | |
1214 | if (cflag & PARENB) { | |
1215 | if (cflag & PARODD) | |
1216 | new_LCR |= SERIAL_ODD_PARITY; | |
1217 | else | |
1218 | new_LCR |= SERIAL_EVEN_PARITY; | |
1219 | } | |
1220 | if (cflag & CSTOPB) | |
1221 | new_LCR |= SERIAL_TWO_STOPB; | |
1222 | else | |
35f077dc | 1223 | new_LCR |= SERIAL_ONE_STOPB; |
d75662e1 | 1224 | |
e8656b02 | 1225 | dev_dbg(&port->dev, "%s - 4\n", __func__); |
d75662e1 BP |
1226 | |
1227 | /* Thats the LCR stuff, go ahead and set it */ | |
1228 | baud = tty_get_baud_rate(tty); | |
1229 | if (!baud) | |
1230 | /* pick a default, any default... */ | |
1231 | baud = 9600; | |
1232 | ||
e8656b02 | 1233 | dev_dbg(&port->dev, "%s - got baud = %d\n", __func__, baud); |
d75662e1 BP |
1234 | |
1235 | divisor = MAX_BAUD_RATE / baud; | |
1236 | remainder = MAX_BAUD_RATE % baud; | |
1237 | /* Round to nearest divisor */ | |
1238 | if (((remainder * 2) >= baud) && (baud != 110)) | |
1239 | divisor++; | |
1240 | ||
1241 | /* | |
1242 | * Set Baud rate to default and turn off (default)flow control here | |
1243 | */ | |
1244 | status = | |
1245 | qt_setuart(port->serial, index, (unsigned short)divisor, new_LCR); | |
1246 | if (status < 0) { | |
e8656b02 | 1247 | dev_dbg(&port->dev, "qt_setuart failed\n"); |
d75662e1 BP |
1248 | return; |
1249 | } | |
1250 | ||
1251 | /* Now determine flow control */ | |
1252 | if (cflag & CRTSCTS) { | |
01295448 YT |
1253 | dev_dbg(&port->dev, "%s - Enabling HW flow control port %d\n", |
1254 | __func__, port->number); | |
d75662e1 BP |
1255 | |
1256 | /* Enable RTS/CTS flow control */ | |
1257 | status = BoxSetHW_FlowCtrl(port->serial, index, 1); | |
1258 | ||
1259 | if (status < 0) { | |
e8656b02 | 1260 | dev_dbg(&port->dev, "BoxSetHW_FlowCtrl failed\n"); |
d75662e1 BP |
1261 | return; |
1262 | } | |
1263 | } else { | |
1264 | /* Disable RTS/CTS flow control */ | |
01295448 YT |
1265 | dev_dbg(&port->dev, |
1266 | "%s - disabling HW flow control port %d\n", | |
1267 | __func__, port->number); | |
d75662e1 BP |
1268 | |
1269 | status = BoxSetHW_FlowCtrl(port->serial, index, 0); | |
1270 | if (status < 0) { | |
e8656b02 | 1271 | dev_dbg(&port->dev, "BoxSetHW_FlowCtrl failed\n"); |
d75662e1 BP |
1272 | return; |
1273 | } | |
1274 | ||
1275 | } | |
1276 | ||
1277 | /* if we are implementing XON/XOFF, set the start and stop character in | |
1278 | * the device */ | |
1279 | if (I_IXOFF(tty) || I_IXON(tty)) { | |
1280 | unsigned char stop_char = STOP_CHAR(tty); | |
1281 | unsigned char start_char = START_CHAR(tty); | |
1282 | status = | |
1283 | BoxSetSW_FlowCtrl(port->serial, index, stop_char, | |
1284 | start_char); | |
1285 | if (status < 0) | |
01295448 YT |
1286 | dev_dbg(&port->dev, |
1287 | "BoxSetSW_FlowCtrl (enabled) failed\n"); | |
d75662e1 BP |
1288 | |
1289 | } else { | |
1290 | /* disable SW flow control */ | |
1291 | status = BoxDisable_SW_FlowCtrl(port->serial, index); | |
1292 | if (status < 0) | |
01295448 YT |
1293 | dev_dbg(&port->dev, |
1294 | "BoxSetSW_FlowCtrl (diabling) failed\n"); | |
d75662e1 BP |
1295 | |
1296 | } | |
9b12daf7 | 1297 | termios->c_cflag &= ~CMSPAR; |
01295448 YT |
1298 | /* FIXME: |
1299 | Error cases should be returning the actual bits changed only | |
1300 | */ | |
d75662e1 BP |
1301 | } |
1302 | ||
1303 | static void qt_break(struct tty_struct *tty, int break_state) | |
1304 | { | |
1305 | struct usb_serial_port *port = tty->driver_data; | |
1306 | struct usb_serial *serial = get_usb_serial(port, __func__); | |
1307 | struct quatech_port *qt_port; | |
1308 | u16 index, onoff; | |
1309 | unsigned int result; | |
d75662e1 BP |
1310 | |
1311 | index = tty->index - serial->minor; | |
1312 | ||
1313 | qt_port = qt_get_port_private(port); | |
1314 | ||
1315 | if (break_state == -1) | |
1316 | onoff = 1; | |
1317 | else | |
1318 | onoff = 0; | |
1319 | ||
fa2d8bbb | 1320 | mutex_lock(&qt_port->lock); |
d75662e1 | 1321 | |
d75662e1 BP |
1322 | result = |
1323 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | |
1324 | QT_BREAK_CONTROL, 0x40, onoff, index, NULL, 0, 300); | |
1325 | ||
fa2d8bbb | 1326 | mutex_unlock(&qt_port->lock); |
d75662e1 BP |
1327 | } |
1328 | ||
1329 | static inline int qt_real_tiocmget(struct tty_struct *tty, | |
1330 | struct usb_serial_port *port, | |
60b33c13 | 1331 | struct usb_serial *serial) |
d75662e1 BP |
1332 | { |
1333 | ||
1334 | u8 mcr; | |
1335 | u8 msr; | |
1336 | unsigned int result = 0; | |
1337 | int status; | |
1338 | unsigned int index; | |
1339 | ||
d75662e1 BP |
1340 | index = tty->index - serial->minor; |
1341 | status = | |
1342 | BoxGetRegister(port->serial, index, MODEM_CONTROL_REGISTER, &mcr); | |
1343 | if (status >= 0) { | |
1344 | status = | |
1345 | BoxGetRegister(port->serial, index, | |
1346 | MODEM_STATUS_REGISTER, &msr); | |
1347 | ||
1348 | } | |
1349 | ||
1350 | if (status >= 0) { | |
1351 | result = ((mcr & SERIAL_MCR_DTR) ? TIOCM_DTR : 0) | |
1352 | /* DTR IS SET */ | |
1353 | | ((mcr & SERIAL_MCR_RTS) ? TIOCM_RTS : 0) | |
1354 | /* RTS IS SET */ | |
1355 | | ((msr & SERIAL_MSR_CTS) ? TIOCM_CTS : 0) | |
1356 | /* CTS is set */ | |
1357 | | ((msr & SERIAL_MSR_CD) ? TIOCM_CAR : 0) | |
1358 | /* Carrier detect is set */ | |
1359 | | ((msr & SERIAL_MSR_RI) ? TIOCM_RI : 0) | |
1360 | /* Ring indicator set */ | |
1361 | | ((msr & SERIAL_MSR_DSR) ? TIOCM_DSR : 0); | |
1362 | /* DSR is set */ | |
1363 | return result; | |
1364 | ||
1365 | } else | |
1366 | return -ESPIPE; | |
1367 | } | |
1368 | ||
1369 | static inline int qt_real_tiocmset(struct tty_struct *tty, | |
1370 | struct usb_serial_port *port, | |
d75662e1 BP |
1371 | struct usb_serial *serial, |
1372 | unsigned int value) | |
1373 | { | |
1374 | ||
1375 | u8 mcr; | |
1376 | int status; | |
1377 | unsigned int index; | |
1378 | ||
d75662e1 BP |
1379 | index = tty->index - serial->minor; |
1380 | status = | |
1381 | BoxGetRegister(port->serial, index, MODEM_CONTROL_REGISTER, &mcr); | |
1382 | if (status < 0) | |
1383 | return -ESPIPE; | |
1384 | ||
1385 | /* | |
1351acce | 1386 | * Turn off the RTS and DTR and loopback and then only turn on what was |
d75662e1 BP |
1387 | * asked for |
1388 | */ | |
1389 | mcr &= ~(SERIAL_MCR_RTS | SERIAL_MCR_DTR | SERIAL_MCR_LOOP); | |
1390 | if (value & TIOCM_RTS) | |
1391 | mcr |= SERIAL_MCR_RTS; | |
1392 | if (value & TIOCM_DTR) | |
1393 | mcr |= SERIAL_MCR_DTR; | |
1394 | if (value & TIOCM_LOOP) | |
1395 | mcr |= SERIAL_MCR_LOOP; | |
1396 | ||
1397 | status = | |
1398 | BoxSetRegister(port->serial, index, MODEM_CONTROL_REGISTER, mcr); | |
1399 | if (status < 0) | |
1400 | return -ESPIPE; | |
1401 | else | |
1402 | return 0; | |
1403 | } | |
1404 | ||
60b33c13 | 1405 | static int qt_tiocmget(struct tty_struct *tty) |
d75662e1 BP |
1406 | { |
1407 | struct usb_serial_port *port = tty->driver_data; | |
1408 | struct usb_serial *serial = get_usb_serial(port, __func__); | |
1409 | struct quatech_port *qt_port = qt_get_port_private(port); | |
7b11eb3e | 1410 | int retval; |
d75662e1 | 1411 | |
d75662e1 BP |
1412 | if (!serial) |
1413 | return -ENODEV; | |
1414 | ||
fa2d8bbb | 1415 | mutex_lock(&qt_port->lock); |
60b33c13 | 1416 | retval = qt_real_tiocmget(tty, port, serial); |
fa2d8bbb | 1417 | mutex_unlock(&qt_port->lock); |
d75662e1 BP |
1418 | return retval; |
1419 | } | |
1420 | ||
20b9d177 | 1421 | static int qt_tiocmset(struct tty_struct *tty, |
d75662e1 BP |
1422 | unsigned int set, unsigned int clear) |
1423 | { | |
1424 | ||
1425 | struct usb_serial_port *port = tty->driver_data; | |
1426 | struct usb_serial *serial = get_usb_serial(port, __func__); | |
1427 | struct quatech_port *qt_port = qt_get_port_private(port); | |
7b11eb3e | 1428 | int retval; |
d75662e1 | 1429 | |
d75662e1 BP |
1430 | if (!serial) |
1431 | return -ENODEV; | |
1432 | ||
fa2d8bbb | 1433 | mutex_lock(&qt_port->lock); |
20b9d177 | 1434 | retval = qt_real_tiocmset(tty, port, serial, set); |
fa2d8bbb | 1435 | mutex_unlock(&qt_port->lock); |
d75662e1 BP |
1436 | return retval; |
1437 | } | |
1438 | ||
1439 | static void qt_throttle(struct tty_struct *tty) | |
1440 | { | |
1441 | struct usb_serial_port *port = tty->driver_data; | |
1442 | struct usb_serial *serial = get_usb_serial(port, __func__); | |
1443 | struct quatech_port *qt_port; | |
d75662e1 | 1444 | |
d75662e1 BP |
1445 | if (!serial) |
1446 | return; | |
1447 | ||
1448 | qt_port = qt_get_port_private(port); | |
1449 | ||
fa2d8bbb | 1450 | mutex_lock(&qt_port->lock); |
d75662e1 BP |
1451 | |
1452 | /* pass on to the driver specific version of this function */ | |
1453 | qt_port->RxHolding = 1; | |
d75662e1 | 1454 | |
fa2d8bbb | 1455 | mutex_unlock(&qt_port->lock); |
d75662e1 BP |
1456 | } |
1457 | ||
7028035d YT |
1458 | static void qt_submit_urb_from_unthrottle(struct usb_serial_port *port, |
1459 | struct usb_serial *serial) | |
1460 | { | |
1461 | int result; | |
1462 | ||
1463 | /* Start reading from the device */ | |
1464 | usb_fill_bulk_urb(port->read_urb, serial->dev, | |
1465 | usb_rcvbulkpipe(serial->dev, | |
1466 | port->bulk_in_endpointAddress), | |
1467 | port->read_urb->transfer_buffer, | |
1468 | port->read_urb->transfer_buffer_length, | |
1469 | qt_read_bulk_callback, port); | |
1470 | ||
1471 | result = usb_submit_urb(port->read_urb, GFP_ATOMIC); | |
1472 | ||
1473 | if (result) | |
1474 | dev_err(&port->dev, | |
1475 | "%s - failed restarting read urb, error %d\n", | |
1476 | __func__, result); | |
1477 | } | |
1478 | ||
d75662e1 BP |
1479 | static void qt_unthrottle(struct tty_struct *tty) |
1480 | { | |
1481 | struct usb_serial_port *port = tty->driver_data; | |
1482 | struct usb_serial *serial = get_usb_serial(port, __func__); | |
1483 | struct quatech_port *qt_port; | |
d75662e1 BP |
1484 | |
1485 | if (!serial) | |
1486 | return; | |
1487 | ||
1488 | qt_port = qt_get_port_private(port); | |
1489 | ||
fa2d8bbb | 1490 | mutex_lock(&qt_port->lock); |
d75662e1 | 1491 | |
d75662e1 | 1492 | if (qt_port->RxHolding == 1) { |
e8656b02 | 1493 | dev_dbg(&port->dev, "%s -qt_port->RxHolding == 1\n", __func__); |
d75662e1 BP |
1494 | |
1495 | qt_port->RxHolding = 0; | |
e8656b02 | 1496 | dev_dbg(&port->dev, "%s - qt_port->RxHolding = 0\n", __func__); |
d75662e1 BP |
1497 | |
1498 | /* if we have a bulk endpoint, start it up */ | |
7028035d YT |
1499 | if ((serial->num_bulk_in) && (qt_port->ReadBulkStopped == 1)) |
1500 | qt_submit_urb_from_unthrottle(port, serial); | |
d75662e1 | 1501 | } |
fa2d8bbb | 1502 | mutex_unlock(&qt_port->lock); |
d75662e1 BP |
1503 | } |
1504 | ||
1505 | static int qt_calc_num_ports(struct usb_serial *serial) | |
1506 | { | |
1507 | int num_ports; | |
1508 | ||
d75662e1 BP |
1509 | num_ports = |
1510 | (serial->interface->cur_altsetting->desc.bNumEndpoints - 1) / 2; | |
1511 | ||
1512 | return num_ports; | |
1513 | } | |
1514 | ||
1515 | static struct usb_serial_driver quatech_device = { | |
1516 | .driver = { | |
1517 | .owner = THIS_MODULE, | |
1518 | .name = "serqt", | |
1519 | }, | |
1520 | .description = DRIVER_DESC, | |
68e24113 | 1521 | .id_table = id_table, |
d75662e1 BP |
1522 | .num_ports = 8, |
1523 | .open = qt_open, | |
1524 | .close = qt_close, | |
1525 | .write = qt_write, | |
1526 | .write_room = qt_write_room, | |
1527 | .chars_in_buffer = qt_chars_in_buffer, | |
1528 | .throttle = qt_throttle, | |
1529 | .unthrottle = qt_unthrottle, | |
1530 | .calc_num_ports = qt_calc_num_ports, | |
1531 | .ioctl = qt_ioctl, | |
1532 | .set_termios = qt_set_termios, | |
1533 | .break_ctl = qt_break, | |
1534 | .tiocmget = qt_tiocmget, | |
1535 | .tiocmset = qt_tiocmset, | |
1536 | .attach = qt_startup, | |
1537 | .release = qt_release, | |
1538 | }; | |
1539 | ||
69276a33 AS |
1540 | static struct usb_serial_driver * const serial_drivers[] = { |
1541 | &quatech_device, NULL | |
1542 | }; | |
1543 | ||
68e24113 | 1544 | module_usb_serial_driver(serial_drivers, id_table); |
d75662e1 BP |
1545 | |
1546 | MODULE_AUTHOR(DRIVER_AUTHOR); | |
1547 | MODULE_DESCRIPTION(DRIVER_DESC); | |
1548 | MODULE_LICENSE("GPL"); |