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