Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Safe Encapsulated USB Serial Driver
0004  *
0005  *      Copyright (C) 2010 Johan Hovold <jhovold@gmail.com>
0006  *      Copyright (C) 2001 Lineo
0007  *      Copyright (C) 2001 Hewlett-Packard
0008  *
0009  * By:
0010  *      Stuart Lynne <sl@lineo.com>, Tom Rushworth <tbr@lineo.com>
0011  */
0012 
0013 /*
0014  * The encapsultaion is designed to overcome difficulties with some USB
0015  * hardware.
0016  *
0017  * While the USB protocol has a CRC over the data while in transit, i.e. while
0018  * being carried over the bus, there is no end to end protection. If the
0019  * hardware has any problems getting the data into or out of the USB transmit
0020  * and receive FIFO's then data can be lost.
0021  *
0022  * This protocol adds a two byte trailer to each USB packet to specify the
0023  * number of bytes of valid data and a 10 bit CRC that will allow the receiver
0024  * to verify that the entire USB packet was received without error.
0025  *
0026  * Because in this case the sender and receiver are the class and function
0027  * drivers there is now end to end protection.
0028  *
0029  * There is an additional option that can be used to force all transmitted
0030  * packets to be padded to the maximum packet size. This provides a work
0031  * around for some devices which have problems with small USB packets.
0032  *
0033  * Assuming a packetsize of N:
0034  *
0035  *      0..N-2  data and optional padding
0036  *
0037  *      N-2     bits 7-2 - number of bytes of valid data
0038  *              bits 1-0 top two bits of 10 bit CRC
0039  *      N-1     bottom 8 bits of 10 bit CRC
0040  *
0041  *
0042  *      | Data Length       | 10 bit CRC                                |
0043  *      + 7 . 6 . 5 . 4 . 3 . 2 . 1 . 0 | 7 . 6 . 5 . 4 . 3 . 2 . 1 . 0 +
0044  *
0045  * The 10 bit CRC is computed across the sent data, followed by the trailer
0046  * with the length set and the CRC set to zero. The CRC is then OR'd into
0047  * the trailer.
0048  *
0049  * When received a 10 bit CRC is computed over the entire frame including
0050  * the trailer and should be equal to zero.
0051  *
0052  * Two module parameters are used to control the encapsulation, if both are
0053  * turned of the module works as a simple serial device with NO
0054  * encapsulation.
0055  *
0056  * See linux/drivers/usbd/serial_fd for a device function driver
0057  * implementation of this.
0058  *
0059  */
0060 
0061 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0062 
0063 #include <linux/kernel.h>
0064 #include <linux/errno.h>
0065 #include <linux/gfp.h>
0066 #include <linux/tty.h>
0067 #include <linux/tty_driver.h>
0068 #include <linux/tty_flip.h>
0069 #include <linux/module.h>
0070 #include <linux/spinlock.h>
0071 #include <linux/uaccess.h>
0072 #include <linux/usb.h>
0073 #include <linux/usb/serial.h>
0074 
0075 static bool safe = true;
0076 static bool padded = IS_ENABLED(CONFIG_USB_SERIAL_SAFE_PADDED);
0077 
0078 #define DRIVER_AUTHOR "sl@lineo.com, tbr@lineo.com, Johan Hovold <jhovold@gmail.com>"
0079 #define DRIVER_DESC "USB Safe Encapsulated Serial"
0080 
0081 MODULE_AUTHOR(DRIVER_AUTHOR);
0082 MODULE_DESCRIPTION(DRIVER_DESC);
0083 MODULE_LICENSE("GPL");
0084 
0085 module_param(safe, bool, 0);
0086 MODULE_PARM_DESC(safe, "Turn Safe Encapsulation On/Off");
0087 
0088 module_param(padded, bool, 0);
0089 MODULE_PARM_DESC(padded, "Pad to full wMaxPacketSize On/Off");
0090 
0091 #define CDC_DEVICE_CLASS                        0x02
0092 
0093 #define CDC_INTERFACE_CLASS                     0x02
0094 #define CDC_INTERFACE_SUBCLASS                  0x06
0095 
0096 #define LINEO_INTERFACE_CLASS                   0xff
0097 
0098 #define LINEO_INTERFACE_SUBCLASS_SAFENET        0x01
0099 #define LINEO_SAFENET_CRC                       0x01
0100 #define LINEO_SAFENET_CRC_PADDED                0x02
0101 
0102 #define LINEO_INTERFACE_SUBCLASS_SAFESERIAL     0x02
0103 #define LINEO_SAFESERIAL_CRC                    0x01
0104 #define LINEO_SAFESERIAL_CRC_PADDED             0x02
0105 
0106 
0107 #define MY_USB_DEVICE(vend, prod, dc, ic, isc) \
0108     .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
0109                USB_DEVICE_ID_MATCH_DEV_CLASS | \
0110                USB_DEVICE_ID_MATCH_INT_CLASS | \
0111                USB_DEVICE_ID_MATCH_INT_SUBCLASS, \
0112     .idVendor = (vend), \
0113     .idProduct = (prod),\
0114     .bDeviceClass = (dc),\
0115     .bInterfaceClass = (ic), \
0116     .bInterfaceSubClass = (isc),
0117 
0118 static const struct usb_device_id id_table[] = {
0119     {MY_USB_DEVICE(0x49f, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},   /* Itsy */
0120     {MY_USB_DEVICE(0x3f0, 0x2101, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},   /* Calypso */
0121     {MY_USB_DEVICE(0x4dd, 0x8001, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},   /* Iris */
0122     {MY_USB_DEVICE(0x4dd, 0x8002, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},   /* Collie */
0123     {MY_USB_DEVICE(0x4dd, 0x8003, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},   /* Collie */
0124     {MY_USB_DEVICE(0x4dd, 0x8004, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},   /* Collie */
0125     {MY_USB_DEVICE(0x5f9, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},   /* Sharp tmp */
0126     {}          /* terminating entry  */
0127 };
0128 
0129 MODULE_DEVICE_TABLE(usb, id_table);
0130 
0131 static const __u16 crc10_table[256] = {
0132     0x000, 0x233, 0x255, 0x066, 0x299, 0x0aa, 0x0cc, 0x2ff,
0133     0x301, 0x132, 0x154, 0x367, 0x198, 0x3ab, 0x3cd, 0x1fe,
0134     0x031, 0x202, 0x264, 0x057, 0x2a8, 0x09b, 0x0fd, 0x2ce,
0135     0x330, 0x103, 0x165, 0x356, 0x1a9, 0x39a, 0x3fc, 0x1cf,
0136     0x062, 0x251, 0x237, 0x004, 0x2fb, 0x0c8, 0x0ae, 0x29d,
0137     0x363, 0x150, 0x136, 0x305, 0x1fa, 0x3c9, 0x3af, 0x19c,
0138     0x053, 0x260, 0x206, 0x035, 0x2ca, 0x0f9, 0x09f, 0x2ac,
0139     0x352, 0x161, 0x107, 0x334, 0x1cb, 0x3f8, 0x39e, 0x1ad,
0140     0x0c4, 0x2f7, 0x291, 0x0a2, 0x25d, 0x06e, 0x008, 0x23b,
0141     0x3c5, 0x1f6, 0x190, 0x3a3, 0x15c, 0x36f, 0x309, 0x13a,
0142     0x0f5, 0x2c6, 0x2a0, 0x093, 0x26c, 0x05f, 0x039, 0x20a,
0143     0x3f4, 0x1c7, 0x1a1, 0x392, 0x16d, 0x35e, 0x338, 0x10b,
0144     0x0a6, 0x295, 0x2f3, 0x0c0, 0x23f, 0x00c, 0x06a, 0x259,
0145     0x3a7, 0x194, 0x1f2, 0x3c1, 0x13e, 0x30d, 0x36b, 0x158,
0146     0x097, 0x2a4, 0x2c2, 0x0f1, 0x20e, 0x03d, 0x05b, 0x268,
0147     0x396, 0x1a5, 0x1c3, 0x3f0, 0x10f, 0x33c, 0x35a, 0x169,
0148     0x188, 0x3bb, 0x3dd, 0x1ee, 0x311, 0x122, 0x144, 0x377,
0149     0x289, 0x0ba, 0x0dc, 0x2ef, 0x010, 0x223, 0x245, 0x076,
0150     0x1b9, 0x38a, 0x3ec, 0x1df, 0x320, 0x113, 0x175, 0x346,
0151     0x2b8, 0x08b, 0x0ed, 0x2de, 0x021, 0x212, 0x274, 0x047,
0152     0x1ea, 0x3d9, 0x3bf, 0x18c, 0x373, 0x140, 0x126, 0x315,
0153     0x2eb, 0x0d8, 0x0be, 0x28d, 0x072, 0x241, 0x227, 0x014,
0154     0x1db, 0x3e8, 0x38e, 0x1bd, 0x342, 0x171, 0x117, 0x324,
0155     0x2da, 0x0e9, 0x08f, 0x2bc, 0x043, 0x270, 0x216, 0x025,
0156     0x14c, 0x37f, 0x319, 0x12a, 0x3d5, 0x1e6, 0x180, 0x3b3,
0157     0x24d, 0x07e, 0x018, 0x22b, 0x0d4, 0x2e7, 0x281, 0x0b2,
0158     0x17d, 0x34e, 0x328, 0x11b, 0x3e4, 0x1d7, 0x1b1, 0x382,
0159     0x27c, 0x04f, 0x029, 0x21a, 0x0e5, 0x2d6, 0x2b0, 0x083,
0160     0x12e, 0x31d, 0x37b, 0x148, 0x3b7, 0x184, 0x1e2, 0x3d1,
0161     0x22f, 0x01c, 0x07a, 0x249, 0x0b6, 0x285, 0x2e3, 0x0d0,
0162     0x11f, 0x32c, 0x34a, 0x179, 0x386, 0x1b5, 0x1d3, 0x3e0,
0163     0x21e, 0x02d, 0x04b, 0x278, 0x087, 0x2b4, 0x2d2, 0x0e1,
0164 };
0165 
0166 #define CRC10_INITFCS     0x000 /* Initial FCS value */
0167 #define CRC10_GOODFCS     0x000 /* Good final FCS value */
0168 #define CRC10_FCS(fcs, c) ((((fcs) << 8) & 0x3ff) ^ crc10_table[((fcs) >> 2) & 0xff] ^ (c))
0169 
0170 /**
0171  * fcs_compute10 - memcpy and calculate 10 bit CRC across buffer
0172  * @sp: pointer to buffer
0173  * @len: number of bytes
0174  * @fcs: starting FCS
0175  *
0176  * Perform a memcpy and calculate fcs using ppp 10bit CRC algorithm. Return
0177  * new 10 bit FCS.
0178  */
0179 static inline __u16 fcs_compute10(unsigned char *sp, int len, __u16 fcs)
0180 {
0181     for (; len-- > 0; fcs = CRC10_FCS(fcs, *sp++));
0182     return fcs;
0183 }
0184 
0185 static void safe_process_read_urb(struct urb *urb)
0186 {
0187     struct usb_serial_port *port = urb->context;
0188     unsigned char *data = urb->transfer_buffer;
0189     unsigned char length = urb->actual_length;
0190     int actual_length;
0191     __u16 fcs;
0192 
0193     if (!length)
0194         return;
0195 
0196     if (!safe)
0197         goto out;
0198 
0199     if (length < 2) {
0200         dev_err(&port->dev, "malformed packet\n");
0201         return;
0202     }
0203 
0204     fcs = fcs_compute10(data, length, CRC10_INITFCS);
0205     if (fcs) {
0206         dev_err(&port->dev, "%s - bad CRC %x\n", __func__, fcs);
0207         return;
0208     }
0209 
0210     actual_length = data[length - 2] >> 2;
0211     if (actual_length > (length - 2)) {
0212         dev_err(&port->dev, "%s - inconsistent lengths %d:%d\n",
0213                 __func__, actual_length, length);
0214         return;
0215     }
0216     dev_info(&urb->dev->dev, "%s - actual: %d\n", __func__, actual_length);
0217     length = actual_length;
0218 out:
0219     tty_insert_flip_string(&port->port, data, length);
0220     tty_flip_buffer_push(&port->port);
0221 }
0222 
0223 static int safe_prepare_write_buffer(struct usb_serial_port *port,
0224                         void *dest, size_t size)
0225 {
0226     unsigned char *buf = dest;
0227     int count;
0228     int trailer_len;
0229     int pkt_len;
0230     __u16 fcs;
0231 
0232     trailer_len = safe ? 2 : 0;
0233 
0234     count = kfifo_out_locked(&port->write_fifo, buf, size - trailer_len,
0235                                 &port->lock);
0236     if (!safe)
0237         return count;
0238 
0239     /* pad if necessary */
0240     if (padded) {
0241         pkt_len = size;
0242         memset(buf + count, '0', pkt_len - count - trailer_len);
0243     } else {
0244         pkt_len = count + trailer_len;
0245     }
0246 
0247     /* set count */
0248     buf[pkt_len - 2] = count << 2;
0249     buf[pkt_len - 1] = 0;
0250 
0251     /* compute fcs and insert into trailer */
0252     fcs = fcs_compute10(buf, pkt_len, CRC10_INITFCS);
0253     buf[pkt_len - 2] |= fcs >> 8;
0254     buf[pkt_len - 1] |= fcs & 0xff;
0255 
0256     return pkt_len;
0257 }
0258 
0259 static int safe_startup(struct usb_serial *serial)
0260 {
0261     struct usb_interface_descriptor *desc;
0262 
0263     if (serial->dev->descriptor.bDeviceClass != CDC_DEVICE_CLASS)
0264         return -ENODEV;
0265 
0266     desc = &serial->interface->cur_altsetting->desc;
0267 
0268     if (desc->bInterfaceClass != LINEO_INTERFACE_CLASS)
0269         return -ENODEV;
0270     if (desc->bInterfaceSubClass != LINEO_INTERFACE_SUBCLASS_SAFESERIAL)
0271         return -ENODEV;
0272 
0273     switch (desc->bInterfaceProtocol) {
0274     case LINEO_SAFESERIAL_CRC:
0275         break;
0276     case LINEO_SAFESERIAL_CRC_PADDED:
0277         padded = true;
0278         break;
0279     default:
0280         return -EINVAL;
0281     }
0282     return 0;
0283 }
0284 
0285 static struct usb_serial_driver safe_device = {
0286     .driver = {
0287         .owner =    THIS_MODULE,
0288         .name =     "safe_serial",
0289     },
0290     .id_table =     id_table,
0291     .num_ports =        1,
0292     .process_read_urb = safe_process_read_urb,
0293     .prepare_write_buffer = safe_prepare_write_buffer,
0294     .attach =       safe_startup,
0295 };
0296 
0297 static struct usb_serial_driver * const serial_drivers[] = {
0298     &safe_device, NULL
0299 };
0300 
0301 module_usb_serial_driver(serial_drivers, id_table);