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