linux/drivers/usb/serial/symbolserial.c
<<
>>
Prefs
   1/*
   2 * Symbol USB barcode to serial driver
   3 *
   4 * Copyright (C) 2009 Greg Kroah-Hartman <gregkh@suse.de>
   5 * Copyright (C) 2009 Novell Inc.
   6 *
   7 *      This program is free software; you can redistribute it and/or
   8 *      modify it under the terms of the GNU General Public License version
   9 *      2 as published by the Free Software Foundation.
  10 */
  11
  12#include <linux/kernel.h>
  13#include <linux/init.h>
  14#include <linux/tty.h>
  15#include <linux/slab.h>
  16#include <linux/tty_driver.h>
  17#include <linux/tty_flip.h>
  18#include <linux/module.h>
  19#include <linux/usb.h>
  20#include <linux/usb/serial.h>
  21#include <linux/uaccess.h>
  22
  23static const struct usb_device_id id_table[] = {
  24        { USB_DEVICE(0x05e0, 0x0600) },
  25        { },
  26};
  27MODULE_DEVICE_TABLE(usb, id_table);
  28
  29/* This structure holds all of the individual device information */
  30struct symbol_private {
  31        struct usb_device *udev;
  32        struct usb_serial *serial;
  33        struct usb_serial_port *port;
  34        unsigned char *int_buffer;
  35        struct urb *int_urb;
  36        int buffer_size;
  37        u8 bInterval;
  38        u8 int_address;
  39        spinlock_t lock;        /* protects the following flags */
  40        bool throttled;
  41        bool actually_throttled;
  42        bool rts;
  43};
  44
  45static void symbol_int_callback(struct urb *urb)
  46{
  47        struct symbol_private *priv = urb->context;
  48        unsigned char *data = urb->transfer_buffer;
  49        struct usb_serial_port *port = priv->port;
  50        int status = urb->status;
  51        struct tty_struct *tty;
  52        int result;
  53        int data_length;
  54
  55        switch (status) {
  56        case 0:
  57                /* success */
  58                break;
  59        case -ECONNRESET:
  60        case -ENOENT:
  61        case -ESHUTDOWN:
  62                /* this urb is terminated, clean up */
  63                dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
  64                        __func__, status);
  65                return;
  66        default:
  67                dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
  68                        __func__, status);
  69                goto exit;
  70        }
  71
  72        usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
  73
  74        if (urb->actual_length > 1) {
  75                data_length = urb->actual_length - 1;
  76
  77                /*
  78                 * Data from the device comes with a 1 byte header:
  79                 *
  80                 * <size of data>data...
  81                 *      This is real data to be sent to the tty layer
  82                 * we pretty much just ignore the size and send everything
  83                 * else to the tty layer.
  84                 */
  85                tty = tty_port_tty_get(&port->port);
  86                if (tty) {
  87                        tty_insert_flip_string(tty, &data[1], data_length);
  88                        tty_flip_buffer_push(tty);
  89                        tty_kref_put(tty);
  90                }
  91        } else {
  92                dev_dbg(&priv->udev->dev,
  93                        "Improper amount of data received from the device, "
  94                        "%d bytes", urb->actual_length);
  95        }
  96
  97exit:
  98        spin_lock(&priv->lock);
  99
 100        /* Continue trying to always read if we should */
 101        if (!priv->throttled) {
 102                usb_fill_int_urb(priv->int_urb, priv->udev,
 103                                 usb_rcvintpipe(priv->udev,
 104                                                priv->int_address),
 105                                 priv->int_buffer, priv->buffer_size,
 106                                 symbol_int_callback, priv, priv->bInterval);
 107                result = usb_submit_urb(priv->int_urb, GFP_ATOMIC);
 108                if (result)
 109                        dev_err(&port->dev,
 110                            "%s - failed resubmitting read urb, error %d\n",
 111                                                        __func__, result);
 112        } else
 113                priv->actually_throttled = true;
 114        spin_unlock(&priv->lock);
 115}
 116
 117static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port)
 118{
 119        struct symbol_private *priv = usb_get_serial_data(port->serial);
 120        unsigned long flags;
 121        int result = 0;
 122
 123        spin_lock_irqsave(&priv->lock, flags);
 124        priv->throttled = false;
 125        priv->actually_throttled = false;
 126        priv->port = port;
 127        spin_unlock_irqrestore(&priv->lock, flags);
 128
 129        /* Start reading from the device */
 130        usb_fill_int_urb(priv->int_urb, priv->udev,
 131                         usb_rcvintpipe(priv->udev, priv->int_address),
 132                         priv->int_buffer, priv->buffer_size,
 133                         symbol_int_callback, priv, priv->bInterval);
 134        result = usb_submit_urb(priv->int_urb, GFP_KERNEL);
 135        if (result)
 136                dev_err(&port->dev,
 137                        "%s - failed resubmitting read urb, error %d\n",
 138                        __func__, result);
 139        return result;
 140}
 141
 142static void symbol_close(struct usb_serial_port *port)
 143{
 144        struct symbol_private *priv = usb_get_serial_data(port->serial);
 145
 146        /* shutdown our urbs */
 147        usb_kill_urb(priv->int_urb);
 148}
 149
 150static void symbol_throttle(struct tty_struct *tty)
 151{
 152        struct usb_serial_port *port = tty->driver_data;
 153        struct symbol_private *priv = usb_get_serial_data(port->serial);
 154
 155        spin_lock_irq(&priv->lock);
 156        priv->throttled = true;
 157        spin_unlock_irq(&priv->lock);
 158}
 159
 160static void symbol_unthrottle(struct tty_struct *tty)
 161{
 162        struct usb_serial_port *port = tty->driver_data;
 163        struct symbol_private *priv = usb_get_serial_data(port->serial);
 164        int result;
 165        bool was_throttled;
 166
 167        spin_lock_irq(&priv->lock);
 168        priv->throttled = false;
 169        was_throttled = priv->actually_throttled;
 170        priv->actually_throttled = false;
 171        spin_unlock_irq(&priv->lock);
 172
 173        if (was_throttled) {
 174                result = usb_submit_urb(priv->int_urb, GFP_KERNEL);
 175                if (result)
 176                        dev_err(&port->dev,
 177                                "%s - failed submitting read urb, error %d\n",
 178                                                        __func__, result);
 179        }
 180}
 181
 182static int symbol_startup(struct usb_serial *serial)
 183{
 184        struct symbol_private *priv;
 185        struct usb_host_interface *intf;
 186        int i;
 187        int retval = -ENOMEM;
 188        bool int_in_found = false;
 189
 190        /* create our private serial structure */
 191        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 192        if (priv == NULL) {
 193                dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
 194                return -ENOMEM;
 195        }
 196        spin_lock_init(&priv->lock);
 197        priv->serial = serial;
 198        priv->port = serial->port[0];
 199        priv->udev = serial->dev;
 200
 201        /* find our interrupt endpoint */
 202        intf = serial->interface->altsetting;
 203        for (i = 0; i < intf->desc.bNumEndpoints; ++i) {
 204                struct usb_endpoint_descriptor *endpoint;
 205
 206                endpoint = &intf->endpoint[i].desc;
 207                if (!usb_endpoint_is_int_in(endpoint))
 208                        continue;
 209
 210                priv->int_urb = usb_alloc_urb(0, GFP_KERNEL);
 211                if (!priv->int_urb) {
 212                        dev_err(&priv->udev->dev, "out of memory\n");
 213                        goto error;
 214                }
 215
 216                priv->buffer_size = usb_endpoint_maxp(endpoint) * 2;
 217                priv->int_buffer = kmalloc(priv->buffer_size, GFP_KERNEL);
 218                if (!priv->int_buffer) {
 219                        dev_err(&priv->udev->dev, "out of memory\n");
 220                        goto error;
 221                }
 222
 223                priv->int_address = endpoint->bEndpointAddress;
 224                priv->bInterval = endpoint->bInterval;
 225
 226                /* set up our int urb */
 227                usb_fill_int_urb(priv->int_urb, priv->udev,
 228                                 usb_rcvintpipe(priv->udev,
 229                                                endpoint->bEndpointAddress),
 230                                 priv->int_buffer, priv->buffer_size,
 231                                 symbol_int_callback, priv, priv->bInterval);
 232
 233                int_in_found = true;
 234                break;
 235                }
 236
 237        if (!int_in_found) {
 238                dev_err(&priv->udev->dev,
 239                        "Error - the proper endpoints were not found!\n");
 240                goto error;
 241        }
 242
 243        usb_set_serial_data(serial, priv);
 244        return 0;
 245
 246error:
 247        usb_free_urb(priv->int_urb);
 248        kfree(priv->int_buffer);
 249        kfree(priv);
 250        return retval;
 251}
 252
 253static void symbol_disconnect(struct usb_serial *serial)
 254{
 255        struct symbol_private *priv = usb_get_serial_data(serial);
 256
 257        usb_kill_urb(priv->int_urb);
 258        usb_free_urb(priv->int_urb);
 259}
 260
 261static void symbol_release(struct usb_serial *serial)
 262{
 263        struct symbol_private *priv = usb_get_serial_data(serial);
 264
 265        kfree(priv->int_buffer);
 266        kfree(priv);
 267}
 268
 269static struct usb_serial_driver symbol_device = {
 270        .driver = {
 271                .owner =        THIS_MODULE,
 272                .name =         "symbol",
 273        },
 274        .id_table =             id_table,
 275        .num_ports =            1,
 276        .attach =               symbol_startup,
 277        .open =                 symbol_open,
 278        .close =                symbol_close,
 279        .disconnect =           symbol_disconnect,
 280        .release =              symbol_release,
 281        .throttle =             symbol_throttle,
 282        .unthrottle =           symbol_unthrottle,
 283};
 284
 285static struct usb_serial_driver * const serial_drivers[] = {
 286        &symbol_device, NULL
 287};
 288
 289module_usb_serial_driver(serial_drivers, id_table);
 290
 291MODULE_LICENSE("GPL");
 292