OTG Error Messages

"Felipe Balbi" <[email protected]>
Newsgroups gmane.linux.usb.devel
Message-ID <[email protected]>
Hello all,

I'm working on a re-write of the otg_whitelist.h in order to give
better support for otg error messages.

According to OTG Supplement... we must be able to send:

Device not supported
Device not responding
Unsupported bus topology

The problem I can see is that it seems like the otg_whitelist.h is not
capable of treating all these messages. I already could export "Device
not supported" on sysfs. I'm exporting these messages in order to
allow applications to pop-up messages to users or something.

The problem I'm having is the match criteria to return the messages
codes to the sysfs entry.

I'm coding, also, a way to enable and disable whitelist on sysfs.

Anyway, anybody has any comment regarding such modification??

I'm sending a preliminary patch attached.

Thanks in advance

-- 
Best Regards,

Felipe Balbi
[email protected]

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/

_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
0001-USB-OTG-Whitelist-Supporting-OTG-error-messages.diff (text/x-patch, 12.5 KB)
From 11f99d85ae5fafe5c86525e17d4534bebdb888f4 Mon Sep 17 00:00:00 2001
From: Felipe Balbi <[email protected]>
Date: Thu, 23 Aug 2007 10:03:25 -0400
Subject: [PATCH] USB: OTG Whitelist: Supporting OTG error messages

Work-in-progress

Signed-off-by: Felipe Balbi <[email protected]>
---
 drivers/usb/core/hub.c           |    2 +-
 drivers/usb/core/otg_whitelist.c |  215 ++++++++++++++++++++++++++++++++++++++
 drivers/usb/core/otg_whitelist.h |  131 +++++++----------------
 drivers/usb/core/sysfs.c         |   56 ++++++++++
 4 files changed, 311 insertions(+), 93 deletions(-)
 create mode 100644 drivers/usb/core/otg_whitelist.c

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index e341a1d..87fc468 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1316,7 +1316,7 @@ int usb_new_device(struct usb_device *udev)
 		}
 	}
 
