diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/gadget/composite.c | 96 |
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; | |||
69 | module_param(iSerialNumber, charp, 0); | 70 | module_param(iSerialNumber, charp, 0); |
70 | MODULE_PARM_DESC(iSerialNumber, "SerialNumber string"); | 71 | MODULE_PARM_DESC(iSerialNumber, "SerialNumber string"); |
71 | 72 | ||
73 | static 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 | ||
1028 | static void | 1052 | static u8 override_id(struct usb_composite_dev *cdev, u8 *desc) |
1029 | string_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 | ||
1041 | static void | 1062 | return *desc; |
1042 | string_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 | ||
1050 | static int composite_bind(struct usb_gadget *gadget) | 1065 | static 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; |