diff options
-rw-r--r-- | drivers/usb/gadget/f_rndis.c | 24 | ||||
-rw-r--r-- | drivers/usb/gadget/u_rndis.h | 3 |
2 files changed, 24 insertions, 3 deletions
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index 139bc9c6f7e0..28d1891f11fa 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c | |||
@@ -682,6 +682,15 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) | |||
682 | 682 | ||
683 | rndis_opts = container_of(f->fi, struct f_rndis_opts, func_inst); | 683 | rndis_opts = container_of(f->fi, struct f_rndis_opts, func_inst); |
684 | 684 | ||
685 | if (cdev->use_os_string) { | ||
686 | f->os_desc_table = kzalloc(sizeof(*f->os_desc_table), | ||
687 | GFP_KERNEL); | ||
688 | if (!f->os_desc_table) | ||
689 | return PTR_ERR(f->os_desc_table); | ||
690 | f->os_desc_n = 1; | ||
691 | f->os_desc_table[0].os_desc = &rndis_opts->rndis_os_desc; | ||
692 | } | ||
693 | |||
685 | /* | 694 | /* |
686 | * in drivers/usb/gadget/configfs.c:configfs_composite_bind() | 695 | * in drivers/usb/gadget/configfs.c:configfs_composite_bind() |
687 | * configurations are bound in sequence with list_for_each_entry, | 696 | * configurations are bound in sequence with list_for_each_entry, |
@@ -693,14 +702,16 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) | |||
693 | gether_set_gadget(rndis_opts->net, cdev->gadget); | 702 | gether_set_gadget(rndis_opts->net, cdev->gadget); |
694 | status = gether_register_netdev(rndis_opts->net); | 703 | status = gether_register_netdev(rndis_opts->net); |
695 | if (status) | 704 | if (status) |
696 | return status; | 705 | goto fail; |
697 | rndis_opts->bound = true; | 706 | rndis_opts->bound = true; |
698 | } | 707 | } |
699 | 708 | ||
700 | us = usb_gstrings_attach(cdev, rndis_strings, | 709 | us = usb_gstrings_attach(cdev, rndis_strings, |
701 | ARRAY_SIZE(rndis_string_defs)); | 710 | ARRAY_SIZE(rndis_string_defs)); |
702 | if (IS_ERR(us)) | 711 | if (IS_ERR(us)) { |
703 | return PTR_ERR(us); | 712 | status = PTR_ERR(us); |
713 | goto fail; | ||
714 | } | ||
704 | rndis_control_intf.iInterface = us[0].id; | 715 | rndis_control_intf.iInterface = us[0].id; |
705 | rndis_data_intf.iInterface = us[1].id; | 716 | rndis_data_intf.iInterface = us[1].id; |
706 | rndis_iad_descriptor.iFunction = us[2].id; | 717 | rndis_iad_descriptor.iFunction = us[2].id; |
@@ -802,6 +813,8 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) | |||
802 | return 0; | 813 | return 0; |
803 | 814 | ||
804 | fail: | 815 | fail: |
816 | kfree(f->os_desc_table); | ||
817 | f->os_desc_n = 0; | ||
805 | usb_free_all_descriptors(f); | 818 | usb_free_all_descriptors(f); |
806 | 819 | ||
807 | if (rndis->notify_req) { | 820 | if (rndis->notify_req) { |
@@ -892,6 +905,8 @@ static struct usb_function_instance *rndis_alloc_inst(void) | |||
892 | opts = kzalloc(sizeof(*opts), GFP_KERNEL); | 905 | opts = kzalloc(sizeof(*opts), GFP_KERNEL); |
893 | if (!opts) | 906 | if (!opts) |
894 | return ERR_PTR(-ENOMEM); | 907 | return ERR_PTR(-ENOMEM); |
908 | opts->rndis_os_desc.ext_compat_id = opts->rndis_ext_compat_id; | ||
909 | |||
895 | mutex_init(&opts->lock); | 910 | mutex_init(&opts->lock); |
896 | opts->func_inst.free_func_inst = rndis_free_inst; | 911 | opts->func_inst.free_func_inst = rndis_free_inst; |
897 | opts->net = gether_setup_default(); | 912 | opts->net = gether_setup_default(); |
@@ -900,6 +915,7 @@ static struct usb_function_instance *rndis_alloc_inst(void) | |||
900 | kfree(opts); | 915 | kfree(opts); |
901 | return ERR_CAST(net); | 916 | return ERR_CAST(net); |
902 | } | 917 | } |
918 | INIT_LIST_HEAD(&opts->rndis_os_desc.ext_prop); | ||
903 | 919 | ||
904 | config_group_init_type_name(&opts->func_inst.group, "", | 920 | config_group_init_type_name(&opts->func_inst.group, "", |
905 | &rndis_func_type); | 921 | &rndis_func_type); |
@@ -925,6 +941,8 @@ static void rndis_unbind(struct usb_configuration *c, struct usb_function *f) | |||
925 | { | 941 | { |
926 | struct f_rndis *rndis = func_to_rndis(f); | 942 | struct f_rndis *rndis = func_to_rndis(f); |
927 | 943 | ||
944 | kfree(f->os_desc_table); | ||
945 | f->os_desc_n = 0; | ||
928 | usb_free_all_descriptors(f); | 946 | usb_free_all_descriptors(f); |
929 | 947 | ||
930 | kfree(rndis->notify_req->buf); | 948 | kfree(rndis->notify_req->buf); |
diff --git a/drivers/usb/gadget/u_rndis.h b/drivers/usb/gadget/u_rndis.h index 7291b15c9dce..e902aa42a297 100644 --- a/drivers/usb/gadget/u_rndis.h +++ b/drivers/usb/gadget/u_rndis.h | |||
@@ -26,6 +26,9 @@ struct f_rndis_opts { | |||
26 | bool bound; | 26 | bool bound; |
27 | bool borrowed_net; | 27 | bool borrowed_net; |
28 | 28 | ||
29 | struct usb_os_desc rndis_os_desc; | ||
30 | char rndis_ext_compat_id[16]; | ||
31 | |||
29 | /* | 32 | /* |
30 | * Read/write access to configfs attributes is handled by configfs. | 33 | * Read/write access to configfs attributes is handled by configfs. |
31 | * | 34 | * |