-	if (!is_targeted(udev)) {
+	if (not_targeted(udev) && is_on()) {
 
 		/* Maybe it can talk to us, though we can't talk to it.
 		 * (Includes HNP test device.)
diff --git a/drivers/usb/core/otg_whitelist.c b/drivers/usb/core/otg_whitelist.c
new file mode 100644
index 0000000..ad4434d
--- /dev/null
+++ b/drivers/usb/core/otg_whitelist.c
@@ -0,0 +1,215 @@
+/*
+ * drivers/usb/core/otg_whitelist.c
+ *
+ * Copyright (C) 2007 Nokia Corporation
+ *
+ * Contact: Felipe Balbi <[email protected]>
+ *
+ * This code is based on previous version of drivers/usb/core/otg_whitelist.h
+ * which is:
+ *
+ * Copyright (C) 2004 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/byteorder/generic.h>
+#include <linux/gfp.h>
+#include <linux/usb.h>
+
+#include "otg_whitelist.h"
+
+/*
+ * This OTG Whitelist is the OTG "Targeted Peripheral List".
+ *
+ * This means we can only use USB_DEVICE macro here and list each device
+ * device separately.
+ *
+ * YOU _SHOULD_ CHANGE THIS LIST TO MATCH YOUR PRODUCT AND ITS TESTING!
+ */
+static struct usb_device_id whitelist_table [] = {
+
+/* hubs are optional in OTG, but very handy ... */
+{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 0), },
+{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 1), },
+
+#ifdef	CONFIG_USB_PRINTER		/* ignoring nonstatic linkage! */
+/* FIXME actually, printers are NOT supposed to use device classes;
+ * they're supposed to use interface classes...
+ */
+{ USB_DEVICE_INFO(7, 1, 1) },
+{ USB_DEVICE_INFO(7, 1, 2) },
+{ USB_DEVICE_INFO(7, 1, 3) },
+#endif
+
+#ifdef	CONFIG_USB_NET_CDCETHER
+/* Linux-USB CDC Ethernet gadget */
+{ USB_DEVICE(0x0525, 0xa4a1), },
+/* Linux-USB CDC Ethernet + RNDIS gadget */
+{ USB_DEVICE(0x0525, 0xa4a2), },
+#endif
+
+#if	defined(CONFIG_USB_TEST) || defined(CONFIG_USB_TEST_MODULE)
+/* gadget zero, for testing */
+{ USB_DEVICE(0x0525, 0xa4a0), },
+#endif
+
+{ }	/* Terminating entry */
+};
+
+struct otg_whitelist *whitelist;
+
+void whitelist_enable(unsigned enable)
+{
+	whitelist->enable = enable;
+}
+
+void add_usb_device(struct usb_device_id *id)
+{
+	struct otg_device	*otg;
+
+	otg = kzalloc(sizeof(*otg), GFP_KERNEL);
+	INIT_LIST_HEAD(&otg->list);
+	otg->id = id;
+	list_add_tail(&otg->list, &whitelist->devs);
+}
+
+void del_usb_device(struct usb_device_id *id)
+{
+	struct otg_device	*otg;
+
+	otg = kzalloc(sizeof(*otg), GFP_KERNEL);
+	INIT_LIST_HEAD(&otg->list);
+	otg->id = id;
+
+	list_for_each_entry(otg, &whitelist->devs, list) {
+
+		if ((otg->id->match_flags & USB_DEVICE_ID_MATCH_DEVICE) &&
+		    (otg->id->idVendor == le16_to_cpu(id->idVendor))) {
+			list_del(&otg->list);
+			break;
+		}
+
+		if ((otg->id->match_flags & USB_DEVICE_ID_MATCH_DEVICE) &&
+		    (otg->id->idProduct == le16_to_cpu(id->idProduct))) {
+			list_del(&otg->list);
+			break;
+		}
+	}
+}
+
+void add_usb_devices(struct usb_device_id *whitelist_table)
+{
+	struct usb_device_id	*id;
+
+	for (id = whitelist_table; id->match_flags; id++)
+		add_usb_device(id);
+}
+
+void print_otg_whitelist()
+{
+	struct otg_device	*otg;
+
+	list_for_each_entry(otg, &whitelist->devs, list) {
+		printk(KERN_INFO "%04x\t%04x\n", le16_to_cpu(otg->id->idVendor),
+				le16_to_cpu(otg->id->idProduct));
+	}
+}
+
+struct otg_whitelist *initialize_list(void)
+{
+	if (!whitelist) {
+		whitelist = kzalloc(sizeof(*whitelist), GFP_KERNEL);
+		INIT_LIST_HEAD(&whitelist->devs);
+		add_usb_devices(whitelist_table);
+	}
+	whitelist_enable(1);
+
+	return whitelist;
+}
+
+int is_on(void)
+{
+	return whitelist->enable;
+}
+
+int print_last_error(char *buf)
+{
+	return sprintf(buf, "otg%02d\n", whitelist->error);
+}
+
+int not_targeted(struct usb_device *dev)
+{
+	struct otg_device	*otg;
+
+	if (!whitelist)
+		whitelist = initialize_list();
+
+	whitelist->error = DEVICE_OK;
+
+	if (!is_on()) {
+		whitelist->error = DEVICE_OK;
+		return whitelist->error;
+	}
+
+	/* possible in developer configs only! */
+	if (!dev->bus->otg_port) {
+		whitelist->error = DEVICE_OK;
+		goto end;
+	}
+
+	/* HNP test device is _never_ targeted (see OTG spec 6.6.6) */
+	if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1a0a &&
+	     le16_to_cpu(dev->descriptor.idProduct) == 0xbadd)) {
+		whitelist->error = DEVICE_NOT_SUPPORTED;
+		goto error;
+	}
+
+	/* NOTE: can't use usb_match_id() since interface caches
+	 * aren't set up yet. this is cut/paste from that code.
+	 */
+	list_for_each_entry(otg, &whitelist->devs, list) {
+
+		whitelist->error = DEVICE_NOT_SUPPORTED;
+
+		if ((otg->id->match_flags & USB_DEVICE_ID_MATCH_DEVICE) &&
+		    (otg->id->idVendor == le16_to_cpu(dev->descriptor.idVendor))) {
+			whitelist->error = DEVICE_OK;
+			goto end;
+		}
+
+		if ((otg->id->match_flags & USB_DEVICE_ID_MATCH_DEVICE) &&
+		    (otg->id->idProduct == le16_to_cpu(dev->descriptor.idProduct))) {
+			whitelist->error = DEVICE_OK;
+			goto end;
+		}
+
+		if ((otg->id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
+		    (otg->id->bDeviceClass == dev->descriptor.bDeviceClass)) {
+			whitelist->error = DEVICE_OK;
+			goto end;
+		}
+
+		goto error;
+	}
+
+	/* add other match criteria here ... */
+
+error:
+	/* OTG MESSAGE: report errors here, customize to match your product */
+	dev_err(&dev->dev, "device v%04x p%04x is not supported\n",
+		le16_to_cpu(dev->descriptor.idVendor),
+		le16_to_cpu(dev->descriptor.idProduct));
+
+	whitelist->error = DEVICE_NOT_SUPPORTED;
+
+end:
+	sysfs_notify(&dev->dev.kobj, NULL, "whitelist");
+	return whitelist->error;
+}
+
diff --git a/drivers/usb/core/otg_whitelist.h b/drivers/usb/core/otg_whitelist.h
index 7f31a49..7dc9593 100644
--- a/drivers/usb/core/otg_whitelist.h
+++ b/drivers/usb/core/otg_whitelist.h
@@ -9,104 +9,51 @@
  * (at your option) any later version.
  */
 
