aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/serial/safe_serial.c290
1 files changed, 157 insertions, 133 deletions
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
index f823e4dcea1e..def52d07a4ea 100644
--- a/drivers/usb/serial/safe_serial.c
+++ b/drivers/usb/serial/safe_serial.c
@@ -13,24 +13,25 @@
13 * Stuart Lynne <sl@lineo.com>, Tom Rushworth <tbr@lineo.com> 13 * Stuart Lynne <sl@lineo.com>, Tom Rushworth <tbr@lineo.com>
14 */ 14 */
15 15
16/* 16/*
17 * The encapsultaion is designed to overcome difficulties with some USB hardware. 17 * The encapsultaion is designed to overcome difficulties with some USB
18 * hardware.
18 * 19 *
19 * While the USB protocol has a CRC over the data while in transit, i.e. while 20 * While the USB protocol has a CRC over the data while in transit, i.e. while
20 * being carried over the bus, there is no end to end protection. If the hardware 21 * being carried over the bus, there is no end to end protection. If the
21 * has any problems getting the data into or out of the USB transmit and receive 22 * hardware has any problems getting the data into or out of the USB transmit
22 * FIFO's then data can be lost. 23 * and receive FIFO's then data can be lost.
23 * 24 *
24 * This protocol adds a two byte trailer to each USB packet to specify the number 25 * This protocol adds a two byte trailer to each USB packet to specify the
25 * of bytes of valid data and a 10 bit CRC that will allow the receiver to verify 26 * number of bytes of valid data and a 10 bit CRC that will allow the receiver
26 * that the entire USB packet was received without error. 27 * to verify that the entire USB packet was received without error.
27 * 28 *
28 * Because in this case the sender and receiver are the class and function drivers 29 * Because in this case the sender and receiver are the class and function
29 * there is now end to end protection. 30 * drivers there is now end to end protection.
30 * 31 *
31 * There is an additional option that can be used to force all transmitted packets 32 * There is an additional option that can be used to force all transmitted
32 * to be padded to the maximum packet size. This provides a work around for some 33 * packets to be padded to the maximum packet size. This provides a work
33 * devices which have problems with small USB packets. 34 * around for some devices which have problems with small USB packets.
34 * 35 *
35 * Assuming a packetsize of N: 36 * Assuming a packetsize of N:
36 * 37 *
@@ -44,11 +45,12 @@
44 * | Data Length | 10 bit CRC | 45 * | Data Length | 10 bit CRC |
45 * + 7 . 6 . 5 . 4 . 3 . 2 . 1 . 0 | 7 . 6 . 5 . 4 . 3 . 2 . 1 . 0 + 46 * + 7 . 6 . 5 . 4 . 3 . 2 . 1 . 0 | 7 . 6 . 5 . 4 . 3 . 2 . 1 . 0 +
46 * 47 *
47 * The 10 bit CRC is computed across the sent data, followed by the trailer with 48 * The 10 bit CRC is computed across the sent data, followed by the trailer
48 * the length set and the CRC set to zero. The CRC is then OR'd into the trailer. 49 * with the length set and the CRC set to zero. The CRC is then OR'd into
50 * the trailer.
49 * 51 *
50 * When received a 10 bit CRC is computed over the entire frame including the trailer 52 * When received a 10 bit CRC is computed over the entire frame including
51 * and should be equal to zero. 53 * the trailer and should be equal to zero.
52 * 54 *
53 * Two module parameters are used to control the encapsulation, if both are 55 * Two module parameters are used to control the encapsulation, if both are
54 * turned of the module works as a simple serial device with NO 56 * turned of the module works as a simple serial device with NO
@@ -69,7 +71,7 @@
69#include <linux/tty_flip.h> 71#include <linux/tty_flip.h>
70#include <linux/module.h> 72#include <linux/module.h>
71#include <linux/spinlock.h> 73#include <linux/spinlock.h>
72#include <asm/uaccess.h> 74#include <linux/uaccess.h>
73#include <linux/usb.h> 75#include <linux/usb.h>
74#include <linux/usb/serial.h> 76#include <linux/usb/serial.h>
75 77
@@ -86,12 +88,12 @@ static int padded = CONFIG_USB_SERIAL_SAFE_PADDED;
86#define DRIVER_AUTHOR "sl@lineo.com, tbr@lineo.com" 88#define DRIVER_AUTHOR "sl@lineo.com, tbr@lineo.com"
87#define DRIVER_DESC "USB Safe Encapsulated Serial" 89#define DRIVER_DESC "USB Safe Encapsulated Serial"
88 90
89MODULE_AUTHOR (DRIVER_AUTHOR); 91MODULE_AUTHOR(DRIVER_AUTHOR);
90MODULE_DESCRIPTION (DRIVER_DESC); 92MODULE_DESCRIPTION(DRIVER_DESC);
91MODULE_LICENSE("GPL"); 93MODULE_LICENSE("GPL");
92 94
93static __u16 vendor; // no default 95static __u16 vendor; /* no default */
94static __u16 product; // no default 96static __u16 product; /* no default */
95module_param(vendor, ushort, 0); 97module_param(vendor, ushort, 0);
96MODULE_PARM_DESC(vendor, "User specified USB idVendor (required)"); 98MODULE_PARM_DESC(vendor, "User specified USB idVendor (required)");
97module_param(product, ushort, 0); 99module_param(product, ushort, 0);
@@ -122,30 +124,31 @@ MODULE_PARM_DESC(padded, "Pad to full wMaxPacketSize On/Off");
122#define LINEO_SAFESERIAL_CRC_PADDED 0x02 124#define LINEO_SAFESERIAL_CRC_PADDED 0x02
123 125
124 126
125#define MY_USB_DEVICE(vend,prod,dc,ic,isc) \ 127#define MY_USB_DEVICE(vend, prod, dc, ic, isc) \
126 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_CLASS | \ 128 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
127 USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS, \ 129 USB_DEVICE_ID_MATCH_DEV_CLASS | \
128 .idVendor = (vend), \ 130 USB_DEVICE_ID_MATCH_INT_CLASS | \
129 .idProduct = (prod),\ 131 USB_DEVICE_ID_MATCH_INT_SUBCLASS, \
130 .bDeviceClass = (dc),\ 132 .idVendor = (vend), \
131 .bInterfaceClass = (ic), \ 133 .idProduct = (prod),\
132 .bInterfaceSubClass = (isc), 134 .bDeviceClass = (dc),\
135 .bInterfaceClass = (ic), \
136 .bInterfaceSubClass = (isc),
133 137
134static struct usb_device_id id_table[] = { 138static struct usb_device_id id_table[] = {
135 {MY_USB_DEVICE (0x49f, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Itsy 139 {MY_USB_DEVICE(0x49f, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Itsy */
136 {MY_USB_DEVICE (0x3f0, 0x2101, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Calypso 140 {MY_USB_DEVICE(0x3f0, 0x2101, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Calypso */
137 {MY_USB_DEVICE (0x4dd, 0x8001, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Iris 141 {MY_USB_DEVICE(0x4dd, 0x8001, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Iris */
138 {MY_USB_DEVICE (0x4dd, 0x8002, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Collie 142 {MY_USB_DEVICE(0x4dd, 0x8002, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Collie */
139 {MY_USB_DEVICE (0x4dd, 0x8003, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Collie 143 {MY_USB_DEVICE(0x4dd, 0x8003, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Collie */
140 {MY_USB_DEVICE (0x4dd, 0x8004, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Collie 144 {MY_USB_DEVICE(0x4dd, 0x8004, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Collie */
141 {MY_USB_DEVICE (0x5f9, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Sharp tmp 145 {MY_USB_DEVICE(0x5f9, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Sharp tmp */
142 // extra null entry for module 146 /* extra null entry for module vendor/produc parameters */
143 // vendor/produc parameters 147 {MY_USB_DEVICE(0, 0, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},
144 {MY_USB_DEVICE (0, 0, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, 148 {} /* terminating entry */
145 {} // terminating entry
146}; 149};
147 150
148MODULE_DEVICE_TABLE (usb, id_table); 151MODULE_DEVICE_TABLE(usb, id_table);
149 152
150static struct usb_driver safe_driver = { 153static struct usb_driver safe_driver = {
151 .name = "safe_serial", 154 .name = "safe_serial",
@@ -156,29 +159,45 @@ static struct usb_driver safe_driver = {
156}; 159};
157 160
158static const __u16 crc10_table[256] = { 161static const __u16 crc10_table[256] = {
159 0x000, 0x233, 0x255, 0x066, 0x299, 0x0aa, 0x0cc, 0x2ff, 0x301, 0x132, 0x154, 0x367, 0x198, 0x3ab, 0x3cd, 0x1fe, 162 0x000, 0x233, 0x255, 0x066, 0x299, 0x0aa, 0x0cc, 0x2ff,
160 0x031, 0x202, 0x264, 0x057, 0x2a8, 0x09b, 0x0fd, 0x2ce, 0x330, 0x103, 0x165, 0x356, 0x1a9, 0x39a, 0x3fc, 0x1cf, 163 0x301, 0x132, 0x154, 0x367, 0x198, 0x3ab, 0x3cd, 0x1fe,
161 0x062, 0x251, 0x237, 0x004, 0x2fb, 0x0c8, 0x0ae, 0x29d, 0x363, 0x150, 0x136, 0x305, 0x1fa, 0x3c9, 0x3af, 0x19c, 164 0x031, 0x202, 0x264, 0x057, 0x2a8, 0x09b, 0x0fd, 0x2ce,
162 0x053, 0x260, 0x206, 0x035, 0x2ca, 0x0f9, 0x09f, 0x2ac, 0x352, 0x161, 0x107, 0x334, 0x1cb, 0x3f8, 0x39e, 0x1ad, 165 0x330, 0x103, 0x165, 0x356, 0x1a9, 0x39a, 0x3fc, 0x1cf,
163 0x0c4, 0x2f7, 0x291, 0x0a2, 0x25d, 0x06e, 0x008, 0x23b, 0x3c5, 0x1f6, 0x190, 0x3a3, 0x15c, 0x36f, 0x309, 0x13a, 166 0x062, 0x251, 0x237, 0x004, 0x2fb, 0x0c8, 0x0ae, 0x29d,
164 0x0f5, 0x2c6, 0x2a0, 0x093, 0x26c, 0x05f, 0x039, 0x20a, 0x3f4, 0x1c7, 0x1a1, 0x392, 0x16d, 0x35e, 0x338, 0x10b, 167 0x363, 0x150, 0x136, 0x305, 0x1fa, 0x3c9, 0x3af, 0x19c,
165 0x0a6, 0x295, 0x2f3, 0x0c0, 0x23f, 0x00c, 0x06a, 0x259, 0x3a7, 0x194, 0x1f2, 0x3c1, 0x13e, 0x30d, 0x36b, 0x158, 168 0x053, 0x260, 0x206, 0x035, 0x2ca, 0x0f9, 0x09f, 0x2ac,
166 0x097, 0x2a4, 0x2c2, 0x0f1, 0x20e, 0x03d, 0x05b, 0x268, 0x396, 0x1a5, 0x1c3, 0x3f0, 0x10f, 0x33c, 0x35a, 0x169, 169 0x352, 0x161, 0x107, 0x334, 0x1cb, 0x3f8, 0x39e, 0x1ad,
167 0x188, 0x3bb, 0x3dd, 0x1ee, 0x311, 0x122, 0x144, 0x377, 0x289, 0x0ba, 0x0dc, 0x2ef, 0x010, 0x223, 0x245, 0x076, 170 0x0c4, 0x2f7, 0x291, 0x0a2, 0x25d, 0x06e, 0x008, 0x23b,
168 0x1b9, 0x38a, 0x3ec, 0x1df, 0x320, 0x113, 0x175, 0x346, 0x2b8, 0x08b, 0x0ed, 0x2de, 0x021, 0x212, 0x274, 0x047, 171 0x3c5, 0x1f6, 0x190, 0x3a3, 0x15c, 0x36f, 0x309, 0x13a,
169 0x1ea, 0x3d9, 0x3bf, 0x18c, 0x373, 0x140, 0x126, 0x315, 0x2eb, 0x0d8, 0x0be, 0x28d, 0x072, 0x241, 0x227, 0x014, 172 0x0f5, 0x2c6, 0x2a0, 0x093, 0x26c, 0x05f, 0x039, 0x20a,
170 0x1db, 0x3e8, 0x38e, 0x1bd, 0x342, 0x171, 0x117, 0x324, 0x2da, 0x0e9, 0x08f, 0x2bc, 0x043, 0x270, 0x216, 0x025, 173 0x3f4, 0x1c7, 0x1a1, 0x392, 0x16d, 0x35e, 0x338, 0x10b,
171 0x14c, 0x37f, 0x319, 0x12a, 0x3d5, 0x1e6, 0x180, 0x3b3, 0x24d, 0x07e, 0x018, 0x22b, 0x0d4, 0x2e7, 0x281, 0x0b2, 174 0x0a6, 0x295, 0x2f3, 0x0c0, 0x23f, 0x00c, 0x06a, 0x259,
172 0x17d, 0x34e, 0x328, 0x11b, 0x3e4, 0x1d7, 0x1b1, 0x382, 0x27c, 0x04f, 0x029, 0x21a, 0x0e5, 0x2d6, 0x2b0, 0x083, 175 0x3a7, 0x194, 0x1f2, 0x3c1, 0x13e, 0x30d, 0x36b, 0x158,
173 0x12e, 0x31d, 0x37b, 0x148, 0x3b7, 0x184, 0x1e2, 0x3d1, 0x22f, 0x01c, 0x07a, 0x249, 0x0b6, 0x285, 0x2e3, 0x0d0, 176 0x097, 0x2a4, 0x2c2, 0x0f1, 0x20e, 0x03d, 0x05b, 0x268,
174 0x11f, 0x32c, 0x34a, 0x179, 0x386, 0x1b5, 0x1d3, 0x3e0, 0x21e, 0x02d, 0x04b, 0x278, 0x087, 0x2b4, 0x2d2, 0x0e1, 177 0x396, 0x1a5, 0x1c3, 0x3f0, 0x10f, 0x33c, 0x35a, 0x169,
178 0x188, 0x3bb, 0x3dd, 0x1ee, 0x311, 0x122, 0x144, 0x377,
179 0x289, 0x0ba, 0x0dc, 0x2ef, 0x010, 0x223, 0x245, 0x076,
180 0x1b9, 0x38a, 0x3ec, 0x1df, 0x320, 0x113, 0x175, 0x346,
181 0x2b8, 0x08b, 0x0ed, 0x2de, 0x021, 0x212, 0x274, 0x047,
182 0x1ea, 0x3d9, 0x3bf, 0x18c, 0x373, 0x140, 0x126, 0x315,
183 0x2eb, 0x0d8, 0x0be, 0x28d, 0x072, 0x241, 0x227, 0x014,
184 0x1db, 0x3e8, 0x38e, 0x1bd, 0x342, 0x171, 0x117, 0x324,
185 0x2da, 0x0e9, 0x08f, 0x2bc, 0x043, 0x270, 0x216, 0x025,
186 0x14c, 0x37f, 0x319, 0x12a, 0x3d5, 0x1e6, 0x180, 0x3b3,
187 0x24d, 0x07e, 0x018, 0x22b, 0x0d4, 0x2e7, 0x281, 0x0b2,
188 0x17d, 0x34e, 0x328, 0x11b, 0x3e4, 0x1d7, 0x1b1, 0x382,
189 0x27c, 0x04f, 0x029, 0x21a, 0x0e5, 0x2d6, 0x2b0, 0x083,
190 0x12e, 0x31d, 0x37b, 0x148, 0x3b7, 0x184, 0x1e2, 0x3d1,
191 0x22f, 0x01c, 0x07a, 0x249, 0x0b6, 0x285, 0x2e3, 0x0d0,
192 0x11f, 0x32c, 0x34a, 0x179, 0x386, 0x1b5, 0x1d3, 0x3e0,
193 0x21e, 0x02d, 0x04b, 0x278, 0x087, 0x2b4, 0x2d2, 0x0e1,
175}; 194};
176 195
177#define CRC10_INITFCS 0x000 // Initial FCS value 196#define CRC10_INITFCS 0x000 /* Initial FCS value */
178#define CRC10_GOODFCS 0x000 // Good final FCS value 197#define CRC10_GOODFCS 0x000 /* Good final FCS value */
179#define CRC10_FCS(fcs, c) ( (((fcs) << 8) & 0x3ff) ^ crc10_table[((fcs) >> 2) & 0xff] ^ (c)) 198#define CRC10_FCS(fcs, c) ((((fcs) << 8) & 0x3ff) ^ crc10_table[((fcs) >> 2) & 0xff] ^ (c))
180 199
181/** 200/**
182 * fcs_compute10 - memcpy and calculate 10 bit CRC across buffer 201 * fcs_compute10 - memcpy and calculate 10 bit CRC across buffer
183 * @sp: pointer to buffer 202 * @sp: pointer to buffer
184 * @len: number of bytes 203 * @len: number of bytes
@@ -187,13 +206,13 @@ static const __u16 crc10_table[256] = {
187 * Perform a memcpy and calculate fcs using ppp 10bit CRC algorithm. Return 206 * Perform a memcpy and calculate fcs using ppp 10bit CRC algorithm. Return
188 * new 10 bit FCS. 207 * new 10 bit FCS.
189 */ 208 */
190static __u16 __inline__ fcs_compute10 (unsigned char *sp, int len, __u16 fcs) 209static __u16 __inline__ fcs_compute10(unsigned char *sp, int len, __u16 fcs)
191{ 210{
192 for (; len-- > 0; fcs = CRC10_FCS (fcs, *sp++)); 211 for (; len-- > 0; fcs = CRC10_FCS(fcs, *sp++));
193 return fcs; 212 return fcs;
194} 213}
195 214
196static void safe_read_bulk_callback (struct urb *urb) 215static void safe_read_bulk_callback(struct urb *urb)
197{ 216{
198 struct usb_serial_port *port = urb->context; 217 struct usb_serial_port *port = urb->context;
199 unsigned char *data = urb->transfer_buffer; 218 unsigned char *data = urb->transfer_buffer;
@@ -201,7 +220,7 @@ static void safe_read_bulk_callback (struct urb *urb)
201 int result; 220 int result;
202 int status = urb->status; 221 int status = urb->status;
203 222
204 dbg ("%s", __func__); 223 dbg("%s", __func__);
205 224
206 if (status) { 225 if (status) {
207 dbg("%s - nonzero read bulk status received: %d", 226 dbg("%s - nonzero read bulk status received: %d",
@@ -209,50 +228,55 @@ static void safe_read_bulk_callback (struct urb *urb)
209 return; 228 return;
210 } 229 }
211 230
212 dbg ("safe_read_bulk_callback length: %d", port->read_urb->actual_length); 231 dbg("safe_read_bulk_callback length: %d",
232 port->read_urb->actual_length);
213#ifdef ECHO_RCV 233#ifdef ECHO_RCV
214 { 234 {
215 int i; 235 int i;
216 unsigned char *cp = port->read_urb->transfer_buffer; 236 unsigned char *cp = port->read_urb->transfer_buffer;
217 for (i = 0; i < port->read_urb->actual_length; i++) { 237 for (i = 0; i < port->read_urb->actual_length; i++) {
218 if ((i % 32) == 0) { 238 if ((i % 32) == 0)
219 printk ("\nru[%02x] ", i); 239 printk("\nru[%02x] ", i);
220 } 240 printk("%02x ", *cp++);
221 printk ("%02x ", *cp++);
222 } 241 }
223 printk ("\n"); 242 printk("\n");
224 } 243 }
225#endif 244#endif
226 if (safe) { 245 if (safe) {
227 __u16 fcs; 246 __u16 fcs;
228 if (!(fcs = fcs_compute10 (data, length, CRC10_INITFCS))) { 247 fcs = fcs_compute10(data, length, CRC10_INITFCS);
248 if (!fcs) {
229 int actual_length = data[length - 2] >> 2; 249 int actual_length = data[length - 2] >> 2;
230 if (actual_length <= (length - 2)) { 250 if (actual_length <= (length - 2)) {
231 info ("%s - actual: %d", __func__, actual_length); 251 info("%s - actual: %d", __func__,
232 tty_insert_flip_string(port->port.tty, data, actual_length); 252 actual_length);
233 tty_flip_buffer_push (port->port.tty); 253 tty_insert_flip_string(port->port.tty,
254 data, actual_length);
255 tty_flip_buffer_push(port->port.tty);
234 } else { 256 } else {
235 err ("%s - inconsistent lengths %d:%d", __func__, 257 err("%s - inconsistent lengths %d:%d",
236 actual_length, length); 258 __func__, actual_length, length);
237 } 259 }
238 } else { 260 } else {
239 err ("%s - bad CRC %x", __func__, fcs); 261 err("%s - bad CRC %x", __func__, fcs);
240 } 262 }
241 } else { 263 } else {
242 tty_insert_flip_string(port->port.tty, data, length); 264 tty_insert_flip_string(port->port.tty, data, length);
243 tty_flip_buffer_push (port->port.tty); 265 tty_flip_buffer_push(port->port.tty);
244 } 266 }
245 267
246 /* Continue trying to always read */ 268 /* Continue trying to always read */
247 usb_fill_bulk_urb (urb, port->serial->dev, 269 usb_fill_bulk_urb(urb, port->serial->dev,
248 usb_rcvbulkpipe (port->serial->dev, port->bulk_in_endpointAddress), 270 usb_rcvbulkpipe(port->serial->dev,
249 urb->transfer_buffer, urb->transfer_buffer_length, 271 port->bulk_in_endpointAddress),
250 safe_read_bulk_callback, port); 272 urb->transfer_buffer, urb->transfer_buffer_length,
251 273 safe_read_bulk_callback, port);
252 if ((result = usb_submit_urb (urb, GFP_ATOMIC))) { 274
253 err ("%s - failed resubmitting read urb, error %d", __func__, result); 275 result = usb_submit_urb(urb, GFP_ATOMIC);
276 if (result)
277 err("%s - failed resubmitting read urb, error %d",
278 __func__, result);
254 /* FIXME: Need a mechanism to retry later if this happens */ 279 /* FIXME: Need a mechanism to retry later if this happens */
255 }
256} 280}
257 281
258static int safe_write(struct tty_struct *tty, struct usb_serial_port *port, 282static int safe_write(struct tty_struct *tty, struct usb_serial_port *port,
@@ -263,23 +287,23 @@ static int safe_write(struct tty_struct *tty, struct usb_serial_port *port,
263 int i; 287 int i;
264 int packet_length; 288 int packet_length;
265 289
266 dbg ("safe_write port: %p %d urb: %p count: %d", port, port->number, port->write_urb, 290 dbg("safe_write port: %p %d urb: %p count: %d",
267 count); 291 port, port->number, port->write_urb, count);
268 292
269 if (!port->write_urb) { 293 if (!port->write_urb) {
270 dbg ("%s - write urb NULL", __func__); 294 dbg("%s - write urb NULL", __func__);
271 return 0; 295 return 0;
272 } 296 }
273 297
274 dbg ("safe_write write_urb: %d transfer_buffer_length", 298 dbg("safe_write write_urb: %d transfer_buffer_length",
275 port->write_urb->transfer_buffer_length); 299 port->write_urb->transfer_buffer_length);
276 300
277 if (!port->write_urb->transfer_buffer_length) { 301 if (!port->write_urb->transfer_buffer_length) {
278 dbg ("%s - write urb transfer_buffer_length zero", __func__); 302 dbg("%s - write urb transfer_buffer_length zero", __func__);
279 return 0; 303 return 0;
280 } 304 }
281 if (count == 0) { 305 if (count == 0) {
282 dbg ("%s - write request of 0 bytes", __func__); 306 dbg("%s - write request of 0 bytes", __func__);
283 return 0; 307 return 0;
284 } 308 }
285 spin_lock_bh(&port->lock); 309 spin_lock_bh(&port->lock);
@@ -291,63 +315,64 @@ static int safe_write(struct tty_struct *tty, struct usb_serial_port *port,
291 port->write_urb_busy = 1; 315 port->write_urb_busy = 1;
292 spin_unlock_bh(&port->lock); 316 spin_unlock_bh(&port->lock);
293 317
294 packet_length = port->bulk_out_size; // get max packetsize 318 packet_length = port->bulk_out_size; /* get max packetsize */
295 319
296 i = packet_length - (safe ? 2 : 0); // get bytes to send 320 i = packet_length - (safe ? 2 : 0); /* get bytes to send */
297 count = (count > i) ? i : count; 321 count = (count > i) ? i : count;
298 322
299 323
300 // get the data into the transfer buffer 324 /* get the data into the transfer buffer */
301 data = port->write_urb->transfer_buffer; 325 data = port->write_urb->transfer_buffer;
302 memset (data, '0', packet_length); 326 memset(data, '0', packet_length);
303 327
304 memcpy (data, buf, count); 328 memcpy(data, buf, count);
305 329
306 if (safe) { 330 if (safe) {
307 __u16 fcs; 331 __u16 fcs;
308 332
309 // pad if necessary 333 /* pad if necessary */
310 if (!padded) { 334 if (!padded)
311 packet_length = count + 2; 335 packet_length = count + 2;
312 } 336 /* set count */
313 // set count
314 data[packet_length - 2] = count << 2; 337 data[packet_length - 2] = count << 2;
315 data[packet_length - 1] = 0; 338 data[packet_length - 1] = 0;
316 339
317 // compute fcs and insert into trailer 340 /* compute fcs and insert into trailer */
318 fcs = fcs_compute10 (data, packet_length, CRC10_INITFCS); 341 fcs = fcs_compute10(data, packet_length, CRC10_INITFCS);
319 data[packet_length - 2] |= fcs >> 8; 342 data[packet_length - 2] |= fcs >> 8;
320 data[packet_length - 1] |= fcs & 0xff; 343 data[packet_length - 1] |= fcs & 0xff;
321 344
322 // set length to send 345 /* set length to send */
323 port->write_urb->transfer_buffer_length = packet_length; 346 port->write_urb->transfer_buffer_length = packet_length;
324 } else { 347 } else {
325 port->write_urb->transfer_buffer_length = count; 348 port->write_urb->transfer_buffer_length = count;
326 } 349 }
327 350
328 usb_serial_debug_data(debug, &port->dev, __func__, count, port->write_urb->transfer_buffer); 351 usb_serial_debug_data(debug, &port->dev, __func__, count,
352 port->write_urb->transfer_buffer);
329#ifdef ECHO_TX 353#ifdef ECHO_TX
330 { 354 {
331 int i; 355 int i;
332 unsigned char *cp = port->write_urb->transfer_buffer; 356 unsigned char *cp = port->write_urb->transfer_buffer;
333 for (i = 0; i < port->write_urb->transfer_buffer_length; i++) { 357 for (i = 0; i < port->write_urb->transfer_buffer_length; i++) {
334 if ((i % 32) == 0) { 358 if ((i % 32) == 0)
335 printk ("\nsu[%02x] ", i); 359 printk("\nsu[%02x] ", i);
336 } 360 printk("%02x ", *cp++);
337 printk ("%02x ", *cp++);
338 } 361 }
339 printk ("\n"); 362 printk("\n");
340 } 363 }
341#endif 364#endif
342 port->write_urb->dev = port->serial->dev; 365 port->write_urb->dev = port->serial->dev;
343 if ((result = usb_submit_urb (port->write_urb, GFP_KERNEL))) { 366 result = usb_submit_urb(port->write_urb, GFP_KERNEL);
367 if (result) {
344 port->write_urb_busy = 0; 368 port->write_urb_busy = 0;
345 err ("%s - failed submitting write urb, error %d", __func__, result); 369 err("%s - failed submitting write urb, error %d",
370 __func__, result);
346 return 0; 371 return 0;
347 } 372 }
348 dbg ("%s urb: %p submitted", __func__, port->write_urb); 373 dbg("%s urb: %p submitted", __func__, port->write_urb);
349 374
350 return (count); 375 return count;
351} 376}
352 377
353static int safe_write_room(struct tty_struct *tty) 378static int safe_write_room(struct tty_struct *tty)
@@ -356,21 +381,19 @@ static int safe_write_room(struct tty_struct *tty)
356 int room = 0; /* Default: no room */ 381 int room = 0; /* Default: no room */
357 unsigned long flags; 382 unsigned long flags;
358 383
359 dbg ("%s", __func__); 384 dbg("%s", __func__);
360 385
361 spin_lock_irqsave(&port->lock, flags); 386 spin_lock_irqsave(&port->lock, flags);
362 if (port->write_urb_busy) 387 if (port->write_urb_busy)
363 room = port->bulk_out_size - (safe ? 2 : 0); 388 room = port->bulk_out_size - (safe ? 2 : 0);
364 spin_unlock_irqrestore(&port->lock, flags); 389 spin_unlock_irqrestore(&port->lock, flags);
365 390
366 if (room) { 391 if (room)
367 dbg ("safe_write_room returns %d", room); 392 dbg("safe_write_room returns %d", room);
368 }
369
370 return room; 393 return room;
371} 394}
372 395
373static int safe_startup (struct usb_serial *serial) 396static int safe_startup(struct usb_serial *serial)
374{ 397{
375 switch (serial->interface->cur_altsetting->desc.bInterfaceProtocol) { 398 switch (serial->interface->cur_altsetting->desc.bInterfaceProtocol) {
376 case LINEO_SAFESERIAL_CRC: 399 case LINEO_SAFESERIAL_CRC:
@@ -398,17 +421,18 @@ static struct usb_serial_driver safe_device = {
398 .attach = safe_startup, 421 .attach = safe_startup,
399}; 422};
400 423
401static int __init safe_init (void) 424static int __init safe_init(void)
402{ 425{
403 int i, retval; 426 int i, retval;
404 427
405 info (DRIVER_VERSION " " DRIVER_AUTHOR); 428 info(DRIVER_VERSION " " DRIVER_AUTHOR);
406 info (DRIVER_DESC); 429 info(DRIVER_DESC);
407 info ("vendor: %x product: %x safe: %d padded: %d\n", vendor, product, safe, padded); 430 info("vendor: %x product: %x safe: %d padded: %d\n",
431 vendor, product, safe, padded);
408 432
409 // if we have vendor / product parameters patch them into id list 433 /* if we have vendor / product parameters patch them into id list */
410 if (vendor || product) { 434 if (vendor || product) {
411 info ("vendor: %x product: %x\n", vendor, product); 435 info("vendor: %x product: %x\n", vendor, product);
412 436
413 for (i = 0; i < ARRAY_SIZE(id_table); i++) { 437 for (i = 0; i < ARRAY_SIZE(id_table); i++) {
414 if (!id_table[i].idVendor && !id_table[i].idProduct) { 438 if (!id_table[i].idVendor && !id_table[i].idProduct) {
@@ -433,11 +457,11 @@ failed_usb_serial_register:
433 return retval; 457 return retval;
434} 458}
435 459
436static void __exit safe_exit (void) 460static void __exit safe_exit(void)
437{ 461{
438 usb_deregister (&safe_driver); 462 usb_deregister(&safe_driver);
439 usb_serial_deregister (&safe_device); 463 usb_serial_deregister(&safe_device);
440} 464}
441 465
442module_init (safe_init); 466module_init(safe_init);
443module_exit (safe_exit); 467module_exit(safe_exit);