aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/composite.c
diff options
context:
space:
mode:
authorMichal Nazarewicz <m.nazarewicz@samsung.com>2010-08-12 11:43:46 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-10-22 13:21:23 -0400
commitad1a8102f957f4d25fc58cdc10736c5ade7557e1 (patch)
treea9bb1ee6b26a2171e43edc77dc51fdb839135d90 /drivers/usb/gadget/composite.c
parentfc19de61ef5c17b6e19766052c6ac85cf31de876 (diff)
USB: gadget: composite: Better string override handling
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>
Diffstat (limited to 'drivers/usb/gadget/composite.c')
-rw-r--r--drivers/usb/gadget/composite.c96
1 files changed, 64 insertions, 32 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index eaa9a599df63..717de39627c7 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -24,6 +24,7 @@
24#include <linux/kernel.h> 24#include <linux/kernel.h>
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/device.h> 26#include <linux/device.h>
27#include <linux/utsname.h>
27 28
28#include <linux/usb/composite.h> 29#include <linux/usb/composite.h>
29 30
@@ -69,6 +70,8 @@ static char *iSerialNumber;
69module_param(iSerialNumber, charp, 0); 70module_param(iSerialNumber, charp, 0);
70MODULE_PARM_DESC(iSerialNumber, "SerialNumber string"); 71MODULE_PARM_DESC(iSerialNumber, "SerialNumber string");
71 72
73static char composite_manufacturer[50];
74
72/*-------------------------------------------------------------------------*/ 75/*-------------------------------------------------------------------------*/
73 76
74/** 77/**
@@ -599,6 +602,7 @@ static int get_string(struct usb_composite_dev *cdev,
599 struct usb_configuration *c; 602 struct usb_configuration *c;
600 struct usb_function *f; 603 struct usb_function *f;
601 int len; 604 int len;
605 const char *str;
602 606
603 /* Yes, not only is USB's I18N support probably more than most 607 /* Yes, not only is USB's I18N support probably more than most
604 * folk will ever care about ... also, it's all supported here. 608 * folk will ever care about ... also, it's all supported here.
@@ -638,9 +642,29 @@ static int get_string(struct usb_composite_dev *cdev,
638 return s->bLength; 642 return s->bLength;
639 } 643 }
640 644
641 /* Otherwise, look up and return a specified string. String IDs 645 /* Otherwise, look up and return a specified string. First
642 * are device-scoped, so we look up each string table we're told 646 * check if the string has not been overridden.
643 * about. These lookups are infrequent; simpler-is-better here. 647 */
648 if (cdev->manufacturer_override == id)
649 str = iManufacturer ?: composite->iManufacturer ?:
650 composite_manufacturer;
651 else if (cdev->product_override == id)
652 str = iProduct ?: composite->iProduct;
653 else if (cdev->serial_override == id)
654 str = iSerialNumber;
655 else
656 str = NULL;
657 if (str) {
658 struct usb_gadget_strings strings = {
659 .language = language,
660 .strings = &(struct usb_string) { 0xff, str }
661 };
662 return usb_gadget_get_string(&strings, 0xff, buf);
663 }
664
665 /* String IDs are device-scoped, so we look up each string
666 * table we're told about. These lookups are infrequent;
667 * simpler-is-better here.
644 */ 668 */
645 if (composite->strings) { 669 if (composite->strings) {
646 len = lookup_string(composite->strings, buf, language, id); 670 len = lookup_string(composite->strings, buf, language, id);
@@ -1025,26 +1049,17 @@ composite_unbind(struct usb_gadget *gadget)
1025 composite = NULL; 1049 composite = NULL;
1026} 1050}
1027 1051
1028static void 1052static u8 override_id(struct usb_composite_dev *cdev, u8 *desc)
1029string_override_one(struct usb_gadget_strings *tab, u8 id, const char *s)
1030{ 1053{
1031 struct usb_string *str = tab->strings; 1054 if (!*desc) {
1032 1055 int ret = usb_string_id(cdev);
1033 for (str = tab->strings; str->s; str++) { 1056 if (unlikely(ret < 0))
1034 if (str->id == id) { 1057 WARNING(cdev, "failed to override string ID\n");
1035 str->s = s; 1058 else
1036 return; 1059 *desc = ret;
1037 }
1038 } 1060 }
1039}
1040 1061
1041static void 1062 return *desc;
1042string_override(struct usb_gadget_strings **tab, u8 id, const char *s)
1043{
1044 while (*tab) {
1045 string_override_one(*tab, id, s);
1046 tab++;
1047 }
1048} 1063}
1049 1064
1050static int composite_bind(struct usb_gadget *gadget) 1065static int composite_bind(struct usb_gadget *gadget)
@@ -1107,19 +1122,34 @@ static int composite_bind(struct usb_gadget *gadget)
1107 cdev->desc = *composite->dev; 1122 cdev->desc = *composite->dev;
1108 cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket; 1123 cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
1109 1124
1110 /* strings can't be assigned before bind() allocates the 1125 /* stirng overrides */
1111 * releavnt identifiers 1126 if (iManufacturer || !cdev->desc.iManufacturer) {
1112 */ 1127 if (!iManufacturer && !composite->iManufacturer &&
1113 if (cdev->desc.iManufacturer && iManufacturer) 1128 !*composite_manufacturer)
1114 string_override(composite->strings, 1129 snprintf(composite_manufacturer,
1115 cdev->desc.iManufacturer, iManufacturer); 1130 sizeof composite_manufacturer,
1116 if (cdev->desc.iProduct && iProduct) 1131 "%s %s with %s",
1117 string_override(composite->strings, 1132 init_utsname()->sysname,
1118 cdev->desc.iProduct, iProduct); 1133 init_utsname()->release,
1119 if (cdev->desc.iSerialNumber && iSerialNumber) 1134 gadget->name);
1120 string_override(composite->strings, 1135
1121 cdev->desc.iSerialNumber, iSerialNumber); 1136 cdev->manufacturer_override =
1137 override_id(cdev, &cdev->desc.iManufacturer);
1138 }
1139
1140 if (iProduct || (!cdev->desc.iProduct && composite->iProduct))
1141 cdev->product_override =
1142 override_id(cdev, &cdev->desc.iProduct);
1143
1144 if (iSerialNumber)
1145 cdev->serial_override =
1146 override_id(cdev, &cdev->desc.iSerialNumber);
1147
1148 /* has userspace failed to provide a serial number? */
1149 if (composite->needs_serial && !cdev->desc.iSerialNumber)
1150 WARNING(cdev, "userspace failed to provide iSerialNumber\n");
1122 1151
1152 /* finish up */
1123 status = device_create_file(&gadget->dev, &dev_attr_suspended); 1153 status = device_create_file(&gadget->dev, &dev_attr_suspended);
1124 if (status) 1154 if (status)
1125 goto fail; 1155 goto fail;
@@ -1217,6 +1247,8 @@ int usb_composite_register(struct usb_composite_driver *driver)
1217 if (!driver || !driver->dev || !driver->bind || composite) 1247 if (!driver || !driver->dev || !driver->bind || composite)
1218 return -EINVAL; 1248 return -EINVAL;
1219 1249
1250 if (!driver->iProduct)
1251 driver->iProduct = driver->name;
1220 if (!driver->name) 1252 if (!driver->name)
1221 driver->name = "composite"; 1253 driver->name = "composite";
1222 composite_driver.function = (char *) driver->name; 1254 composite_driver.function = (char *) driver->name;