aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/metro-usb.c
diff options
context:
space:
mode:
authorAleksey Babahin <tamerlan311@gmail.com>2012-03-08 16:18:43 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-03-08 16:24:09 -0500
commit43d186fe992da93bb1dd34a7dd4534719624431c (patch)
tree680e7601f983dd716a540938c7a75c620505b2d8 /drivers/usb/serial/metro-usb.c
parent33d2832ab0149a26418d360af3c444969a63fb28 (diff)
USB: serial: add metro-usb driver to the tree
This driver is for the Metrologic barcode scanner. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/serial/metro-usb.c')
-rw-r--r--drivers/usb/serial/metro-usb.c622
1 files changed, 622 insertions, 0 deletions
diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c
new file mode 100644
index 000000000000..5b8ed50e5dda
--- /dev/null
+++ b/drivers/usb/serial/metro-usb.c
@@ -0,0 +1,622 @@
1/*
2 Date Created: 9/15/2006
3 File Name: metro-usb.c
4 Description: metro-usb.c is the drivers main source file. The driver is a USB to Serial converter.
5 The driver takes USB data and sends it to a virtual ttyUSB# serial port.
6 The driver interfaces with the usbserial.ko driver supplied by Linux.
7
8 NOTES:
9 To install the driver:
10 1. Install the usbserial.ko module supplied by Linux with: # insmod usbserial.ko
11 2. Install the metro-usb.ko module with: # insmod metro-usb.ko vender=0x#### product=0x#### debug=1
12 The vendor, product and debug parameters are optional.
13
14 Some of this code is credited to Linux USB open source files that are distributed with Linux.
15
16 Copyright: 2007 Metrologic Instruments. All rights reserved.
17 Copyright: 2011 Azimut Ltd. <http://azimutrzn.ru/>
18 Requirements: gedit.exe, notepad.exe
19
20 Revision History:
21
22 Date: Developer: Revisions:
23 ------------------------------------------------------------------------------
24 1/30/2007 Philip Nicastro Initial release. (v1.0.0.0)
25 2/27/2007 Philip Nicastro Changed the metrousb_read_int_callback function to use a loop with the tty_insert_flip_char function to copy each byte to the tty layer. Removed the tty_buffer_request_room and the tty_insert_flip_string function calls. These calls were not supported on Fedora.
26 2/27/2007 Philip Nicastro Released. (v1.1.0.0)
27 10/07/2011 Aleksey Babahin Update for new kernel (tested on 2.6.38)
28 Add unidirection mode support
29
30
31*/
32
33#include <linux/kernel.h>
34#include <linux/init.h>
35#include <linux/tty.h>
36#include <linux/module.h>
37#include <linux/usb.h>
38#include <linux/errno.h>
39#include <linux/slab.h>
40#include <linux/tty_driver.h>
41#include <linux/tty_flip.h>
42#include <linux/moduleparam.h>
43#include <linux/spinlock.h>
44#include <asm/uaccess.h>
45#include <linux/errno.h>
46#include "metro-usb.h"
47#include <linux/usb/serial.h>
48
49/* Version Information */
50#define DRIVER_VERSION "v1.2.0.0"
51#define DRIVER_DESC "Metrologic Instruments Inc. - USB-POS driver"
52
53/* Device table list. */
54static struct usb_device_id id_table [] = {
55 { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID) },
56 { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_UNI) },
57 { }, /* Optional paramenter entry. */
58 { }, /* Terminating entry. */
59};
60MODULE_DEVICE_TABLE(usb, id_table);
61
62/* Input parameter constants. */
63static int debug;
64static __u16 vendor;
65static __u16 product;
66
67/* Function prototypes. */
68static void metrousb_cleanup (struct usb_serial_port *port);
69static void metrousb_close (struct usb_serial_port *port);
70static int metrousb_open (struct tty_struct *tty, struct usb_serial_port *port);
71static void metrousb_read_int_callback (struct urb *urb);
72static void metrousb_shutdown (struct usb_serial *serial);
73static int metrousb_startup (struct usb_serial *serial);
74static void metrousb_throttle(struct tty_struct *tty);
75static int metrousb_tiocmget(struct tty_struct *tty);
76static int metrousb_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear);
77static void metrousb_unthrottle(struct tty_struct *tty);
78
79/* Driver structure. */
80static struct usb_driver metrousb_driver = {
81 .name = "metro-usb",
82 .probe = usb_serial_probe,
83 .disconnect = usb_serial_disconnect,
84 .id_table = id_table
85};
86
87/* Device structure. */
88static struct usb_serial_driver metrousb_device = {
89 .driver = {
90 .owner = THIS_MODULE,
91 .name = "metro-usb",
92 },
93 .description = "Metrologic USB to serial converter.",
94 .id_table = id_table,
95 .usb_driver = &metrousb_driver,
96 .num_ports = 1,
97 .open = metrousb_open,
98 .close = metrousb_close,
99 .read_int_callback = metrousb_read_int_callback,
100 .attach = metrousb_startup,
101 .release = metrousb_shutdown,
102 .throttle = metrousb_throttle,
103 .unthrottle = metrousb_unthrottle,
104 .tiocmget = metrousb_tiocmget,
105 .tiocmset = metrousb_tiocmset,
106};
107
108/* ----------------------------------------------------------------------------------------------
109 Description:
110 Clean up any urbs and port information.
111
112 Input:
113 struct usb_serial_port *: pointer to a usb_serial_port structure.
114
115 Output:
116 int: Returns true (0) if successful, false otherwise.
117*/
118static void metrousb_cleanup (struct usb_serial_port *port)
119{
120 dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number);
121
122 if (port->serial->dev) {
123 /* Shutdown any interrupt in urbs. */
124 if (port->interrupt_in_urb) {
125 usb_unlink_urb(port->interrupt_in_urb);
126 usb_kill_urb(port->interrupt_in_urb);
127 }
128
129 // temp
130 // this will be needed for the write urb
131 /* Shutdown any interrupt_out_urbs. */
132 //if (serial->num_bulk_in)
133 // usb_kill_urb(port->read_urb);
134 }
135}
136
137/* ----------------------------------------------------------------------------------------------
138 Description:
139 Close the open serial port. Cleanup any open serial port information.
140
141 Input:
142 struct usb_serial_port *: pointer to a usb_serial_port structure.
143 struct file *: pointer to a file structure.
144
145 Output:
146 int: Returns true (0) if successful, false otherwise.
147*/
148static void metrousb_close (struct usb_serial_port *port)
149{
150 dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number);
151 metrousb_cleanup(port);
152}
153
154/* ----------------------------------------------------------------------------------------------
155 Description:
156 Driver exit.
157
158 Input:
159 None:
160
161 Output:
162 None:
163*/
164static void __exit metrousb_exit(void)
165{
166 dbg("METRO-USB - %s", __FUNCTION__);
167
168 usb_deregister(&metrousb_driver);
169 usb_serial_deregister(&metrousb_device);
170}
171
172/* ----------------------------------------------------------------------------------------------
173 Description:
174 Driver initialization.
175
176 Input:
177 None:
178
179 Output:
180 int: Returns true (0) if successful, false otherwise.
181*/
182static int __init metrousb_init(void)
183{
184 int retval = 0;
185 int i = 0;
186
187 dbg("METRO-USB - %s", __FUNCTION__);
188
189 /* Add the device parameters if entered. */
190 if ((vendor > 0) && (product > 0)) {
191 struct usb_device_id usb_dev_temp[] = { {USB_DEVICE(vendor, product) } };
192
193 /* Find the last entry in id_table */
194 for (i=0; i < ARRAY_SIZE(id_table); i++) {
195 if (id_table[i].idVendor == 0) {
196 id_table[i] = usb_dev_temp[0];
197 break;
198 }
199 }
200
201 dbg("METRO-USB - %s - support added for unknown device: vendor=0x%x - product=0x%x", __FUNCTION__, vendor, product);
202 printk(KERN_INFO "Metro USB-POS support added for unknown device: vendor=0x%x - product=0x%x", vendor, product);
203 }
204
205 /* Register the devices. */
206 retval = usb_serial_register(&metrousb_device);
207 if (retval)
208 return retval;
209
210 /* Register the driver. */
211 retval = usb_register(&metrousb_driver);
212 if (retval)
213 usb_serial_deregister(&metrousb_device);
214
215 printk(KERN_INFO DRIVER_DESC " : " DRIVER_VERSION);
216
217 return retval;
218}
219
220/* ----------------------------------------------------------------------------------------------
221 Description:
222 Open the drivers serial port.
223
224 Input:
225 struct usb_serial_port *: pointer to a usb_serial_port structure.
226 struct file *: pointer to a file structure.
227
228 Output:
229 int: Returns true (0) if successful, false otherwise.
230*/
231static int metrousb_open (struct tty_struct *tty, struct usb_serial_port *port)
232{
233 struct usb_serial *serial = port->serial;
234 struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
235 unsigned long flags = 0;
236 int result = 0;
237
238 dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number);
239
240 /* Make sure the urb is initialized. */
241 if (!port->interrupt_in_urb) {
242 dbg("METRO-USB - %s - interrupt urb not initialized for port number=%d", __FUNCTION__, port->number);
243 return -ENODEV;
244 }
245
246 /* Set the private data information for the port. */
247 spin_lock_irqsave(&metro_priv->lock, flags);
248 metro_priv->control_state = 0;
249 metro_priv->throttled = 0;
250 spin_unlock_irqrestore(&metro_priv->lock, flags);
251
252 /*
253 * Force low_latency on so that our tty_push actually forces the data
254 * through, otherwise it is scheduled, and with high data rates (like
255 * with OHCI) data can get lost.
256 */
257 if (tty) {
258 tty->low_latency = 1;
259 }
260
261 /* Clear the urb pipe. */
262 usb_clear_halt(serial->dev, port->interrupt_in_urb->pipe);
263
264 /* Start reading from the device */
265 usb_fill_int_urb (port->interrupt_in_urb, serial->dev,
266 usb_rcvintpipe (serial->dev, port->interrupt_in_endpointAddress),
267 port->interrupt_in_urb->transfer_buffer,
268 port->interrupt_in_urb->transfer_buffer_length,
269 metrousb_read_int_callback, port, 1);
270 result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
271
272 if (result) {
273 dbg("METRO-USB - %s - failed submitting interrupt in urb for port number=%d, error code=%d"
274 , __FUNCTION__, port->number, result);
275 goto exit;
276 }
277
278 dbg("METRO-USB - %s - port open for port number=%d", __FUNCTION__, port->number);
279exit:
280 return result;
281}
282
283/* ----------------------------------------------------------------------------------------------
284 Description:
285 Read the port from the read interrupt.
286
287 Input:
288 struct urb *: urb structure to get data.
289 struct pt_regs *: pt_regs structure.
290
291 Output:
292 None:
293*/
294static void metrousb_read_int_callback (struct urb *urb)
295{
296 struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
297 struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
298 struct tty_struct *tty;
299 unsigned char *data = urb->transfer_buffer;
300 int throttled = 0;
301 int result = 0;
302 unsigned long flags = 0;
303
304 dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number);
305
306 switch (urb->status) {
307 case 0:
308 /* Success status, read from the port. */
309 break;
310 case -ECONNRESET:
311 case -ENOENT:
312 case -ESHUTDOWN:
313 /* urb has been terminated. */
314 dbg("METRO-USB - %s - urb shutting down, port number=%d, error code=%d",
315 __FUNCTION__, port->number, result);
316 return;
317 default:
318 dbg("METRO-USB - %s - non-zero urb received, port number=%d, error code=%d",
319 __FUNCTION__, port->number, result);
320 goto exit;
321 }
322
323
324 /* Set the data read from the usb port into the serial port buffer. */
325 tty = tty_port_tty_get(&port->port);
326 if (!tty) {
327 dbg("%s - bad tty pointer - exiting", __func__);
328 return;
329 }
330
331 if (tty && urb->actual_length) {
332 // Loop through the data copying each byte to the tty layer.
333 tty_insert_flip_string(tty, data, urb->actual_length);
334
335 // Force the data to the tty layer.
336 tty_flip_buffer_push(tty);
337 }
338 tty_kref_put(tty);
339
340 /* Set any port variables. */
341 spin_lock_irqsave(&metro_priv->lock, flags);
342 throttled = metro_priv->throttled;
343 spin_unlock_irqrestore(&metro_priv->lock, flags);
344
345 /* Continue trying to read if set. */
346 if (!throttled) {
347 usb_fill_int_urb (port->interrupt_in_urb, port->serial->dev,
348 usb_rcvintpipe (port->serial->dev, port->interrupt_in_endpointAddress),
349 port->interrupt_in_urb->transfer_buffer,
350 port->interrupt_in_urb->transfer_buffer_length,
351 metrousb_read_int_callback, port, 1);
352
353 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
354
355 if (result) {
356 dbg("METRO-USB - %s - failed submitting interrupt in urb for port number=%d, error code=%d",
357 __FUNCTION__, port->number, result);
358 }
359 }
360 return;
361
362exit:
363 /* Try to resubmit the urb. */
364 result = usb_submit_urb (urb, GFP_ATOMIC);
365 if (result) {
366 dbg("METRO-USB - %s - failed submitting interrupt in urb for port number=%d, error code=%d",
367 __FUNCTION__, port->number, result);
368 }
369}
370
371/* ----------------------------------------------------------------------------------------------
372 Description:
373 Set the modem control state for the entered serial port.
374
375 Input:
376 struct usb_serial_port *: pointer to a usb_serial_port structure.
377 unsigned int: control state value to set.
378
379 Output:
380 int: Returns true (0) if successful, false otherwise.
381*/
382static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int control_state)
383{
384 int retval = 0;
385 unsigned char mcr = METROUSB_MCR_NONE;
386
387 dbg("METRO-USB - %s - control state=%d", __FUNCTION__, control_state);
388
389 /* Set the modem control value. */
390 if (control_state & TIOCM_DTR)
391 mcr |= METROUSB_MCR_DTR;
392 if (control_state & TIOCM_RTS)
393 mcr |= METROUSB_MCR_RTS;
394
395 /* Send the command to the usb port. */
396 retval = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
397 METROUSB_SET_REQUEST_TYPE, METROUSB_SET_MODEM_CTRL_REQUEST,
398 control_state, 0, NULL, 0, WDR_TIMEOUT);
399 if (retval < 0)
400 dbg("METRO-USB - %s - set modem ctrl=0x%x failed, error code=%d", __FUNCTION__, mcr, retval);
401
402 return retval;
403}
404
405
406/* ----------------------------------------------------------------------------------------------
407 Description:
408 Shutdown the driver.
409
410 Input:
411 struct usb_serial *: pointer to a usb-serial structure.
412
413 Output:
414 int: Returns true (0) if successful, false otherwise.
415*/
416static void metrousb_shutdown (struct usb_serial *serial)
417{
418 int i = 0;
419
420 dbg("METRO-USB - %s", __FUNCTION__);
421
422 /* Stop reading and writing on all ports. */
423 for (i=0; i < serial->num_ports; ++i) {
424 /* Close any open urbs. */
425 metrousb_cleanup(serial->port[i]);
426
427 /* Free memory. */
428 kfree(usb_get_serial_port_data(serial->port[i]));
429 usb_set_serial_port_data(serial->port[i], NULL);
430
431 dbg("METRO-USB - %s - freed port number=%d", __FUNCTION__, serial->port[i]->number);
432 }
433}
434
435/* ----------------------------------------------------------------------------------------------
436 Description:
437 Startup the driver.
438
439 Input:
440 struct usb_serial *: pointer to a usb-serial structure.
441
442 Output:
443 int: Returns true (0) if successful, false otherwise.
444*/
445static int metrousb_startup(struct usb_serial *serial)
446{
447 struct metrousb_private *metro_priv;
448 struct usb_serial_port *port;
449 int i = 0;
450
451 dbg("METRO-USB - %s", __FUNCTION__);
452
453 /* Loop through the serial ports setting up the private structures.
454 * Currently we only use one port. */
455 for (i = 0; i < serial->num_ports; ++i) {
456 port = serial->port[i];
457
458 /* Declare memory. */
459 metro_priv = (struct metrousb_private *) kmalloc (sizeof(struct metrousb_private), GFP_KERNEL);
460 if (!metro_priv)
461 return -ENOMEM;
462
463 /* Clear memory. */
464 memset (metro_priv, 0x00, sizeof(struct metrousb_private));
465
466 /* Initialize memory. */
467 spin_lock_init(&metro_priv->lock);
468 usb_set_serial_port_data(port, metro_priv);
469
470 dbg("METRO-USB - %s - port number=%d.", __FUNCTION__, port->number);
471 }
472
473 return 0;
474}
475
476/* ----------------------------------------------------------------------------------------------
477 Description:
478 Set the serial port throttle to stop reading from the port.
479
480 Input:
481 struct usb_serial_port *: pointer to a usb_serial_port structure.
482
483 Output:
484 None:
485*/
486static void metrousb_throttle (struct tty_struct *tty)
487{
488 struct usb_serial_port *port = tty->driver_data;
489 struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
490 unsigned long flags = 0;
491
492 dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number);
493
494 /* Set the private information for the port to stop reading data. */
495 spin_lock_irqsave(&metro_priv->lock, flags);
496 metro_priv->throttled = 1;
497 spin_unlock_irqrestore(&metro_priv->lock, flags);
498}
499
500/* ----------------------------------------------------------------------------------------------
501 Description:
502 Get the serial port control line states.
503
504 Input:
505 struct usb_serial_port *: pointer to a usb_serial_port structure.
506 struct file *: pointer to a file structure.
507
508 Output:
509 int: Returns the state of the control lines.
510*/
511static int metrousb_tiocmget (struct tty_struct *tty)
512{
513 unsigned long control_state = 0;
514 struct usb_serial_port *port = tty->driver_data;
515 struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
516 unsigned long flags = 0;
517
518 dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number);
519
520 spin_lock_irqsave(&metro_priv->lock, flags);
521 control_state = metro_priv->control_state;
522 spin_unlock_irqrestore(&metro_priv->lock, flags);
523
524 return control_state;
525}
526
527/* ----------------------------------------------------------------------------------------------
528 Description:
529 Set the serial port control line states.
530
531 Input:
532 struct usb_serial_port *: pointer to a usb_serial_port structure.
533 struct file *: pointer to a file structure.
534 unsigned int: line state to set.
535 unsigned int: line state to clear.
536
537 Output:
538 int: Returns the state of the control lines.
539*/
540static int metrousb_tiocmset (struct tty_struct *tty,
541 unsigned int set, unsigned int clear)
542{
543 struct usb_serial_port *port = tty->driver_data;
544 struct usb_serial *serial = port->serial;
545 struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
546 unsigned long flags = 0;
547 unsigned long control_state = 0;
548
549 dbg("METRO-USB - %s - port number=%d, set=%d, clear=%d", __FUNCTION__, port->number, set, clear);
550
551 spin_lock_irqsave(&metro_priv->lock, flags);
552 control_state = metro_priv->control_state;
553
554 // Set the RTS and DTR values.
555 if (set & TIOCM_RTS)
556 control_state |= TIOCM_RTS;
557 if (set & TIOCM_DTR)
558 control_state |= TIOCM_DTR;
559 if (clear & TIOCM_RTS)
560 control_state &= ~TIOCM_RTS;
561 if (clear & TIOCM_DTR)
562 control_state &= ~TIOCM_DTR;
563
564 metro_priv->control_state = control_state;
565 spin_unlock_irqrestore(&metro_priv->lock, flags);
566 return metrousb_set_modem_ctrl(serial, control_state);
567}
568
569/* ----------------------------------------------------------------------------------------------
570 Description:
571 Set the serial port unthrottle to resume reading from the port.
572
573 Input:
574 struct usb_serial_port *: pointer to a usb_serial_port structure.
575
576 Output:
577 None:
578*/
579static void metrousb_unthrottle (struct tty_struct *tty)
580{
581 struct usb_serial_port *port = tty->driver_data;
582 struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
583 unsigned long flags = 0;
584 int result = 0;
585
586 dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number);
587
588 /* Set the private information for the port to resume reading data. */
589 spin_lock_irqsave(&metro_priv->lock, flags);
590 metro_priv->throttled = 0;
591 spin_unlock_irqrestore(&metro_priv->lock, flags);
592
593 /* Submit the urb to read from the port. */
594 port->interrupt_in_urb->dev = port->serial->dev;
595 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
596 if (result) {
597 dbg("METRO-USB - %s - failed submitting interrupt in urb for port number=%d, error code=%d",
598 __FUNCTION__, port->number, result);
599 }
600}
601
602/* Standard module function. */
603module_init(metrousb_init);
604module_exit(metrousb_exit);
605MODULE_LICENSE("GPL");
606MODULE_AUTHOR( "Philip Nicastro" );
607MODULE_AUTHOR( "Aleksey Babahin <tamerlan311@gmail.com>" );
608MODULE_DESCRIPTION( DRIVER_DESC );
609
610/* Module input parameters */
611module_param(debug, bool, S_IRUGO | S_IWUSR);
612MODULE_PARM_DESC(debug, "Print debug info (bool 1=on, 0=off)");
613
614module_param(vendor, ushort, 0);
615MODULE_PARM_DESC(vendor, "User specified vendor ID (ushort)");
616
617module_param(product, ushort, 0);
618MODULE_PARM_DESC(product, "User specified product ID (ushort)");
619
620
621
622