-/*
- * This OTG Whitelist is the OTG "Targeted Peripheral List".  It should
- * mostly use of USB_DEVICE() or USB_DEVICE_VER() entries..
- *
- * YOU _SHOULD_ CHANGE THIS LIST TO MATCH YOUR PRODUCT AND ITS TESTING!
- */ 
-
-static struct usb_device_id whitelist_table [] = {
-
-/* hubs are optional in OTG, but very handy ... */
-{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 0), },
-{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 1), },
-
-#ifdef	CONFIG_USB_PRINTER		/* ignoring nonstatic linkage! */
-/* FIXME actually, printers are NOT supposed to use device classes;
- * they're supposed to use interface classes...
- */
-{ USB_DEVICE_INFO(7, 1, 1) },
-{ USB_DEVICE_INFO(7, 1, 2) },
-{ USB_DEVICE_INFO(7, 1, 3) },
-#endif
-
-#ifdef	CONFIG_USB_NET_CDCETHER
-/* Linux-USB CDC Ethernet gadget */
-{ USB_DEVICE(0x0525, 0xa4a1), },
-/* Linux-USB CDC Ethernet + RNDIS gadget */
-{ USB_DEVICE(0x0525, 0xa4a2), },
-#endif
-
-#if	defined(CONFIG_USB_TEST) || defined(CONFIG_USB_TEST_MODULE)
-/* gadget zero, for testing */
-{ USB_DEVICE(0x0525, 0xa4a0), },
-#endif
-
-{ }	/* Terminating entry */
+enum {
+	DEVICE_OK,
+	DEVICE_NOT_SUPPORTED,
+	DEVICE_NO_RESPONSE
 };
 
