1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Opticon USB barcode to serial driver |
4 | * |
5 | * Copyright (C) 2011 - 2012 Johan Hovold <jhovold@gmail.com> |
6 | * Copyright (C) 2011 Martin Jansen <martin.jansen@opticon.com> |
7 | * Copyright (C) 2008 - 2009 Greg Kroah-Hartman <gregkh@suse.de> |
8 | * Copyright (C) 2008 - 2009 Novell Inc. |
9 | */ |
10 | |
11 | #include <linux/kernel.h> |
12 | #include <linux/tty.h> |
13 | #include <linux/tty_driver.h> |
14 | #include <linux/slab.h> |
15 | #include <linux/tty_flip.h> |
16 | #include <linux/serial.h> |
17 | #include <linux/module.h> |
18 | #include <linux/usb.h> |
19 | #include <linux/usb/serial.h> |
20 | #include <linux/uaccess.h> |
21 | |
22 | #define CONTROL_RTS 0x02 |
23 | #define RESEND_CTS_STATE 0x03 |
24 | |
25 | /* max number of write urbs in flight */ |
26 | #define URB_UPPER_LIMIT 8 |
27 | |
28 | /* This driver works for the Opticon 1D barcode reader |
29 | * an examples of 1D barcode types are EAN, UPC, Code39, IATA etc.. */ |
30 | #define DRIVER_DESC "Opticon USB barcode to serial driver (1D)" |
31 | |
32 | static const struct usb_device_id id_table[] = { |
33 | { USB_DEVICE(0x065a, 0x0009) }, |
34 | { }, |
35 | }; |
36 | MODULE_DEVICE_TABLE(usb, id_table); |
37 | |
38 | /* This structure holds all of the individual device information */ |
39 | struct opticon_private { |
40 | spinlock_t lock; /* protects the following flags */ |
41 | bool rts; |
42 | bool cts; |
43 | int outstanding_urbs; |
44 | int outstanding_bytes; |
45 | |
46 | struct usb_anchor anchor; |
47 | }; |
48 | |
49 | |
50 | static void opticon_process_data_packet(struct usb_serial_port *port, |
51 | const unsigned char *buf, size_t len) |
52 | { |
53 | tty_insert_flip_string(port: &port->port, chars: buf, size: len); |
54 | tty_flip_buffer_push(port: &port->port); |
55 | } |
56 | |
57 | static void opticon_process_status_packet(struct usb_serial_port *port, |
58 | const unsigned char *buf, size_t len) |
59 | { |
60 | struct opticon_private *priv = usb_get_serial_port_data(port); |
61 | unsigned long flags; |
62 | |
63 | spin_lock_irqsave(&priv->lock, flags); |
64 | if (buf[0] == 0x00) |
65 | priv->cts = false; |
66 | else |
67 | priv->cts = true; |
68 | spin_unlock_irqrestore(lock: &priv->lock, flags); |
69 | } |
70 | |
71 | static void opticon_process_read_urb(struct urb *urb) |
72 | { |
73 | struct usb_serial_port *port = urb->context; |
74 | const unsigned char *hdr = urb->transfer_buffer; |
75 | const unsigned char *data = hdr + 2; |
76 | size_t data_len = urb->actual_length - 2; |
77 | |
78 | if (urb->actual_length <= 2) { |
79 | dev_dbg(&port->dev, "malformed packet received: %d bytes\n" , |
80 | urb->actual_length); |
81 | return; |
82 | } |
83 | /* |
84 | * Data from the device comes with a 2 byte header: |
85 | * |
86 | * <0x00><0x00>data... |
87 | * This is real data to be sent to the tty layer |
88 | * <0x00><0x01>level |
89 | * This is a CTS level change, the third byte is the CTS |
90 | * value (0 for low, 1 for high). |
91 | */ |
92 | if ((hdr[0] == 0x00) && (hdr[1] == 0x00)) { |
93 | opticon_process_data_packet(port, buf: data, len: data_len); |
94 | } else if ((hdr[0] == 0x00) && (hdr[1] == 0x01)) { |
95 | opticon_process_status_packet(port, buf: data, len: data_len); |
96 | } else { |
97 | dev_dbg(&port->dev, "unknown packet received: %02x %02x\n" , |
98 | hdr[0], hdr[1]); |
99 | } |
100 | } |
101 | |
102 | static int send_control_msg(struct usb_serial_port *port, u8 requesttype, |
103 | u8 val) |
104 | { |
105 | struct usb_serial *serial = port->serial; |
106 | int retval; |
107 | u8 *buffer; |
108 | |
109 | buffer = kzalloc(size: 1, GFP_KERNEL); |
110 | if (!buffer) |
111 | return -ENOMEM; |
112 | |
113 | buffer[0] = val; |
114 | /* Send the message to the vendor control endpoint |
115 | * of the connected device */ |
116 | retval = usb_control_msg(dev: serial->dev, usb_sndctrlpipe(serial->dev, 0), |
117 | request: requesttype, |
118 | USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, |
119 | value: 0, index: 0, data: buffer, size: 1, USB_CTRL_SET_TIMEOUT); |
120 | kfree(objp: buffer); |
121 | |
122 | if (retval < 0) |
123 | return retval; |
124 | |
125 | return 0; |
126 | } |
127 | |
128 | static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port) |
129 | { |
130 | struct opticon_private *priv = usb_get_serial_port_data(port); |
131 | unsigned long flags; |
132 | int res; |
133 | |
134 | spin_lock_irqsave(&priv->lock, flags); |
135 | priv->rts = false; |
136 | spin_unlock_irqrestore(lock: &priv->lock, flags); |
137 | |
138 | /* Clear RTS line */ |
139 | send_control_msg(port, CONTROL_RTS, val: 0); |
140 | |
141 | /* clear the halt status of the endpoint */ |
142 | usb_clear_halt(dev: port->serial->dev, pipe: port->read_urb->pipe); |
143 | |
144 | res = usb_serial_generic_open(tty, port); |
145 | if (res) |
146 | return res; |
147 | |
148 | /* Request CTS line state, sometimes during opening the current |
149 | * CTS state can be missed. */ |
150 | send_control_msg(port, RESEND_CTS_STATE, val: 1); |
151 | |
152 | return res; |
153 | } |
154 | |
155 | static void opticon_close(struct usb_serial_port *port) |
156 | { |
157 | struct opticon_private *priv = usb_get_serial_port_data(port); |
158 | |
159 | usb_kill_anchored_urbs(anchor: &priv->anchor); |
160 | |
161 | usb_serial_generic_close(port); |
162 | } |
163 | |
164 | static void opticon_write_control_callback(struct urb *urb) |
165 | { |
166 | struct usb_serial_port *port = urb->context; |
167 | struct opticon_private *priv = usb_get_serial_port_data(port); |
168 | int status = urb->status; |
169 | unsigned long flags; |
170 | |
171 | /* free up the transfer buffer, as usb_free_urb() does not do this */ |
172 | kfree(objp: urb->transfer_buffer); |
173 | |
174 | /* setup packet may be set if we're using it for writing */ |
175 | kfree(objp: urb->setup_packet); |
176 | |
177 | if (status) |
178 | dev_dbg(&port->dev, |
179 | "%s - non-zero urb status received: %d\n" , |
180 | __func__, status); |
181 | |
182 | spin_lock_irqsave(&priv->lock, flags); |
183 | --priv->outstanding_urbs; |
184 | priv->outstanding_bytes -= urb->transfer_buffer_length; |
185 | spin_unlock_irqrestore(lock: &priv->lock, flags); |
186 | |
187 | usb_serial_port_softint(port); |
188 | } |
189 | |
190 | static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, |
191 | const unsigned char *buf, int count) |
192 | { |
193 | struct opticon_private *priv = usb_get_serial_port_data(port); |
194 | struct usb_serial *serial = port->serial; |
195 | struct urb *urb; |
196 | unsigned char *buffer; |
197 | unsigned long flags; |
198 | struct usb_ctrlrequest *dr; |
199 | int ret = -ENOMEM; |
200 | |
201 | spin_lock_irqsave(&priv->lock, flags); |
202 | if (priv->outstanding_urbs > URB_UPPER_LIMIT) { |
203 | spin_unlock_irqrestore(lock: &priv->lock, flags); |
204 | dev_dbg(&port->dev, "%s - write limit hit\n" , __func__); |
205 | return 0; |
206 | } |
207 | priv->outstanding_urbs++; |
208 | priv->outstanding_bytes += count; |
209 | spin_unlock_irqrestore(lock: &priv->lock, flags); |
210 | |
211 | buffer = kmemdup(p: buf, size: count, GFP_ATOMIC); |
212 | if (!buffer) |
213 | goto error_no_buffer; |
214 | |
215 | urb = usb_alloc_urb(iso_packets: 0, GFP_ATOMIC); |
216 | if (!urb) |
217 | goto error_no_urb; |
218 | |
219 | usb_serial_debug_data(dev: &port->dev, function: __func__, size: count, data: buffer); |
220 | |
221 | /* The connected devices do not have a bulk write endpoint, |
222 | * to transmit data to de barcode device the control endpoint is used */ |
223 | dr = kmalloc(size: sizeof(struct usb_ctrlrequest), GFP_ATOMIC); |
224 | if (!dr) |
225 | goto error_no_dr; |
226 | |
227 | dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT; |
228 | dr->bRequest = 0x01; |
229 | dr->wValue = 0; |
230 | dr->wIndex = 0; |
231 | dr->wLength = cpu_to_le16(count); |
232 | |
233 | usb_fill_control_urb(urb, dev: serial->dev, |
234 | usb_sndctrlpipe(serial->dev, 0), |
235 | setup_packet: (unsigned char *)dr, transfer_buffer: buffer, buffer_length: count, |
236 | complete_fn: opticon_write_control_callback, context: port); |
237 | |
238 | usb_anchor_urb(urb, anchor: &priv->anchor); |
239 | |
240 | /* send it down the pipe */ |
241 | ret = usb_submit_urb(urb, GFP_ATOMIC); |
242 | if (ret) { |
243 | dev_err(&port->dev, "failed to submit write urb: %d\n" , ret); |
244 | usb_unanchor_urb(urb); |
245 | goto error; |
246 | } |
247 | |
248 | /* we are done with this urb, so let the host driver |
249 | * really free it when it is finished with it */ |
250 | usb_free_urb(urb); |
251 | |
252 | return count; |
253 | error: |
254 | kfree(objp: dr); |
255 | error_no_dr: |
256 | usb_free_urb(urb); |
257 | error_no_urb: |
258 | kfree(objp: buffer); |
259 | error_no_buffer: |
260 | spin_lock_irqsave(&priv->lock, flags); |
261 | --priv->outstanding_urbs; |
262 | priv->outstanding_bytes -= count; |
263 | spin_unlock_irqrestore(lock: &priv->lock, flags); |
264 | |
265 | return ret; |
266 | } |
267 | |
268 | static unsigned int opticon_write_room(struct tty_struct *tty) |
269 | { |
270 | struct usb_serial_port *port = tty->driver_data; |
271 | struct opticon_private *priv = usb_get_serial_port_data(port); |
272 | unsigned long flags; |
273 | |
274 | /* |
275 | * We really can take almost anything the user throws at us |
276 | * but let's pick a nice big number to tell the tty |
277 | * layer that we have lots of free space, unless we don't. |
278 | */ |
279 | spin_lock_irqsave(&priv->lock, flags); |
280 | if (priv->outstanding_urbs > URB_UPPER_LIMIT * 2 / 3) { |
281 | spin_unlock_irqrestore(lock: &priv->lock, flags); |
282 | dev_dbg(&port->dev, "%s - write limit hit\n" , __func__); |
283 | return 0; |
284 | } |
285 | spin_unlock_irqrestore(lock: &priv->lock, flags); |
286 | |
287 | return 2048; |
288 | } |
289 | |
290 | static unsigned int opticon_chars_in_buffer(struct tty_struct *tty) |
291 | { |
292 | struct usb_serial_port *port = tty->driver_data; |
293 | struct opticon_private *priv = usb_get_serial_port_data(port); |
294 | unsigned long flags; |
295 | unsigned int count; |
296 | |
297 | spin_lock_irqsave(&priv->lock, flags); |
298 | count = priv->outstanding_bytes; |
299 | spin_unlock_irqrestore(lock: &priv->lock, flags); |
300 | |
301 | return count; |
302 | } |
303 | |
304 | static int opticon_tiocmget(struct tty_struct *tty) |
305 | { |
306 | struct usb_serial_port *port = tty->driver_data; |
307 | struct opticon_private *priv = usb_get_serial_port_data(port); |
308 | unsigned long flags; |
309 | int result = 0; |
310 | |
311 | spin_lock_irqsave(&priv->lock, flags); |
312 | if (priv->rts) |
313 | result |= TIOCM_RTS; |
314 | if (priv->cts) |
315 | result |= TIOCM_CTS; |
316 | spin_unlock_irqrestore(lock: &priv->lock, flags); |
317 | |
318 | dev_dbg(&port->dev, "%s - %x\n" , __func__, result); |
319 | return result; |
320 | } |
321 | |
322 | static int opticon_tiocmset(struct tty_struct *tty, |
323 | unsigned int set, unsigned int clear) |
324 | { |
325 | struct usb_serial_port *port = tty->driver_data; |
326 | struct opticon_private *priv = usb_get_serial_port_data(port); |
327 | unsigned long flags; |
328 | bool rts; |
329 | bool changed = false; |
330 | int ret; |
331 | |
332 | /* We only support RTS so we only handle that */ |
333 | spin_lock_irqsave(&priv->lock, flags); |
334 | |
335 | rts = priv->rts; |
336 | if (set & TIOCM_RTS) |
337 | priv->rts = true; |
338 | if (clear & TIOCM_RTS) |
339 | priv->rts = false; |
340 | changed = rts ^ priv->rts; |
341 | spin_unlock_irqrestore(lock: &priv->lock, flags); |
342 | |
343 | if (!changed) |
344 | return 0; |
345 | |
346 | ret = send_control_msg(port, CONTROL_RTS, val: !rts); |
347 | if (ret) |
348 | return usb_translate_errors(error_code: ret); |
349 | |
350 | return 0; |
351 | } |
352 | |
353 | static int opticon_port_probe(struct usb_serial_port *port) |
354 | { |
355 | struct opticon_private *priv; |
356 | |
357 | priv = kzalloc(size: sizeof(*priv), GFP_KERNEL); |
358 | if (!priv) |
359 | return -ENOMEM; |
360 | |
361 | spin_lock_init(&priv->lock); |
362 | init_usb_anchor(anchor: &priv->anchor); |
363 | |
364 | usb_set_serial_port_data(port, data: priv); |
365 | |
366 | return 0; |
367 | } |
368 | |
369 | static void opticon_port_remove(struct usb_serial_port *port) |
370 | { |
371 | struct opticon_private *priv = usb_get_serial_port_data(port); |
372 | |
373 | kfree(objp: priv); |
374 | } |
375 | |
376 | static struct usb_serial_driver opticon_device = { |
377 | .driver = { |
378 | .owner = THIS_MODULE, |
379 | .name = "opticon" , |
380 | }, |
381 | .id_table = id_table, |
382 | .num_ports = 1, |
383 | .num_bulk_in = 1, |
384 | .bulk_in_size = 256, |
385 | .port_probe = opticon_port_probe, |
386 | .port_remove = opticon_port_remove, |
387 | .open = opticon_open, |
388 | .close = opticon_close, |
389 | .write = opticon_write, |
390 | .write_room = opticon_write_room, |
391 | .chars_in_buffer = opticon_chars_in_buffer, |
392 | .throttle = usb_serial_generic_throttle, |
393 | .unthrottle = usb_serial_generic_unthrottle, |
394 | .tiocmget = opticon_tiocmget, |
395 | .tiocmset = opticon_tiocmset, |
396 | .process_read_urb = opticon_process_read_urb, |
397 | }; |
398 | |
399 | static struct usb_serial_driver * const serial_drivers[] = { |
400 | &opticon_device, NULL |
401 | }; |
402 | |
403 | module_usb_serial_driver(serial_drivers, id_table); |
404 | |
405 | MODULE_DESCRIPTION(DRIVER_DESC); |
406 | MODULE_LICENSE("GPL v2" ); |
407 | |