diff options
author | Johan Hovold <jhovold@gmail.com> | 2012-11-18 07:23:35 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-11-21 16:33:56 -0500 |
commit | 32802077ce90ba955a9c50c6b27e6e6015a907bf (patch) | |
tree | 382c84c80a6fab2019968e7c40358298ae281943 /drivers/usb/serial/opticon.c | |
parent | 5ad473492ada0ab05bcf15791b7a41c587d831c7 (diff) |
USB: opticon: refactor reab-urb processing
Refactor and clean up read-urb processing.
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/serial/opticon.c')
-rw-r--r-- | drivers/usb/serial/opticon.c | 105 |
1 files changed, 59 insertions, 46 deletions
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 36fdab7b016f..8d6ece048f07 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c | |||
@@ -50,6 +50,64 @@ struct opticon_private { | |||
50 | }; | 50 | }; |
51 | 51 | ||
52 | 52 | ||
53 | static void opticon_process_data_packet(struct usb_serial_port *port, | ||
54 | const unsigned char *buf, size_t len) | ||
55 | { | ||
56 | struct tty_struct *tty; | ||
57 | |||
58 | tty = tty_port_tty_get(&port->port); | ||
59 | if (!tty) | ||
60 | return; | ||
61 | |||
62 | tty_insert_flip_string(tty, buf, len); | ||
63 | tty_flip_buffer_push(tty); | ||
64 | tty_kref_put(tty); | ||
65 | } | ||
66 | |||
67 | static void opticon_process_status_packet(struct usb_serial_port *port, | ||
68 | const unsigned char *buf, size_t len) | ||
69 | { | ||
70 | struct opticon_private *priv = usb_get_serial_port_data(port); | ||
71 | unsigned long flags; | ||
72 | |||
73 | spin_lock_irqsave(&priv->lock, flags); | ||
74 | if (buf[0] == 0x00) | ||
75 | priv->cts = false; | ||
76 | else | ||
77 | priv->cts = true; | ||
78 | spin_unlock_irqrestore(&priv->lock, flags); | ||
79 | } | ||
80 | |||
81 | static void opticon_process_read_urb(struct urb *urb) | ||
82 | { | ||
83 | struct usb_serial_port *port = urb->context; | ||
84 | const unsigned char *hdr = urb->transfer_buffer; | ||
85 | const unsigned char *data = hdr + 2; | ||
86 | size_t data_len = urb->actual_length - 2; | ||
87 | |||
88 | if (urb->actual_length <= 2) { | ||
89 | dev_dbg(&port->dev, "malformed packet received: %d bytes\n", | ||
90 | urb->actual_length); | ||
91 | return; | ||
92 | } | ||
93 | /* | ||
94 | * Data from the device comes with a 2 byte header: | ||
95 | * | ||
96 | * <0x00><0x00>data... | ||
97 | * This is real data to be sent to the tty layer | ||
98 | * <0x00><0x01>level | ||
99 | * This is a CTS level change, the third byte is the CTS | ||
100 | * value (0 for low, 1 for high). | ||
101 | */ | ||
102 | if ((hdr[0] == 0x00) && (hdr[1] == 0x00)) { | ||
103 | opticon_process_data_packet(port, data, data_len); | ||
104 | } else if ((hdr[0] == 0x00) && (hdr[1] == 0x01)) { | ||
105 | opticon_process_status_packet(port, data, data_len); | ||
106 | } else { | ||
107 | dev_dbg(&port->dev, "unknown packet received: %02x %02x\n", | ||
108 | hdr[0], hdr[1]); | ||
109 | } | ||
110 | } | ||
53 | 111 | ||
54 | static void opticon_read_bulk_callback(struct urb *urb) | 112 | static void opticon_read_bulk_callback(struct urb *urb) |
55 | { | 113 | { |
@@ -57,10 +115,7 @@ static void opticon_read_bulk_callback(struct urb *urb) | |||
57 | struct opticon_private *priv = usb_get_serial_port_data(port); | 115 | struct opticon_private *priv = usb_get_serial_port_data(port); |
58 | unsigned char *data = urb->transfer_buffer; | 116 | unsigned char *data = urb->transfer_buffer; |
59 | int status = urb->status; | 117 | int status = urb->status; |
60 | struct tty_struct *tty; | ||
61 | int result; | 118 | int result; |
62 | int data_length; | ||
63 | unsigned long flags; | ||
64 | 119 | ||
65 | switch (status) { | 120 | switch (status) { |
66 | case 0: | 121 | case 0: |
@@ -81,49 +136,7 @@ static void opticon_read_bulk_callback(struct urb *urb) | |||
81 | 136 | ||
82 | usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data); | 137 | usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data); |
83 | 138 | ||
84 | if (urb->actual_length > 2) { | 139 | opticon_process_read_urb(urb); |
85 | data_length = urb->actual_length - 2; | ||
86 | |||
87 | /* | ||
88 | * Data from the device comes with a 2 byte header: | ||
89 | * | ||
90 | * <0x00><0x00>data... | ||
91 | * This is real data to be sent to the tty layer | ||
92 | * <0x00><0x01)level | ||
93 | * This is a CTS level change, the third byte is the CTS | ||
94 | * value (0 for low, 1 for high). | ||
95 | */ | ||
96 | if ((data[0] == 0x00) && (data[1] == 0x00)) { | ||
97 | /* real data, send it to the tty layer */ | ||
98 | tty = tty_port_tty_get(&port->port); | ||
99 | if (tty) { | ||
100 | tty_insert_flip_string(tty, data + 2, | ||
101 | data_length); | ||
102 | tty_flip_buffer_push(tty); | ||
103 | tty_kref_put(tty); | ||
104 | } | ||
105 | } else { | ||
106 | if ((data[0] == 0x00) && (data[1] == 0x01)) { | ||
107 | spin_lock_irqsave(&priv->lock, flags); | ||
108 | /* CTS status information package */ | ||
109 | if (data[2] == 0x00) | ||
110 | priv->cts = false; | ||
111 | else | ||
112 | priv->cts = true; | ||
113 | spin_unlock_irqrestore(&priv->lock, flags); | ||
114 | } else { | ||
115 | dev_dbg(&port->dev, | ||
116 | "Unknown data packet received from the device:" | ||
117 | " %2x %2x\n", | ||
118 | data[0], data[1]); | ||
119 | } | ||
120 | } | ||
121 | } else { | ||
122 | dev_dbg(&port->dev, | ||
123 | "Improper amount of data received from the device, " | ||
124 | "%d bytes", urb->actual_length); | ||
125 | } | ||
126 | |||
127 | exit: | 140 | exit: |
128 | spin_lock(&priv->lock); | 141 | spin_lock(&priv->lock); |
129 | 142 | ||