summary refs log tree commit diff
path: root/drivers/usb
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2006-03-17 17:40:08 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2006-03-20 14:50:03 -0800
commite9a66c64bb7033cb0180d419b2008acf7a141adc (patch)
treef5adde064f836c753ec4ae471540dbf539c22802 /drivers/usb
parentda81817fbd744ce70983f1d3c61841265003c7f4 (diff)
downloadlinux-e9a66c64bb7033cb0180d419b2008acf7a141adc.tar.gz
[PATCH] USB serial: add navman driver
Thanks to Warren Lewis <wlewis@scn.org> for the information needed to
write the driver and for testing it out.

Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/serial/Kconfig7
-rw-r--r--drivers/usb/serial/Makefile1
-rw-r--r--drivers/usb/serial/navman.c157
3 files changed, 165 insertions, 0 deletions
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index be5dc80836c3..5a8a2c91c2b2 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -403,6 +403,13 @@ config USB_SERIAL_MCT_U232
 	  To compile this driver as a module, choose M here: the
 	  module will be called mct_u232.
 
+config USB_SERIAL_NAVMAN
+	tristate "USB Navman GPS device"
+	depends on USB_SERIAL
+	help
+	  To compile this driver as a module, choose M here: the
+	  module will be called navman.
+
 config USB_SERIAL_PL2303
 	tristate "USB Prolific 2303 Single Port Serial Driver"
 	depends on USB_SERIAL
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index f0b04420cea1..f7fe4172efed 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA)		+= keyspan_pda.o
 obj-$(CONFIG_USB_SERIAL_KLSI)			+= kl5kusb105.o
 obj-$(CONFIG_USB_SERIAL_KOBIL_SCT)		+= kobil_sct.o
 obj-$(CONFIG_USB_SERIAL_MCT_U232)		+= mct_u232.o
+obj-$(CONFIG_USB_SERIAL_NAVMAN)			+= navman.o
 obj-$(CONFIG_USB_SERIAL_OMNINET)		+= omninet.o
 obj-$(CONFIG_USB_SERIAL_OPTION)			+= option.o
 obj-$(CONFIG_USB_SERIAL_PL2303)			+= pl2303.o
diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c
new file mode 100644
index 000000000000..7f544081032e
--- /dev/null
+++ b/drivers/usb/serial/navman.c
@@ -0,0 +1,157 @@
+/*
+ * Navman Serial USB driver
+ *
+ * Copyright (C) 2006 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	version 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include "usb-serial.h"
+
+static int debug;
+
+static struct usb_device_id id_table [] = {
+	{ USB_DEVICE(0x0a99, 0x0001) },	/* Talon Technology device */
+	{ },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_driver navman_driver = {
+	.name =		"navman",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table,
+	.no_dynamic_id = 	1,
+};
+
+static void navman_read_int_callback(struct urb *urb, struct pt_regs *regs)
+{
+	struct usb_serial_port *port = urb->context;
+	unsigned char *data = urb->transfer_buffer;
+	struct tty_struct *tty;
+	int result;
+
+	switch (urb->status) {
+	case 0:
+		/* success */
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/* this urb is terminated, clean up */
+		dbg("%s - urb shutting down with status: %d",
+		    __FUNCTION__, urb->status);
+		return;
+	default:
+		dbg("%s - nonzero urb status received: %d",
+		    __FUNCTION__, urb->status);
+		goto exit;
+	}
+
+	usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
+			      urb->actual_length, data);
+
+	tty = port->tty;
+	if (tty && urb->actual_length) {
+		tty_buffer_request_room(tty, urb->actual_length);
+		tty_insert_flip_string(tty, data, urb->actual_length);
+		tty_flip_buffer_push(tty);
+	}
+
+exit:
+	result = usb_submit_urb(urb, GFP_ATOMIC);
+	if (result)
+		dev_err(&urb->dev->dev,
+			"%s - Error %d submitting interrupt urb\n",
+			__FUNCTION__, result);
+}
+
+static int navman_open(struct usb_serial_port *port, struct file *filp)
+{
+	int result = 0;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	if (port->interrupt_in_urb) {
+		dbg("%s - adding interrupt input for treo", __FUNCTION__);
+		result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+		if (result)
+			dev_err(&port->dev,
+				"%s - failed submitting interrupt urb, error %d\n",
+				__FUNCTION__, result);
+	}
+	return result;
+}
+
+static void navman_close(struct usb_serial_port *port, struct file *filp)
+{
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	if (port->interrupt_in_urb)
+		usb_kill_urb(port->interrupt_in_urb);
+}
+
+static int navman_write(struct usb_serial_port *port,
+			const unsigned char *buf, int count)
+{
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	/*
+	 * This device can't write any data, only read from the device
+	 * so we just silently eat all data sent to us and say it was
+	 * successfully sent.
+	 * Evil, I know, but do you have a better idea?
+	 */
+
+	return count;
+}
+
+static struct usb_serial_driver navman_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"navman",
+	},
+	.id_table =		id_table,
+	.num_interrupt_in =	NUM_DONT_CARE,
+	.num_bulk_in =		NUM_DONT_CARE,
+	.num_bulk_out =		NUM_DONT_CARE,
+	.num_ports =		1,
+	.open =			navman_open,
+	.close = 		navman_close,
+	.write = 		navman_write,
+	.read_int_callback =	navman_read_int_callback,
+};
+
+static int __init navman_init(void)
+{
+	int retval;
+
+	retval = usb_serial_register(&navman_device);
+	if (retval)
+		return retval;
+	retval = usb_register(&navman_driver);
+	if (retval)
+		usb_serial_deregister(&navman_device);
+	return retval;
+}
+
+static void __exit navman_exit(void)
+{
+	usb_deregister(&navman_driver);
+	usb_serial_deregister(&navman_device);
+}
+
+module_init(navman_init);
+module_exit(navman_exit);
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");