xref: /openbmc/linux/drivers/usb/serial/safe_serial.c (revision 1a59d1b8)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Safe Encapsulated USB Serial Driver
4  *
5  *      Copyright (C) 2010 Johan Hovold <jhovold@gmail.com>
6  *      Copyright (C) 2001 Lineo
7  *      Copyright (C) 2001 Hewlett-Packard
8  *
9  * By:
10  *      Stuart Lynne <sl@lineo.com>, Tom Rushworth <tbr@lineo.com>
11  */
12 
13 /*
14  * The encapsultaion is designed to overcome difficulties with some USB
15  * hardware.
16  *
17  * While the USB protocol has a CRC over the data while in transit, i.e. while
18  * being carried over the bus, there is no end to end protection. If the
19  * hardware has any problems getting the data into or out of the USB transmit
20  * and receive FIFO's then data can be lost.
21  *
22  * This protocol adds a two byte trailer to each USB packet to specify the
23  * number of bytes of valid data and a 10 bit CRC that will allow the receiver
24  * to verify that the entire USB packet was received without error.
25  *
26  * Because in this case the sender and receiver are the class and function
27  * drivers there is now end to end protection.
28  *
29  * There is an additional option that can be used to force all transmitted
30  * packets to be padded to the maximum packet size. This provides a work
31  * around for some devices which have problems with small USB packets.
32  *
33  * Assuming a packetsize of N:
34  *
35  *      0..N-2  data and optional padding
36  *
37  *      N-2     bits 7-2 - number of bytes of valid data
38  *              bits 1-0 top two bits of 10 bit CRC
39  *      N-1     bottom 8 bits of 10 bit CRC
40  *
41  *
42  *      | Data Length       | 10 bit CRC                                |
43  *      + 7 . 6 . 5 . 4 . 3 . 2 . 1 . 0 | 7 . 6 . 5 . 4 . 3 . 2 . 1 . 0 +
44  *
45  * The 10 bit CRC is computed across the sent data, followed by the trailer
46  * with the length set and the CRC set to zero. The CRC is then OR'd into
47  * the trailer.
48  *
49  * When received a 10 bit CRC is computed over the entire frame including
50  * the trailer and should be equal to zero.
51  *
52  * Two module parameters are used to control the encapsulation, if both are
53  * turned of the module works as a simple serial device with NO
54  * encapsulation.
55  *
56  * See linux/drivers/usbd/serial_fd for a device function driver
57  * implementation of this.
58  *
59  */
60 
61 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
62 
63 #include <linux/kernel.h>
64 #include <linux/errno.h>
65 #include <linux/gfp.h>
66 #include <linux/tty.h>
67 #include <linux/tty_driver.h>
68 #include <linux/tty_flip.h>
69 #include <linux/module.h>
70 #include <linux/spinlock.h>
71 #include <linux/uaccess.h>
72 #include <linux/usb.h>
73 #include <linux/usb/serial.h>
74 
75 static bool safe = true;
76 static bool padded = IS_ENABLED(CONFIG_USB_SERIAL_SAFE_PADDED);
77 
78 #define DRIVER_AUTHOR "sl@lineo.com, tbr@lineo.com, Johan Hovold <jhovold@gmail.com>"
79 #define DRIVER_DESC "USB Safe Encapsulated Serial"
80 
81 MODULE_AUTHOR(DRIVER_AUTHOR);
82 MODULE_DESCRIPTION(DRIVER_DESC);
83 MODULE_LICENSE("GPL");
84 
85 module_param(safe, bool, 0);
86 MODULE_PARM_DESC(safe, "Turn Safe Encapsulation On/Off");
87 
88 module_param(padded, bool, 0);
89 MODULE_PARM_DESC(padded, "Pad to full wMaxPacketSize On/Off");
90 
91 #define CDC_DEVICE_CLASS                        0x02
92 
93 #define CDC_INTERFACE_CLASS                     0x02
94 #define CDC_INTERFACE_SUBCLASS                  0x06
95 
96 #define LINEO_INTERFACE_CLASS                   0xff
97 
98 #define LINEO_INTERFACE_SUBCLASS_SAFENET        0x01
99 #define LINEO_SAFENET_CRC                       0x01
100 #define LINEO_SAFENET_CRC_PADDED                0x02
101 
102 #define LINEO_INTERFACE_SUBCLASS_SAFESERIAL     0x02
103 #define LINEO_SAFESERIAL_CRC                    0x01
104 #define LINEO_SAFESERIAL_CRC_PADDED             0x02
105 
106 
107 #define MY_USB_DEVICE(vend, prod, dc, ic, isc) \
108 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
109 		       USB_DEVICE_ID_MATCH_DEV_CLASS | \
110 		       USB_DEVICE_ID_MATCH_INT_CLASS | \
111 		       USB_DEVICE_ID_MATCH_INT_SUBCLASS, \
112 	.idVendor = (vend), \
113 	.idProduct = (prod),\
114 	.bDeviceClass = (dc),\
115 	.bInterfaceClass = (ic), \
116 	.bInterfaceSubClass = (isc),
117 
118 static const struct usb_device_id id_table[] = {
119 	{MY_USB_DEVICE(0x49f, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	/* Itsy */
120 	{MY_USB_DEVICE(0x3f0, 0x2101, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	/* Calypso */
121 	{MY_USB_DEVICE(0x4dd, 0x8001, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	/* Iris */
122 	{MY_USB_DEVICE(0x4dd, 0x8002, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	/* Collie */
123 	{MY_USB_DEVICE(0x4dd, 0x8003, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	/* Collie */
124 	{MY_USB_DEVICE(0x4dd, 0x8004, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	/* Collie */
125 	{MY_USB_DEVICE(0x5f9, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	/* Sharp tmp */
126 	{}			/* terminating entry  */
127 };
128 
129 MODULE_DEVICE_TABLE(usb, id_table);
130 
131 static const __u16 crc10_table[256] = {
132 	0x000, 0x233, 0x255, 0x066, 0x299, 0x0aa, 0x0cc, 0x2ff,
133 	0x301, 0x132, 0x154, 0x367, 0x198, 0x3ab, 0x3cd, 0x1fe,
134 	0x031, 0x202, 0x264, 0x057, 0x2a8, 0x09b, 0x0fd, 0x2ce,
135 	0x330, 0x103, 0x165, 0x356, 0x1a9, 0x39a, 0x3fc, 0x1cf,
136 	0x062, 0x251, 0x237, 0x004, 0x2fb, 0x0c8, 0x0ae, 0x29d,
137 	0x363, 0x150, 0x136, 0x305, 0x1fa, 0x3c9, 0x3af, 0x19c,
138 	0x053, 0x260, 0x206, 0x035, 0x2ca, 0x0f9, 0x09f, 0x2ac,
139 	0x352, 0x161, 0x107, 0x334, 0x1cb, 0x3f8, 0x39e, 0x1ad,
140 	0x0c4, 0x2f7, 0x291, 0x0a2, 0x25d, 0x06e, 0x008, 0x23b,
141 	0x3c5, 0x1f6, 0x190, 0x3a3, 0x15c, 0x36f, 0x309, 0x13a,
142 	0x0f5, 0x2c6, 0x2a0, 0x093, 0x26c, 0x05f, 0x039, 0x20a,
143 	0x3f4, 0x1c7, 0x1a1, 0x392, 0x16d, 0x35e, 0x338, 0x10b,
144 	0x0a6, 0x295, 0x2f3, 0x0c0, 0x23f, 0x00c, 0x06a, 0x259,
145 	0x3a7, 0x194, 0x1f2, 0x3c1, 0x13e, 0x30d, 0x36b, 0x158,
146 	0x097, 0x2a4, 0x2c2, 0x0f1, 0x20e, 0x03d, 0x05b, 0x268,
147 	0x396, 0x1a5, 0x1c3, 0x3f0, 0x10f, 0x33c, 0x35a, 0x169,
148 	0x188, 0x3bb, 0x3dd, 0x1ee, 0x311, 0x122, 0x144, 0x377,
149 	0x289, 0x0ba, 0x0dc, 0x2ef, 0x010, 0x223, 0x245, 0x076,
150 	0x1b9, 0x38a, 0x3ec, 0x1df, 0x320, 0x113, 0x175, 0x346,
151 	0x2b8, 0x08b, 0x0ed, 0x2de, 0x021, 0x212, 0x274, 0x047,
152 	0x1ea, 0x3d9, 0x3bf, 0x18c, 0x373, 0x140, 0x126, 0x315,
153 	0x2eb, 0x0d8, 0x0be, 0x28d, 0x072, 0x241, 0x227, 0x014,
154 	0x1db, 0x3e8, 0x38e, 0x1bd, 0x342, 0x171, 0x117, 0x324,
155 	0x2da, 0x0e9, 0x08f, 0x2bc, 0x043, 0x270, 0x216, 0x025,
156 	0x14c, 0x37f, 0x319, 0x12a, 0x3d5, 0x1e6, 0x180, 0x3b3,
157 	0x24d, 0x07e, 0x018, 0x22b, 0x0d4, 0x2e7, 0x281, 0x0b2,
158 	0x17d, 0x34e, 0x328, 0x11b, 0x3e4, 0x1d7, 0x1b1, 0x382,
159 	0x27c, 0x04f, 0x029, 0x21a, 0x0e5, 0x2d6, 0x2b0, 0x083,
160 	0x12e, 0x31d, 0x37b, 0x148, 0x3b7, 0x184, 0x1e2, 0x3d1,
161 	0x22f, 0x01c, 0x07a, 0x249, 0x0b6, 0x285, 0x2e3, 0x0d0,
162 	0x11f, 0x32c, 0x34a, 0x179, 0x386, 0x1b5, 0x1d3, 0x3e0,
163 	0x21e, 0x02d, 0x04b, 0x278, 0x087, 0x2b4, 0x2d2, 0x0e1,
164 };
165 
166 #define CRC10_INITFCS     0x000	/* Initial FCS value */
167 #define CRC10_GOODFCS     0x000	/* Good final FCS value */
168 #define CRC10_FCS(fcs, c) ((((fcs) << 8) & 0x3ff) ^ crc10_table[((fcs) >> 2) & 0xff] ^ (c))
169 
170 /**
171  * fcs_compute10 - memcpy and calculate 10 bit CRC across buffer
172  * @sp: pointer to buffer
173  * @len: number of bytes
174  * @fcs: starting FCS
175  *
176  * Perform a memcpy and calculate fcs using ppp 10bit CRC algorithm. Return
177  * new 10 bit FCS.
178  */
179 static inline __u16 fcs_compute10(unsigned char *sp, int len, __u16 fcs)
180 {
181 	for (; len-- > 0; fcs = CRC10_FCS(fcs, *sp++));
182 	return fcs;
183 }
184 
185 static void safe_process_read_urb(struct urb *urb)
186 {
187 	struct usb_serial_port *port = urb->context;
188 	unsigned char *data = urb->transfer_buffer;
189 	unsigned char length = urb->actual_length;
190 	int actual_length;
191 	__u16 fcs;
192 
193 	if (!length)
194 		return;
195 
196 	if (!safe)
197 		goto out;
198 
199 	if (length < 2) {
200 		dev_err(&port->dev, "malformed packet\n");
201 		return;
202 	}
203 
204 	fcs = fcs_compute10(data, length, CRC10_INITFCS);
205 	if (fcs) {
206 		dev_err(&port->dev, "%s - bad CRC %x\n", __func__, fcs);
207 		return;
208 	}
209 
210 	actual_length = data[length - 2] >> 2;
211 	if (actual_length > (length - 2)) {
212 		dev_err(&port->dev, "%s - inconsistent lengths %d:%d\n",
213 				__func__, actual_length, length);
214 		return;
215 	}
216 	dev_info(&urb->dev->dev, "%s - actual: %d\n", __func__, actual_length);
217 	length = actual_length;
218 out:
219 	tty_insert_flip_string(&port->port, data, length);
220 	tty_flip_buffer_push(&port->port);
221 }
222 
223 static int safe_prepare_write_buffer(struct usb_serial_port *port,
224 						void *dest, size_t size)
225 {
226 	unsigned char *buf = dest;
227 	int count;
228 	int trailer_len;
229 	int pkt_len;
230 	__u16 fcs;
231 
232 	trailer_len = safe ? 2 : 0;
233 
234 	count = kfifo_out_locked(&port->write_fifo, buf, size - trailer_len,
235 								&port->lock);
236 	if (!safe)
237 		return count;
238 
239 	/* pad if necessary */
240 	if (padded) {
241 		pkt_len = size;
242 		memset(buf + count, '0', pkt_len - count - trailer_len);
243 	} else {
244 		pkt_len = count + trailer_len;
245 	}
246 
247 	/* set count */
248 	buf[pkt_len - 2] = count << 2;
249 	buf[pkt_len - 1] = 0;
250 
251 	/* compute fcs and insert into trailer */
252 	fcs = fcs_compute10(buf, pkt_len, CRC10_INITFCS);
253 	buf[pkt_len - 2] |= fcs >> 8;
254 	buf[pkt_len - 1] |= fcs & 0xff;
255 
256 	return pkt_len;
257 }
258 
259 static int safe_startup(struct usb_serial *serial)
260 {
261 	struct usb_interface_descriptor	*desc;
262 
263 	if (serial->dev->descriptor.bDeviceClass != CDC_DEVICE_CLASS)
264 		return -ENODEV;
265 
266 	desc = &serial->interface->cur_altsetting->desc;
267 
268 	if (desc->bInterfaceClass != LINEO_INTERFACE_CLASS)
269 		return -ENODEV;
270 	if (desc->bInterfaceSubClass != LINEO_INTERFACE_SUBCLASS_SAFESERIAL)
271 		return -ENODEV;
272 
273 	switch (desc->bInterfaceProtocol) {
274 	case LINEO_SAFESERIAL_CRC:
275 		break;
276 	case LINEO_SAFESERIAL_CRC_PADDED:
277 		padded = true;
278 		break;
279 	default:
280 		return -EINVAL;
281 	}
282 	return 0;
283 }
284 
285 static struct usb_serial_driver safe_device = {
286 	.driver = {
287 		.owner =	THIS_MODULE,
288 		.name =		"safe_serial",
289 	},
290 	.id_table =		id_table,
291 	.num_ports =		1,
292 	.process_read_urb =	safe_process_read_urb,
293 	.prepare_write_buffer =	safe_prepare_write_buffer,
294 	.attach =		safe_startup,
295 };
296 
297 static struct usb_serial_driver * const serial_drivers[] = {
298 	&safe_device, NULL
299 };
300 
301 module_usb_serial_driver(serial_drivers, id_table);
302