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