symbolserial.c (4702B)
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 void 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 170static struct usb_serial_driver symbol_device = { 171 .driver = { 172 .owner = THIS_MODULE, 173 .name = "symbol", 174 }, 175 .id_table = id_table, 176 .num_ports = 1, 177 .num_interrupt_in = 1, 178 .port_probe = symbol_port_probe, 179 .port_remove = symbol_port_remove, 180 .open = symbol_open, 181 .close = symbol_close, 182 .throttle = symbol_throttle, 183 .unthrottle = symbol_unthrottle, 184 .read_int_callback = symbol_int_callback, 185}; 186 187static struct usb_serial_driver * const serial_drivers[] = { 188 &symbol_device, NULL 189}; 190 191module_usb_serial_driver(serial_drivers, id_table); 192 193MODULE_LICENSE("GPL v2");