diff options
Diffstat (limited to 'drivers/usb/acm.c')
-rw-r--r-- | drivers/usb/acm.c | 36 |
1 files changed, 18 insertions, 18 deletions
diff --git a/drivers/usb/acm.c b/drivers/usb/acm.c index 154d5cd22..1459f1d10 100644 --- a/drivers/usb/acm.c +++ b/drivers/usb/acm.c @@ -1,5 +1,5 @@ /* - * acm.c Version 0.14 + * acm.c Version 0.15 * * Copyright (c) 1999 Armin Fuerst <fuerst@in.tum.de> * Copyright (c) 1999 Pavel Machek <pavel@suse.cz> @@ -17,6 +17,7 @@ * v0.12 - added TIOCM ioctls, added break handling, made struct acm kmalloced * v0.13 - added termios, added hangup * v0.14 - sized down struct acm + * v0.15 - fixed flow control again - characters could be lost */ /* @@ -137,6 +138,7 @@ struct acm { unsigned int writesize; /* max packet size for the output bulk endpoint */ unsigned int used; /* someone has this acm's device open */ unsigned int minor; /* acm minor number */ + unsigned char throttle; /* throttled by tty layer */ unsigned char clocal; /* termios CLOCAL */ }; @@ -210,8 +212,6 @@ static void acm_ctrl_irq(struct urb *urb) dr->request, dr->index, dr->length, data[0], data[1]); return; } - - return; } static void acm_read_bulk(struct urb *urb) @@ -219,24 +219,25 @@ static void acm_read_bulk(struct urb *urb) struct acm *acm = urb->context; struct tty_struct *tty = acm->tty; unsigned char *data = urb->transfer_buffer; - int i; + int i = 0; if (!ACM_READY(acm)) return; - if (!urb->status) { - - for (i = 0; i < urb->actual_length; i++) + if (!urb->status & !acm->throttle) { + for (i = 0; i < urb->actual_length && !acm->throttle; i++) tty_insert_flip_char(tty, data[i], 0); - tty_flip_buffer_push(tty); - } else dbg("nonzero read bulk status received: %d", urb->status); - if (usb_submit_urb(urb)) - dbg("failed resubmitting read urb"); - - return; + if (!acm->throttle) { + urb->actual_length = 0; + if (usb_submit_urb(urb)) + dbg("failed resubmitting read urb"); + } else { + memmove(data, data + i, urb->actual_length - i); + urb->actual_length -= i; + } } static void acm_write_bulk(struct urb *urb) @@ -253,8 +254,6 @@ static void acm_write_bulk(struct urb *urb) (tty->ldisc.write_wakeup)(tty); wake_up_interruptible(&tty->write_wait); - - return; } /* @@ -347,15 +346,16 @@ static void acm_tty_throttle(struct tty_struct *tty) { struct acm *acm = tty->driver_data; if (!ACM_READY(acm)) return; - usb_unlink_urb(&acm->readurb); + acm->throttle = 1; } static void acm_tty_unthrottle(struct tty_struct *tty) { struct acm *acm = tty->driver_data; if (!ACM_READY(acm)) return; - if (usb_submit_urb(&acm->readurb)) - dbg("usb_submit_urb(read bulk) in unthrottle() failed"); + acm->throttle = 0; + if (acm->readurb.status != -EINPROGRESS) + acm_read_bulk(&acm->readurb); } static void acm_tty_break_ctl(struct tty_struct *tty, int state) |