Re: [PATCH] Add support for Mobilcom Debitel USB UMTS Surf-Stick to option driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Matthias Urlichs wrote:
> On Fri, 2009-11-27 at 13:49 +0100, Gernot Hillier wrote:
>> +       /* 4G Systems W14 simply ignores this message on interface 0 & 1 
>> +          and would cause long timeouts when calling usb_control_msg()  */
>> +       if (serial->dev->descriptor.idVendor == FOUR_G_SYSTEMS_VENDOR_ID &&
>> +               serial->dev->descriptor.idProduct == FOUR_G_SYSTEMS_PRODUCT_W14 &&
>> +               (ifNum == 0 || ifNum == 1) )
>> +               return -EIO;
>>
> I'd appreciate if you'd implement this generically.
> 
> I.e., use the driver_info field of struct usb_device for an appropriate
> blacklist flag. (It's not going to be the only one.)
> 

Ok, so here's my first shot at it. Code was mostly stolen from drivers/usb/
serial/sierra.c. 

Additionally, I needed to add some pieces because blacklist info is needed
in option_send_setup() where I don't have easy access to struct usb_
device_id. So far, I had no better idea than remembering the info in our
private structure.

I also prepared things to include the D-Link DWM 652 exceptions from
option_probe() (that's the intention of OPTION_BLACKLIST_RESERVED_IF).
 
Could you please confirm if this is what you wanted - if yes, I can
probably repost the patch in three parts (blacklisting infrastructure, add
4G W14 blacklist info, port D-Link DWM 652 blacklist info) with
appropriate summaries.

--- drivers/usb/serial/option.c.orig	2009-12-08 05:52:13.000000000 +0100
+++ drivers/usb/serial/option.c	2009-12-08 06:53:43.000000000 +0100
@@ -340,6 +340,28 @@ static int  option_resume(struct usb_ser
 #define FOUR_G_SYSTEMS_VENDOR_ID		0x1c9e
 #define FOUR_G_SYSTEMS_PRODUCT_W14		0x9603
 
+/* some devices interfaces need special handling due to a number of reasons */
+typedef enum {
+		OPTION_BLACKLIST_NONE = 0,
+		OPTION_BLACKLIST_SENDSETUP = 1,
+		OPTION_BLACKLIST_RESERVED_IF = 2
+} option_blacklist_reason_t;
+
+struct option_blacklist_info {
+	const u32 infolen;	/* number of interface numbers on blacklist */
+	const u8  *ifaceinfo;	/* pointer to the array holding the numbers */
+	option_blacklist_reason_t reason;
+};
+
+static const u8 four_g_w14_no_sendsetup[] = { 0, 1 };
+static const struct option_blacklist_info four_g_w14_blacklist = {
+	.infolen = ARRAY_SIZE(four_g_w14_no_sendsetup),
+	.ifaceinfo = four_g_w14_no_sendsetup,
+	.reason = OPTION_BLACKLIST_SENDSETUP
+};
+
+
+
 static struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -604,7 +626,9 @@ static struct usb_device_id option_ids[]
 	{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) },
 	{ USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
 	{ USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
-	{ USB_DEVICE(FOUR_G_SYSTEMS_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14) },
+ 	{ USB_DEVICE(FOUR_G_SYSTEMS_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14),
+ 	  .driver_info = (kernel_ulong_t)&four_g_w14_blacklist
+ 	},
 	{ } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
@@ -668,6 +692,7 @@ struct option_intf_private {
 	spinlock_t susp_lock;
 	unsigned int suspended:1;
 	int in_flight;
+	struct option_blacklist_info *blacklist_info;	
 };
 
 struct option_port_private {
@@ -737,9 +762,27 @@ static int option_probe(struct usb_seria
 	if (!data)
 		return -ENOMEM;
 	spin_lock_init(&data->susp_lock);
+	data->blacklist_info = (struct option_blacklist_info*) id->driver_info;
 	return 0;
 }
 
+static option_blacklist_reason_t is_blacklisted(const u8 ifnum,
+				const struct option_blacklist_info *blacklist)
+{
+	const u8  *info;
+	int i;
+
+	if (blacklist) {
+		info = blacklist->ifaceinfo;
+
+		for (i = 0; i < blacklist->infolen; i++) {
+			if (info[i] == ifnum)
+				return blacklist->reason;
+		}
+	}
+	return OPTION_BLACKLIST_NONE;
+}
+
 static void option_set_termios(struct tty_struct *tty,
 		struct usb_serial_port *port, struct ktermios *old_termios)
 {
@@ -1170,11 +1213,18 @@ static void option_setup_urbs(struct usb
 static int option_send_setup(struct usb_serial_port *port)
 {
 	struct usb_serial *serial = port->serial;
+	struct option_intf_private *intfdata = (struct option_intf_private *) serial->private;
 	struct option_port_private *portdata;
 	int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
 	int val = 0;
 	dbg("%s", __func__);
 
+	if (is_blacklisted(ifNum, intfdata->blacklist_info) == 
+						OPTION_BLACKLIST_SENDSETUP) {
+		dbg("No send_setup on blacklisted interface #%d\n", ifNum);
+		return -EIO;
+	}
+
 	portdata = usb_get_serial_port_data(port);
 
 	if (portdata->dtr_state)
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux