xref: /openbmc/linux/drivers/usb/serial/navman.c (revision a509a7e4)
1e9a66c64SGreg Kroah-Hartman /*
2e9a66c64SGreg Kroah-Hartman  * Navman Serial USB driver
3e9a66c64SGreg Kroah-Hartman  *
4e9a66c64SGreg Kroah-Hartman  * Copyright (C) 2006 Greg Kroah-Hartman <gregkh@suse.de>
5e9a66c64SGreg Kroah-Hartman  *
6e9a66c64SGreg Kroah-Hartman  *	This program is free software; you can redistribute it and/or
7e9a66c64SGreg Kroah-Hartman  *	modify it under the terms of the GNU General Public License
8e9a66c64SGreg Kroah-Hartman  *	version 2 as published by the Free Software Foundation.
9a5b6f60cSAlan Cox  *
10a5b6f60cSAlan Cox  * TODO:
11a5b6f60cSAlan Cox  *	Add termios method that uses copy_hw but also kills all echo
12a5b6f60cSAlan Cox  *	flags as the navman is rx only so cannot echo.
13e9a66c64SGreg Kroah-Hartman  */
14e9a66c64SGreg Kroah-Hartman 
15e9a66c64SGreg Kroah-Hartman #include <linux/kernel.h>
16e9a66c64SGreg Kroah-Hartman #include <linux/init.h>
17e9a66c64SGreg Kroah-Hartman #include <linux/tty.h>
18e9a66c64SGreg Kroah-Hartman #include <linux/tty_flip.h>
19e9a66c64SGreg Kroah-Hartman #include <linux/module.h>
20e9a66c64SGreg Kroah-Hartman #include <linux/usb.h>
21a969888cSGreg Kroah-Hartman #include <linux/usb/serial.h>
22e9a66c64SGreg Kroah-Hartman 
23e9a66c64SGreg Kroah-Hartman static int debug;
24e9a66c64SGreg Kroah-Hartman 
25e9a66c64SGreg Kroah-Hartman static struct usb_device_id id_table [] = {
26e9a66c64SGreg Kroah-Hartman 	{ USB_DEVICE(0x0a99, 0x0001) },	/* Talon Technology device */
27e9a66c64SGreg Kroah-Hartman 	{ },
28e9a66c64SGreg Kroah-Hartman };
29e9a66c64SGreg Kroah-Hartman MODULE_DEVICE_TABLE(usb, id_table);
30e9a66c64SGreg Kroah-Hartman 
31e9a66c64SGreg Kroah-Hartman static struct usb_driver navman_driver = {
32e9a66c64SGreg Kroah-Hartman 	.name =		"navman",
33e9a66c64SGreg Kroah-Hartman 	.probe =	usb_serial_probe,
34e9a66c64SGreg Kroah-Hartman 	.disconnect =	usb_serial_disconnect,
35e9a66c64SGreg Kroah-Hartman 	.id_table =	id_table,
36e9a66c64SGreg Kroah-Hartman 	.no_dynamic_id = 	1,
37e9a66c64SGreg Kroah-Hartman };
38e9a66c64SGreg Kroah-Hartman 
397d12e780SDavid Howells static void navman_read_int_callback(struct urb *urb)
40e9a66c64SGreg Kroah-Hartman {
41e9a66c64SGreg Kroah-Hartman 	struct usb_serial_port *port = urb->context;
42e9a66c64SGreg Kroah-Hartman 	unsigned char *data = urb->transfer_buffer;
43e9a66c64SGreg Kroah-Hartman 	struct tty_struct *tty;
449965d612SGreg Kroah-Hartman 	int status = urb->status;
45e9a66c64SGreg Kroah-Hartman 	int result;
46e9a66c64SGreg Kroah-Hartman 
479965d612SGreg Kroah-Hartman 	switch (status) {
48e9a66c64SGreg Kroah-Hartman 	case 0:
49e9a66c64SGreg Kroah-Hartman 		/* success */
50e9a66c64SGreg Kroah-Hartman 		break;
51e9a66c64SGreg Kroah-Hartman 	case -ECONNRESET:
52e9a66c64SGreg Kroah-Hartman 	case -ENOENT:
53e9a66c64SGreg Kroah-Hartman 	case -ESHUTDOWN:
54e9a66c64SGreg Kroah-Hartman 		/* this urb is terminated, clean up */
55e9a66c64SGreg Kroah-Hartman 		dbg("%s - urb shutting down with status: %d",
56441b62c1SHarvey Harrison 		    __func__, status);
57e9a66c64SGreg Kroah-Hartman 		return;
58e9a66c64SGreg Kroah-Hartman 	default:
59e9a66c64SGreg Kroah-Hartman 		dbg("%s - nonzero urb status received: %d",
60441b62c1SHarvey Harrison 		    __func__, status);
61e9a66c64SGreg Kroah-Hartman 		goto exit;
62e9a66c64SGreg Kroah-Hartman 	}
63e9a66c64SGreg Kroah-Hartman 
64441b62c1SHarvey Harrison 	usb_serial_debug_data(debug, &port->dev, __func__,
65e9a66c64SGreg Kroah-Hartman 			      urb->actual_length, data);
66e9a66c64SGreg Kroah-Hartman 
674a90f09bSAlan Cox 	tty = tty_port_tty_get(&port->port);
68e9a66c64SGreg Kroah-Hartman 	if (tty && urb->actual_length) {
69e9a66c64SGreg Kroah-Hartman 		tty_buffer_request_room(tty, urb->actual_length);
70e9a66c64SGreg Kroah-Hartman 		tty_insert_flip_string(tty, data, urb->actual_length);
71e9a66c64SGreg Kroah-Hartman 		tty_flip_buffer_push(tty);
72e9a66c64SGreg Kroah-Hartman 	}
734a90f09bSAlan Cox 	tty_kref_put(tty);
74e9a66c64SGreg Kroah-Hartman 
75e9a66c64SGreg Kroah-Hartman exit:
76e9a66c64SGreg Kroah-Hartman 	result = usb_submit_urb(urb, GFP_ATOMIC);
77e9a66c64SGreg Kroah-Hartman 	if (result)
78e9a66c64SGreg Kroah-Hartman 		dev_err(&urb->dev->dev,
79e9a66c64SGreg Kroah-Hartman 			"%s - Error %d submitting interrupt urb\n",
80441b62c1SHarvey Harrison 			__func__, result);
81e9a66c64SGreg Kroah-Hartman }
82e9a66c64SGreg Kroah-Hartman 
83a509a7e4SAlan Cox static int navman_open(struct tty_struct *tty, struct usb_serial_port *port)
84e9a66c64SGreg Kroah-Hartman {
85e9a66c64SGreg Kroah-Hartman 	int result = 0;
86e9a66c64SGreg Kroah-Hartman 
87441b62c1SHarvey Harrison 	dbg("%s - port %d", __func__, port->number);
88e9a66c64SGreg Kroah-Hartman 
89e9a66c64SGreg Kroah-Hartman 	if (port->interrupt_in_urb) {
90441b62c1SHarvey Harrison 		dbg("%s - adding interrupt input for treo", __func__);
91e9a66c64SGreg Kroah-Hartman 		result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
92e9a66c64SGreg Kroah-Hartman 		if (result)
93e9a66c64SGreg Kroah-Hartman 			dev_err(&port->dev,
94e9a66c64SGreg Kroah-Hartman 				"%s - failed submitting interrupt urb, error %d\n",
95441b62c1SHarvey Harrison 				__func__, result);
96e9a66c64SGreg Kroah-Hartman 	}
97e9a66c64SGreg Kroah-Hartman 	return result;
98e9a66c64SGreg Kroah-Hartman }
99e9a66c64SGreg Kroah-Hartman 
100335f8514SAlan Cox static void navman_close(struct usb_serial_port *port)
101e9a66c64SGreg Kroah-Hartman {
102441b62c1SHarvey Harrison 	dbg("%s - port %d", __func__, port->number);
103e9a66c64SGreg Kroah-Hartman 
104e9a66c64SGreg Kroah-Hartman 	usb_kill_urb(port->interrupt_in_urb);
105e9a66c64SGreg Kroah-Hartman }
106e9a66c64SGreg Kroah-Hartman 
10795da310eSAlan Cox static int navman_write(struct tty_struct *tty, struct usb_serial_port *port,
108e9a66c64SGreg Kroah-Hartman 			const unsigned char *buf, int count)
109e9a66c64SGreg Kroah-Hartman {
110441b62c1SHarvey Harrison 	dbg("%s - port %d", __func__, port->number);
111e9a66c64SGreg Kroah-Hartman 
112e9a66c64SGreg Kroah-Hartman 	/*
113e9a66c64SGreg Kroah-Hartman 	 * This device can't write any data, only read from the device
114e9a66c64SGreg Kroah-Hartman 	 */
115a5b6f60cSAlan Cox 	return -EOPNOTSUPP;
116e9a66c64SGreg Kroah-Hartman }
117e9a66c64SGreg Kroah-Hartman 
118e9a66c64SGreg Kroah-Hartman static struct usb_serial_driver navman_device = {
119e9a66c64SGreg Kroah-Hartman 	.driver = {
120e9a66c64SGreg Kroah-Hartman 		.owner =	THIS_MODULE,
121e9a66c64SGreg Kroah-Hartman 		.name =		"navman",
122e9a66c64SGreg Kroah-Hartman 	},
123e9a66c64SGreg Kroah-Hartman 	.id_table =		id_table,
124d9b1b787SJohannes Hölzl 	.usb_driver =		&navman_driver,
125e9a66c64SGreg Kroah-Hartman 	.num_ports =		1,
126e9a66c64SGreg Kroah-Hartman 	.open =			navman_open,
127e9a66c64SGreg Kroah-Hartman 	.close = 		navman_close,
128e9a66c64SGreg Kroah-Hartman 	.write = 		navman_write,
129e9a66c64SGreg Kroah-Hartman 	.read_int_callback =	navman_read_int_callback,
130e9a66c64SGreg Kroah-Hartman };
131e9a66c64SGreg Kroah-Hartman 
132e9a66c64SGreg Kroah-Hartman static int __init navman_init(void)
133e9a66c64SGreg Kroah-Hartman {
134e9a66c64SGreg Kroah-Hartman 	int retval;
135e9a66c64SGreg Kroah-Hartman 
136e9a66c64SGreg Kroah-Hartman 	retval = usb_serial_register(&navman_device);
137e9a66c64SGreg Kroah-Hartman 	if (retval)
138e9a66c64SGreg Kroah-Hartman 		return retval;
139e9a66c64SGreg Kroah-Hartman 	retval = usb_register(&navman_driver);
140e9a66c64SGreg Kroah-Hartman 	if (retval)
141e9a66c64SGreg Kroah-Hartman 		usb_serial_deregister(&navman_device);
142e9a66c64SGreg Kroah-Hartman 	return retval;
143e9a66c64SGreg Kroah-Hartman }
144e9a66c64SGreg Kroah-Hartman 
145e9a66c64SGreg Kroah-Hartman static void __exit navman_exit(void)
146e9a66c64SGreg Kroah-Hartman {
147e9a66c64SGreg Kroah-Hartman 	usb_deregister(&navman_driver);
148e9a66c64SGreg Kroah-Hartman 	usb_serial_deregister(&navman_device);
149e9a66c64SGreg Kroah-Hartman }
150e9a66c64SGreg Kroah-Hartman 
151e9a66c64SGreg Kroah-Hartman module_init(navman_init);
152e9a66c64SGreg Kroah-Hartman module_exit(navman_exit);
153e9a66c64SGreg Kroah-Hartman MODULE_LICENSE("GPL");
154e9a66c64SGreg Kroah-Hartman 
155e9a66c64SGreg Kroah-Hartman module_param(debug, bool, S_IRUGO | S_IWUSR);
156e9a66c64SGreg Kroah-Hartman MODULE_PARM_DESC(debug, "Debug enabled or not");
157