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