-static int is_targeted(struct usb_device *dev)
-{
-	struct usb_device_id	*id = whitelist_table;
-
-	/* possible in developer configs only! */
-	if (!dev->bus->otg_port)
-		return 1;
-
-	/* HNP test device is _never_ targeted (see OTG spec 6.6.6) */
-	if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1a0a && 
-	     le16_to_cpu(dev->descriptor.idProduct) == 0xbadd))
-		return 0;
-
-	/* NOTE: can't use usb_match_id() since interface caches
-	 * aren't set up yet. this is cut/paste from that code.
-	 */
-	for (id = whitelist_table; id->match_flags; id++) {
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
-		    id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
-		    id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
-			continue;
-
-		/* No need to test id->bcdDevice_lo != 0, since 0 is never
-		   greater than any unsigned number. */
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
-		    (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
-		    (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
-		    (id->bDeviceClass != dev->descriptor.bDeviceClass))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
-		    (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
-		    (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
-			continue;
-
-		return 1;
-	}
-
-	/* add other match criteria here ... */
+struct otg_whitelist {
+	unsigned		error;
+	struct list_head	devs;
+	unsigned		enable:1;
+};
 
+struct otg_device {
+	struct usb_device_id	*id;
+	struct list_head	list;
+};
 
-	/* OTG MESSAGE: report errors here, customize to match your product */
-	dev_err(&dev->dev, "device v%04x p%04x is not supported\n",
-		le16_to_cpu(dev->descriptor.idVendor),
-		le16_to_cpu(dev->descriptor.idProduct));
 #ifdef	CONFIG_USB_OTG_WHITELIST
-	return 0;
+extern int not_targeted(struct usb_device *);
+extern int is_on(void);
+extern int print_last_error(char *);
+extern void print_otg_whitelist(void);
+extern void add_usb_device(struct usb_device_id *);
+extern void del_usb_device(struct usb_device_id *);
+extern void whitelist_enable(unsigned);
 #else
+static inline int not_targeted(struct usb_device *dev)
+{
+	return DEVICE_OK;
+}
+static inline int is_on(void)
+{
 	return 1;
-#endif
 }
+static inline int print_last_error(char *c)
+{
+	return 0;
+}
+static inline void print_otg_whitelist(void)
+{ }
+static inline void add_usb_device(struct usb_device_id *i)
+{ }
+static inline void del_usb_device(struct usb_device_id *i)
+{ }
+static inline void whitelist_enable(unsigned e)
+{ }
+#endif
 
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 2ab222b..e83ca8d 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -91,6 +91,59 @@ usb_string_attr(product);
 usb_string_attr(manufacturer);
 usb_string_attr(serial);
 
+#ifdef CONFIG_USB_OTG
+static ssize_t
+otg_whitelist_store(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t n)
+{
+	struct usb_device	*udev = to_usb_device(dev);
+	struct usb_device_id	*id;
+	char			str[6];
+	int			idVendor;
+	int			idProduct;
+
+	usb_lock_device(udev);
+
+	sscanf(buf, "%s %04x:%04x", str, &idVendor, &idProduct);
+
+	id = kzalloc(sizeof(*id), GFP_KERNEL);
+
+	id->match_flags	= USB_DEVICE_ID_MATCH_DEVICE;
+	id->idVendor	= idVendor;
+	id->idProduct	= idProduct;
+
+	if (!strncmp(str, "add", 3))
+		add_usb_device(id);
+	if (!strncmp(str, "del", 3))
+		del_usb_device(id);
+	if (!strncmp(str, "print", 5))
+		print_otg_whitelist();
+	if (!strncmp(str, "on", 2))
+		whitelist_enable(1);
+	if (!strncmp(str, "off", 3))
+		whitelist_enable(0);
+
+	usb_unlock_device(udev);
+
+	return n;
+}
+
+static ssize_t
+otg_whitelist_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct usb_device	*udev = to_usb_device(dev);
+	struct otg_whitelist	*list = kzalloc(sizeof(*list), GFP_KERNEL);
+	int			ret;
+
+	usb_lock_device(udev);
+	ret = print_last_error(buf);
+	usb_unlock_device(udev);
+
+	return ret;
+}
+static DEVICE_ATTR(whitelist, 0644, otg_whitelist_show, otg_whitelist_store);
+#endif /* CONFIG_USB_OTG */
+
 static ssize_t
 show_speed(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -430,6 +483,9 @@ static struct attribute *dev_attrs[] = {
 	&dev_attr_bNumConfigurations.attr,
 	&dev_attr_bMaxPacketSize0.attr,
 	&dev_attr_speed.attr,
+#ifdef CONFIG_USB_OTG
+	&dev_attr_whitelist.attr,
+#endif
 	&dev_attr_busnum.attr,
 	&dev_attr_devnum.attr,
 	&dev_attr_version.attr,
-- 
1.5.3.rc5.11.g312e
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.