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