linux/drivers/usb/serial/symbolserial.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Symbol USB barcode to serial driver
   4 *
   5 * Copyright (C) 2013 Johan Hovold <jhovold@gmail.com>
   6 * Copyright (C) 2009 Greg Kroah-Hartman <gregkh@suse.de>
   7 * Copyright (C) 2009 Novell Inc.
   8 */
   9
  10#include <linux/kernel.h>
  11#include <linux/tty.h>
  12#include <linux/slab.h>
  13#include <linux/tty_driver.h>
  14#include <linux/tty_flip.h>
  15#include <linux/module.h>
  16#include <linux/usb.h>
  17#include <linux/usb/serial.h>
  18#include <linux/uaccess.h>
  19
  20static const struct usb_device_id id_table[] = {
  21        { USB_DEVICE(0x05e0, 0x0600) },
  22        { },
  23};
  24MODULE_DEVICE_TABLE(usb, id_table);
  25
  26struct symbol_private {
  27        spinlock_t lock;        /* protects the following flags */
  28        bool throttled;
  29        bool actually_throttled;
  30};
  31
  32static void symbol_int_callback(struct urb *urb)
  33{
  34        struct usb_serial_port *port = urb->context;
  35        struct symbol_private *priv = usb_get_serial_port_data(port);
  36        unsigned char *data = urb->transfer_buffer;
  37        int status = urb->status;
  38        unsigned long flags;
  39        int result;
  40        int data_length;
  41
  42        switch (status) {
  43        case 0:
  44                /* success */
  45                break;
  46        case -ECONNRESET:
  47        case -ENOENT:
  48        case -ESHUTDOWN:
  49                /* this urb is terminated, clean up */
  50                dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
  51                        __func__, status);
  52                return;
  53        default:
  54                dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
  55                        __func__, status);
  56                goto exit;
  57        }
  58
  59        usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
  60
  61        /*
  62         * Data from the device comes with a 1 byte header:
  63         *
  64         * <size of data> <data>...
  65         */
  66        if (urb->actual_length > 1) {
  67                data_length = data[0];
  68                if (data_length > (urb->actual_length - 1))
  69                        data_length = urb->actual_length - 1;
  70                tty_insert_flip_string(&port->port, &data[1], data_length);
  71                tty_flip_buffer_push(&port->port);
  72        } else {
  73                dev_dbg(&port->dev, "%s - short packet\n", __func__);
  74        }
  75
  76exit:
  77        spin_lock_irqsave(&priv->lock, flags);
  78
  79        /* Continue trying to always read if we should */
  80        if (!priv->throttled) {
  81                result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
  82                if (result)
  83                        dev_err(&port->dev,
  84                            "%s - failed resubmitting read urb, error %d\n",
  85                                                        __func__, result);
  86        } else
  87                priv->actually_throttled = true;
  88        spin_unlock_irqrestore(&priv->lock, flags);
  89}
  90
  91static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port)
  92{
  93        struct symbol_private *priv = usb_get_serial_port_data(port);
  94        unsigned long flags;
  95        int result = 0;
  96
  97        spin_lock_irqsave(&priv->lock, flags);
  98        priv->throttled = false;
  99        priv->actually_throttled = false;
 100        spin_unlock_irqrestore(&priv->lock, flags);
 101
 102        /* Start reading from the device */
 103        result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
 104        if (result)
 105                dev_err(&port->dev,
 106                        "%s - failed resubmitting read urb, error %d\n",
 107                        __func__, result);
 108        return result;
 109}
 110
 111static void symbol_close(struct usb_serial_port *port)
 112{
 113        usb_kill_urb(port->interrupt_in_urb);
 114}
 115
 116static void symbol_throttle(struct tty_struct *tty)
 117{
 118        struct usb_serial_port *port = tty->driver_data;
 119        struct symbol_private *priv = usb_get_serial_port_data(port);
 120
 121        spin_lock_irq(&priv->lock);
 122        priv->throttled = true;
 123        spin_unlock_irq(&priv->lock);
 124}
 125
 126static void symbol_unthrottle(struct tty_struct *tty)
 127{
 128        struct usb_serial_port *port = tty->driver_data;
 129        struct symbol_private *priv = usb_get_serial_port_data(port);
 130        int result;
 131        bool was_throttled;
 132
 133        spin_lock_irq(&priv->lock);
 134        priv->throttled = false;
 135        was_throttled = priv->actually_throttled;
 136        priv->actually_throttled = false;
 137        spin_unlock_irq(&priv->lock);
 138
 139        if (was_throttled) {
 140                result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
 141                if (result)
 142                        dev_err(&port->dev,
 143                                "%s - failed submitting read urb, error %d\n",
 144                                                        __func__, result);
 145        }
 146}
 147
 148static int symbol_port_probe(struct usb_serial_port *port)
 149{
 150        struct symbol_private *priv;
 151
 152        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 153        if (!priv)
 154                return -ENOMEM;
 155
 156        spin_lock_init(&priv->lock);
 157
 158        usb_set_serial_port_data(port, priv);
 159
 160        return 0;
 161}
 162
 163static int symbol_port_remove(struct usb_serial_port *port)
 164{
 165        struct symbol_private *priv = usb_get_serial_port_data(port);
 166
 167        kfree(priv);
 168
 169        return 0;
 170}
 171
 172static struct usb_serial_driver symbol_device = {
 173        .driver = {
 174                .owner =        THIS_MODULE,
 175                .name =         "symbol",
 176        },
 177        .id_table =             id_table,
 178        .num_ports =            1,
 179        .num_interrupt_in =     1,
 180        .port_probe =           symbol_port_probe,
 181        .port_remove =          symbol_port_remove,
 182        .open =                 symbol_open,
 183        .close =                symbol_close,
 184        .throttle =             symbol_throttle,
 185        .unthrottle =           symbol_unthrottle,
 186        .read_int_callback =    symbol_int_callback,
 187};
 188
 189static struct usb_serial_driver * const serial_drivers[] = {
 190        &symbol_device, NULL
 191};
 192
 193module_usb_serial_driver(serial_drivers, id_table);
 194
 195MODULE_LICENSE("GPL v2");
 196