Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Symbol USB barcode to serial driver
0004  *
0005  * Copyright (C) 2013 Johan Hovold <jhovold@gmail.com>
0006  * Copyright (C) 2009 Greg Kroah-Hartman <gregkh@suse.de>
0007  * Copyright (C) 2009 Novell Inc.
0008  */
0009 
0010 #include <linux/kernel.h>
0011 #include <linux/tty.h>
0012 #include <linux/slab.h>
0013 #include <linux/tty_driver.h>
0014 #include <linux/tty_flip.h>
0015 #include <linux/module.h>
0016 #include <linux/usb.h>
0017 #include <linux/usb/serial.h>
0018 #include <linux/uaccess.h>
0019 
0020 static const struct usb_device_id id_table[] = {
0021     { USB_DEVICE(0x05e0, 0x0600) },
0022     { },
0023 };
0024 MODULE_DEVICE_TABLE(usb, id_table);
0025 
0026 struct symbol_private {
0027     spinlock_t lock;    /* protects the following flags */
0028     bool throttled;
0029     bool actually_throttled;
0030 };
0031 
0032 static void symbol_int_callback(struct urb *urb)
0033 {
0034     struct usb_serial_port *port = urb->context;
0035     struct symbol_private *priv = usb_get_serial_port_data(port);
0036     unsigned char *data = urb->transfer_buffer;
0037     int status = urb->status;
0038     unsigned long flags;
0039     int result;
0040     int data_length;
0041 
0042     switch (status) {
0043     case 0:
0044         /* success */
0045         break;
0046     case -ECONNRESET:
0047     case -ENOENT:
0048     case -ESHUTDOWN:
0049         /* this urb is terminated, clean up */
0050         dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
0051             __func__, status);
0052         return;
0053     default:
0054         dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
0055             __func__, status);
0056         goto exit;
0057     }
0058 
0059     usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
0060 
0061     /*
0062      * Data from the device comes with a 1 byte header:
0063      *
0064      * <size of data> <data>...
0065      */
0066     if (urb->actual_length > 1) {
0067         data_length = data[0];
0068         if (data_length > (urb->actual_length - 1))
0069             data_length = urb->actual_length - 1;
0070         tty_insert_flip_string(&port->port, &data[1], data_length);
0071         tty_flip_buffer_push(&port->port);
0072     } else {
0073         dev_dbg(&port->dev, "%s - short packet\n", __func__);
0074     }
0075 
0076 exit:
0077     spin_lock_irqsave(&priv->lock, flags);
0078 
0079     /* Continue trying to always read if we should */
0080     if (!priv->throttled) {
0081         result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
0082         if (result)
0083             dev_err(&port->dev,
0084                 "%s - failed resubmitting read urb, error %d\n",
0085                             __func__, result);
0086     } else
0087         priv->actually_throttled = true;
0088     spin_unlock_irqrestore(&priv->lock, flags);
0089 }
0090 
0091 static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port)
0092 {
0093     struct symbol_private *priv = usb_get_serial_port_data(port);
0094     unsigned long flags;
0095     int result = 0;
0096 
0097     spin_lock_irqsave(&priv->lock, flags);
0098     priv->throttled = false;
0099     priv->actually_throttled = false;
0100     spin_unlock_irqrestore(&priv->lock, flags);
0101 
0102     /* Start reading from the device */
0103     result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
0104     if (result)
0105         dev_err(&port->dev,
0106             "%s - failed resubmitting read urb, error %d\n",
0107             __func__, result);
0108     return result;
0109 }
0110 
0111 static void symbol_close(struct usb_serial_port *port)
0112 {
0113     usb_kill_urb(port->interrupt_in_urb);
0114 }
0115 
0116 static void symbol_throttle(struct tty_struct *tty)
0117 {
0118     struct usb_serial_port *port = tty->driver_data;
0119     struct symbol_private *priv = usb_get_serial_port_data(port);
0120 
0121     spin_lock_irq(&priv->lock);
0122     priv->throttled = true;
0123     spin_unlock_irq(&priv->lock);
0124 }
0125 
0126 static void symbol_unthrottle(struct tty_struct *tty)
0127 {
0128     struct usb_serial_port *port = tty->driver_data;
0129     struct symbol_private *priv = usb_get_serial_port_data(port);
0130     int result;
0131     bool was_throttled;
0132 
0133     spin_lock_irq(&priv->lock);
0134     priv->throttled = false;
0135     was_throttled = priv->actually_throttled;
0136     priv->actually_throttled = false;
0137     spin_unlock_irq(&priv->lock);
0138 
0139     if (was_throttled) {
0140         result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
0141         if (result)
0142             dev_err(&port->dev,
0143                 "%s - failed submitting read urb, error %d\n",
0144                             __func__, result);
0145     }
0146 }
0147 
0148 static int symbol_port_probe(struct usb_serial_port *port)
0149 {
0150     struct symbol_private *priv;
0151 
0152     priv = kzalloc(sizeof(*priv), GFP_KERNEL);
0153     if (!priv)
0154         return -ENOMEM;
0155 
0156     spin_lock_init(&priv->lock);
0157 
0158     usb_set_serial_port_data(port, priv);
0159 
0160     return 0;
0161 }
0162 
0163 static void symbol_port_remove(struct usb_serial_port *port)
0164 {
0165     struct symbol_private *priv = usb_get_serial_port_data(port);
0166 
0167     kfree(priv);
0168 }
0169 
0170 static struct usb_serial_driver symbol_device = {
0171     .driver = {
0172         .owner =    THIS_MODULE,
0173         .name =     "symbol",
0174     },
0175     .id_table =     id_table,
0176     .num_ports =        1,
0177     .num_interrupt_in = 1,
0178     .port_probe =       symbol_port_probe,
0179     .port_remove =      symbol_port_remove,
0180     .open =         symbol_open,
0181     .close =        symbol_close,
0182     .throttle =         symbol_throttle,
0183     .unthrottle =       symbol_unthrottle,
0184     .read_int_callback =    symbol_int_callback,
0185 };
0186 
0187 static struct usb_serial_driver * const serial_drivers[] = {
0188     &symbol_device, NULL
0189 };
0190 
0191 module_usb_serial_driver(serial_drivers, id_table);
0192 
0193 MODULE_LICENSE("GPL v2");