linux/drivers/usb/serial/safe_serial.c
<<
>>
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/init.h>
  68#include <linux/slab.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        int result;
 221        int status = urb->status;
 222
 223        dbg("%s", __func__);
 224
 225        if (status) {
 226                dbg("%s - nonzero read bulk status received: %d",
 227                    __func__, status);
 228                return;
 229        }
 230
 231        dbg("safe_read_bulk_callback length: %d",
 232                                        port->read_urb->actual_length);
 233#ifdef ECHO_RCV
 234        {
 235                int i;
 236                unsigned char *cp = port->read_urb->transfer_buffer;
 237                for (i = 0; i < port->read_urb->actual_length; i++) {
 238                        if ((i % 32) == 0)
 239                                printk("\nru[%02x] ", i);
 240                        printk("%02x ", *cp++);
 241                }
 242                printk("\n");
 243        }
 244#endif
 245        if (safe) {
 246                __u16 fcs;
 247                fcs = fcs_compute10(data, length, CRC10_INITFCS);
 248                if (!fcs) {
 249                        int actual_length = data[length - 2] >> 2;
 250                        if (actual_length <= (length - 2)) {
 251                                info("%s - actual: %d", __func__,
 252                                                        actual_length);
 253                                tty_insert_flip_string(port->port.tty,
 254                                                        data, actual_length);
 255                                tty_flip_buffer_push(port->port.tty);
 256                        } else {
 257                                err("%s - inconsistent lengths %d:%d",
 258                                        __func__, actual_length, length);
 259                        }
 260                } else {
 261                        err("%s - bad CRC %x", __func__, fcs);
 262                }
 263        } else {
 264                tty_insert_flip_string(port->port.tty, data, length);
 265                tty_flip_buffer_push(port->port.tty);
 266        }
 267
 268        /* Continue trying to always read  */
 269        usb_fill_bulk_urb(urb, port->serial->dev,
 270                        usb_rcvbulkpipe(port->serial->dev,
 271                                        port->bulk_in_endpointAddress),
 272                        urb->transfer_buffer, urb->transfer_buffer_length,
 273                        safe_read_bulk_callback, port);
 274
 275        result = usb_submit_urb(urb, GFP_ATOMIC);
 276        if (result)
 277                err("%s - failed resubmitting read urb, error %d",
 278                                                        __func__, result);
 279                /* FIXME: Need a mechanism to retry later if this happens */
 280}
 281
 282static int safe_write(struct tty_struct *tty, struct usb_serial_port *port,
 283                                        const unsigned char *buf, int count)
 284{
 285        unsigned char *data;
 286        int result;
 287        int i;
 288        int packet_length;
 289
 290        dbg("safe_write port: %p %d urb: %p count: %d",
 291                                port, port->number, port->write_urb, count);
 292
 293        if (!port->write_urb) {
 294                dbg("%s - write urb NULL", __func__);
 295                return 0;
 296        }
 297
 298        dbg("safe_write write_urb: %d transfer_buffer_length",
 299             port->write_urb->transfer_buffer_length);
 300
 301        if (!port->write_urb->transfer_buffer_length) {
 302                dbg("%s - write urb transfer_buffer_length zero", __func__);
 303                return 0;
 304        }
 305        if (count == 0) {
 306                dbg("%s - write request of 0 bytes", __func__);
 307                return 0;
 308        }
 309        spin_lock_bh(&port->lock);
 310        if (port->write_urb_busy) {
 311                spin_unlock_bh(&port->lock);
 312                dbg("%s - already writing", __func__);
 313                return 0;
 314        }
 315        port->write_urb_busy = 1;
 316        spin_unlock_bh(&port->lock);
 317
 318        packet_length = port->bulk_out_size;    /* get max packetsize */
 319
 320        i = packet_length - (safe ? 2 : 0);     /* get bytes to send */
 321        count = (count > i) ? i : count;
 322
 323
 324        /* get the data into the transfer buffer */
 325        data = port->write_urb->transfer_buffer;
 326        memset(data, '0', packet_length);
 327
 328        memcpy(data, buf, count);
 329
 330        if (safe) {
 331                __u16 fcs;
 332
 333                /* pad if necessary */
 334                if (!padded)
 335                        packet_length = count + 2;
 336                /* set count */
 337                data[packet_length - 2] = count << 2;
 338                data[packet_length - 1] = 0;
 339
 340                /* compute fcs and insert into trailer */
 341                fcs = fcs_compute10(data, packet_length, CRC10_INITFCS);
 342                data[packet_length - 2] |= fcs >> 8;
 343                data[packet_length - 1] |= fcs & 0xff;
 344
 345                /* set length to send */
 346                port->write_urb->transfer_buffer_length = packet_length;
 347        } else {
 348                port->write_urb->transfer_buffer_length = count;
 349        }
 350
 351        usb_serial_debug_data(debug, &port->dev, __func__, count,
 352                                        port->write_urb->transfer_buffer);
 353#ifdef ECHO_TX
 354        {
 355                int i;
 356                unsigned char *cp = port->write_urb->transfer_buffer;
 357                for (i = 0; i < port->write_urb->transfer_buffer_length; i++) {
 358                        if ((i % 32) == 0)
 359                                printk("\nsu[%02x] ", i);
 360                        printk("%02x ", *cp++);
 361                }
 362                printk("\n");
 363        }
 364#endif
 365        port->write_urb->dev = port->serial->dev;
 366        result = usb_submit_urb(port->write_urb, GFP_KERNEL);
 367        if (result) {
 368                port->write_urb_busy = 0;
 369                err("%s - failed submitting write urb, error %d",
 370                                                        __func__, result);
 371                return 0;
 372        }
 373        dbg("%s urb: %p submitted", __func__, port->write_urb);
 374
 375        return count;
 376}
 377
 378static int safe_write_room(struct tty_struct *tty)
 379{
 380        struct usb_serial_port *port = tty->driver_data;
 381        int room = 0;           /* Default: no room */
 382        unsigned long flags;
 383
 384        dbg("%s", __func__);
 385
 386        spin_lock_irqsave(&port->lock, flags);
 387        if (port->write_urb_busy)
 388                room = port->bulk_out_size - (safe ? 2 : 0);
 389        spin_unlock_irqrestore(&port->lock, flags);
 390
 391        if (room)
 392                dbg("safe_write_room returns %d", room);
 393        return room;
 394}
 395
 396static int safe_startup(struct usb_serial *serial)
 397{
 398        switch (serial->interface->cur_altsetting->desc.bInterfaceProtocol) {
 399        case LINEO_SAFESERIAL_CRC:
 400                break;
 401        case LINEO_SAFESERIAL_CRC_PADDED:
 402                padded = 1;
 403                break;
 404        default:
 405                return -EINVAL;
 406        }
 407        return 0;
 408}
 409
 410static struct usb_serial_driver safe_device = {
 411        .driver = {
 412                .owner =        THIS_MODULE,
 413                .name =         "safe_serial",
 414        },
 415        .id_table =             id_table,
 416        .usb_driver =           &safe_driver,
 417        .num_ports =            1,
 418        .write =                safe_write,
 419        .write_room =           safe_write_room,
 420        .read_bulk_callback =   safe_read_bulk_callback,
 421        .attach =               safe_startup,
 422};
 423
 424static int __init safe_init(void)
 425{
 426        int i, retval;
 427
 428        info(DRIVER_VERSION " " DRIVER_AUTHOR);
 429        info(DRIVER_DESC);
 430        info("vendor: %x product: %x safe: %d padded: %d\n",
 431                                        vendor, product, safe, padded);
 432
 433        /* if we have vendor / product parameters patch them into id list */
 434        if (vendor || product) {
 435                info("vendor: %x product: %x\n", vendor, product);
 436
 437                for (i = 0; i < ARRAY_SIZE(id_table); i++) {
 438                        if (!id_table[i].idVendor && !id_table[i].idProduct) {
 439                                id_table[i].idVendor = vendor;
 440                                id_table[i].idProduct = product;
 441                                break;
 442                        }
 443                }
 444        }
 445
 446        retval = usb_serial_register(&safe_device);
 447        if (retval)
 448                goto failed_usb_serial_register;
 449        retval = usb_register(&safe_driver);
 450        if (retval)
 451                goto failed_usb_register;
 452
 453        return 0;
 454failed_usb_register:
 455        usb_serial_deregister(&safe_device);
 456failed_usb_serial_register:
 457        return retval;
 458}
 459
 460static void __exit safe_exit(void)
 461{
 462        usb_deregister(&safe_driver);
 463        usb_serial_deregister(&safe_device);
 464}
 465
 466module_init(safe_init);
 467module_exit(safe_exit);
 468
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.