X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=drivers%2Fusb%2Fgadget%2Fcomposite.c;h=717de39627c782e23eef1fd203d2fafada8dc7ab;hb=ad1a8102f957f4d25fc58cdc10736c5ade7557e1;hp=e483f80822d27003c7da89f0b472a91cde93b110;hpb=36450e9c953b2a6838def5945de8ae508141e834;p=platform%2Fadaptation%2Frenesas_rcar%2Frenesas_kernel.git diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index e483f80..717de39 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -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_composite_dev *cdev, 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_composite_dev *cdev, 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); @@ -723,12 +747,12 @@ int usb_string_ids_tab(struct usb_composite_dev *cdev, struct usb_string *str) /** * usb_string_ids_n() - allocate unused string IDs in batch - * @cdev: the device whose string descriptor IDs are being allocated + * @c: the device whose string descriptor IDs are being allocated * @n: number of string IDs to allocate * Context: single threaded during gadget setup * * Returns the first requested ID. This ID and next @n-1 IDs are now - * valid IDs. At least providind that @n is non zore because if it + * valid IDs. At least provided that @n is non-zero because if it * is, returns last requested ID which is now very useful information. * * @usb_string_ids_n() is called from bind() callbacks to allocate @@ -1025,26 +1049,17 @@ composite_unbind(struct usb_gadget *gadget) 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) @@ -1074,7 +1089,13 @@ static int composite_bind(struct usb_gadget *gadget) cdev->bufsiz = USB_BUFSIZ; cdev->driver = composite; - usb_gadget_set_selfpowered(gadget); + /* + * As per USB compliance update, a device that is actively drawing + * more than 100mA from USB must report itself as bus-powered in + * the GetStatus(DEVICE) call. + */ + if (CONFIG_USB_GADGET_VBUS_DRAW <= USB_SELF_POWER_VBUS_MAX_DRAW) + usb_gadget_set_selfpowered(gadget); /* interface and string IDs start at zero via kzalloc. * we force endpoints to start unassigned; few controller @@ -1101,19 +1122,34 @@ static int composite_bind(struct usb_gadget *gadget) 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; @@ -1211,6 +1247,8 @@ int usb_composite_register(struct usb_composite_driver *driver) 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;