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