.. | .. |
---|
50 | 50 | #define KERNEL_VER bin2bcd(((LINUX_VERSION_CODE >> 8) & 0x0ff)) |
---|
51 | 51 | |
---|
52 | 52 | enum { |
---|
| 53 | + AST_VHUB_STR_INDEX_MAX = 4, |
---|
53 | 54 | AST_VHUB_STR_MANUF = 3, |
---|
54 | 55 | AST_VHUB_STR_PRODUCT = 2, |
---|
55 | 56 | AST_VHUB_STR_SERIAL = 1, |
---|
.. | .. |
---|
72 | 73 | .bNumConfigurations = 1, |
---|
73 | 74 | }; |
---|
74 | 75 | |
---|
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 | | - |
---|
82 | 76 | /* |
---|
83 | 77 | * Configuration descriptor: same comments as above |
---|
84 | 78 | * regarding handling USB1 mode. |
---|
.. | .. |
---|
93 | 87 | USB_DT_INTERFACE_SIZE + \ |
---|
94 | 88 | USB_DT_ENDPOINT_SIZE) |
---|
95 | 89 | |
---|
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 = { |
---|
101 | 91 | .cfg = { |
---|
102 | 92 | .bLength = USB_DT_CONFIG_SIZE, |
---|
103 | 93 | .bDescriptorType = USB_DT_CONFIG, |
---|
.. | .. |
---|
266 | 256 | u8 desc_type, u16 len) |
---|
267 | 257 | { |
---|
268 | 258 | size_t dsize; |
---|
| 259 | + struct ast_vhub *vhub = ep->vhub; |
---|
269 | 260 | |
---|
270 | 261 | EPDBG(ep, "GET_DESCRIPTOR(type:%d)\n", desc_type); |
---|
271 | 262 | |
---|
.. | .. |
---|
281 | 272 | switch(desc_type) { |
---|
282 | 273 | case USB_DT_DEVICE: |
---|
283 | 274 | 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)); |
---|
286 | 277 | BUILD_BUG_ON(USB_DT_DEVICE_SIZE >= AST_VHUB_EP0_MAX_PACKET); |
---|
287 | 278 | break; |
---|
288 | 279 | case USB_DT_CONFIG: |
---|
289 | 280 | 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)); |
---|
292 | 283 | BUILD_BUG_ON(AST_VHUB_CONF_DESC_SIZE >= AST_VHUB_EP0_MAX_PACKET); |
---|
293 | 284 | break; |
---|
294 | 285 | case USB_DT_HUB: |
---|
295 | 286 | 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); |
---|
299 | 290 | break; |
---|
300 | 291 | default: |
---|
301 | 292 | return std_req_stall; |
---|
.. | .. |
---|
305 | 296 | if (len > dsize) |
---|
306 | 297 | len = dsize; |
---|
307 | 298 | |
---|
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 | | - |
---|
312 | 299 | /* Shoot it from the EP buffer */ |
---|
313 | 300 | 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; |
---|
314 | 348 | } |
---|
315 | 349 | |
---|
316 | 350 | static int ast_vhub_rep_string(struct ast_vhub_ep *ep, |
---|
317 | 351 | u8 string_id, u16 lang_id, |
---|
318 | 352 | u16 len) |
---|
319 | 353 | { |
---|
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; |
---|
321 | 358 | |
---|
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; |
---|
327 | 365 | |
---|
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) |
---|
329 | 370 | return std_req_stall; |
---|
330 | 371 | |
---|
331 | 372 | /* Shoot it from the EP buffer */ |
---|
| 373 | + memcpy(ep->buf, buf, rc); |
---|
332 | 374 | return ast_vhub_reply(ep, NULL, min_t(u16, rc, len)); |
---|
333 | 375 | } |
---|
334 | 376 | |
---|
.. | .. |
---|
449 | 491 | USB_PORT_STAT_C_OVERCURRENT | |
---|
450 | 492 | USB_PORT_STAT_C_RESET | |
---|
451 | 493 | USB_PORT_STAT_C_L1; |
---|
452 | | - p->change |= chg; |
---|
453 | 494 | |
---|
| 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; |
---|
454 | 503 | ast_vhub_update_hub_ep1(vhub, port); |
---|
455 | 504 | } |
---|
456 | 505 | } |
---|
.. | .. |
---|
497 | 546 | * we let the normal host wake path deal with it later. |
---|
498 | 547 | */ |
---|
499 | 548 | 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++) { |
---|
501 | 550 | struct ast_vhub_port *p = &vhub->ports[i]; |
---|
502 | 551 | |
---|
503 | 552 | if (!(p->status & USB_PORT_STAT_SUSPEND)) |
---|
.. | .. |
---|
580 | 629 | struct ast_vhub *vhub = ep->vhub; |
---|
581 | 630 | struct ast_vhub_port *p; |
---|
582 | 631 | |
---|
583 | | - if (port == 0 || port > AST_VHUB_NUM_PORTS) |
---|
| 632 | + if (port == 0 || port > vhub->max_ports) |
---|
584 | 633 | return std_req_stall; |
---|
585 | 634 | port--; |
---|
586 | 635 | p = &vhub->ports[port]; |
---|
.. | .. |
---|
623 | 672 | struct ast_vhub *vhub = ep->vhub; |
---|
624 | 673 | struct ast_vhub_port *p; |
---|
625 | 674 | |
---|
626 | | - if (port == 0 || port > AST_VHUB_NUM_PORTS) |
---|
| 675 | + if (port == 0 || port > vhub->max_ports) |
---|
627 | 676 | return std_req_stall; |
---|
628 | 677 | port--; |
---|
629 | 678 | p = &vhub->ports[port]; |
---|
.. | .. |
---|
669 | 718 | struct ast_vhub *vhub = ep->vhub; |
---|
670 | 719 | u16 stat, chg; |
---|
671 | 720 | |
---|
672 | | - if (port == 0 || port > AST_VHUB_NUM_PORTS) |
---|
| 721 | + if (port == 0 || port > vhub->max_ports) |
---|
673 | 722 | return std_req_stall; |
---|
674 | 723 | port--; |
---|
675 | 724 | |
---|
.. | .. |
---|
723 | 772 | case ClearPortFeature: |
---|
724 | 773 | EPDBG(ep, "ClearPortFeature(%d,%d)\n", wIndex & 0xf, wValue); |
---|
725 | 774 | 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); |
---|
726 | 781 | default: |
---|
727 | 782 | EPDBG(ep, "Unknown class request\n"); |
---|
728 | 783 | } |
---|
.. | .. |
---|
744 | 799 | * Forward to unsuspended ports without changing |
---|
745 | 800 | * their connection status. |
---|
746 | 801 | */ |
---|
747 | | - for (i = 0; i < AST_VHUB_NUM_PORTS; i++) { |
---|
| 802 | + for (i = 0; i < vhub->max_ports; i++) { |
---|
748 | 803 | struct ast_vhub_port *p = &vhub->ports[i]; |
---|
749 | 804 | |
---|
750 | 805 | if (!(p->status & USB_PORT_STAT_SUSPEND)) |
---|
.. | .. |
---|
767 | 822 | * Forward to unsuspended ports without changing |
---|
768 | 823 | * their connection status. |
---|
769 | 824 | */ |
---|
770 | | - for (i = 0; i < AST_VHUB_NUM_PORTS; i++) { |
---|
| 825 | + for (i = 0; i < vhub->max_ports; i++) { |
---|
771 | 826 | struct ast_vhub_port *p = &vhub->ports[i]; |
---|
772 | 827 | |
---|
773 | 828 | if (!(p->status & USB_PORT_STAT_SUSPEND)) |
---|
.. | .. |
---|
801 | 856 | * Clear all port status, disable gadgets and "suspend" |
---|
802 | 857 | * them. They will be woken up by a port reset. |
---|
803 | 858 | */ |
---|
804 | | - for (i = 0; i < AST_VHUB_NUM_PORTS; i++) { |
---|
| 859 | + for (i = 0; i < vhub->max_ports; i++) { |
---|
805 | 860 | struct ast_vhub_port *p = &vhub->ports[i]; |
---|
806 | 861 | |
---|
807 | 862 | /* Only keep the connected flag */ |
---|
.. | .. |
---|
821 | 876 | writel(0, vhub->regs + AST_VHUB_EP1_STS_CHG); |
---|
822 | 877 | } |
---|
823 | 878 | |
---|
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) |
---|
825 | 1047 | { |
---|
826 | 1048 | vhub->speed = USB_SPEED_UNKNOWN; |
---|
827 | 1049 | INIT_WORK(&vhub->wake_work, ast_vhub_wake_work); |
---|
828 | | -} |
---|
829 | 1050 | |
---|
| 1051 | + return ast_vhub_init_desc(vhub); |
---|
| 1052 | +} |
---|