0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
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)},
0120 {MY_USB_DEVICE(0x3f0, 0x2101, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},
0121 {MY_USB_DEVICE(0x4dd, 0x8001, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},
0122 {MY_USB_DEVICE(0x4dd, 0x8002, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},
0123 {MY_USB_DEVICE(0x4dd, 0x8003, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},
0124 {MY_USB_DEVICE(0x4dd, 0x8004, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},
0125 {MY_USB_DEVICE(0x5f9, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},
0126 {}
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
0167 #define CRC10_GOODFCS 0x000
0168 #define CRC10_FCS(fcs, c) ((((fcs) << 8) & 0x3ff) ^ crc10_table[((fcs) >> 2) & 0xff] ^ (c))
0169
0170
0171
0172
0173
0174
0175
0176
0177
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
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
0248 buf[pkt_len - 2] = count << 2;
0249 buf[pkt_len - 1] = 0;
0250
0251
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);