hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/usb/gadget/udc/aspeed-vhub/hub.c
....@@ -50,6 +50,7 @@
5050 #define KERNEL_VER bin2bcd(((LINUX_VERSION_CODE >> 8) & 0x0ff))
5151
5252 enum {
53
+ AST_VHUB_STR_INDEX_MAX = 4,
5354 AST_VHUB_STR_MANUF = 3,
5455 AST_VHUB_STR_PRODUCT = 2,
5556 AST_VHUB_STR_SERIAL = 1,
....@@ -72,13 +73,6 @@
7273 .bNumConfigurations = 1,
7374 };
7475
75
-/* Patches to the above when forcing USB1 mode */
76
-static void ast_vhub_patch_dev_desc_usb1(struct usb_device_descriptor *desc)
77
-{
78
- desc->bcdUSB = cpu_to_le16(0x0100);
79
- desc->bDeviceProtocol = 0;
80
-}
81
-
8276 /*
8377 * Configuration descriptor: same comments as above
8478 * regarding handling USB1 mode.
....@@ -93,11 +87,7 @@
9387 USB_DT_INTERFACE_SIZE + \
9488 USB_DT_ENDPOINT_SIZE)
9589
96
-static const struct ast_vhub_full_cdesc {
97
- struct usb_config_descriptor cfg;
98
- struct usb_interface_descriptor intf;
99
- struct usb_endpoint_descriptor ep;
100
-} __attribute__ ((packed)) ast_vhub_conf_desc = {
90
+static const struct ast_vhub_full_cdesc ast_vhub_conf_desc = {
10191 .cfg = {
10292 .bLength = USB_DT_CONFIG_SIZE,
10393 .bDescriptorType = USB_DT_CONFIG,
....@@ -266,6 +256,7 @@
266256 u8 desc_type, u16 len)
267257 {
268258 size_t dsize;
259
+ struct ast_vhub *vhub = ep->vhub;
269260
270261 EPDBG(ep, "GET_DESCRIPTOR(type:%d)\n", desc_type);
271262
....@@ -281,21 +272,21 @@
281272 switch(desc_type) {
282273 case USB_DT_DEVICE:
283274 dsize = USB_DT_DEVICE_SIZE;
284
- memcpy(ep->buf, &ast_vhub_dev_desc, dsize);
285
- BUILD_BUG_ON(dsize > sizeof(ast_vhub_dev_desc));
275
+ memcpy(ep->buf, &vhub->vhub_dev_desc, dsize);
276
+ BUILD_BUG_ON(dsize > sizeof(vhub->vhub_dev_desc));
286277 BUILD_BUG_ON(USB_DT_DEVICE_SIZE >= AST_VHUB_EP0_MAX_PACKET);
287278 break;
288279 case USB_DT_CONFIG:
289280 dsize = AST_VHUB_CONF_DESC_SIZE;
290
- memcpy(ep->buf, &ast_vhub_conf_desc, dsize);
291
- BUILD_BUG_ON(dsize > sizeof(ast_vhub_conf_desc));
281
+ memcpy(ep->buf, &vhub->vhub_conf_desc, dsize);
282
+ BUILD_BUG_ON(dsize > sizeof(vhub->vhub_conf_desc));
292283 BUILD_BUG_ON(AST_VHUB_CONF_DESC_SIZE >= AST_VHUB_EP0_MAX_PACKET);
293284 break;
294285 case USB_DT_HUB:
295286 dsize = AST_VHUB_HUB_DESC_SIZE;
296
- memcpy(ep->buf, &ast_vhub_hub_desc, dsize);
297
- BUILD_BUG_ON(dsize > sizeof(ast_vhub_hub_desc));
298
- BUILD_BUG_ON(AST_VHUB_HUB_DESC_SIZE >= AST_VHUB_EP0_MAX_PACKET);
287
+ memcpy(ep->buf, &vhub->vhub_hub_desc, dsize);
288
+ BUILD_BUG_ON(dsize > sizeof(vhub->vhub_hub_desc));
289
+ BUILD_BUG_ON(AST_VHUB_HUB_DESC_SIZE >= AST_VHUB_EP0_MAX_PACKET);
299290 break;
300291 default:
301292 return std_req_stall;
....@@ -305,30 +296,81 @@
305296 if (len > dsize)
306297 len = dsize;
307298
308
- /* Patch it if forcing USB1 */
309
- if (desc_type == USB_DT_DEVICE && ep->vhub->force_usb1)
310
- ast_vhub_patch_dev_desc_usb1(ep->buf);
311
-
312299 /* Shoot it from the EP buffer */
313300 return ast_vhub_reply(ep, NULL, len);
301
+}
302
+
303
+static struct usb_gadget_strings*
304
+ast_vhub_str_of_container(struct usb_gadget_string_container *container)
305
+{
306
+ return (struct usb_gadget_strings *)container->stash;
307
+}
308
+
309
+static int ast_vhub_collect_languages(struct ast_vhub *vhub, void *buf,
310
+ size_t size)
311
+{
312
+ int rc, hdr_len, nlangs, max_langs;
313
+ struct usb_gadget_strings *lang_str;
314
+ struct usb_gadget_string_container *container;
315
+ struct usb_string_descriptor *sdesc = buf;
316
+
317
+ nlangs = 0;
318
+ hdr_len = sizeof(struct usb_descriptor_header);
319
+ max_langs = (size - hdr_len) / sizeof(sdesc->wData[0]);
320
+ list_for_each_entry(container, &vhub->vhub_str_desc, list) {
321
+ if (nlangs >= max_langs)
322
+ break;
323
+
324
+ lang_str = ast_vhub_str_of_container(container);
325
+ sdesc->wData[nlangs++] = cpu_to_le16(lang_str->language);
326
+ }
327
+
328
+ rc = hdr_len + nlangs * sizeof(sdesc->wData[0]);
329
+ sdesc->bLength = rc;
330
+ sdesc->bDescriptorType = USB_DT_STRING;
331
+
332
+ return rc;
333
+}
334
+
335
+static struct usb_gadget_strings *ast_vhub_lookup_string(struct ast_vhub *vhub,
336
+ u16 lang_id)
337
+{
338
+ struct usb_gadget_strings *lang_str;
339
+ struct usb_gadget_string_container *container;
340
+
341
+ list_for_each_entry(container, &vhub->vhub_str_desc, list) {
342
+ lang_str = ast_vhub_str_of_container(container);
343
+ if (lang_str->language == lang_id)
344
+ return lang_str;
345
+ }
346
+
347
+ return NULL;
314348 }
315349
316350 static int ast_vhub_rep_string(struct ast_vhub_ep *ep,
317351 u8 string_id, u16 lang_id,
318352 u16 len)
319353 {
320
- int rc = usb_gadget_get_string (&ast_vhub_strings, string_id, ep->buf);
354
+ int rc;
355
+ u8 buf[256];
356
+ struct ast_vhub *vhub = ep->vhub;
357
+ struct usb_gadget_strings *lang_str;
321358
322
- /*
323
- * This should never happen unless we put too big strings in
324
- * the array above
325
- */
326
- BUG_ON(rc >= AST_VHUB_EP0_MAX_PACKET);
359
+ if (string_id == 0) {
360
+ rc = ast_vhub_collect_languages(vhub, buf, sizeof(buf));
361
+ } else {
362
+ lang_str = ast_vhub_lookup_string(vhub, lang_id);
363
+ if (!lang_str)
364
+ return std_req_stall;
327365
328
- if (rc < 0)
366
+ rc = usb_gadget_get_string(lang_str, string_id, buf);
367
+ }
368
+
369
+ if (rc < 0 || rc >= AST_VHUB_EP0_MAX_PACKET)
329370 return std_req_stall;
330371
331372 /* Shoot it from the EP buffer */
373
+ memcpy(ep->buf, buf, rc);
332374 return ast_vhub_reply(ep, NULL, min_t(u16, rc, len));
333375 }
334376
....@@ -449,8 +491,15 @@
449491 USB_PORT_STAT_C_OVERCURRENT |
450492 USB_PORT_STAT_C_RESET |
451493 USB_PORT_STAT_C_L1;
452
- p->change |= chg;
453494
495
+ /*
496
+ * We only set USB_PORT_STAT_C_ENABLE if we are disabling
497
+ * the port as per USB spec, otherwise MacOS gets upset
498
+ */
499
+ if (p->status & USB_PORT_STAT_ENABLE)
500
+ chg &= ~USB_PORT_STAT_C_ENABLE;
501
+
502
+ p->change = chg;
454503 ast_vhub_update_hub_ep1(vhub, port);
455504 }
456505 }
....@@ -497,7 +546,7 @@
497546 * we let the normal host wake path deal with it later.
498547 */
499548 spin_lock_irqsave(&vhub->lock, flags);
500
- for (i = 0; i < AST_VHUB_NUM_PORTS; i++) {
549
+ for (i = 0; i < vhub->max_ports; i++) {
501550 struct ast_vhub_port *p = &vhub->ports[i];
502551
503552 if (!(p->status & USB_PORT_STAT_SUSPEND))
....@@ -580,7 +629,7 @@
580629 struct ast_vhub *vhub = ep->vhub;
581630 struct ast_vhub_port *p;
582631
583
- if (port == 0 || port > AST_VHUB_NUM_PORTS)
632
+ if (port == 0 || port > vhub->max_ports)
584633 return std_req_stall;
585634 port--;
586635 p = &vhub->ports[port];
....@@ -623,7 +672,7 @@
623672 struct ast_vhub *vhub = ep->vhub;
624673 struct ast_vhub_port *p;
625674
626
- if (port == 0 || port > AST_VHUB_NUM_PORTS)
675
+ if (port == 0 || port > vhub->max_ports)
627676 return std_req_stall;
628677 port--;
629678 p = &vhub->ports[port];
....@@ -669,7 +718,7 @@
669718 struct ast_vhub *vhub = ep->vhub;
670719 u16 stat, chg;
671720
672
- if (port == 0 || port > AST_VHUB_NUM_PORTS)
721
+ if (port == 0 || port > vhub->max_ports)
673722 return std_req_stall;
674723 port--;
675724
....@@ -723,6 +772,12 @@
723772 case ClearPortFeature:
724773 EPDBG(ep, "ClearPortFeature(%d,%d)\n", wIndex & 0xf, wValue);
725774 return ast_vhub_clr_port_feature(ep, wIndex & 0xf, wValue);
775
+ case ClearTTBuffer:
776
+ case ResetTT:
777
+ case StopTT:
778
+ return std_req_complete;
779
+ case GetTTState:
780
+ return ast_vhub_simple_reply(ep, 0, 0, 0, 0);
726781 default:
727782 EPDBG(ep, "Unknown class request\n");
728783 }
....@@ -744,7 +799,7 @@
744799 * Forward to unsuspended ports without changing
745800 * their connection status.
746801 */
747
- for (i = 0; i < AST_VHUB_NUM_PORTS; i++) {
802
+ for (i = 0; i < vhub->max_ports; i++) {
748803 struct ast_vhub_port *p = &vhub->ports[i];
749804
750805 if (!(p->status & USB_PORT_STAT_SUSPEND))
....@@ -767,7 +822,7 @@
767822 * Forward to unsuspended ports without changing
768823 * their connection status.
769824 */
770
- for (i = 0; i < AST_VHUB_NUM_PORTS; i++) {
825
+ for (i = 0; i < vhub->max_ports; i++) {
771826 struct ast_vhub_port *p = &vhub->ports[i];
772827
773828 if (!(p->status & USB_PORT_STAT_SUSPEND))
....@@ -801,7 +856,7 @@
801856 * Clear all port status, disable gadgets and "suspend"
802857 * them. They will be woken up by a port reset.
803858 */
804
- for (i = 0; i < AST_VHUB_NUM_PORTS; i++) {
859
+ for (i = 0; i < vhub->max_ports; i++) {
805860 struct ast_vhub_port *p = &vhub->ports[i];
806861
807862 /* Only keep the connected flag */
....@@ -821,9 +876,177 @@
821876 writel(0, vhub->regs + AST_VHUB_EP1_STS_CHG);
822877 }
823878
824
-void ast_vhub_init_hub(struct ast_vhub *vhub)
879
+static void ast_vhub_of_parse_dev_desc(struct ast_vhub *vhub,
880
+ const struct device_node *vhub_np)
881
+{
882
+ u16 id;
883
+ u32 data;
884
+
885
+ if (!of_property_read_u32(vhub_np, "vhub-vendor-id", &data)) {
886
+ id = (u16)data;
887
+ vhub->vhub_dev_desc.idVendor = cpu_to_le16(id);
888
+ }
889
+ if (!of_property_read_u32(vhub_np, "vhub-product-id", &data)) {
890
+ id = (u16)data;
891
+ vhub->vhub_dev_desc.idProduct = cpu_to_le16(id);
892
+ }
893
+ if (!of_property_read_u32(vhub_np, "vhub-device-revision", &data)) {
894
+ id = (u16)data;
895
+ vhub->vhub_dev_desc.bcdDevice = cpu_to_le16(id);
896
+ }
897
+}
898
+
899
+static void ast_vhub_fixup_usb1_dev_desc(struct ast_vhub *vhub)
900
+{
901
+ vhub->vhub_dev_desc.bcdUSB = cpu_to_le16(0x0100);
902
+ vhub->vhub_dev_desc.bDeviceProtocol = 0;
903
+}
904
+
905
+static struct usb_gadget_string_container*
906
+ast_vhub_str_container_alloc(struct ast_vhub *vhub)
907
+{
908
+ unsigned int size;
909
+ struct usb_string *str_array;
910
+ struct usb_gadget_strings *lang_str;
911
+ struct usb_gadget_string_container *container;
912
+
913
+ size = sizeof(*container);
914
+ size += sizeof(struct usb_gadget_strings);
915
+ size += sizeof(struct usb_string) * AST_VHUB_STR_INDEX_MAX;
916
+ container = devm_kzalloc(&vhub->pdev->dev, size, GFP_KERNEL);
917
+ if (!container)
918
+ return ERR_PTR(-ENOMEM);
919
+
920
+ lang_str = ast_vhub_str_of_container(container);
921
+ str_array = (struct usb_string *)(lang_str + 1);
922
+ lang_str->strings = str_array;
923
+ return container;
924
+}
925
+
926
+static void ast_vhub_str_deep_copy(struct usb_gadget_strings *dest,
927
+ const struct usb_gadget_strings *src)
928
+{
929
+ struct usb_string *src_array = src->strings;
930
+ struct usb_string *dest_array = dest->strings;
931
+
932
+ dest->language = src->language;
933
+ if (src_array && dest_array) {
934
+ do {
935
+ *dest_array = *src_array;
936
+ dest_array++;
937
+ src_array++;
938
+ } while (src_array->s);
939
+ }
940
+}
941
+
942
+static int ast_vhub_str_alloc_add(struct ast_vhub *vhub,
943
+ const struct usb_gadget_strings *src_str)
944
+{
945
+ struct usb_gadget_strings *dest_str;
946
+ struct usb_gadget_string_container *container;
947
+
948
+ container = ast_vhub_str_container_alloc(vhub);
949
+ if (IS_ERR(container))
950
+ return PTR_ERR(container);
951
+
952
+ dest_str = ast_vhub_str_of_container(container);
953
+ ast_vhub_str_deep_copy(dest_str, src_str);
954
+ list_add_tail(&container->list, &vhub->vhub_str_desc);
955
+
956
+ return 0;
957
+}
958
+
959
+static const struct {
960
+ const char *name;
961
+ u8 id;
962
+} str_id_map[] = {
963
+ {"manufacturer", AST_VHUB_STR_MANUF},
964
+ {"product", AST_VHUB_STR_PRODUCT},
965
+ {"serial-number", AST_VHUB_STR_SERIAL},
966
+ {},
967
+};
968
+
969
+static int ast_vhub_of_parse_str_desc(struct ast_vhub *vhub,
970
+ const struct device_node *desc_np)
971
+{
972
+ u32 langid;
973
+ int ret = 0;
974
+ int i, offset;
975
+ const char *str;
976
+ struct device_node *child;
977
+ struct usb_string str_array[AST_VHUB_STR_INDEX_MAX];
978
+ struct usb_gadget_strings lang_str = {
979
+ .strings = (struct usb_string *)str_array,
980
+ };
981
+
982
+ for_each_child_of_node(desc_np, child) {
983
+ if (of_property_read_u32(child, "reg", &langid))
984
+ continue; /* no language identifier specified */
985
+
986
+ if (!usb_validate_langid(langid))
987
+ continue; /* invalid language identifier */
988
+
989
+ lang_str.language = langid;
990
+ for (i = offset = 0; str_id_map[i].name; i++) {
991
+ str = of_get_property(child, str_id_map[i].name, NULL);
992
+ if (str) {
993
+ str_array[offset].s = str;
994
+ str_array[offset].id = str_id_map[i].id;
995
+ offset++;
996
+ }
997
+ }
998
+ str_array[offset].id = 0;
999
+ str_array[offset].s = NULL;
1000
+
1001
+ ret = ast_vhub_str_alloc_add(vhub, &lang_str);
1002
+ if (ret) {
1003
+ of_node_put(child);
1004
+ break;
1005
+ }
1006
+ }
1007
+
1008
+ return ret;
1009
+}
1010
+
1011
+static int ast_vhub_init_desc(struct ast_vhub *vhub)
1012
+{
1013
+ int ret;
1014
+ struct device_node *desc_np;
1015
+ const struct device_node *vhub_np = vhub->pdev->dev.of_node;
1016
+
1017
+ /* Initialize vhub Device Descriptor. */
1018
+ memcpy(&vhub->vhub_dev_desc, &ast_vhub_dev_desc,
1019
+ sizeof(vhub->vhub_dev_desc));
1020
+ ast_vhub_of_parse_dev_desc(vhub, vhub_np);
1021
+ if (vhub->force_usb1)
1022
+ ast_vhub_fixup_usb1_dev_desc(vhub);
1023
+
1024
+ /* Initialize vhub Configuration Descriptor. */
1025
+ memcpy(&vhub->vhub_conf_desc, &ast_vhub_conf_desc,
1026
+ sizeof(vhub->vhub_conf_desc));
1027
+
1028
+ /* Initialize vhub Hub Descriptor. */
1029
+ memcpy(&vhub->vhub_hub_desc, &ast_vhub_hub_desc,
1030
+ sizeof(vhub->vhub_hub_desc));
1031
+ vhub->vhub_hub_desc.bNbrPorts = vhub->max_ports;
1032
+
1033
+ /* Initialize vhub String Descriptors. */
1034
+ INIT_LIST_HEAD(&vhub->vhub_str_desc);
1035
+ desc_np = of_get_child_by_name(vhub_np, "vhub-strings");
1036
+ if (desc_np) {
1037
+ ret = ast_vhub_of_parse_str_desc(vhub, desc_np);
1038
+ of_node_put(desc_np);
1039
+ }
1040
+ else
1041
+ ret = ast_vhub_str_alloc_add(vhub, &ast_vhub_strings);
1042
+
1043
+ return ret;
1044
+}
1045
+
1046
+int ast_vhub_init_hub(struct ast_vhub *vhub)
8251047 {
8261048 vhub->speed = USB_SPEED_UNKNOWN;
8271049 INIT_WORK(&vhub->wake_work, ast_vhub_wake_work);
828
-}
8291050
1051
+ return ast_vhub_init_desc(vhub);
1052
+}