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