GNU Linux-libre 4.19.286-gnu1
[releases.git] / drivers / usb / serial / symbolserial.c
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
20 static const struct usb_device_id id_table[] = {
21         { USB_DEVICE(0x05e0, 0x0600) },
22         { },
23 };
24 MODULE_DEVICE_TABLE(usb, id_table);
25
26 struct symbol_private {
27         spinlock_t lock;        /* protects the following flags */
28         bool throttled;
29         bool actually_throttled;
30 };
31
32 static 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
76 exit:
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
91 static 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
111 static void symbol_close(struct usb_serial_port *port)
112 {
113         usb_kill_urb(port->interrupt_in_urb);
114 }
115
116 static 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
126 static 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
148 static 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
163 static 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
172 static 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
189 static struct usb_serial_driver * const serial_drivers[] = {
190         &symbol_device, NULL
191 };
192
193 module_usb_serial_driver(serial_drivers, id_table);
194
195 MODULE_LICENSE("GPL v2");