All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kevin Lloyd <klloyd@sierrawireless.com>
To: gregkh@suse.de
Cc: linux-kernel@vger.kernel.org, linux@sierrawireless.com,
	linux-usb@vger.kernel.org, linux-usb-devel@lists.sourceforge.net
Subject: [PATCH] usb-serial: Sierra driver - add devices and update dtr
Date: Thu, 10 Jan 2008 11:11:04 -0800	[thread overview]
Message-ID: <1199992265.9266.19.camel@linux-z60t> (raw)

From: Kevin Lloyd <linux@sierrawireless.com>

This patch is targeted for the 2.6.24-rc7 kernel.

The following improvements were made:
 - Added new product support: MC5725, AC 880 U, MP 3G (UMTS & CDMA)
 - Fixed control line issue where asserting DTR on ep5 would close ep2
 - Added support for calc_num_ports (will help support future composite devices)

This also covers the devices added by j@twu.net and agilmore@wirelessbeehive.com since their patches were not committed to the 2.6.23-rc7 kernel.

Signed-off-by: Kevin Lloyd <linux@sierrawireless.com>
---

--- /home/shared/kernels/linux-2.6.24-rc7-final/drivers/usb/serial/sierra.c.orig	2008-01-09 17:37:40.000000000 -0800
+++ /home/shared/kernels/linux-2.6.24-rc7-final/drivers/usb/serial/sierra.c	2008-01-10 11:08:57.000000000 -0800
@@ -1,7 +1,7 @@
 /*
   USB Driver for Sierra Wireless
 
-  Copyright (C) 2006, 2007  Kevin Lloyd <linux@sierrawireless.com>
+  Copyright (C) 2008  Kevin Lloyd <linux@sierrawireless.com>
 
   IMPORTANT DISCLAIMER: This driver is not commercially supported by
   Sierra Wireless. Use at your own risk.
@@ -14,7 +14,7 @@
   Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org>
 */
 
-#define DRIVER_VERSION "v.1.2.5b"
+#define DRIVER_VERSION "v.1.2.7"
 #define DRIVER_AUTHOR "Kevin Lloyd <linux@sierrawireless.com>"
 #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
 
@@ -26,10 +26,12 @@
 #include <linux/module.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
+#include <linux/usb/ch9.h>
 
+#define SWIMS_USB_REQUEST_SetPower	0x00
+#define SWIMS_USB_REQUEST_SetNmea	0x07
 #define SWIMS_USB_REQUEST_SetMode	0x0B
-#define SWIMS_USB_REQUEST_TYPE_SetMode	0x40
-#define SWIMS_USB_INDEX_SetMode		0x0000
+#define SWIMS_USB_REQUEST_TYPE_VSC_SET	0x40
 #define SWIMS_SET_MODE_Modem		0x0001
 
 /* per port private data */
@@ -38,6 +40,8 @@
 #define IN_BUFLEN	4096
 
 static int debug;
+static int nmea = 0;
+static int truinstall = 1;
 
 enum devicetype {
 	DEVICE_3_PORT =		0,
@@ -50,48 +54,90 @@ static int sierra_set_power_state(struct
 	int result;
 	dev_dbg(&udev->dev, "%s", "SET POWER STATE");
 	result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-			0x00,			/* __u8 request      */
-			0x40,			/* __u8 request type */
-			swiState,		/* __u16 value       */
-			0,			/* __u16 index       */
-			NULL,			/* void *data        */
-			0,			/* __u16 size 	     */
-			USB_CTRL_SET_TIMEOUT);	/* int timeout 	     */
+			SWIMS_USB_REQUEST_SetPower,	/* __u8 request      */
+			SWIMS_USB_REQUEST_TYPE_VSC_SET,	/* __u8 request type */
+			swiState,			/* __u16 value       */
+			0,				/* __u16 index       */
+			NULL,				/* void *data        */
+			0,				/* __u16 size 	     */
+			USB_CTRL_SET_TIMEOUT);		/* int timeout 	     */
 	return result;
 }
 
-static int sierra_set_ms_mode(struct usb_device *udev, __u16 eSocMode)
+static int sierra_set_ms_mode(struct usb_device *udev, __u16 eSWocMode)
 {
 	int result;
 	dev_dbg(&udev->dev, "%s", "DEVICE MODE SWITCH");
 	result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
 			SWIMS_USB_REQUEST_SetMode,	/* __u8 request      */
-			SWIMS_USB_REQUEST_TYPE_SetMode,	/* __u8 request type */
-			eSocMode,			/* __u16 value       */
-			SWIMS_USB_INDEX_SetMode,	/* __u16 index       */
+			SWIMS_USB_REQUEST_TYPE_VSC_SET,	/* __u8 request type */
+			eSWocMode,			/* __u16 value       */
+			0x0000,				/* __u16 index       */
 			NULL,				/* void *data        */
 			0,				/* __u16 size 	     */
 			USB_CTRL_SET_TIMEOUT);		/* int timeout       */
 	return result;
 }
 
