blob: d0c47e1dab1009a02761f866e76e44e740bc0e24 [file] [log] [blame]
Aleksey Babahin43d186f2012-03-08 13:18:43 -08001/*
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
Greg Kroah-Hartmanfdac0f62012-03-08 13:37:32 -080011 2. Install the metro-usb.ko module with: # insmod metro-usb.ko
Aleksey Babahin43d186f2012-03-08 13:18:43 -080012
13 Some of this code is credited to Linux USB open source files that are distributed with Linux.
14
15 Copyright: 2007 Metrologic Instruments. All rights reserved.
16 Copyright: 2011 Azimut Ltd. <http://azimutrzn.ru/>
17 Requirements: gedit.exe, notepad.exe
18
19 Revision History:
20
21 Date: Developer: Revisions:
22 ------------------------------------------------------------------------------
23 1/30/2007 Philip Nicastro Initial release. (v1.0.0.0)
24 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.
25 2/27/2007 Philip Nicastro Released. (v1.1.0.0)
26 10/07/2011 Aleksey Babahin Update for new kernel (tested on 2.6.38)
27 Add unidirection mode support
28
29
30*/
31
32#include <linux/kernel.h>
33#include <linux/init.h>
34#include <linux/tty.h>
35#include <linux/module.h>
36#include <linux/usb.h>
37#include <linux/errno.h>
38#include <linux/slab.h>
39#include <linux/tty_driver.h>
40#include <linux/tty_flip.h>
41#include <linux/moduleparam.h>
42#include <linux/spinlock.h>
43#include <asm/uaccess.h>
44#include <linux/errno.h>
45#include "metro-usb.h"
46#include <linux/usb/serial.h>
47
48/* Version Information */
49#define DRIVER_VERSION "v1.2.0.0"
50#define DRIVER_DESC "Metrologic Instruments Inc. - USB-POS driver"
51
52/* Device table list. */
53static struct usb_device_id id_table [] = {
54 { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID) },
55 { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_UNI) },
Aleksey Babahin43d186f2012-03-08 13:18:43 -080056 { }, /* Terminating entry. */
57};
58MODULE_DEVICE_TABLE(usb, id_table);
59
60/* Input parameter constants. */
Greg Kroah-Hartmanfdac0f62012-03-08 13:37:32 -080061static bool debug;
Aleksey Babahin43d186f2012-03-08 13:18:43 -080062
63/* Function prototypes. */
64static void metrousb_cleanup (struct usb_serial_port *port);
65static void metrousb_close (struct usb_serial_port *port);
66static int metrousb_open (struct tty_struct *tty, struct usb_serial_port *port);
67static void metrousb_read_int_callback (struct urb *urb);
68static void metrousb_shutdown (struct usb_serial *serial);
69static int metrousb_startup (struct usb_serial *serial);
70static void metrousb_throttle(struct tty_struct *tty);
71static int metrousb_tiocmget(struct tty_struct *tty);
72static int metrousb_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear);
73static void metrousb_unthrottle(struct tty_struct *tty);
74
75/* Driver structure. */
76static struct usb_driver metrousb_driver = {
77 .name = "metro-usb",
78 .probe = usb_serial_probe,
79 .disconnect = usb_serial_disconnect,
80 .id_table = id_table
81};
82
83/* Device structure. */
84static struct usb_serial_driver metrousb_device = {
85 .driver = {
86 .owner = THIS_MODULE,
87 .name = "metro-usb",
88 },
89 .description = "Metrologic USB to serial converter.",
90 .id_table = id_table,
Aleksey Babahin43d186f2012-03-08 13:18:43 -080091 .num_ports = 1,
92 .open = metrousb_open,
93 .close = metrousb_close,
94 .read_int_callback = metrousb_read_int_callback,
95 .attach = metrousb_startup,
96 .release = metrousb_shutdown,
97 .throttle = metrousb_throttle,
98 .unthrottle = metrousb_unthrottle,
99 .tiocmget = metrousb_tiocmget,
100 .tiocmset = metrousb_tiocmset,
101};
102
Greg Kroah-Hartman11a4f402012-03-08 13:33:04 -0800103static struct usb_serial_driver * const serial_drivers[] = {
104 &metrousb_device,
105 NULL,
106};
107
Aleksey Babahin43d186f2012-03-08 13:18:43 -0800108/* ----------------------------------------------------------------------------------------------
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{
Greg Kroah-Hartman11a4f402012-03-08 13:33:04 -0800166 usb_serial_deregister_drivers(&metrousb_driver, serial_drivers);
Aleksey Babahin43d186f2012-03-08 13:18:43 -0800167}
168
169/* ----------------------------------------------------------------------------------------------
170 Description:
171 Driver initialization.
172
173 Input:
174 None:
175
176 Output:
177 int: Returns true (0) if successful, false otherwise.
178*/
179static int __init metrousb_init(void)
180{
181 int retval = 0;
Aleksey Babahin43d186f2012-03-08 13:18:43 -0800182
183 dbg("METRO-USB - %s", __FUNCTION__);
184
Aleksey Babahin43d186f2012-03-08 13:18:43 -0800185 /* Register the devices. */
Greg Kroah-Hartman11a4f402012-03-08 13:33:04 -0800186 retval = usb_serial_register_drivers(&metrousb_driver, serial_drivers);
Aleksey Babahin43d186f2012-03-08 13:18:43 -0800187 if (retval)
188 return retval;
189
Aleksey Babahin43d186f2012-03-08 13:18:43 -0800190 printk(KERN_INFO DRIVER_DESC " : " DRIVER_VERSION);
191
192 return retval;
193}
194
195/* ----------------------------------------------------------------------------------------------
196 Description:
197 Open the drivers serial port.
198
199 Input:
200 struct usb_serial_port *: pointer to a usb_serial_port structure.
201 struct file *: pointer to a file structure.
202
203 Output:
204 int: Returns true (0) if successful, false otherwise.
205*/
206static int metrousb_open (struct tty_struct *tty, struct usb_serial_port *port)
207{
208 struct usb_serial *serial = port->serial;
209 struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
210 unsigned long flags = 0;
211 int result = 0;
212
213 dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number);
214
215 /* Make sure the urb is initialized. */
216 if (!port->interrupt_in_urb) {
217 dbg("METRO-USB - %s - interrupt urb not initialized for port number=%d", __FUNCTION__, port->number);
218 return -ENODEV;
219 }
220
221 /* Set the private data information for the port. */
222 spin_lock_irqsave(&metro_priv->lock, flags);
223 metro_priv->control_state = 0;
224 metro_priv->throttled = 0;
225 spin_unlock_irqrestore(&metro_priv->lock, flags);
226
227 /*
228 * Force low_latency on so that our tty_push actually forces the data
229 * through, otherwise it is scheduled, and with high data rates (like
230 * with OHCI) data can get lost.
231 */
232 if (tty) {
233 tty->low_latency = 1;
234 }
235
236 /* Clear the urb pipe. */
237 usb_clear_halt(serial->dev, port->interrupt_in_urb->pipe);
238
239 /* Start reading from the device */
240 usb_fill_int_urb (port->interrupt_in_urb, serial->dev,
241 usb_rcvintpipe (serial->dev, port->interrupt_in_endpointAddress),
242 port->interrupt_in_urb->transfer_buffer,
243 port->interrupt_in_urb->transfer_buffer_length,
244 metrousb_read_int_callback, port, 1);
245 result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
246
247 if (result) {
248 dbg("METRO-USB - %s - failed submitting interrupt in urb for port number=%d, error code=%d"
249 , __FUNCTION__, port->number, result);
250 goto exit;
251 }
252
253 dbg("METRO-USB - %s - port open for port number=%d", __FUNCTION__, port->number);
254exit:
255 return result;
256}
257
258/* ----------------------------------------------------------------------------------------------
259 Description:
260 Read the port from the read interrupt.
261
262 Input:
263 struct urb *: urb structure to get data.
264 struct pt_regs *: pt_regs structure.
265
266 Output:
267 None:
268*/
269static void metrousb_read_int_callback (struct urb *urb)
270{
271 struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
272 struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
273 struct tty_struct *tty;
274 unsigned char *data = urb->transfer_buffer;
275 int throttled = 0;
276 int result = 0;
277 unsigned long flags = 0;
278
279 dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number);
280
281 switch (urb->status) {
282 case 0:
283 /* Success status, read from the port. */
284 break;
285 case -ECONNRESET:
286 case -ENOENT:
287 case -ESHUTDOWN:
288 /* urb has been terminated. */
289 dbg("METRO-USB - %s - urb shutting down, port number=%d, error code=%d",
290 __FUNCTION__, port->number, result);
291 return;
292 default:
293 dbg("METRO-USB - %s - non-zero urb received, port number=%d, error code=%d",
294 __FUNCTION__, port->number, result);
295 goto exit;
296 }
297
298
299 /* Set the data read from the usb port into the serial port buffer. */
300 tty = tty_port_tty_get(&port->port);
301 if (!tty) {
302 dbg("%s - bad tty pointer - exiting", __func__);
303 return;
304 }
305
306 if (tty && urb->actual_length) {
307 // Loop through the data copying each byte to the tty layer.
308 tty_insert_flip_string(tty, data, urb->actual_length);
309
310 // Force the data to the tty layer.
311 tty_flip_buffer_push(tty);
312 }
313 tty_kref_put(tty);
314
315 /* Set any port variables. */
316 spin_lock_irqsave(&metro_priv->lock, flags);
317 throttled = metro_priv->throttled;
318 spin_unlock_irqrestore(&metro_priv->lock, flags);
319
320 /* Continue trying to read if set. */
321 if (!throttled) {
322 usb_fill_int_urb (port->interrupt_in_urb, port->serial->dev,
323 usb_rcvintpipe (port->serial->dev, port->interrupt_in_endpointAddress),
324 port->interrupt_in_urb->transfer_buffer,
325 port->interrupt_in_urb->transfer_buffer_length,
326 metrousb_read_int_callback, port, 1);
327
328 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
329
330 if (result) {
331 dbg("METRO-USB - %s - failed submitting interrupt in urb for port number=%d, error code=%d",
332 __FUNCTION__, port->number, result);
333 }
334 }
335 return;
336
337exit:
338 /* Try to resubmit the urb. */
339 result = usb_submit_urb (urb, GFP_ATOMIC);
340 if (result) {
341 dbg("METRO-USB - %s - failed submitting interrupt in urb for port number=%d, error code=%d",
342 __FUNCTION__, port->number, result);
343 }
344}
345
346/* ----------------------------------------------------------------------------------------------
347 Description:
348 Set the modem control state for the entered serial port.
349
350 Input:
351 struct usb_serial_port *: pointer to a usb_serial_port structure.
352 unsigned int: control state value to set.
353
354 Output:
355 int: Returns true (0) if successful, false otherwise.
356*/
357static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int control_state)
358{
359 int retval = 0;
360 unsigned char mcr = METROUSB_MCR_NONE;
361
362 dbg("METRO-USB - %s - control state=%d", __FUNCTION__, control_state);
363
364 /* Set the modem control value. */
365 if (control_state & TIOCM_DTR)
366 mcr |= METROUSB_MCR_DTR;
367 if (control_state & TIOCM_RTS)
368 mcr |= METROUSB_MCR_RTS;
369
370 /* Send the command to the usb port. */
371 retval = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
372 METROUSB_SET_REQUEST_TYPE, METROUSB_SET_MODEM_CTRL_REQUEST,
373 control_state, 0, NULL, 0, WDR_TIMEOUT);
374 if (retval < 0)
375 dbg("METRO-USB - %s - set modem ctrl=0x%x failed, error code=%d", __FUNCTION__, mcr, retval);
376
377 return retval;
378}
379
380
381/* ----------------------------------------------------------------------------------------------
382 Description:
383 Shutdown the driver.
384
385 Input:
386 struct usb_serial *: pointer to a usb-serial structure.
387
388 Output:
389 int: Returns true (0) if successful, false otherwise.
390*/
391static void metrousb_shutdown (struct usb_serial *serial)
392{
393 int i = 0;
394
395 dbg("METRO-USB - %s", __FUNCTION__);
396
397 /* Stop reading and writing on all ports. */
398 for (i=0; i < serial->num_ports; ++i) {
399 /* Close any open urbs. */
400 metrousb_cleanup(serial->port[i]);
401
402 /* Free memory. */
403 kfree(usb_get_serial_port_data(serial->port[i]));
404 usb_set_serial_port_data(serial->port[i], NULL);
405
406 dbg("METRO-USB - %s - freed port number=%d", __FUNCTION__, serial->port[i]->number);
407 }
408}
409
410/* ----------------------------------------------------------------------------------------------
411 Description:
412 Startup the driver.
413
414 Input:
415 struct usb_serial *: pointer to a usb-serial structure.
416
417 Output:
418 int: Returns true (0) if successful, false otherwise.
419*/
420static int metrousb_startup(struct usb_serial *serial)
421{
422 struct metrousb_private *metro_priv;
423 struct usb_serial_port *port;
424 int i = 0;
425
426 dbg("METRO-USB - %s", __FUNCTION__);
427
428 /* Loop through the serial ports setting up the private structures.
429 * Currently we only use one port. */
430 for (i = 0; i < serial->num_ports; ++i) {
431 port = serial->port[i];
432
433 /* Declare memory. */
434 metro_priv = (struct metrousb_private *) kmalloc (sizeof(struct metrousb_private), GFP_KERNEL);
435 if (!metro_priv)
436 return -ENOMEM;
437
438 /* Clear memory. */
439 memset (metro_priv, 0x00, sizeof(struct metrousb_private));
440
441 /* Initialize memory. */
442 spin_lock_init(&metro_priv->lock);
443 usb_set_serial_port_data(port, metro_priv);
444
445 dbg("METRO-USB - %s - port number=%d.", __FUNCTION__, port->number);
446 }
447
448 return 0;
449}
450
451/* ----------------------------------------------------------------------------------------------
452 Description:
453 Set the serial port throttle to stop reading from the port.
454
455 Input:
456 struct usb_serial_port *: pointer to a usb_serial_port structure.
457
458 Output:
459 None:
460*/
461static void metrousb_throttle (struct tty_struct *tty)
462{
463 struct usb_serial_port *port = tty->driver_data;
464 struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
465 unsigned long flags = 0;
466
467 dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number);
468
469 /* Set the private information for the port to stop reading data. */
470 spin_lock_irqsave(&metro_priv->lock, flags);
471 metro_priv->throttled = 1;
472 spin_unlock_irqrestore(&metro_priv->lock, flags);
473}
474
475/* ----------------------------------------------------------------------------------------------
476 Description:
477 Get the serial port control line states.
478
479 Input:
480 struct usb_serial_port *: pointer to a usb_serial_port structure.
481 struct file *: pointer to a file structure.
482
483 Output:
484 int: Returns the state of the control lines.
485*/
486static int metrousb_tiocmget (struct tty_struct *tty)
487{
488 unsigned long control_state = 0;
489 struct usb_serial_port *port = tty->driver_data;
490 struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
491 unsigned long flags = 0;
492
493 dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number);
494
495 spin_lock_irqsave(&metro_priv->lock, flags);
496 control_state = metro_priv->control_state;
497 spin_unlock_irqrestore(&metro_priv->lock, flags);
498
499 return control_state;
500}
501
502/* ----------------------------------------------------------------------------------------------
503 Description:
504 Set the serial port control line states.
505
506 Input:
507 struct usb_serial_port *: pointer to a usb_serial_port structure.
508 struct file *: pointer to a file structure.
509 unsigned int: line state to set.
510 unsigned int: line state to clear.
511
512 Output:
513 int: Returns the state of the control lines.
514*/
515static int metrousb_tiocmset (struct tty_struct *tty,
516 unsigned int set, unsigned int clear)
517{
518 struct usb_serial_port *port = tty->driver_data;
519 struct usb_serial *serial = port->serial;
520 struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
521 unsigned long flags = 0;
522 unsigned long control_state = 0;
523
524 dbg("METRO-USB - %s - port number=%d, set=%d, clear=%d", __FUNCTION__, port->number, set, clear);
525
526 spin_lock_irqsave(&metro_priv->lock, flags);
527 control_state = metro_priv->control_state;
528
529 // Set the RTS and DTR values.
530 if (set & TIOCM_RTS)
531 control_state |= TIOCM_RTS;
532 if (set & TIOCM_DTR)
533 control_state |= TIOCM_DTR;
534 if (clear & TIOCM_RTS)
535 control_state &= ~TIOCM_RTS;
536 if (clear & TIOCM_DTR)
537 control_state &= ~TIOCM_DTR;
538
539 metro_priv->control_state = control_state;
540 spin_unlock_irqrestore(&metro_priv->lock, flags);
541 return metrousb_set_modem_ctrl(serial, control_state);
542}
543
544/* ----------------------------------------------------------------------------------------------
545 Description:
546 Set the serial port unthrottle to resume reading from the port.
547
548 Input:
549 struct usb_serial_port *: pointer to a usb_serial_port structure.
550
551 Output:
552 None:
553*/
554static void metrousb_unthrottle (struct tty_struct *tty)
555{
556 struct usb_serial_port *port = tty->driver_data;
557 struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
558 unsigned long flags = 0;
559 int result = 0;
560
561 dbg("METRO-USB - %s - port number=%d", __FUNCTION__, port->number);
562
563 /* Set the private information for the port to resume reading data. */
564 spin_lock_irqsave(&metro_priv->lock, flags);
565 metro_priv->throttled = 0;
566 spin_unlock_irqrestore(&metro_priv->lock, flags);
567
568 /* Submit the urb to read from the port. */
569 port->interrupt_in_urb->dev = port->serial->dev;
570 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
571 if (result) {
572 dbg("METRO-USB - %s - failed submitting interrupt in urb for port number=%d, error code=%d",
573 __FUNCTION__, port->number, result);
574 }
575}
576
577/* Standard module function. */
578module_init(metrousb_init);
579module_exit(metrousb_exit);
580MODULE_LICENSE("GPL");
581MODULE_AUTHOR( "Philip Nicastro" );
582MODULE_AUTHOR( "Aleksey Babahin <tamerlan311@gmail.com>" );
583MODULE_DESCRIPTION( DRIVER_DESC );
584
585/* Module input parameters */
586module_param(debug, bool, S_IRUGO | S_IWUSR);
587MODULE_PARM_DESC(debug, "Print debug info (bool 1=on, 0=off)");