aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Hung <hpeter@gmail.com>2015-03-17 05:48:20 -0400
committerJohan Hovold <johan@kernel.org>2015-03-27 12:29:25 -0400
commit8885078949fbb78c6be39ed2c653e4e883568e2f (patch)
treecbd2838759b0f8a3f3502fc101c6ba7add06785e
parentb830d07dc3f6891cd4788f651fa240d32fdbc068 (diff)
USB: f81232: implement RX bulk-in EP
The F81232 bulk-in is RX data + LSR channel, data format is [LSR+Data][LSR+Data]..... , We had implemented in f81232_process_read_urb(). Signed-off-by: Peter Hung <hpeter+linux_kernel@gmail.com> [johan: reword comment in process_read_urb ] Signed-off-by: Johan Hovold <johan@kernel.org>
-rw-r--r--drivers/usb/serial/f81232.c75
1 files changed, 41 insertions, 34 deletions
diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c
index 669a2f2e7fdb..4664cf4cc7a8 100644
--- a/drivers/usb/serial/f81232.c
+++ b/drivers/usb/serial/f81232.c
@@ -23,6 +23,7 @@
23#include <linux/uaccess.h> 23#include <linux/uaccess.h>
24#include <linux/usb.h> 24#include <linux/usb.h>
25#include <linux/usb/serial.h> 25#include <linux/usb/serial.h>
26#include <linux/serial_reg.h>
26 27
27static const struct usb_device_id id_table[] = { 28static const struct usb_device_id id_table[] = {
28 { USB_DEVICE(0x1934, 0x0706) }, 29 { USB_DEVICE(0x1934, 0x0706) },
@@ -104,44 +105,50 @@ exit:
104static void f81232_process_read_urb(struct urb *urb) 105static void f81232_process_read_urb(struct urb *urb)
105{ 106{
106 struct usb_serial_port *port = urb->context; 107 struct usb_serial_port *port = urb->context;
107 struct f81232_private *priv = usb_get_serial_port_data(port);
108 unsigned char *data = urb->transfer_buffer; 108 unsigned char *data = urb->transfer_buffer;
109 char tty_flag = TTY_NORMAL; 109 char tty_flag;
110 unsigned long flags; 110 unsigned int i;
111 u8 line_status; 111 u8 lsr;
112 int i;
113 112
114 /* update line status */ 113 /*
115 spin_lock_irqsave(&priv->lock, flags); 114 * When opening the port we get a 1-byte packet with the current LSR,
116 line_status = priv->modem_status; 115 * which we discard.
117 priv->modem_status &= ~UART_STATE_TRANSIENT_MASK; 116 */
118 spin_unlock_irqrestore(&priv->lock, flags); 117 if ((urb->actual_length < 2) || (urb->actual_length % 2))
119
120 if (!urb->actual_length)
121 return; 118 return;
122 119
123 /* break takes precedence over parity, */ 120 /* bulk-in data: [LSR(1Byte)+DATA(1Byte)][LSR(1Byte)+DATA(1Byte)]... */
124 /* which takes precedence over framing errors */ 121
125 if (line_status & UART_BREAK_ERROR) 122 for (i = 0; i < urb->actual_length; i += 2) {
126 tty_flag = TTY_BREAK; 123 tty_flag = TTY_NORMAL;
127 else if (line_status & UART_PARITY_ERROR) 124 lsr = data[i];
128 tty_flag = TTY_PARITY; 125
129 else if (line_status & UART_FRAME_ERROR) 126 if (lsr & UART_LSR_BRK_ERROR_BITS) {
130 tty_flag = TTY_FRAME; 127 if (lsr & UART_LSR_BI) {
131 dev_dbg(&port->dev, "%s - tty_flag = %d\n", __func__, tty_flag); 128 tty_flag = TTY_BREAK;
132 129 port->icount.brk++;
133 /* overrun is special, not associated with a char */ 130 usb_serial_handle_break(port);
134 if (line_status & UART_OVERRUN_ERROR) 131 } else if (lsr & UART_LSR_PE) {
135 tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); 132 tty_flag = TTY_PARITY;
136 133 port->icount.parity++;
137 if (port->port.console && port->sysrq) { 134 } else if (lsr & UART_LSR_FE) {
138 for (i = 0; i < urb->actual_length; ++i) 135 tty_flag = TTY_FRAME;
139 if (!usb_serial_handle_sysrq_char(port, data[i])) 136 port->icount.frame++;
140 tty_insert_flip_char(&port->port, data[i], 137 }
141 tty_flag); 138
142 } else { 139 if (lsr & UART_LSR_OE) {
143 tty_insert_flip_string_fixed_flag(&port->port, data, tty_flag, 140 port->icount.overrun++;
144 urb->actual_length); 141 tty_insert_flip_char(&port->port, 0,
142 TTY_OVERRUN);
143 }
144 }
145
146 if (port->port.console && port->sysrq) {
147 if (usb_serial_handle_sysrq_char(port, data[i + 1]))
148 continue;
149 }
150
151 tty_insert_flip_char(&port->port, data[i + 1], tty_flag);
145 } 152 }
146 153
147 tty_flip_buffer_push(&port->port); 154 tty_flip_buffer_push(&port->port);