-static int sierra_probe(struct usb_interface *iface,
-			const struct usb_device_id *id)
+int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable)
 {
 	int result;
+	dev_dbg(&udev->dev, "%s", "NMEA Enable sent");
+	result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+			SWIMS_USB_REQUEST_SetNmea,	/* __u8 request      */
+			SWIMS_USB_REQUEST_TYPE_VSC_SET,	/* __u8 request type */
+			enable,				/* __u16 value       */
+			0x0000,				/* __u16 index       */
+			NULL,				/* void *data        */
+			0,				/* __u16 size 	     */
+			USB_CTRL_SET_TIMEOUT);		/* int timeout       */
+	return result;
+}
+
+static int sierra_calc_num_ports(struct usb_serial *serial)
+{
+	int result;
+	int *num_ports = usb_get_serial_data(serial);
+
+	result = *num_ports;
+
+	if (result) {
+		kfree(num_ports);
+		usb_set_serial_data(serial, NULL);
+	}
+
+	return result;
+}
+
+static int sierra_probe(struct usb_serial *serial,
+	const struct usb_device_id *id)
+{
+	int result = 0;
 	struct usb_device *udev;
+	int *num_ports;
+	num_ports = kmalloc(sizeof(*num_ports), GFP_KERNEL);
 
-	udev = usb_get_dev(interface_to_usbdev(iface));
+	udev = serial->dev;
 
 	/* Check if in installer mode */
-	if (id->driver_info == DEVICE_INSTALLER) {
-		dev_dbg(&udev->dev, "%s", "FOUND DEVICE(SW)\n");
+	if (truinstall && id->driver_info == DEVICE_INSTALLER) {
+		dev_dbg(&udev->dev, "%s", "FOUND TRU-INSTALL DEVICE(SW)\n");
 		result = sierra_set_ms_mode(udev, SWIMS_SET_MODE_Modem);
 		/*We do not want to bind to the device when in installer mode*/
 		return -EIO;
-	}
+	} else if (id->driver_info == DEVICE_1_PORT)
+		*num_ports = 1;
+	else if (serial->interface->cur_altsetting->desc.bInterfaceNumber == 0x99)
+		*num_ports = 0;
+	else
+		*num_ports = 3;
+	/*
+	 * save off our num_ports info so that we can use it in the
+	 * calc_num_ports callback
+	 */
+	usb_set_serial_data(serial, (void *)num_ports);
 
-	return usb_serial_probe(iface, id);
+	return result;
 }
 
 static struct usb_device_id id_table [] = {
@@ -100,9 +146,11 @@ static struct usb_device_id id_table [] 
 	{ USB_DEVICE(0x1199, 0x0218) },	/* Sierra Wireless MC5720 */
 	{ USB_DEVICE(0x0f30, 0x1b1d) },	/* Sierra Wireless MC5720 */
 	{ USB_DEVICE(0x1199, 0x0020) },	/* Sierra Wireless MC5725 */
+	{ USB_DEVICE(0x1199, 0x0220) },	/* Sierra Wireless MC5725 */
 	{ USB_DEVICE(0x1199, 0x0019) },	/* Sierra Wireless AirCard 595 */
 	{ USB_DEVICE(0x1199, 0x0021) },	/* Sierra Wireless AirCard 597E */
 	{ USB_DEVICE(0x1199, 0x0120) },	/* Sierra Wireless USB Dongle 595U */
+	{ USB_DEVICE(0x1199, 0x0023) },	/* Sierra Wireless AirCard */
 
 	{ USB_DEVICE(0x1199, 0x6802) },	/* Sierra Wireless MC8755 */
 	{ USB_DEVICE(0x1199, 0x6804) },	/* Sierra Wireless MC8755 */
@@ -115,6 +163,11 @@ static struct usb_device_id id_table [] 
 	{ USB_DEVICE(0x1199, 0x6851) },	/* Sierra Wireless AirCard 881 */
 	{ USB_DEVICE(0x1199, 0x6852) },	/* Sierra Wireless AirCard 880 E */
 	{ USB_DEVICE(0x1199, 0x6853) },	/* Sierra Wireless AirCard 881 E */
+	{ USB_DEVICE(0x1199, 0x6855) },	/* Sierra Wireless AirCard 880 U */
+	{ USB_DEVICE(0x1199, 0x6856) },	/* Sierra Wireless AirCard 881 U */
+
+	{ USB_DEVICE(0x1199, 0x6468) }, /* Sierra Wireless MP3G - EVDO */
+	{ USB_DEVICE(0x1199, 0x6469) }, /* Sierra Wireless MP3G - UMTS/HSPA */
 
 	{ USB_DEVICE(0x1199, 0x0112), .driver_info = DEVICE_1_PORT }, /* Sierra Wireless AirCard 580 */
 	{ USB_DEVICE(0x0F3D, 0x0112), .driver_info = DEVICE_1_PORT }, /* Airprime/Sierra PC 5220 */
@@ -124,45 +177,14 @@ static struct usb_device_id id_table [] 
 };
 MODULE_DEVICE_TABLE(usb, id_table);
 
