diff options
author | Peter Hung <hpeter@gmail.com> | 2015-03-17 05:48:20 -0400 |
---|---|---|
committer | Johan Hovold <johan@kernel.org> | 2015-03-27 12:29:25 -0400 |
commit | 8885078949fbb78c6be39ed2c653e4e883568e2f (patch) | |
tree | cbd2838759b0f8a3f3502fc101c6ba7add06785e | |
parent | b830d07dc3f6891cd4788f651fa240d32fdbc068 (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.c | 75 |
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 | ||
27 | static const struct usb_device_id id_table[] = { | 28 | static const struct usb_device_id id_table[] = { |
28 | { USB_DEVICE(0x1934, 0x0706) }, | 29 | { USB_DEVICE(0x1934, 0x0706) }, |
@@ -104,44 +105,50 @@ exit: | |||
104 | static void f81232_process_read_urb(struct urb *urb) | 105 | static 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); |