diff options
Diffstat (limited to 'drivers/usb/serial/kl5kusb105.c')
-rw-r--r-- | drivers/usb/serial/kl5kusb105.c | 436 |
1 files changed, 69 insertions, 367 deletions
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 8eef91ba4b1c..cdbe8bf7f674 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * KLSI KL5KUSB105 chip RS232 converter driver | 2 | * KLSI KL5KUSB105 chip RS232 converter driver |
3 | * | 3 | * |
4 | * Copyright (C) 2010 Johan Hovold <jhovold@gmail.com> | ||
4 | * Copyright (C) 2001 Utz-Uwe Haus <haus@uuhaus.de> | 5 | * Copyright (C) 2001 Utz-Uwe Haus <haus@uuhaus.de> |
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -34,17 +35,6 @@ | |||
34 | * implement handshaking or decide that we do not support it | 35 | * implement handshaking or decide that we do not support it |
35 | */ | 36 | */ |
36 | 37 | ||
37 | /* History: | ||
38 | * 0.3a - implemented pools of write URBs | ||
39 | * 0.3 - alpha version for public testing | ||
40 | * 0.2 - TIOCMGET works, so autopilot(1) can be used! | ||
41 | * 0.1 - can be used to do pilot-xfer -p /dev/ttyUSB0 -l | ||
42 | * | ||
43 | * The driver skeleton is mainly based on mct_u232.c and various other | ||
44 | * pieces of code shamelessly copied from the drivers/usb/serial/ directory. | ||
45 | */ | ||
46 | |||
47 | |||
48 | #include <linux/kernel.h> | 38 | #include <linux/kernel.h> |
49 | #include <linux/errno.h> | 39 | #include <linux/errno.h> |
50 | #include <linux/init.h> | 40 | #include <linux/init.h> |
@@ -64,8 +54,8 @@ static int debug; | |||
64 | /* | 54 | /* |
65 | * Version Information | 55 | * Version Information |
66 | */ | 56 | */ |
67 | #define DRIVER_VERSION "v0.3a" | 57 | #define DRIVER_VERSION "v0.4" |
68 | #define DRIVER_AUTHOR "Utz-Uwe Haus <haus@uuhaus.de>" | 58 | #define DRIVER_AUTHOR "Utz-Uwe Haus <haus@uuhaus.de>, Johan Hovold <jhovold@gmail.com>" |
69 | #define DRIVER_DESC "KLSI KL5KUSB105 chipset USB->Serial Converter driver" | 59 | #define DRIVER_DESC "KLSI KL5KUSB105 chipset USB->Serial Converter driver" |
70 | 60 | ||
71 | 61 | ||
@@ -73,23 +63,17 @@ static int debug; | |||
73 | * Function prototypes | 63 | * Function prototypes |
74 | */ | 64 | */ |
75 | static int klsi_105_startup(struct usb_serial *serial); | 65 | static int klsi_105_startup(struct usb_serial *serial); |
76 | static void klsi_105_disconnect(struct usb_serial *serial); | ||
77 | static void klsi_105_release(struct usb_serial *serial); | 66 | static void klsi_105_release(struct usb_serial *serial); |
78 | static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port); | 67 | static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port); |
79 | static void klsi_105_close(struct usb_serial_port *port); | 68 | static void klsi_105_close(struct usb_serial_port *port); |
80 | static int klsi_105_write(struct tty_struct *tty, | ||
81 | struct usb_serial_port *port, const unsigned char *buf, int count); | ||
82 | static void klsi_105_write_bulk_callback(struct urb *urb); | ||
83 | static int klsi_105_chars_in_buffer(struct tty_struct *tty); | ||
84 | static int klsi_105_write_room(struct tty_struct *tty); | ||
85 | static void klsi_105_read_bulk_callback(struct urb *urb); | ||
86 | static void klsi_105_set_termios(struct tty_struct *tty, | 69 | static void klsi_105_set_termios(struct tty_struct *tty, |
87 | struct usb_serial_port *port, struct ktermios *old); | 70 | struct usb_serial_port *port, struct ktermios *old); |
88 | static void klsi_105_throttle(struct tty_struct *tty); | ||
89 | static void klsi_105_unthrottle(struct tty_struct *tty); | ||
90 | static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file); | 71 | static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file); |
91 | static int klsi_105_tiocmset(struct tty_struct *tty, struct file *file, | 72 | static int klsi_105_tiocmset(struct tty_struct *tty, struct file *file, |
92 | unsigned int set, unsigned int clear); | 73 | unsigned int set, unsigned int clear); |
74 | static void klsi_105_process_read_urb(struct urb *urb); | ||
75 | static int klsi_105_prepare_write_buffer(struct usb_serial_port *port, | ||
76 | void *dest, size_t size); | ||
93 | 77 | ||
94 | /* | 78 | /* |
95 | * All of the device info needed for the KLSI converters. | 79 | * All of the device info needed for the KLSI converters. |
@@ -107,7 +91,7 @@ static struct usb_driver kl5kusb105d_driver = { | |||
107 | .probe = usb_serial_probe, | 91 | .probe = usb_serial_probe, |
108 | .disconnect = usb_serial_disconnect, | 92 | .disconnect = usb_serial_disconnect, |
109 | .id_table = id_table, | 93 | .id_table = id_table, |
110 | .no_dynamic_id = 1, | 94 | .no_dynamic_id = 1, |
111 | }; | 95 | }; |
112 | 96 | ||
113 | static struct usb_serial_driver kl5kusb105d_device = { | 97 | static struct usb_serial_driver kl5kusb105d_device = { |
@@ -115,26 +99,23 @@ static struct usb_serial_driver kl5kusb105d_device = { | |||
115 | .owner = THIS_MODULE, | 99 | .owner = THIS_MODULE, |
116 | .name = "kl5kusb105d", | 100 | .name = "kl5kusb105d", |
117 | }, | 101 | }, |
118 | .description = "KL5KUSB105D / PalmConnect", | 102 | .description = "KL5KUSB105D / PalmConnect", |
119 | .usb_driver = &kl5kusb105d_driver, | 103 | .usb_driver = &kl5kusb105d_driver, |
120 | .id_table = id_table, | 104 | .id_table = id_table, |
121 | .num_ports = 1, | 105 | .num_ports = 1, |
122 | .open = klsi_105_open, | 106 | .bulk_out_size = 64, |
123 | .close = klsi_105_close, | 107 | .open = klsi_105_open, |
124 | .write = klsi_105_write, | 108 | .close = klsi_105_close, |
125 | .write_bulk_callback = klsi_105_write_bulk_callback, | 109 | .set_termios = klsi_105_set_termios, |
126 | .chars_in_buffer = klsi_105_chars_in_buffer, | 110 | /*.break_ctl = klsi_105_break_ctl,*/ |
127 | .write_room = klsi_105_write_room, | 111 | .tiocmget = klsi_105_tiocmget, |
128 | .read_bulk_callback = klsi_105_read_bulk_callback, | 112 | .tiocmset = klsi_105_tiocmset, |
129 | .set_termios = klsi_105_set_termios, | 113 | .attach = klsi_105_startup, |
130 | /*.break_ctl = klsi_105_break_ctl,*/ | 114 | .release = klsi_105_release, |
131 | .tiocmget = klsi_105_tiocmget, | 115 | .throttle = usb_serial_generic_throttle, |
132 | .tiocmset = klsi_105_tiocmset, | 116 | .unthrottle = usb_serial_generic_unthrottle, |
133 | .attach = klsi_105_startup, | 117 | .process_read_urb = klsi_105_process_read_urb, |
134 | .disconnect = klsi_105_disconnect, | 118 | .prepare_write_buffer = klsi_105_prepare_write_buffer, |
135 | .release = klsi_105_release, | ||
136 | .throttle = klsi_105_throttle, | ||
137 | .unthrottle = klsi_105_unthrottle, | ||
138 | }; | 119 | }; |
139 | 120 | ||
140 | struct klsi_105_port_settings { | 121 | struct klsi_105_port_settings { |
@@ -145,18 +126,11 @@ struct klsi_105_port_settings { | |||
145 | __u8 unknown2; | 126 | __u8 unknown2; |
146 | } __attribute__ ((packed)); | 127 | } __attribute__ ((packed)); |
147 | 128 | ||
148 | /* we implement a pool of NUM_URBS urbs per usb_serial */ | ||
149 | #define NUM_URBS 1 | ||
150 | #define URB_TRANSFER_BUFFER_SIZE 64 | ||
151 | struct klsi_105_private { | 129 | struct klsi_105_private { |
152 | struct klsi_105_port_settings cfg; | 130 | struct klsi_105_port_settings cfg; |
153 | struct ktermios termios; | 131 | struct ktermios termios; |
154 | unsigned long line_state; /* modem line settings */ | 132 | unsigned long line_state; /* modem line settings */ |
155 | /* write pool */ | ||
156 | struct urb *write_urb_pool[NUM_URBS]; | ||
157 | spinlock_t lock; | 133 | spinlock_t lock; |
158 | unsigned long bytes_in; | ||
159 | unsigned long bytes_out; | ||
160 | }; | 134 | }; |
161 | 135 | ||
162 | 136 | ||
@@ -189,7 +163,7 @@ static int klsi_105_chg_port_settings(struct usb_serial_port *port, | |||
189 | settings->pktlen, settings->baudrate, settings->databits, | 163 | settings->pktlen, settings->baudrate, settings->databits, |
190 | settings->unknown1, settings->unknown2); | 164 | settings->unknown1, settings->unknown2); |
191 | return rc; | 165 | return rc; |
192 | } /* klsi_105_chg_port_settings */ | 166 | } |
193 | 167 | ||
194 | /* translate a 16-bit status value from the device to linux's TIO bits */ | 168 | /* translate a 16-bit status value from the device to linux's TIO bits */ |
195 | static unsigned long klsi_105_status2linestate(const __u16 status) | 169 | static unsigned long klsi_105_status2linestate(const __u16 status) |
@@ -202,6 +176,7 @@ static unsigned long klsi_105_status2linestate(const __u16 status) | |||
202 | 176 | ||
203 | return res; | 177 | return res; |
204 | } | 178 | } |
179 | |||
205 | /* | 180 | /* |
206 | * Read line control via vendor command and return result through | 181 | * Read line control via vendor command and return result through |
207 | * *line_state_p | 182 | * *line_state_p |
@@ -258,7 +233,7 @@ static int klsi_105_get_line_state(struct usb_serial_port *port, | |||
258 | static int klsi_105_startup(struct usb_serial *serial) | 233 | static int klsi_105_startup(struct usb_serial *serial) |
259 | { | 234 | { |
260 | struct klsi_105_private *priv; | 235 | struct klsi_105_private *priv; |
261 | int i, j; | 236 | int i; |
262 | 237 | ||
263 | /* check if we support the product id (see keyspan.c) | 238 | /* check if we support the product id (see keyspan.c) |
264 | * FIXME | 239 | * FIXME |
@@ -282,29 +257,9 @@ static int klsi_105_startup(struct usb_serial *serial) | |||
282 | 257 | ||
283 | priv->line_state = 0; | 258 | priv->line_state = 0; |
284 | 259 | ||
285 | priv->bytes_in = 0; | ||
286 | priv->bytes_out = 0; | ||
287 | usb_set_serial_port_data(serial->port[i], priv); | 260 | usb_set_serial_port_data(serial->port[i], priv); |
288 | 261 | ||
289 | spin_lock_init(&priv->lock); | 262 | spin_lock_init(&priv->lock); |
290 | for (j = 0; j < NUM_URBS; j++) { | ||
291 | struct urb *urb = usb_alloc_urb(0, GFP_KERNEL); | ||
292 | |||
293 | priv->write_urb_pool[j] = urb; | ||
294 | if (urb == NULL) { | ||
295 | dev_err(&serial->dev->dev, "No more urbs???\n"); | ||
296 | goto err_cleanup; | ||
297 | } | ||
298 | |||
299 | urb->transfer_buffer = | ||
300 | kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); | ||
301 | if (!urb->transfer_buffer) { | ||
302 | dev_err(&serial->dev->dev, | ||
303 | "%s - out of memory for urb buffers.\n", | ||
304 | __func__); | ||
305 | goto err_cleanup; | ||
306 | } | ||
307 | } | ||
308 | 263 | ||
309 | /* priv->termios is left uninitalized until port opening */ | 264 | /* priv->termios is left uninitalized until port opening */ |
310 | init_waitqueue_head(&serial->port[i]->write_wait); | 265 | init_waitqueue_head(&serial->port[i]->write_wait); |
@@ -315,44 +270,11 @@ static int klsi_105_startup(struct usb_serial *serial) | |||
315 | err_cleanup: | 270 | err_cleanup: |
316 | for (; i >= 0; i--) { | 271 | for (; i >= 0; i--) { |
317 | priv = usb_get_serial_port_data(serial->port[i]); | 272 | priv = usb_get_serial_port_data(serial->port[i]); |
318 | for (j = 0; j < NUM_URBS; j++) { | 273 | kfree(priv); |
319 | if (priv->write_urb_pool[j]) { | ||
320 | kfree(priv->write_urb_pool[j]->transfer_buffer); | ||
321 | usb_free_urb(priv->write_urb_pool[j]); | ||
322 | } | ||
323 | } | ||
324 | usb_set_serial_port_data(serial->port[i], NULL); | 274 | usb_set_serial_port_data(serial->port[i], NULL); |
325 | } | 275 | } |
326 | return -ENOMEM; | 276 | return -ENOMEM; |
327 | } /* klsi_105_startup */ | 277 | } |
328 | |||
329 | |||
330 | static void klsi_105_disconnect(struct usb_serial *serial) | ||
331 | { | ||
332 | int i; | ||
333 | |||
334 | dbg("%s", __func__); | ||
335 | |||
336 | /* stop reads and writes on all ports */ | ||
337 | for (i = 0; i < serial->num_ports; ++i) { | ||
338 | struct klsi_105_private *priv = | ||
339 | usb_get_serial_port_data(serial->port[i]); | ||
340 | |||
341 | if (priv) { | ||
342 | /* kill our write urb pool */ | ||
343 | int j; | ||
344 | struct urb **write_urbs = priv->write_urb_pool; | ||
345 | |||
346 | for (j = 0; j < NUM_URBS; j++) { | ||
347 | if (write_urbs[j]) { | ||
348 | usb_kill_urb(write_urbs[j]); | ||
349 | usb_free_urb(write_urbs[j]); | ||
350 | } | ||
351 | } | ||
352 | } | ||
353 | } | ||
354 | } /* klsi_105_disconnect */ | ||
355 | |||
356 | 278 | ||
357 | static void klsi_105_release(struct usb_serial *serial) | 279 | static void klsi_105_release(struct usb_serial *serial) |
358 | { | 280 | { |
@@ -360,13 +282,9 @@ static void klsi_105_release(struct usb_serial *serial) | |||
360 | 282 | ||
361 | dbg("%s", __func__); | 283 | dbg("%s", __func__); |
362 | 284 | ||
363 | for (i = 0; i < serial->num_ports; ++i) { | 285 | for (i = 0; i < serial->num_ports; ++i) |
364 | struct klsi_105_private *priv = | 286 | kfree(usb_get_serial_port_data(serial->port[i])); |
365 | usb_get_serial_port_data(serial->port[i]); | 287 | } |
366 | |||
367 | kfree(priv); | ||
368 | } | ||
369 | } /* klsi_105_release */ | ||
370 | 288 | ||
371 | static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) | 289 | static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) |
372 | { | 290 | { |
@@ -416,18 +334,8 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
416 | spin_unlock_irqrestore(&priv->lock, flags); | 334 | spin_unlock_irqrestore(&priv->lock, flags); |
417 | 335 | ||
418 | /* READ_ON and urb submission */ | 336 | /* READ_ON and urb submission */ |
419 | usb_fill_bulk_urb(port->read_urb, port->serial->dev, | 337 | rc = usb_serial_generic_open(tty, port); |
420 | usb_rcvbulkpipe(port->serial->dev, | ||
421 | port->bulk_in_endpointAddress), | ||
422 | port->read_urb->transfer_buffer, | ||
423 | port->read_urb->transfer_buffer_length, | ||
424 | klsi_105_read_bulk_callback, | ||
425 | port); | ||
426 | |||
427 | rc = usb_submit_urb(port->read_urb, GFP_KERNEL); | ||
428 | if (rc) { | 338 | if (rc) { |
429 | dev_err(&port->dev, "%s - failed submitting read urb, " | ||
430 | "error %d\n", __func__, rc); | ||
431 | retval = rc; | 339 | retval = rc; |
432 | goto exit; | 340 | goto exit; |
433 | } | 341 | } |
@@ -460,12 +368,10 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
460 | exit: | 368 | exit: |
461 | kfree(cfg); | 369 | kfree(cfg); |
462 | return retval; | 370 | return retval; |
463 | } /* klsi_105_open */ | 371 | } |
464 | |||
465 | 372 | ||
466 | static void klsi_105_close(struct usb_serial_port *port) | 373 | static void klsi_105_close(struct usb_serial_port *port) |
467 | { | 374 | { |
468 | struct klsi_105_private *priv = usb_get_serial_port_data(port); | ||
469 | int rc; | 375 | int rc; |
470 | 376 | ||
471 | dbg("%s port %d", __func__, port->number); | 377 | dbg("%s port %d", __func__, port->number); |
@@ -488,239 +394,62 @@ static void klsi_105_close(struct usb_serial_port *port) | |||
488 | mutex_unlock(&port->serial->disc_mutex); | 394 | mutex_unlock(&port->serial->disc_mutex); |
489 | 395 | ||
490 | /* shutdown our bulk reads and writes */ | 396 | /* shutdown our bulk reads and writes */ |
491 | usb_kill_urb(port->write_urb); | 397 | usb_serial_generic_close(port); |
492 | usb_kill_urb(port->read_urb); | 398 | |
493 | /* unlink our write pool */ | ||
494 | /* FIXME */ | ||
495 | /* wgg - do I need this? I think so. */ | 399 | /* wgg - do I need this? I think so. */ |
496 | usb_kill_urb(port->interrupt_in_urb); | 400 | usb_kill_urb(port->interrupt_in_urb); |
497 | dev_info(&port->serial->dev->dev, | 401 | } |
498 | "port stats: %ld bytes in, %ld bytes out\n", | ||
499 | priv->bytes_in, priv->bytes_out); | ||
500 | } /* klsi_105_close */ | ||
501 | |||
502 | 402 | ||
503 | /* We need to write a complete 64-byte data block and encode the | 403 | /* We need to write a complete 64-byte data block and encode the |
504 | * number actually sent in the first double-byte, LSB-order. That | 404 | * number actually sent in the first double-byte, LSB-order. That |
505 | * leaves at most 62 bytes of payload. | 405 | * leaves at most 62 bytes of payload. |
506 | */ | 406 | */ |
507 | #define KLSI_105_DATA_OFFSET 2 /* in the bulk urb data block */ | 407 | #define KLSI_HDR_LEN 2 |
508 | 408 | static int klsi_105_prepare_write_buffer(struct usb_serial_port *port, | |
509 | 409 | void *dest, size_t size) | |
510 | static int klsi_105_write(struct tty_struct *tty, | ||
511 | struct usb_serial_port *port, const unsigned char *buf, int count) | ||
512 | { | 410 | { |
513 | struct klsi_105_private *priv = usb_get_serial_port_data(port); | 411 | unsigned char *buf = dest; |
514 | int result, size; | 412 | int count; |
515 | int bytes_sent = 0; | ||
516 | |||
517 | dbg("%s - port %d", __func__, port->number); | ||
518 | |||
519 | while (count > 0) { | ||
520 | /* try to find a free urb (write 0 bytes if none) */ | ||
521 | struct urb *urb = NULL; | ||
522 | unsigned long flags; | ||
523 | int i; | ||
524 | /* since the pool is per-port we might not need | ||
525 | the spin lock !? */ | ||
526 | spin_lock_irqsave(&priv->lock, flags); | ||
527 | for (i = 0; i < NUM_URBS; i++) { | ||
528 | if (priv->write_urb_pool[i]->status != -EINPROGRESS) { | ||
529 | urb = priv->write_urb_pool[i]; | ||
530 | dbg("%s - using pool URB %d", __func__, i); | ||
531 | break; | ||
532 | } | ||
533 | } | ||
534 | spin_unlock_irqrestore(&priv->lock, flags); | ||
535 | |||
536 | if (urb == NULL) { | ||
537 | dbg("%s - no more free urbs", __func__); | ||
538 | goto exit; | ||
539 | } | ||
540 | |||
541 | if (urb->transfer_buffer == NULL) { | ||
542 | urb->transfer_buffer = | ||
543 | kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC); | ||
544 | if (urb->transfer_buffer == NULL) { | ||
545 | dev_err(&port->dev, | ||
546 | "%s - no more kernel memory...\n", | ||
547 | __func__); | ||
548 | goto exit; | ||
549 | } | ||
550 | } | ||
551 | |||
552 | size = min(count, port->bulk_out_size - KLSI_105_DATA_OFFSET); | ||
553 | size = min(size, URB_TRANSFER_BUFFER_SIZE - | ||
554 | KLSI_105_DATA_OFFSET); | ||
555 | |||
556 | memcpy(urb->transfer_buffer + KLSI_105_DATA_OFFSET, buf, size); | ||
557 | |||
558 | /* write payload size into transfer buffer */ | ||
559 | ((__u8 *)urb->transfer_buffer)[0] = (__u8) (size & 0xFF); | ||
560 | ((__u8 *)urb->transfer_buffer)[1] = (__u8) ((size & 0xFF00)>>8); | ||
561 | |||
562 | /* set up our urb */ | ||
563 | usb_fill_bulk_urb(urb, port->serial->dev, | ||
564 | usb_sndbulkpipe(port->serial->dev, | ||
565 | port->bulk_out_endpointAddress), | ||
566 | urb->transfer_buffer, | ||
567 | URB_TRANSFER_BUFFER_SIZE, | ||
568 | klsi_105_write_bulk_callback, | ||
569 | port); | ||
570 | |||
571 | /* send the data out the bulk port */ | ||
572 | result = usb_submit_urb(urb, GFP_ATOMIC); | ||
573 | if (result) { | ||
574 | dev_err(&port->dev, | ||
575 | "%s - failed submitting write urb, error %d\n", | ||
576 | __func__, result); | ||
577 | goto exit; | ||
578 | } | ||
579 | buf += size; | ||
580 | bytes_sent += size; | ||
581 | count -= size; | ||
582 | } | ||
583 | exit: | ||
584 | /* lockless, but it's for debug info only... */ | ||
585 | priv->bytes_out += bytes_sent; | ||
586 | |||
587 | return bytes_sent; /* that's how much we wrote */ | ||
588 | } /* klsi_105_write */ | ||
589 | |||
590 | static void klsi_105_write_bulk_callback(struct urb *urb) | ||
591 | { | ||
592 | struct usb_serial_port *port = urb->context; | ||
593 | int status = urb->status; | ||
594 | |||
595 | dbg("%s - port %d", __func__, port->number); | ||
596 | |||
597 | if (status) { | ||
598 | dbg("%s - nonzero write bulk status received: %d", __func__, | ||
599 | status); | ||
600 | return; | ||
601 | } | ||
602 | 413 | ||
603 | usb_serial_port_softint(port); | 414 | count = kfifo_out_locked(&port->write_fifo, buf + KLSI_HDR_LEN, size, |
604 | } /* klsi_105_write_bulk_completion_callback */ | 415 | &port->lock); |
416 | put_unaligned_le16(count, buf); | ||
605 | 417 | ||
606 | 418 | return count + KLSI_HDR_LEN; | |
607 | /* return number of characters currently in the writing process */ | ||
608 | static int klsi_105_chars_in_buffer(struct tty_struct *tty) | ||
609 | { | ||
610 | struct usb_serial_port *port = tty->driver_data; | ||
611 | int chars = 0; | ||
612 | int i; | ||
613 | unsigned long flags; | ||
614 | struct klsi_105_private *priv = usb_get_serial_port_data(port); | ||
615 | |||
616 | spin_lock_irqsave(&priv->lock, flags); | ||
617 | |||
618 | for (i = 0; i < NUM_URBS; ++i) { | ||
619 | if (priv->write_urb_pool[i]->status == -EINPROGRESS) | ||
620 | chars += URB_TRANSFER_BUFFER_SIZE; | ||
621 | } | ||
622 | |||
623 | spin_unlock_irqrestore(&priv->lock, flags); | ||
624 | |||
625 | dbg("%s - returns %d", __func__, chars); | ||
626 | return chars; | ||
627 | } | 419 | } |
628 | 420 | ||
629 | static int klsi_105_write_room(struct tty_struct *tty) | 421 | /* The data received is preceded by a length double-byte in LSB-first order. |
630 | { | 422 | */ |
631 | struct usb_serial_port *port = tty->driver_data; | 423 | static void klsi_105_process_read_urb(struct urb *urb) |
632 | unsigned long flags; | ||
633 | int i; | ||
634 | int room = 0; | ||
635 | struct klsi_105_private *priv = usb_get_serial_port_data(port); | ||
636 | |||
637 | spin_lock_irqsave(&priv->lock, flags); | ||
638 | for (i = 0; i < NUM_URBS; ++i) { | ||
639 | if (priv->write_urb_pool[i]->status != -EINPROGRESS) | ||
640 | room += URB_TRANSFER_BUFFER_SIZE; | ||
641 | } | ||
642 | |||
643 | spin_unlock_irqrestore(&priv->lock, flags); | ||
644 | |||
645 | dbg("%s - returns %d", __func__, room); | ||
646 | return room; | ||
647 | } | ||
648 | |||
649 | |||
650 | |||
651 | static void klsi_105_read_bulk_callback(struct urb *urb) | ||
652 | { | 424 | { |
653 | struct usb_serial_port *port = urb->context; | 425 | struct usb_serial_port *port = urb->context; |
654 | struct klsi_105_private *priv = usb_get_serial_port_data(port); | ||
655 | struct tty_struct *tty; | ||
656 | unsigned char *data = urb->transfer_buffer; | 426 | unsigned char *data = urb->transfer_buffer; |
657 | int rc; | 427 | struct tty_struct *tty; |
658 | int status = urb->status; | 428 | unsigned len; |
659 | 429 | ||
660 | dbg("%s - port %d", __func__, port->number); | 430 | /* empty urbs seem to happen, we ignore them */ |
431 | if (!urb->actual_length) | ||
432 | return; | ||
661 | 433 | ||
662 | /* The urb might have been killed. */ | 434 | if (urb->actual_length <= KLSI_HDR_LEN) { |
663 | if (status) { | 435 | dbg("%s - malformed packet", __func__); |
664 | dbg("%s - nonzero read bulk status received: %d", __func__, | ||
665 | status); | ||
666 | return; | 436 | return; |
667 | } | 437 | } |
668 | 438 | ||
669 | /* The data received is again preceded by a length double-byte in LSB- | 439 | tty = tty_port_tty_get(&port->port); |
670 | * first order (see klsi_105_write() ) | 440 | if (!tty) |
671 | */ | 441 | return; |
672 | if (urb->actual_length == 0) { | ||
673 | /* empty urbs seem to happen, we ignore them */ | ||
674 | /* dbg("%s - emtpy URB", __func__); */ | ||
675 | ; | ||
676 | } else if (urb->actual_length <= 2) { | ||
677 | dbg("%s - size %d URB not understood", __func__, | ||
678 | urb->actual_length); | ||
679 | usb_serial_debug_data(debug, &port->dev, __func__, | ||
680 | urb->actual_length, data); | ||
681 | } else { | ||
682 | int bytes_sent = ((__u8 *) data)[0] + | ||
683 | ((unsigned int) ((__u8 *) data)[1] << 8); | ||
684 | tty = tty_port_tty_get(&port->port); | ||
685 | /* we should immediately resubmit the URB, before attempting | ||
686 | * to pass the data on to the tty layer. But that needs locking | ||
687 | * against re-entry an then mixed-up data because of | ||
688 | * intermixed tty_flip_buffer_push()s | ||
689 | * FIXME | ||
690 | */ | ||
691 | usb_serial_debug_data(debug, &port->dev, __func__, | ||
692 | urb->actual_length, data); | ||
693 | |||
694 | if (bytes_sent + 2 > urb->actual_length) { | ||
695 | dbg("%s - trying to read more data than available" | ||
696 | " (%d vs. %d)", __func__, | ||
697 | bytes_sent+2, urb->actual_length); | ||
698 | /* cap at implied limit */ | ||
699 | bytes_sent = urb->actual_length - 2; | ||
700 | } | ||
701 | |||
702 | tty_insert_flip_string(tty, data + 2, bytes_sent); | ||
703 | tty_flip_buffer_push(tty); | ||
704 | tty_kref_put(tty); | ||
705 | 442 | ||
706 | /* again lockless, but debug info only */ | 443 | len = get_unaligned_le16(data); |
707 | priv->bytes_in += bytes_sent; | 444 | if (len > urb->actual_length - KLSI_HDR_LEN) { |
445 | dbg("%s - packet length mismatch", __func__); | ||
446 | len = urb->actual_length - KLSI_HDR_LEN; | ||
708 | } | 447 | } |
709 | /* Continue trying to always read */ | ||
710 | usb_fill_bulk_urb(port->read_urb, port->serial->dev, | ||
711 | usb_rcvbulkpipe(port->serial->dev, | ||
712 | port->bulk_in_endpointAddress), | ||
713 | port->read_urb->transfer_buffer, | ||
714 | port->read_urb->transfer_buffer_length, | ||
715 | klsi_105_read_bulk_callback, | ||
716 | port); | ||
717 | rc = usb_submit_urb(port->read_urb, GFP_ATOMIC); | ||
718 | if (rc) | ||
719 | dev_err(&port->dev, | ||
720 | "%s - failed resubmitting read urb, error %d\n", | ||
721 | __func__, rc); | ||
722 | } /* klsi_105_read_bulk_callback */ | ||
723 | 448 | ||
449 | tty_insert_flip_string(tty, data + KLSI_HDR_LEN, len); | ||
450 | tty_flip_buffer_push(tty); | ||
451 | tty_kref_put(tty); | ||
452 | } | ||
724 | 453 | ||
725 | static void klsi_105_set_termios(struct tty_struct *tty, | 454 | static void klsi_105_set_termios(struct tty_struct *tty, |
726 | struct usb_serial_port *port, | 455 | struct usb_serial_port *port, |
@@ -887,8 +616,7 @@ static void klsi_105_set_termios(struct tty_struct *tty, | |||
887 | klsi_105_chg_port_settings(port, cfg); | 616 | klsi_105_chg_port_settings(port, cfg); |
888 | err: | 617 | err: |
889 | kfree(cfg); | 618 | kfree(cfg); |
890 | } /* klsi_105_set_termios */ | 619 | } |
891 | |||
892 | 620 | ||
893 | #if 0 | 621 | #if 0 |
894 | static void mct_u232_break_ctl(struct tty_struct *tty, int break_state) | 622 | static void mct_u232_break_ctl(struct tty_struct *tty, int break_state) |
@@ -906,7 +634,7 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state) | |||
906 | lcr |= MCT_U232_SET_BREAK; | 634 | lcr |= MCT_U232_SET_BREAK; |
907 | 635 | ||
908 | mct_u232_set_line_ctrl(serial, lcr); | 636 | mct_u232_set_line_ctrl(serial, lcr); |
909 | } /* mct_u232_break_ctl */ | 637 | } |
910 | #endif | 638 | #endif |
911 | 639 | ||
912 | static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file) | 640 | static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file) |
@@ -962,29 +690,6 @@ static int klsi_105_tiocmset(struct tty_struct *tty, struct file *file, | |||
962 | return retval; | 690 | return retval; |
963 | } | 691 | } |
964 | 692 | ||
965 | static void klsi_105_throttle(struct tty_struct *tty) | ||
966 | { | ||
967 | struct usb_serial_port *port = tty->driver_data; | ||
968 | dbg("%s - port %d", __func__, port->number); | ||
969 | usb_kill_urb(port->read_urb); | ||
970 | } | ||
971 | |||
972 | static void klsi_105_unthrottle(struct tty_struct *tty) | ||
973 | { | ||
974 | struct usb_serial_port *port = tty->driver_data; | ||
975 | int result; | ||
976 | |||
977 | dbg("%s - port %d", __func__, port->number); | ||
978 | |||
979 | port->read_urb->dev = port->serial->dev; | ||
980 | result = usb_submit_urb(port->read_urb, GFP_KERNEL); | ||
981 | if (result) | ||
982 | dev_err(&port->dev, | ||
983 | "%s - failed submitting read urb, error %d\n", | ||
984 | __func__, result); | ||
985 | } | ||
986 | |||
987 | |||
988 | 693 | ||
989 | static int __init klsi_105_init(void) | 694 | static int __init klsi_105_init(void) |
990 | { | 695 | { |
@@ -1005,7 +710,6 @@ failed_usb_serial_register: | |||
1005 | return retval; | 710 | return retval; |
1006 | } | 711 | } |
1007 | 712 | ||
1008 | |||
1009 | static void __exit klsi_105_exit(void) | 713 | static void __exit klsi_105_exit(void) |
1010 | { | 714 | { |
1011 | usb_deregister(&kl5kusb105d_driver); | 715 | usb_deregister(&kl5kusb105d_driver); |
@@ -1023,5 +727,3 @@ MODULE_LICENSE("GPL"); | |||
1023 | 727 | ||
1024 | module_param(debug, bool, S_IRUGO | S_IWUSR); | 728 | module_param(debug, bool, S_IRUGO | S_IWUSR); |
1025 | MODULE_PARM_DESC(debug, "enable extensive debugging messages"); | 729 | MODULE_PARM_DESC(debug, "enable extensive debugging messages"); |
1026 | |||
1027 | /* vim: set sts=8 ts=8 sw=8: */ | ||