-static struct usb_device_id id_table_1port [] = {
-	{ USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */
-	{ USB_DEVICE(0x0F3D, 0x0112) }, /* AirPrime/Sierra PC 5220 */
-	{ }
-};
-
-static struct usb_device_id id_table_3port [] = {
-	{ USB_DEVICE(0x1199, 0x0017) },	/* Sierra Wireless EM5625 */
-	{ USB_DEVICE(0x1199, 0x0018) },	/* Sierra Wireless MC5720 */
-	{ USB_DEVICE(0x0f30, 0x1b1d) },	/* Sierra Wireless MC5720 */
-	{ USB_DEVICE(0x1199, 0x0218) },	/* Sierra Wireless MC5720 */
-	{ USB_DEVICE(0x1199, 0x0020) },	/* Sierra Wireless MC5725 */
-	{ USB_DEVICE(0x1199, 0x0019) },	/* Sierra Wireless AirCard 595 */
-	{ USB_DEVICE(0x1199, 0x0021) },	/* Sierra Wireless AirCard 597E */
-	{ USB_DEVICE(0x1199, 0x0120) },	/* Sierra Wireless USB Dongle 595U*/
-
-	{ USB_DEVICE(0x1199, 0x6802) },	/* Sierra Wireless MC8755 */
-	{ USB_DEVICE(0x1199, 0x6804) },	/* Sierra Wireless MC8755 */
-	{ USB_DEVICE(0x1199, 0x6803) },	/* Sierra Wireless MC8765 */
-	{ USB_DEVICE(0x1199, 0x6812) },	/* Sierra Wireless MC8775 & AC 875U */
-	{ USB_DEVICE(0x1199, 0x6820) },	/* Sierra Wireless AirCard 875 */
-	{ USB_DEVICE(0x1199, 0x6832) },	/* Sierra Wireless MC8780*/
-	{ USB_DEVICE(0x1199, 0x6833) },	/* Sierra Wireless MC8781*/
-	{ USB_DEVICE(0x1199, 0x6850) },	/* Sierra Wireless AirCard 880 */
-	{ USB_DEVICE(0x1199, 0x6851) },	/* Sierra Wireless AirCard 881 */
-	{ USB_DEVICE(0x1199, 0x6852) },	/* Sierra Wireless AirCard 880E */
-	{ USB_DEVICE(0x1199, 0x6853) },	/* Sierra Wireless AirCard 881E */
-	{ }
-};
-
 static struct usb_driver sierra_driver = {
 	.name       = "sierra",
-	.probe      = sierra_probe,
+	.probe      = usb_serial_probe,
 	.disconnect = usb_serial_disconnect,
 	.id_table   = id_table,
 	.no_dynamic_id = 	1,
 };
 
-
 struct sierra_port_private {
 	spinlock_t lock;	/* lock the structure */
 	int outstanding_urbs;	/* number of out urbs in flight */
@@ -184,6 +206,7 @@ static int sierra_send_setup(struct usb_
 {
 	struct usb_serial *serial = port->serial;
 	struct sierra_port_private *portdata;
+	__u16 interface = 0;
 
 	dbg("%s", __FUNCTION__);
 
@@ -196,9 +219,18 @@ static int sierra_send_setup(struct usb_
 		if (portdata->rts_state)
 			val |= 0x02;
 
+		/* Determine which port is targeted */
+		if (port->bulk_out_endpointAddress == 2)
+			interface = 0;
+		else if (port->bulk_out_endpointAddress == 4)
+			interface = 1;
+		else if (port->bulk_out_endpointAddress == 5)
+			interface = 2;
+
 		return usb_control_msg(serial->dev,
 				usb_rcvctrlpipe(serial->dev, 0),
-				0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
+				0x22, 0x21, val, interface,
+				NULL, 0, USB_CTRL_SET_TIMEOUT);
 	}
 
 	return 0;
@@ -582,6 +614,10 @@ static int sierra_startup(struct usb_ser
 	/*Set Device mode to D0 */
 	sierra_set_power_state(serial->dev, 0x0000);
 
+	/*Check NMEA and set */
+	if (nmea)
+		sierra_vsc_set_nmea(serial->dev, 1);
+
 	/* Now setup per port private data */
 	for (i = 0; i < serial->num_ports; i++) {
 		port = serial->port[i];
@@ -642,47 +678,19 @@ static void sierra_shutdown(struct usb_s
 	}
 }
 
-static struct usb_serial_driver sierra_1port_device = {
+static struct usb_serial_driver sierra_device = {
 	.driver = {
 		.owner =	THIS_MODULE,
 		.name =		"sierra1",
 	},
-	.description       = "Sierra USB modem (1 port)",
-	.id_table          = id_table_1port,
+	.description       = "Sierra USB modem",
+	.id_table          = id_table,
 	.usb_driver        = &sierra_driver,
 	.num_interrupt_in  = NUM_DONT_CARE,
-	.num_bulk_in       = 1,
-	.num_bulk_out      = 1,
-	.num_ports         = 1,
-	.open              = sierra_open,
-	.close             = sierra_close,
-	.write             = sierra_write,
-	.write_room        = sierra_write_room,
-	.chars_in_buffer   = sierra_chars_in_buffer,
-	.throttle          = sierra_rx_throttle,
-	.unthrottle        = sierra_rx_unthrottle,
-	.ioctl             = sierra_ioctl,
-	.set_termios       = sierra_set_termios,
-	.break_ctl         = sierra_break_ctl,
-	.tiocmget          = sierra_tiocmget,
-	.tiocmset          = sierra_tiocmset,
-	.attach            = sierra_startup,
-	.shutdown          = sierra_shutdown,
-	.read_int_callback = sierra_instat_callback,
-};
-
-static struct usb_serial_driver sierra_3port_device = {
-	.driver = {
-		.owner =	THIS_MODULE,
-		.name =		"sierra3",
-	},
-	.description       = "Sierra USB modem (3 port)",
-	.id_table          = id_table_3port,
-	.usb_driver        = &sierra_driver,
-	.num_interrupt_in  = NUM_DONT_CARE,
-	.num_bulk_in       = 3,
-	.num_bulk_out      = 3,
-	.num_ports         = 3,
+	.num_bulk_in       = NUM_DONT_CARE,
+	.num_bulk_out      = NUM_DONT_CARE,
+	.calc_num_ports	   = sierra_calc_num_ports,
+	.probe		   = sierra_probe,
 	.open              = sierra_open,
 	.close             = sierra_close,
 	.write             = sierra_write,
@@ -704,12 +712,9 @@ static struct usb_serial_driver sierra_3
 static int __init sierra_init(void)
 {
 	int retval;
-	retval = usb_serial_register(&sierra_1port_device);
-	if (retval)
-		goto failed_1port_device_register;
-	retval = usb_serial_register(&sierra_3port_device);
+	retval = usb_serial_register(&sierra_device);
 	if (retval)
-		goto failed_3port_device_register;
+		goto failed_device_register;
 
 
 	retval = usb_register(&sierra_driver);
@@ -721,18 +726,15 @@ static int __init sierra_init(void)
 	return 0;
 
 failed_driver_register:
-	usb_serial_deregister(&sierra_3port_device);
-failed_3port_device_register:
-	usb_serial_deregister(&sierra_1port_device);
-failed_1port_device_register:
+	usb_serial_deregister(&sierra_device);
+failed_device_register:
 	return retval;
 }
 
 static void __exit sierra_exit(void)
 {
 	usb_deregister (&sierra_driver);
-	usb_serial_deregister(&sierra_1port_device);
-	usb_serial_deregister(&sierra_3port_device);
+	usb_serial_deregister(&sierra_device);
 }
 
 module_init(sierra_init);
@@ -743,6 +745,12 @@ MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
 
+module_param(truinstall, bool, 0);
+MODULE_PARM_DESC(truinstall, "TRU-Install support");
+
+module_param(nmea, bool, 0);
+MODULE_PARM_DESC(nmea, "NMEA streaming");
+
 #ifdef CONFIG_USB_DEBUG
 module_param(debug, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug messages");

             reply	other threads:[~2008-01-10 19:26 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-01-10 19:11 Kevin Lloyd [this message]
2008-01-10 19:54 ` [PATCH] usb-serial: Sierra driver - add devices and update dtr Greg KH
2008-01-11 17:24   ` Kevin Lloyd
2008-01-11 21:02     ` Greg KH
2008-01-14 17:21       ` Kevin Lloyd
2008-01-17 18:04         ` Greg KH
2008-01-17 23:15           ` Kevin Lloyd
2008-01-19  0:35             ` Greg KH

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1199992265.9266.19.camel@linux-z60t \
    --to=klloyd@sierrawireless.com \
    --cc=gregkh@suse.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb-devel@lists.sourceforge.net \
    --cc=linux-usb@vger.kernel.org \
    --cc=linux@sierrawireless.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.