| From 5d1678a33c731b56e245e888fdae5e88efce0997 Mon Sep 17 00:00:00 2001 |
| From: Johan Hovold <johan@kernel.org> |
| Date: Tue, 18 Nov 2014 11:25:19 +0100 |
| Subject: USB: keyspan: fix tty line-status reporting |
| |
| From: Johan Hovold <johan@kernel.org> |
| |
| commit 5d1678a33c731b56e245e888fdae5e88efce0997 upstream. |
| |
| Fix handling of TTY error flags, which are not bitmasks and must |
| specifically not be ORed together as this prevents the line discipline |
| from recognising them. |
| |
| Also insert null characters when reporting overrun errors as these are |
| not associated with the received character. |
| |
| Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") |
| Signed-off-by: Johan Hovold <johan@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/usb/serial/keyspan.c | 76 +++++++++++++++++++++++++++---------------- |
| 1 file changed, 48 insertions(+), 28 deletions(-) |
| |
| --- a/drivers/usb/serial/keyspan.c |
| +++ b/drivers/usb/serial/keyspan.c |
| @@ -322,14 +322,19 @@ static void usa26_indat_callback(struct |
| /* some bytes had errors, every byte has status */ |
| dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__); |
| for (i = 0; i + 1 < urb->actual_length; i += 2) { |
| - int stat = data[i], flag = 0; |
| - if (stat & RXERROR_OVERRUN) |
| - flag |= TTY_OVERRUN; |
| - if (stat & RXERROR_FRAMING) |
| - flag |= TTY_FRAME; |
| - if (stat & RXERROR_PARITY) |
| - flag |= TTY_PARITY; |
| + int stat = data[i]; |
| + int flag = TTY_NORMAL; |
| + |
| + if (stat & RXERROR_OVERRUN) { |
| + tty_insert_flip_char(&port->port, 0, |
| + TTY_OVERRUN); |
| + } |
| /* XXX should handle break (0x10) */ |
| + if (stat & RXERROR_PARITY) |
| + flag = TTY_PARITY; |
| + else if (stat & RXERROR_FRAMING) |
| + flag = TTY_FRAME; |
| + |
| tty_insert_flip_char(&port->port, data[i+1], |
| flag); |
| } |
| @@ -667,14 +672,19 @@ static void usa49_indat_callback(struct |
| } else { |
| /* some bytes had errors, every byte has status */ |
| for (i = 0; i + 1 < urb->actual_length; i += 2) { |
| - int stat = data[i], flag = 0; |
| - if (stat & RXERROR_OVERRUN) |
| - flag |= TTY_OVERRUN; |
| - if (stat & RXERROR_FRAMING) |
| - flag |= TTY_FRAME; |
| - if (stat & RXERROR_PARITY) |
| - flag |= TTY_PARITY; |
| + int stat = data[i]; |
| + int flag = TTY_NORMAL; |
| + |
| + if (stat & RXERROR_OVERRUN) { |
| + tty_insert_flip_char(&port->port, 0, |
| + TTY_OVERRUN); |
| + } |
| /* XXX should handle break (0x10) */ |
| + if (stat & RXERROR_PARITY) |
| + flag = TTY_PARITY; |
| + else if (stat & RXERROR_FRAMING) |
| + flag = TTY_FRAME; |
| + |
| tty_insert_flip_char(&port->port, data[i+1], |
| flag); |
| } |
| @@ -731,15 +741,19 @@ static void usa49wg_indat_callback(struc |
| */ |
| for (x = 0; x + 1 < len && |
| i + 1 < urb->actual_length; x += 2) { |
| - int stat = data[i], flag = 0; |
| + int stat = data[i]; |
| + int flag = TTY_NORMAL; |
| |
| - if (stat & RXERROR_OVERRUN) |
| - flag |= TTY_OVERRUN; |
| - if (stat & RXERROR_FRAMING) |
| - flag |= TTY_FRAME; |
| - if (stat & RXERROR_PARITY) |
| - flag |= TTY_PARITY; |
| + if (stat & RXERROR_OVERRUN) { |
| + tty_insert_flip_char(&port->port, 0, |
| + TTY_OVERRUN); |
| + } |
| /* XXX should handle break (0x10) */ |
| + if (stat & RXERROR_PARITY) |
| + flag = TTY_PARITY; |
| + else if (stat & RXERROR_FRAMING) |
| + flag = TTY_FRAME; |
| + |
| tty_insert_flip_char(&port->port, data[i+1], |
| flag); |
| i += 2; |
| @@ -802,14 +816,20 @@ static void usa90_indat_callback(struct |
| /* some bytes had errors, every byte has status */ |
| dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__); |
| for (i = 0; i + 1 < urb->actual_length; i += 2) { |
| - int stat = data[i], flag = 0; |
| - if (stat & RXERROR_OVERRUN) |
| - flag |= TTY_OVERRUN; |
| - if (stat & RXERROR_FRAMING) |
| - flag |= TTY_FRAME; |
| - if (stat & RXERROR_PARITY) |
| - flag |= TTY_PARITY; |
| + int stat = data[i]; |
| + int flag = TTY_NORMAL; |
| + |
| + if (stat & RXERROR_OVERRUN) { |
| + tty_insert_flip_char( |
| + &port->port, 0, |
| + TTY_OVERRUN); |
| + } |
| /* XXX should handle break (0x10) */ |
| + if (stat & RXERROR_PARITY) |
| + flag = TTY_PARITY; |
| + else if (stat & RXERROR_FRAMING) |
| + flag = TTY_FRAME; |
| + |
| tty_insert_flip_char(&port->port, |
| data[i+1], flag); |
| } |