diff options
author | Bill Pemberton <wfp5p@virginia.edu> | 2009-05-31 15:49:43 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-06-19 14:00:56 -0400 |
commit | d75662e164d5175c5e5f9339ff4d6f6980613d96 (patch) | |
tree | 3f08149504b3643d3913354991d6da1017dd8fec | |
parent | 0d99b6eb851fbea9e31ad23f70c8f9fbefd6e4e8 (diff) |
Staging: Add serqt_usb2, a rewrite of serqt_usb for the usb-serial layer
This is the serqt_usb driver rewritten to use usb-serial.
Signed-off-by: Bill Pemberton <wfp5p@virginia.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/staging/serqt_usb2/Kconfig | 9 | ||||
-rw-r--r-- | drivers/staging/serqt_usb2/Makefile | 1 | ||||
-rw-r--r-- | drivers/staging/serqt_usb2/serqt_usb2.c | 1664 |
3 files changed, 1674 insertions, 0 deletions
diff --git a/drivers/staging/serqt_usb2/Kconfig b/drivers/staging/serqt_usb2/Kconfig new file mode 100644 index 000000000000..f4fed40e23dd --- /dev/null +++ b/drivers/staging/serqt_usb2/Kconfig | |||
@@ -0,0 +1,9 @@ | |||
1 | config USB_SERIAL_QUATECH2 | ||
2 | tristate "USB Quatech ESU-100 8 Port Serial Driver" | ||
3 | depends on USB_SERIAL | ||
4 | help | ||
5 | Say Y here if you want to use the Quatech ESU-100 8 port usb to | ||
6 | serial adapter. | ||
7 | |||
8 | To compile this driver as a module, choose M here: the | ||
9 | module will be called serqt_usb2. | ||
diff --git a/drivers/staging/serqt_usb2/Makefile b/drivers/staging/serqt_usb2/Makefile new file mode 100644 index 000000000000..21578617f7e8 --- /dev/null +++ b/drivers/staging/serqt_usb2/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_USB_SERIAL_QUATECH2) += serqt_usb2.o | |||
diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c new file mode 100644 index 000000000000..581232b719fd --- /dev/null +++ b/drivers/staging/serqt_usb2/serqt_usb2.c | |||
@@ -0,0 +1,1664 @@ | |||
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 | |||
129 | static struct usb_device_id serqt_id_table[] = { | ||
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 | |||
287 | static void ProcessRxChar(struct usb_serial_port *port, unsigned char Data) | ||
288 | { | ||
289 | struct tty_struct *tty; | ||
290 | struct urb *urb = port->read_urb; | ||
291 | tty = tty_port_tty_get(&port->port); | ||
292 | |||
293 | /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */ | ||
294 | |||
295 | if (tty && urb->actual_length) { | ||
296 | tty_buffer_request_room(tty, 1); | ||
297 | tty_insert_flip_string(tty, &Data, 1); | ||
298 | /* tty_flip_buffer_push(tty); */ | ||
299 | } | ||
300 | |||
301 | return; | ||
302 | } | ||
303 | |||
304 | static void qt_write_bulk_callback(struct urb *urb) | ||
305 | { | ||
306 | struct tty_struct *tty; | ||
307 | int status; | ||
308 | struct quatech_port *quatech_port; | ||
309 | |||
310 | status = urb->status; | ||
311 | |||
312 | if (status) { | ||
313 | dbg("nonzero write bulk status received:%d\n", status); | ||
314 | return; | ||
315 | } | ||
316 | |||
317 | quatech_port = urb->context; | ||
318 | |||
319 | dbg("%s - port %d\n", __func__, quatech_port->port_num); | ||
320 | |||
321 | tty = tty_port_tty_get(&quatech_port->port->port); | ||
322 | |||
323 | if (tty) | ||
324 | tty_wakeup(tty); | ||
325 | tty_kref_put(tty); | ||
326 | } | ||
327 | |||
328 | static void qt_interrupt_callback(struct urb *urb) | ||
329 | { | ||
330 | /* FIXME */ | ||
331 | } | ||
332 | |||
333 | static void qt_read_bulk_callback(struct urb *urb) | ||
334 | { | ||
335 | |||
336 | struct usb_serial_port *port = urb->context; | ||
337 | struct usb_serial *serial = get_usb_serial(port, __func__); | ||
338 | struct quatech_port *qt_port = qt_get_port_private(port); | ||
339 | unsigned char *data; | ||
340 | struct tty_struct *tty; | ||
341 | unsigned int index; | ||
342 | unsigned int RxCount; | ||
343 | int i, result; | ||
344 | int flag, flag_data; | ||
345 | |||
346 | if (urb->status) { | ||
347 | qt_port->ReadBulkStopped = 1; | ||
348 | dbg("%s - nonzero write bulk status received: %d\n", | ||
349 | __func__, urb->status); | ||
350 | return; | ||
351 | } | ||
352 | |||
353 | tty = tty_port_tty_get(&port->port); | ||
354 | if (!tty) { | ||
355 | dbg("%s - bad tty pointer - exiting", __func__); | ||
356 | return; | ||
357 | } | ||
358 | |||
359 | data = urb->transfer_buffer; | ||
360 | |||
361 | RxCount = urb->actual_length; | ||
362 | |||
363 | /* index = MINOR(port->tty->device) - serial->minor; */ | ||
364 | index = tty->index - serial->minor; | ||
365 | |||
366 | dbg("%s - port %d\n", __func__, port->number); | ||
367 | dbg("%s - port->RxHolding = %d\n", __func__, qt_port->RxHolding); | ||
368 | |||
369 | if (port_paranoia_check(port, __func__) != 0) { | ||
370 | dbg("%s - port_paranoia_check, exiting\n", __func__); | ||
371 | qt_port->ReadBulkStopped = 1; | ||
372 | return; | ||
373 | } | ||
374 | |||
375 | if (!serial) { | ||
376 | dbg("%s - bad serial pointer, exiting\n", __func__); | ||
377 | return; | ||
378 | } | ||
379 | if (qt_port->closePending == 1) { | ||
380 | /* Were closing , stop reading */ | ||
381 | dbg("%s - (qt_port->closepending == 1\n", __func__); | ||
382 | qt_port->ReadBulkStopped = 1; | ||
383 | return; | ||
384 | } | ||
385 | |||
386 | /* | ||
387 | * RxHolding is asserted by throttle, if we assert it, we're not | ||
388 | * receiving any more characters and let the box handle the flow | ||
389 | * control | ||
390 | */ | ||
391 | if (qt_port->RxHolding == 1) { | ||
392 | qt_port->ReadBulkStopped = 1; | ||
393 | return; | ||
394 | } | ||
395 | |||
396 | if (urb->status) { | ||
397 | qt_port->ReadBulkStopped = 1; | ||
398 | |||
399 | dbg("%s - nonzero read bulk status received: %d\n", | ||
400 | __func__, urb->status); | ||
401 | return; | ||
402 | } | ||
403 | |||
404 | if (tty && RxCount) { | ||
405 | flag_data = 0; | ||
406 | for (i = 0; i < RxCount; ++i) { | ||
407 | /* Look ahead code here */ | ||
408 | if ((i <= (RxCount - 3)) && (data[i] == 0x1b) | ||
409 | && (data[i + 1] == 0x1b)) { | ||
410 | flag = 0; | ||
411 | switch (data[i + 2]) { | ||
412 | case 0x00: | ||
413 | /* line status change 4th byte must follow */ | ||
414 | if (i > (RxCount - 4)) { | ||
415 | dbg("Illegal escape seuences in received data\n"); | ||
416 | break; | ||
417 | } | ||
418 | ProcessLineStatus(qt_port, data[i + 3]); | ||
419 | i += 3; | ||
420 | flag = 1; | ||
421 | break; | ||
422 | |||
423 | case 0x01: | ||
424 | /* Modem status status change 4th byte must follow */ | ||
425 | dbg("Modem status status. \n"); | ||
426 | if (i > (RxCount - 4)) { | ||
427 | dbg("Illegal escape sequences in received data\n"); | ||
428 | break; | ||
429 | } | ||
430 | ProcessModemStatus(qt_port, | ||
431 | data[i + 3]); | ||
432 | i += 3; | ||
433 | flag = 1; | ||
434 | break; | ||
435 | case 0xff: | ||
436 | dbg("No status sequence. \n"); | ||
437 | |||
438 | ProcessRxChar(port, data[i]); | ||
439 | ProcessRxChar(port, data[i + 1]); | ||
440 | i += 2; | ||
441 | break; | ||
442 | } | ||
443 | if (flag == 1) | ||
444 | continue; | ||
445 | } | ||
446 | |||
447 | if (tty && urb->actual_length) { | ||
448 | tty_buffer_request_room(tty, 1); | ||
449 | tty_insert_flip_string(tty, (data + i), 1); | ||
450 | } | ||
451 | |||
452 | } | ||
453 | tty_flip_buffer_push(tty); | ||
454 | } | ||
455 | |||
456 | /* Continue trying to always read */ | ||
457 | usb_fill_bulk_urb(port->read_urb, serial->dev, | ||
458 | usb_rcvbulkpipe(serial->dev, | ||
459 | port->bulk_in_endpointAddress), | ||
460 | port->read_urb->transfer_buffer, | ||
461 | port->read_urb->transfer_buffer_length, | ||
462 | qt_read_bulk_callback, port); | ||
463 | result = usb_submit_urb(port->read_urb, GFP_ATOMIC); | ||
464 | if (result) | ||
465 | dbg("%s - failed resubmitting read urb, error %d", | ||
466 | __func__, result); | ||
467 | else { | ||
468 | if (tty && RxCount) { | ||
469 | tty_flip_buffer_push(tty); | ||
470 | tty_schedule_flip(tty); | ||
471 | } | ||
472 | } | ||
473 | |||
474 | schedule_work(&port->work); | ||
475 | } | ||
476 | |||
477 | /* | ||
478 | * qt_get_device | ||
479 | * Issue a GET_DEVICE vendor-specific request on the default control pipe If | ||
480 | * successful, fills in the qt_get_device_data structure pointed to by | ||
481 | * device_data, otherwise return a negative error number of the problem. | ||
482 | */ | ||
483 | |||
484 | static int qt_get_device(struct usb_serial *serial, | ||
485 | struct qt_get_device_data *device_data) | ||
486 | { | ||
487 | int result; | ||
488 | unsigned char *transfer_buffer; | ||
489 | |||
490 | transfer_buffer = | ||
491 | kmalloc(sizeof(struct qt_get_device_data), GFP_KERNEL); | ||
492 | if (!transfer_buffer) | ||
493 | return -ENOMEM; | ||
494 | |||
495 | result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | ||
496 | QT_SET_GET_DEVICE, 0xc0, 0, 0, | ||
497 | transfer_buffer, | ||
498 | sizeof(struct qt_get_device_data), 300); | ||
499 | if (result > 0) | ||
500 | memcpy(device_data, transfer_buffer, | ||
501 | sizeof(struct qt_get_device_data)); | ||
502 | kfree(transfer_buffer); | ||
503 | |||
504 | return result; | ||
505 | } | ||
506 | |||
507 | /**************************************************************************** | ||
508 | * BoxSetPrebufferLevel | ||
509 | TELLS BOX WHEN TO ASSERT FLOW CONTROL | ||
510 | ****************************************************************************/ | ||
511 | static int BoxSetPrebufferLevel(struct usb_serial *serial) | ||
512 | { | ||
513 | int result; | ||
514 | __u16 buffer_length; | ||
515 | |||
516 | buffer_length = PREFUFF_LEVEL_CONSERVATIVE; | ||
517 | result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | ||
518 | QT_GET_SET_PREBUF_TRIG_LVL, 0x40, | ||
519 | buffer_length, 0, NULL, 0, 300); | ||
520 | return result; | ||
521 | } | ||
522 | |||
523 | /**************************************************************************** | ||
524 | * BoxSetATC | ||
525 | TELLS BOX WHEN TO ASSERT automatic transmitter control | ||
526 | ****************************************************************************/ | ||
527 | static int BoxSetATC(struct usb_serial *serial, __u16 n_Mode) | ||
528 | { | ||
529 | int result; | ||
530 | __u16 buffer_length; | ||
531 | |||
532 | buffer_length = PREFUFF_LEVEL_CONSERVATIVE; | ||
533 | |||
534 | result = | ||
535 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | ||
536 | QT_SET_ATF, 0x40, n_Mode, 0, NULL, 0, 300); | ||
537 | |||
538 | return result; | ||
539 | } | ||
540 | |||
541 | /** | ||
542 | * qt_set_device | ||
543 | * Issue a SET_DEVICE vendor-specific request on the default control pipe If | ||
544 | * successful returns the number of bytes written, otherwise it returns a | ||
545 | * negative error number of the problem. | ||
546 | */ | ||
547 | static int qt_set_device(struct usb_serial *serial, | ||
548 | struct qt_get_device_data *device_data) | ||
549 | { | ||
550 | int result; | ||
551 | __u16 length; | ||
552 | __u16 PortSettings; | ||
553 | |||
554 | PortSettings = ((__u16) (device_data->portb)); | ||
555 | PortSettings = (PortSettings << 8); | ||
556 | PortSettings += ((__u16) (device_data->porta)); | ||
557 | |||
558 | length = sizeof(struct qt_get_device_data); | ||
559 | dbg("%s - PortSettings = 0x%x\n", __func__, PortSettings); | ||
560 | |||
561 | result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | ||
562 | QT_SET_GET_DEVICE, 0x40, PortSettings, | ||
563 | 0, NULL, 0, 300); | ||
564 | return result; | ||
565 | } | ||
566 | |||
567 | static int qt_open_channel(struct usb_serial *serial, __u16 Uart_Number, | ||
568 | struct qt_open_channel_data *pDeviceData) | ||
569 | { | ||
570 | int result; | ||
571 | |||
572 | result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | ||
573 | QT_OPEN_CLOSE_CHANNEL, | ||
574 | USBD_TRANSFER_DIRECTION_IN, 1, Uart_Number, | ||
575 | pDeviceData, | ||
576 | sizeof(struct qt_open_channel_data), 300); | ||
577 | |||
578 | return result; | ||
579 | |||
580 | } | ||
581 | |||
582 | static int qt_close_channel(struct usb_serial *serial, __u16 Uart_Number) | ||
583 | { | ||
584 | int result; | ||
585 | |||
586 | result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | ||
587 | QT_OPEN_CLOSE_CHANNEL, | ||
588 | USBD_TRANSFER_DIRECTION_OUT, 0, Uart_Number, | ||
589 | NULL, 0, 300); | ||
590 | |||
591 | return result; | ||
592 | |||
593 | } | ||
594 | |||
595 | /**************************************************************************** | ||
596 | * BoxGetRegister | ||
597 | * issuse a GET_REGISTER vendor-spcific request on the default control pipe | ||
598 | * If successful, fills in the pValue with the register value asked for | ||
599 | ****************************************************************************/ | ||
600 | static int BoxGetRegister(struct usb_serial *serial, unsigned short Uart_Number, | ||
601 | unsigned short Register_Num, __u8 *pValue) | ||
602 | { | ||
603 | int result; | ||
604 | __u16 current_length; | ||
605 | |||
606 | current_length = sizeof(struct qt_get_device_data); | ||
607 | |||
608 | result = | ||
609 | usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | ||
610 | QT_GET_SET_REGISTER, 0xC0, Register_Num, | ||
611 | Uart_Number, (void *)pValue, sizeof(*pValue), 300); | ||
612 | |||
613 | return result; | ||
614 | } | ||
615 | |||
616 | /**************************************************************************** | ||
617 | * BoxSetRegister | ||
618 | * issuse a GET_REGISTER vendor-spcific request on the default control pipe | ||
619 | * If successful, fills in the pValue with the register value asked for | ||
620 | ****************************************************************************/ | ||
621 | static int BoxSetRegister(struct usb_serial *serial, unsigned short Uart_Number, | ||
622 | unsigned short Register_Num, unsigned short Value) | ||
623 | { | ||
624 | int result; | ||
625 | unsigned short RegAndByte; | ||
626 | |||
627 | RegAndByte = Value; | ||
628 | RegAndByte = RegAndByte << 8; | ||
629 | RegAndByte = RegAndByte + Register_Num; | ||
630 | |||
631 | /* | ||
632 | result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | ||
633 | QT_GET_SET_REGISTER, 0xC0, Register_Num, | ||
634 | Uart_Number, NULL, 0, 300); | ||
635 | */ | ||
636 | |||
637 | result = | ||
638 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | ||
639 | QT_GET_SET_REGISTER, 0x40, RegAndByte, Uart_Number, | ||
640 | NULL, 0, 300); | ||
641 | |||
642 | return result; | ||
643 | } | ||
644 | |||
645 | /* | ||
646 | * qt_setuart | ||
647 | * issuse a SET_UART vendor-spcific request on the default control pipe | ||
648 | * If successful sets baud rate divisor and LCR value | ||
649 | */ | ||
650 | static int qt_setuart(struct usb_serial *serial, unsigned short Uart_Number, | ||
651 | unsigned short default_divisor, unsigned char default_LCR) | ||
652 | { | ||
653 | int result; | ||
654 | unsigned short UartNumandLCR; | ||
655 | |||
656 | UartNumandLCR = (default_LCR << 8) + Uart_Number; | ||
657 | |||
658 | result = | ||
659 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | ||
660 | QT_GET_SET_UART, 0x40, default_divisor, | ||
661 | UartNumandLCR, NULL, 0, 300); | ||
662 | |||
663 | return result; | ||
664 | } | ||
665 | |||
666 | static int BoxSetHW_FlowCtrl(struct usb_serial *serial, unsigned int index, | ||
667 | int bSet) | ||
668 | { | ||
669 | __u8 mcr = 0; | ||
670 | __u8 msr = 0, MOUT_Value = 0; | ||
671 | unsigned int status; | ||
672 | |||
673 | if (bSet == 1) { | ||
674 | /* flow control, box will clear RTS line to prevent remote */ | ||
675 | mcr = SERIAL_MCR_RTS; | ||
676 | } /* device from xmitting more chars */ | ||
677 | else { | ||
678 | /* no flow control to remote device */ | ||
679 | mcr = 0; | ||
680 | |||
681 | } | ||
682 | MOUT_Value = mcr << 8; | ||
683 | |||
684 | if (bSet == 1) { | ||
685 | /* flow control, box will inhibit xmit data if CTS line is | ||
686 | * asserted */ | ||
687 | msr = SERIAL_MSR_CTS; | ||
688 | } else { | ||
689 | /* Box will not inhimbe xmit data due to CTS line */ | ||
690 | msr = 0; | ||
691 | } | ||
692 | MOUT_Value |= msr; | ||
693 | |||
694 | status = | ||
695 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | ||
696 | QT_HW_FLOW_CONTROL_MASK, 0x40, MOUT_Value, | ||
697 | index, NULL, 0, 300); | ||
698 | return status; | ||
699 | |||
700 | } | ||
701 | |||
702 | static int BoxSetSW_FlowCtrl(struct usb_serial *serial, __u16 index, | ||
703 | unsigned char stop_char, unsigned char start_char) | ||
704 | { | ||
705 | __u16 nSWflowout; | ||
706 | int result; | ||
707 | |||
708 | nSWflowout = start_char << 8; | ||
709 | nSWflowout = (unsigned short)stop_char; | ||
710 | |||
711 | result = | ||
712 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | ||
713 | QT_SW_FLOW_CONTROL_MASK, 0x40, nSWflowout, | ||
714 | index, NULL, 0, 300); | ||
715 | return result; | ||
716 | |||
717 | } | ||
718 | |||
719 | static int BoxDisable_SW_FlowCtrl(struct usb_serial *serial, __u16 index) | ||
720 | { | ||
721 | int result; | ||
722 | |||
723 | result = | ||
724 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | ||
725 | QT_SW_FLOW_CONTROL_DISABLE, 0x40, 0, index, | ||
726 | NULL, 0, 300); | ||
727 | return result; | ||
728 | |||
729 | } | ||
730 | |||
731 | static int qt_startup(struct usb_serial *serial) | ||
732 | { | ||
733 | struct usb_serial_port *port; | ||
734 | struct quatech_port *qt_port; | ||
735 | struct qt_get_device_data DeviceData; | ||
736 | int i; | ||
737 | int status; | ||
738 | |||
739 | dbg("enterting %s", __func__); | ||
740 | |||
741 | /* Now setup per port private data */ | ||
742 | for (i = 0; i < serial->num_ports; i++) { | ||
743 | port = serial->port[i]; | ||
744 | qt_port = kzalloc(sizeof(*qt_port), GFP_KERNEL); | ||
745 | if (!qt_port) { | ||
746 | dbg("%s: kmalloc for quatech_port (%d) failed!.", | ||
747 | __func__, i); | ||
748 | return -ENOMEM; | ||
749 | } | ||
750 | spin_lock_init(&qt_port->lock); | ||
751 | |||
752 | usb_set_serial_port_data(port, qt_port); | ||
753 | |||
754 | } | ||
755 | |||
756 | status = qt_get_device(serial, &DeviceData); | ||
757 | if (status < 0) { | ||
758 | dbg(__FILE__ "box_get_device failed"); | ||
759 | goto startup_error; | ||
760 | } | ||
761 | |||
762 | dbg(__FILE__ "DeviceData.portb = 0x%x", DeviceData.portb); | ||
763 | |||
764 | DeviceData.portb &= ~FULLPWRBIT; | ||
765 | dbg(__FILE__ "Changing DeviceData.portb to 0x%x", DeviceData.portb); | ||
766 | |||
767 | status = qt_set_device(serial, &DeviceData); | ||
768 | if (status < 0) { | ||
769 | dbg(__FILE__ "qt_set_device failed\n"); | ||
770 | goto startup_error; | ||
771 | } | ||
772 | |||
773 | status = qt_get_device(serial, &DeviceData); | ||
774 | if (status < 0) { | ||
775 | dbg(__FILE__ "qt_get_device failed"); | ||
776 | goto startup_error; | ||
777 | } | ||
778 | |||
779 | switch (serial->dev->descriptor.idProduct) { | ||
780 | case QUATECH_SSU100: | ||
781 | case QUATECH_DSU100: | ||
782 | case QUATECH_QSU100: | ||
783 | case QUATECH_ESU100A: | ||
784 | case QUATECH_ESU100B: | ||
785 | case QUATECH_HSU100A: | ||
786 | case QUATECH_HSU100B: | ||
787 | case QUATECH_HSU100C: | ||
788 | case QUATECH_HSU100D: | ||
789 | DeviceData.porta &= ~(RR_BITS | DUPMODE_BITS); | ||
790 | DeviceData.porta |= CLKS_X4; | ||
791 | DeviceData.portb &= ~(LOOPMODE_BITS); | ||
792 | DeviceData.portb |= RS232_MODE; | ||
793 | break; | ||
794 | |||
795 | case QUATECH_SSU200: | ||
796 | case QUATECH_DSU200: | ||
797 | case QUATECH_QSU200: | ||
798 | case QUATECH_ESU200A: | ||
799 | case QUATECH_ESU200B: | ||
800 | case QUATECH_HSU200A: | ||
801 | case QUATECH_HSU200B: | ||
802 | case QUATECH_HSU200C: | ||
803 | case QUATECH_HSU200D: | ||
804 | DeviceData.porta &= ~(RR_BITS | DUPMODE_BITS); | ||
805 | DeviceData.porta |= CLKS_X4; | ||
806 | DeviceData.portb &= ~(LOOPMODE_BITS); | ||
807 | DeviceData.portb |= ALL_LOOPBACK; | ||
808 | break; | ||
809 | default: | ||
810 | DeviceData.porta &= ~(RR_BITS | DUPMODE_BITS); | ||
811 | DeviceData.porta |= CLKS_X4; | ||
812 | DeviceData.portb &= ~(LOOPMODE_BITS); | ||
813 | DeviceData.portb |= RS232_MODE; | ||
814 | break; | ||
815 | |||
816 | } | ||
817 | |||
818 | status = BoxSetPrebufferLevel(serial); /* sets to default value */ | ||
819 | if (status < 0) { | ||
820 | dbg(__FILE__ "BoxSetPrebufferLevel failed\n"); | ||
821 | goto startup_error; | ||
822 | } | ||
823 | |||
824 | status = BoxSetATC(serial, ATC_DISABLED); | ||
825 | if (status < 0) { | ||
826 | dbg(__FILE__ "BoxSetATC failed\n"); | ||
827 | goto startup_error; | ||
828 | } | ||
829 | |||
830 | dbg(__FILE__ "DeviceData.portb = 0x%x", DeviceData.portb); | ||
831 | |||
832 | DeviceData.portb |= NEXT_BOARD_POWER_BIT; | ||
833 | dbg(__FILE__ "Changing DeviceData.portb to 0x%x", DeviceData.portb); | ||
834 | |||
835 | status = qt_set_device(serial, &DeviceData); | ||
836 | if (status < 0) { | ||
837 | dbg(__FILE__ "qt_set_device failed\n"); | ||
838 | goto startup_error; | ||
839 | } | ||
840 | |||
841 | dbg("Exit Success %s\n", __func__); | ||
842 | |||
843 | return 0; | ||
844 | |||
845 | startup_error: | ||
846 | for (i = 0; i < serial->num_ports; i++) { | ||
847 | port = serial->port[i]; | ||
848 | qt_port = qt_get_port_private(port); | ||
849 | kfree(qt_port); | ||
850 | usb_set_serial_port_data(port, NULL); | ||
851 | } | ||
852 | |||
853 | dbg("Exit fail %s\n", __func__); | ||
854 | |||
855 | return -EIO; | ||
856 | } | ||
857 | |||
858 | static void qt_release(struct usb_serial *serial) | ||
859 | { | ||
860 | struct usb_serial_port *port; | ||
861 | struct quatech_port *qt_port; | ||
862 | int i; | ||
863 | |||
864 | dbg("enterting %s", __func__); | ||
865 | |||
866 | for (i = 0; i < serial->num_ports; i++) { | ||
867 | port = serial->port[i]; | ||
868 | if (!port) | ||
869 | continue; | ||
870 | |||
871 | qt_port = usb_get_serial_port_data(port); | ||
872 | kfree(qt_port); | ||
873 | usb_set_serial_port_data(port, NULL); | ||
874 | } | ||
875 | |||
876 | } | ||
877 | |||
878 | int qt_open(struct tty_struct *tty, | ||
879 | struct usb_serial_port *port, struct file *filp) | ||
880 | { | ||
881 | struct usb_serial *serial; | ||
882 | struct quatech_port *quatech_port; | ||
883 | struct quatech_port *port0; | ||
884 | struct qt_open_channel_data ChannelData; | ||
885 | |||
886 | int result; | ||
887 | |||
888 | if (port_paranoia_check(port, __func__)) | ||
889 | return -ENODEV; | ||
890 | |||
891 | dbg("%s - port %d\n", __func__, port->number); | ||
892 | |||
893 | serial = port->serial; | ||
894 | |||
895 | if (serial_paranoia_check(serial, __func__)) | ||
896 | return -ENODEV; | ||
897 | |||
898 | quatech_port = qt_get_port_private(port); | ||
899 | port0 = qt_get_port_private(serial->port[0]); | ||
900 | |||
901 | if (quatech_port == NULL || port0 == NULL) | ||
902 | return -ENODEV; | ||
903 | |||
904 | usb_clear_halt(serial->dev, port->write_urb->pipe); | ||
905 | usb_clear_halt(serial->dev, port->read_urb->pipe); | ||
906 | port0->open_ports++; | ||
907 | |||
908 | result = qt_get_device(serial, &port0->DeviceData); | ||
909 | |||
910 | /* Port specific setups */ | ||
911 | result = qt_open_channel(serial, port->number, &ChannelData); | ||
912 | if (result < 0) { | ||
913 | dbg(__FILE__ "qt_open_channel failed\n"); | ||
914 | return result; | ||
915 | } | ||
916 | dbg(__FILE__ "qt_open_channel completed.\n"); | ||
917 | |||
918 | /* FIXME: are these needed? Does it even do anything useful? */ | ||
919 | quatech_port->shadowLSR = ChannelData.line_status & | ||
920 | (SERIAL_LSR_OE | SERIAL_LSR_PE | SERIAL_LSR_FE | SERIAL_LSR_BI); | ||
921 | |||
922 | quatech_port->shadowMSR = ChannelData.modem_status & | ||
923 | (SERIAL_MSR_CTS | SERIAL_MSR_DSR | SERIAL_MSR_RI | SERIAL_MSR_CD); | ||
924 | |||
925 | /* Set Baud rate to default and turn off (default)flow control here */ | ||
926 | result = qt_setuart(serial, port->number, DEFAULT_DIVISOR, DEFAULT_LCR); | ||
927 | if (result < 0) { | ||
928 | dbg(__FILE__ "qt_setuart failed\n"); | ||
929 | return result; | ||
930 | } | ||
931 | dbg(__FILE__ "qt_setuart completed.\n"); | ||
932 | |||
933 | /* | ||
934 | * Put this here to make it responsive to stty and defauls set by | ||
935 | * the tty layer | ||
936 | */ | ||
937 | /* FIXME: is this needed? */ | ||
938 | /* qt_set_termios(tty, port, NULL); */ | ||
939 | |||
940 | /* Check to see if we've set up our endpoint info yet */ | ||
941 | if (port0->open_ports == 1) { | ||
942 | if (serial->port[0]->interrupt_in_buffer == NULL) { | ||
943 | /* set up interrupt urb */ | ||
944 | usb_fill_int_urb(serial->port[0]->interrupt_in_urb, | ||
945 | serial->dev, | ||
946 | usb_rcvintpipe(serial->dev, | ||
947 | serial->port[0]->interrupt_in_endpointAddress), | ||
948 | serial->port[0]->interrupt_in_buffer, | ||
949 | serial->port[0]-> | ||
950 | interrupt_in_urb->transfer_buffer_length, | ||
951 | qt_interrupt_callback, serial, | ||
952 | serial->port[0]-> | ||
953 | interrupt_in_urb->interval); | ||
954 | |||
955 | result = | ||
956 | usb_submit_urb(serial->port[0]->interrupt_in_urb, | ||
957 | GFP_KERNEL); | ||
958 | if (result) { | ||
959 | dev_err(&port->dev, | ||
960 | "%s - Error %d submitting " | ||
961 | "interrupt urb\n", __func__, result); | ||
962 | } | ||
963 | |||
964 | } | ||
965 | |||
966 | } | ||
967 | |||
968 | dbg("port number is %d \n", port->number); | ||
969 | dbg("serial number is %d \n", port->serial->minor); | ||
970 | dbg("Bulkin endpoint is %d \n", port->bulk_in_endpointAddress); | ||
971 | dbg("BulkOut endpoint is %d \n", port->bulk_out_endpointAddress); | ||
972 | dbg("Interrupt endpoint is %d \n", port->interrupt_in_endpointAddress); | ||
973 | dbg("port's number in the device is %d\n", quatech_port->port_num); | ||
974 | quatech_port->read_urb = port->read_urb; | ||
975 | |||
976 | /* set up our bulk in urb */ | ||
977 | |||
978 | usb_fill_bulk_urb(quatech_port->read_urb, | ||
979 | serial->dev, | ||
980 | usb_rcvbulkpipe(serial->dev, | ||
981 | port->bulk_in_endpointAddress), | ||
982 | port->bulk_in_buffer, | ||
983 | quatech_port->read_urb->transfer_buffer_length, | ||
984 | qt_read_bulk_callback, quatech_port); | ||
985 | |||
986 | dbg("qt_open: bulkin endpoint is %d\n", port->bulk_in_endpointAddress); | ||
987 | quatech_port->read_urb_busy = true; | ||
988 | result = usb_submit_urb(quatech_port->read_urb, GFP_KERNEL); | ||
989 | if (result) { | ||
990 | dev_err(&port->dev, | ||
991 | "%s - Error %d submitting control urb\n", | ||
992 | __func__, result); | ||
993 | quatech_port->read_urb_busy = false; | ||
994 | } | ||
995 | |||
996 | /* initialize our wait queues */ | ||
997 | init_waitqueue_head(&quatech_port->wait); | ||
998 | init_waitqueue_head(&quatech_port->msr_wait); | ||
999 | |||
1000 | /* initialize our icount structure */ | ||
1001 | memset(&(quatech_port->icount), 0x00, sizeof(quatech_port->icount)); | ||
1002 | |||
1003 | return 0; | ||
1004 | |||
1005 | } | ||
1006 | |||
1007 | static int qt_chars_in_buffer(struct tty_struct *tty) | ||
1008 | { | ||
1009 | struct usb_serial_port *port = tty->driver_data; | ||
1010 | struct usb_serial *serial; | ||
1011 | int chars = 0; | ||
1012 | |||
1013 | serial = get_usb_serial(port, __func__); | ||
1014 | |||
1015 | dbg("%s - port %d\n", __func__, port->number); | ||
1016 | |||
1017 | if (serial->num_bulk_out) { | ||
1018 | if (port->write_urb->status == -EINPROGRESS) | ||
1019 | chars = port->write_urb->transfer_buffer_length; | ||
1020 | } | ||
1021 | |||
1022 | dbg("%s - returns %d\n", __func__, chars); | ||
1023 | |||
1024 | return chars; | ||
1025 | } | ||
1026 | |||
1027 | static void qt_block_until_empty(struct tty_struct *tty, | ||
1028 | struct quatech_port *qt_port) | ||
1029 | { | ||
1030 | int timeout = HZ / 10; | ||
1031 | int wait = 30; | ||
1032 | int count; | ||
1033 | |||
1034 | while (1) { | ||
1035 | |||
1036 | count = qt_chars_in_buffer(tty); | ||
1037 | |||
1038 | if (count <= 0) | ||
1039 | return; | ||
1040 | |||
1041 | interruptible_sleep_on_timeout(&qt_port->wait, timeout); | ||
1042 | |||
1043 | wait--; | ||
1044 | if (wait == 0) { | ||
1045 | dbg("%s - TIMEOUT", __func__); | ||
1046 | return; | ||
1047 | } else { | ||
1048 | wait = 30; | ||
1049 | } | ||
1050 | } | ||
1051 | } | ||
1052 | |||
1053 | static void qt_close(struct tty_struct *tty, struct usb_serial_port *port, | ||
1054 | struct file *filp) | ||
1055 | { | ||
1056 | struct usb_serial *serial = port->serial; | ||
1057 | struct quatech_port *qt_port; | ||
1058 | struct quatech_port *port0; | ||
1059 | int status; | ||
1060 | unsigned int index; | ||
1061 | status = 0; | ||
1062 | |||
1063 | dbg("%s - port %d\n", __func__, port->number); | ||
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); | ||
1078 | |||
1079 | /* Close uart channel */ | ||
1080 | status = qt_close_channel(serial, index); | ||
1081 | if (status < 0) | ||
1082 | dbg("%s - port %d qt_close_channel failed.\n", | ||
1083 | __func__, port->number); | ||
1084 | |||
1085 | port0->open_ports--; | ||
1086 | |||
1087 | dbg("qt_num_open_ports in close%d:in port%d\n", | ||
1088 | port0->open_ports, port->number); | ||
1089 | |||
1090 | if (port0->open_ports == 0) { | ||
1091 | if (serial->port[0]->interrupt_in_urb) { | ||
1092 | dbg("%s", "Shutdown interrupt_in_urb\n"); | ||
1093 | usb_kill_urb(serial->port[0]->interrupt_in_urb); | ||
1094 | } | ||
1095 | |||
1096 | } | ||
1097 | |||
1098 | if (qt_port->write_urb) { | ||
1099 | /* if this urb had a transfer buffer already (old tx) free it */ | ||
1100 | if (qt_port->write_urb->transfer_buffer != NULL) | ||
1101 | kfree(qt_port->write_urb->transfer_buffer); | ||
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 | |||
1193 | static int qt_ioctl(struct tty_struct *tty, struct file *file, | ||
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 | ||
1279 | new_LCR |= SERIAL_TWO_STOPB; | ||
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, | ||
1385 | struct file *file, struct usb_serial *serial) | ||
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, | ||
1427 | struct file *file, | ||
1428 | struct usb_serial *serial, | ||
1429 | unsigned int value) | ||
1430 | { | ||
1431 | |||
1432 | u8 mcr; | ||
1433 | int status; | ||
1434 | unsigned int index; | ||
1435 | |||
1436 | dbg("%s - port %d\n", __func__, port->number); | ||
1437 | |||
1438 | index = tty->index - serial->minor; | ||
1439 | status = | ||
1440 | BoxGetRegister(port->serial, index, MODEM_CONTROL_REGISTER, &mcr); | ||
1441 | if (status < 0) | ||
1442 | return -ESPIPE; | ||
1443 | |||
1444 | /* | ||
1445 | * Turn off the RTS and DTR and loopbcck and then only turn on what was | ||
1446 | * asked for | ||
1447 | */ | ||
1448 | mcr &= ~(SERIAL_MCR_RTS | SERIAL_MCR_DTR | SERIAL_MCR_LOOP); | ||
1449 | if (value & TIOCM_RTS) | ||
1450 | mcr |= SERIAL_MCR_RTS; | ||
1451 | if (value & TIOCM_DTR) | ||
1452 | mcr |= SERIAL_MCR_DTR; | ||
1453 | if (value & TIOCM_LOOP) | ||
1454 | mcr |= SERIAL_MCR_LOOP; | ||
1455 | |||
1456 | status = | ||
1457 | BoxSetRegister(port->serial, index, MODEM_CONTROL_REGISTER, mcr); | ||
1458 | if (status < 0) | ||
1459 | return -ESPIPE; | ||
1460 | else | ||
1461 | return 0; | ||
1462 | } | ||
1463 | |||
1464 | static int qt_tiocmget(struct tty_struct *tty, struct file *file) | ||
1465 | { | ||
1466 | struct usb_serial_port *port = tty->driver_data; | ||
1467 | struct usb_serial *serial = get_usb_serial(port, __func__); | ||
1468 | struct quatech_port *qt_port = qt_get_port_private(port); | ||
1469 | int retval = -ENODEV; | ||
1470 | unsigned long flags; | ||
1471 | |||
1472 | dbg("In %s \n", __func__); | ||
1473 | |||
1474 | if (!serial) | ||
1475 | return -ENODEV; | ||
1476 | |||
1477 | spin_lock_irqsave(&qt_port->lock, flags); | ||
1478 | |||
1479 | dbg("%s - port %d\n", __func__, port->number); | ||
1480 | dbg("%s - port->RxHolding = %d\n", __func__, qt_port->RxHolding); | ||
1481 | |||
1482 | retval = qt_real_tiocmget(tty, port, file, serial); | ||
1483 | |||
1484 | spin_unlock_irqrestore(&qt_port->lock, flags); | ||
1485 | return retval; | ||
1486 | } | ||
1487 | |||
1488 | static int qt_tiocmset(struct tty_struct *tty, struct file *file, | ||
1489 | unsigned int set, unsigned int clear) | ||
1490 | { | ||
1491 | |||
1492 | struct usb_serial_port *port = tty->driver_data; | ||
1493 | struct usb_serial *serial = get_usb_serial(port, __func__); | ||
1494 | struct quatech_port *qt_port = qt_get_port_private(port); | ||
1495 | unsigned long flags; | ||
1496 | int retval = -ENODEV; | ||
1497 | |||
1498 | dbg("In %s \n", __func__); | ||
1499 | |||
1500 | if (!serial) | ||
1501 | return -ENODEV; | ||
1502 | |||
1503 | spin_lock_irqsave(&qt_port->lock, flags); | ||
1504 | |||
1505 | dbg("%s - port %d \n", __func__, port->number); | ||
1506 | dbg("%s - qt_port->RxHolding = %d\n", __func__, qt_port->RxHolding); | ||
1507 | |||
1508 | retval = qt_real_tiocmset(tty, port, file, serial, set); | ||
1509 | |||
1510 | spin_unlock_irqrestore(&qt_port->lock, flags); | ||
1511 | return retval; | ||
1512 | } | ||
1513 | |||
1514 | static void qt_throttle(struct tty_struct *tty) | ||
1515 | { | ||
1516 | struct usb_serial_port *port = tty->driver_data; | ||
1517 | struct usb_serial *serial = get_usb_serial(port, __func__); | ||
1518 | struct quatech_port *qt_port; | ||
1519 | unsigned long flags; | ||
1520 | |||
1521 | dbg("%s - port %d\n", __func__, port->number); | ||
1522 | |||
1523 | if (!serial) | ||
1524 | return; | ||
1525 | |||
1526 | qt_port = qt_get_port_private(port); | ||
1527 | |||
1528 | spin_lock_irqsave(&qt_port->lock, flags); | ||
1529 | |||
1530 | /* pass on to the driver specific version of this function */ | ||
1531 | qt_port->RxHolding = 1; | ||
1532 | dbg("%s - port->RxHolding = 1\n", __func__); | ||
1533 | |||
1534 | spin_unlock_irqrestore(&qt_port->lock, flags); | ||
1535 | return; | ||
1536 | } | ||
1537 | |||
1538 | static void qt_unthrottle(struct tty_struct *tty) | ||
1539 | { | ||
1540 | struct usb_serial_port *port = tty->driver_data; | ||
1541 | struct usb_serial *serial = get_usb_serial(port, __func__); | ||
1542 | struct quatech_port *qt_port; | ||
1543 | unsigned long flags; | ||
1544 | unsigned int result; | ||
1545 | |||
1546 | if (!serial) | ||
1547 | return; | ||
1548 | |||
1549 | qt_port = qt_get_port_private(port); | ||
1550 | |||
1551 | spin_lock_irqsave(&qt_port->lock, flags); | ||
1552 | |||
1553 | dbg("%s - port %d\n", __func__, port->number); | ||
1554 | |||
1555 | if (qt_port->RxHolding == 1) { | ||
1556 | dbg("%s -qt_port->RxHolding == 1\n", __func__); | ||
1557 | |||
1558 | qt_port->RxHolding = 0; | ||
1559 | dbg("%s - qt_port->RxHolding = 0\n", __func__); | ||
1560 | |||
1561 | /* if we have a bulk endpoint, start it up */ | ||
1562 | if ((serial->num_bulk_in) && (qt_port->ReadBulkStopped == 1)) { | ||
1563 | /* Start reading from the device */ | ||
1564 | usb_fill_bulk_urb(port->read_urb, serial->dev, | ||
1565 | usb_rcvbulkpipe(serial->dev, | ||
1566 | port->bulk_in_endpointAddress), | ||
1567 | port->read_urb->transfer_buffer, | ||
1568 | port->read_urb-> | ||
1569 | transfer_buffer_length, | ||
1570 | qt_read_bulk_callback, port); | ||
1571 | result = usb_submit_urb(port->read_urb, GFP_ATOMIC); | ||
1572 | if (result) | ||
1573 | err("%s - failed restarting read urb, error %d", | ||
1574 | __func__, result); | ||
1575 | } | ||
1576 | } | ||
1577 | spin_unlock_irqrestore(&qt_port->lock, flags); | ||
1578 | return; | ||
1579 | |||
1580 | } | ||
1581 | |||
1582 | static int qt_calc_num_ports(struct usb_serial *serial) | ||
1583 | { | ||
1584 | int num_ports; | ||
1585 | |||
1586 | dbg("numberofendpoints: %d \n", | ||
1587 | (int)serial->interface->cur_altsetting->desc.bNumEndpoints); | ||
1588 | dbg("numberofendpoints: %d \n", | ||
1589 | (int)serial->interface->altsetting->desc.bNumEndpoints); | ||
1590 | |||
1591 | num_ports = | ||
1592 | (serial->interface->cur_altsetting->desc.bNumEndpoints - 1) / 2; | ||
1593 | |||
1594 | return num_ports; | ||
1595 | } | ||
1596 | |||
1597 | static struct usb_serial_driver quatech_device = { | ||
1598 | .driver = { | ||
1599 | .owner = THIS_MODULE, | ||
1600 | .name = "serqt", | ||
1601 | }, | ||
1602 | .description = DRIVER_DESC, | ||
1603 | .usb_driver = &serqt_usb_driver, | ||
1604 | .id_table = serqt_id_table, | ||
1605 | .num_ports = 8, | ||
1606 | .open = qt_open, | ||
1607 | .close = qt_close, | ||
1608 | .write = qt_write, | ||
1609 | .write_room = qt_write_room, | ||
1610 | .chars_in_buffer = qt_chars_in_buffer, | ||
1611 | .throttle = qt_throttle, | ||
1612 | .unthrottle = qt_unthrottle, | ||
1613 | .calc_num_ports = qt_calc_num_ports, | ||
1614 | .ioctl = qt_ioctl, | ||
1615 | .set_termios = qt_set_termios, | ||
1616 | .break_ctl = qt_break, | ||
1617 | .tiocmget = qt_tiocmget, | ||
1618 | .tiocmset = qt_tiocmset, | ||
1619 | .attach = qt_startup, | ||
1620 | .release = qt_release, | ||
1621 | }; | ||
1622 | |||
1623 | static int __init serqt_usb_init(void) | ||
1624 | { | ||
1625 | int retval; | ||
1626 | |||
1627 | dbg("%s\n", __func__); | ||
1628 | |||
1629 | /* register with usb-serial */ | ||
1630 | retval = usb_serial_register(&quatech_device); | ||
1631 | |||
1632 | if (retval) | ||
1633 | goto failed_usb_serial_register; | ||
1634 | |||
1635 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" | ||
1636 | DRIVER_DESC "\n"); | ||
1637 | |||
1638 | /* register with usb */ | ||
1639 | |||
1640 | retval = usb_register(&serqt_usb_driver); | ||
1641 | if (retval == 0) | ||
1642 | return 0; | ||
1643 | |||
1644 | /* if we're here, usb_register() failed */ | ||
1645 | usb_serial_deregister(&quatech_device); | ||
1646 | failed_usb_serial_register: | ||
1647 | return retval; | ||
1648 | } | ||
1649 | |||
1650 | static void __exit serqt_usb_exit(void) | ||
1651 | { | ||
1652 | usb_deregister(&serqt_usb_driver); | ||
1653 | usb_serial_deregister(&quatech_device); | ||
1654 | } | ||
1655 | |||
1656 | module_init(serqt_usb_init); | ||
1657 | module_exit(serqt_usb_exit); | ||
1658 | |||
1659 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
1660 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
1661 | MODULE_LICENSE("GPL"); | ||
1662 | |||
1663 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
1664 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | ||