diff options
Diffstat (limited to 'usb/usb-gadget-composite-better-string-override-handling.patch')
| -rw-r--r-- | usb/usb-gadget-composite-better-string-override-handling.patch | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/usb/usb-gadget-composite-better-string-override-handling.patch b/usb/usb-gadget-composite-better-string-override-handling.patch new file mode 100644 index 00000000000000..34788c65066e0d --- /dev/null +++ b/usb/usb-gadget-composite-better-string-override-handling.patch @@ -0,0 +1,234 @@ +From linux-usb-owner@vger.kernel.org Wed Sep 1 14:09:23 2010 +Date: Thu, 12 Aug 2010 17:43:46 +0200 +From: Michal Nazarewicz <m.nazarewicz@samsung.com> +Subject: USB: gadget: composite: Better string override handling +To: linux-usb@vger.kernel.org, Greg KH <greg@kroah.com> +Cc: linux-kernel@vger.kernel.org +Message-id: <48e2d6507f004252a012cf25bc0a06e5cb69808f.1281625724.git.m.nazarewicz@samsung.com> + +The iManufatcurer, iProduct and iSerialNumber composite module +parameters were only used when the gadget driver registers +strings for manufacturer, product and serial number. If the +gadget never bothered to set corresponding fields in USB device +descriptors those module parameters are ignored. + +This commit makes the parameters work even if the strings ID +have not been assigned. It also changes the way IDs are +overridden -- what IDs are overridden is now saved in +usb_composite_dev structure -- which makes it unnecessary to +modify the string tables the way previous code did. + +The commit also adds a iProduct and iManufatcurer fields to the +usb_composite_device structure. If they are set, appropriate +strings are reserved and added to device descriptor. This makes +it unnecessary for gadget drivers to maintain code for setting +those. If iProduct is not set it defaults to +usb_composite_device::name; if iManufatcurer is not set +a default "<system> <release> with <gadget-name>" is used. + +The last thing is that if needs_serial field of +usb_composite_device is set and user failed to provided +iSerialNumber parameter a warning is issued. + +Signed-off-by: Michal Nazarewicz <m.nazarewicz@samsung.com> +Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/gadget/composite.c | 96 +++++++++++++++++++++++++++-------------- + include/linux/usb/composite.h | 13 +++++ + 2 files changed, 77 insertions(+), 32 deletions(-) + +--- a/drivers/usb/gadget/composite.c ++++ b/drivers/usb/gadget/composite.c +@@ -24,6 +24,7 @@ + #include <linux/kernel.h> + #include <linux/slab.h> + #include <linux/device.h> ++#include <linux/utsname.h> + + #include <linux/usb/composite.h> + +@@ -69,6 +70,8 @@ static char *iSerialNumber; + module_param(iSerialNumber, charp, 0); + MODULE_PARM_DESC(iSerialNumber, "SerialNumber string"); + ++static char composite_manufacturer[50]; ++ + /*-------------------------------------------------------------------------*/ + + /** +@@ -599,6 +602,7 @@ static int get_string(struct usb_composi + struct usb_configuration *c; + struct usb_function *f; + int len; ++ const char *str; + + /* Yes, not only is USB's I18N support probably more than most + * folk will ever care about ... also, it's all supported here. +@@ -638,9 +642,29 @@ static int get_string(struct usb_composi + return s->bLength; + } + +- /* Otherwise, look up and return a specified string. String IDs +- * are device-scoped, so we look up each string table we're told +- * about. These lookups are infrequent; simpler-is-better here. ++ /* Otherwise, look up and return a specified string. First ++ * check if the string has not been overridden. ++ */ ++ if (cdev->manufacturer_override == id) ++ str = iManufacturer ?: composite->iManufacturer ?: ++ composite_manufacturer; ++ else if (cdev->product_override == id) ++ str = iProduct ?: composite->iProduct; ++ else if (cdev->serial_override == id) ++ str = iSerialNumber; ++ else ++ str = NULL; ++ if (str) { ++ struct usb_gadget_strings strings = { ++ .language = language, ++ .strings = &(struct usb_string) { 0xff, str } ++ }; ++ return usb_gadget_get_string(&strings, 0xff, buf); ++ } ++ ++ /* String IDs are device-scoped, so we look up each string ++ * table we're told about. These lookups are infrequent; ++ * simpler-is-better here. + */ + if (composite->strings) { + len = lookup_string(composite->strings, buf, language, id); +@@ -1025,26 +1049,17 @@ composite_unbind(struct usb_gadget *gadg + composite = NULL; + } + +-static void +-string_override_one(struct usb_gadget_strings *tab, u8 id, const char *s) ++static u8 override_id(struct usb_composite_dev *cdev, u8 *desc) + { +- struct usb_string *str = tab->strings; +- +- for (str = tab->strings; str->s; str++) { +- if (str->id == id) { +- str->s = s; +- return; +- } ++ if (!*desc) { ++ int ret = usb_string_id(cdev); ++ if (unlikely(ret < 0)) ++ WARNING(cdev, "failed to override string ID\n"); ++ else ++ *desc = ret; + } +-} + +-static void +-string_override(struct usb_gadget_strings **tab, u8 id, const char *s) +-{ +- while (*tab) { +- string_override_one(*tab, id, s); +- tab++; +- } ++ return *desc; + } + + static int composite_bind(struct usb_gadget *gadget) +@@ -1107,19 +1122,34 @@ static int composite_bind(struct usb_gad + cdev->desc = *composite->dev; + cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket; + +- /* strings can't be assigned before bind() allocates the +- * releavnt identifiers +- */ +- if (cdev->desc.iManufacturer && iManufacturer) +- string_override(composite->strings, +- cdev->desc.iManufacturer, iManufacturer); +- if (cdev->desc.iProduct && iProduct) +- string_override(composite->strings, +- cdev->desc.iProduct, iProduct); +- if (cdev->desc.iSerialNumber && iSerialNumber) +- string_override(composite->strings, +- cdev->desc.iSerialNumber, iSerialNumber); ++ /* stirng overrides */ ++ if (iManufacturer || !cdev->desc.iManufacturer) { ++ if (!iManufacturer && !composite->iManufacturer && ++ !*composite_manufacturer) ++ snprintf(composite_manufacturer, ++ sizeof composite_manufacturer, ++ "%s %s with %s", ++ init_utsname()->sysname, ++ init_utsname()->release, ++ gadget->name); ++ ++ cdev->manufacturer_override = ++ override_id(cdev, &cdev->desc.iManufacturer); ++ } ++ ++ if (iProduct || (!cdev->desc.iProduct && composite->iProduct)) ++ cdev->product_override = ++ override_id(cdev, &cdev->desc.iProduct); ++ ++ if (iSerialNumber) ++ cdev->serial_override = ++ override_id(cdev, &cdev->desc.iSerialNumber); ++ ++ /* has userspace failed to provide a serial number? */ ++ if (composite->needs_serial && !cdev->desc.iSerialNumber) ++ WARNING(cdev, "userspace failed to provide iSerialNumber\n"); + ++ /* finish up */ + status = device_create_file(&gadget->dev, &dev_attr_suspended); + if (status) + goto fail; +@@ -1217,6 +1247,8 @@ int usb_composite_register(struct usb_co + if (!driver || !driver->dev || !driver->bind || composite) + return -EINVAL; + ++ if (!driver->iProduct) ++ driver->iProduct = driver->name; + if (!driver->name) + driver->name = "composite"; + composite_driver.function = (char *) driver->name; +--- a/include/linux/usb/composite.h ++++ b/include/linux/usb/composite.h +@@ -237,10 +237,17 @@ int usb_add_config(struct usb_composite_ + /** + * struct usb_composite_driver - groups configurations into a gadget + * @name: For diagnostics, identifies the driver. ++ * @iProduct: Used as iProduct override if @dev->iProduct is not set. ++ * If NULL value of @name is taken. ++ * @iManufacturer: Used as iManufacturer override if @dev->iManufacturer is ++ * not set. If NULL a default "<system> <release> with <udc>" value ++ * will be used. + * @dev: Template descriptor for the device, including default device + * identifiers. + * @strings: tables of strings, keyed by identifiers assigned during bind() + * and language IDs provided in control requests ++ * @needs_serial: set to 1 if the gadget needs userspace to provide ++ * a serial number. If one is not provided, warning will be printed. + * @bind: (REQUIRED) Used to allocate resources that are shared across the + * whole device, such as string IDs, and add its configurations using + * @usb_add_config(). This may fail by returning a negative errno +@@ -266,8 +273,11 @@ int usb_add_config(struct usb_composite_ + */ + struct usb_composite_driver { + const char *name; ++ const char *iProduct; ++ const char *iManufacturer; + const struct usb_device_descriptor *dev; + struct usb_gadget_strings **strings; ++ unsigned needs_serial:1; + + /* REVISIT: bind() functions can be marked __init, which + * makes trouble for section mismatch analysis. See if +@@ -334,6 +344,9 @@ struct usb_composite_dev { + struct list_head configs; + struct usb_composite_driver *driver; + u8 next_string_id; ++ u8 manufacturer_override; ++ u8 product_override; ++ u8 serial_override; + + /* the gadget driver won't enable the data pullup + * while the deactivation count is nonzero. |
