]> Git Repo - linux.git/blob - drivers/usb/serial/symbolserial.c
Merge tag 'acpi-fix-4.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
[linux.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 <[email protected]>
6  * Copyright (C) 2009 Greg Kroah-Hartman <[email protected]>
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         int result;
39         int data_length;
40
41         switch (status) {
42         case 0:
43                 /* success */
44                 break;
45         case -ECONNRESET:
46         case -ENOENT:
47         case -ESHUTDOWN:
48                 /* this urb is terminated, clean up */
49                 dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
50                         __func__, status);
51                 return;
52         default:
53                 dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n",
54                         __func__, status);
55                 goto exit;
56         }
57
58         usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
59
60         /*
61          * Data from the device comes with a 1 byte header:
62          *
63          * <size of data> <data>...
64          */
65         if (urb->actual_length > 1) {
66                 data_length = data[0];
67                 if (data_length > (urb->actual_length - 1))
68                         data_length = urb->actual_length - 1;
69                 tty_insert_flip_string(&port->port, &data[1], data_length);
70                 tty_flip_buffer_push(&port->port);
71         } else {
72                 dev_dbg(&port->dev, "%s - short packet\n", __func__);
73         }
74
75 exit:
76         spin_lock(&priv->lock);
77
78         /* Continue trying to always read if we should */
79         if (!priv->throttled) {
80                 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
81                 if (result)
82                         dev_err(&port->dev,
83                             "%s - failed resubmitting read urb, error %d\n",
84                                                         __func__, result);
85         } else
86                 priv->actually_throttled = true;
87         spin_unlock(&priv->lock);
88 }
89
90 static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port)
91 {
92         struct symbol_private *priv = usb_get_serial_port_data(port);
93         unsigned long flags;
94         int result = 0;
95
96         spin_lock_irqsave(&priv->lock, flags);
97         priv->throttled = false;
98         priv->actually_throttled = false;
99         spin_unlock_irqrestore(&priv->lock, flags);
100
101         /* Start reading from the device */
102         result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
103         if (result)
104                 dev_err(&port->dev,
105                         "%s - failed resubmitting read urb, error %d\n",
106                         __func__, result);
107         return result;
108 }
109
110 static void symbol_close(struct usb_serial_port *port)
111 {
112         usb_kill_urb(port->interrupt_in_urb);
113 }
114
115 static void symbol_throttle(struct tty_struct *tty)
116 {
117         struct usb_serial_port *port = tty->driver_data;
118         struct symbol_private *priv = usb_get_serial_port_data(port);
119
120         spin_lock_irq(&priv->lock);
121         priv->throttled = true;
122         spin_unlock_irq(&priv->lock);
123 }
124
125 static void symbol_unthrottle(struct tty_struct *tty)
126 {
127         struct usb_serial_port *port = tty->driver_data;
128         struct symbol_private *priv = usb_get_serial_port_data(port);
129         int result;
130         bool was_throttled;
131
132         spin_lock_irq(&priv->lock);
133         priv->throttled = false;
134         was_throttled = priv->actually_throttled;
135         priv->actually_throttled = false;
136         spin_unlock_irq(&priv->lock);
137
138         if (was_throttled) {
139                 result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
140                 if (result)
141                         dev_err(&port->dev,
142                                 "%s - failed submitting read urb, error %d\n",
143                                                         __func__, result);
144         }
145 }
146
147 static int symbol_port_probe(struct usb_serial_port *port)
148 {
149         struct symbol_private *priv;
150
151         priv = kzalloc(sizeof(*priv), GFP_KERNEL);
152         if (!priv)
153                 return -ENOMEM;
154
155         spin_lock_init(&priv->lock);
156
157         usb_set_serial_port_data(port, priv);
158
159         return 0;
160 }
161
162 static int symbol_port_remove(struct usb_serial_port *port)
163 {
164         struct symbol_private *priv = usb_get_serial_port_data(port);
165
166         kfree(priv);
167
168         return 0;
169 }
170
171 static struct usb_serial_driver symbol_device = {
172         .driver = {
173                 .owner =        THIS_MODULE,
174                 .name =         "symbol",
175         },
176         .id_table =             id_table,
177         .num_ports =            1,
178         .num_interrupt_in =     1,
179         .port_probe =           symbol_port_probe,
180         .port_remove =          symbol_port_remove,
181         .open =                 symbol_open,
182         .close =                symbol_close,
183         .throttle =             symbol_throttle,
184         .unthrottle =           symbol_unthrottle,
185         .read_int_callback =    symbol_int_callback,
186 };
187
188 static struct usb_serial_driver * const serial_drivers[] = {
189         &symbol_device, NULL
190 };
191
192 module_usb_serial_driver(serial_drivers, id_table);
193
194 MODULE_LICENSE("GPL v2");
This page took 0.043947 seconds and 4 git commands to generate.