usb: gadget: f_rndis: OS descriptors support
In order for usb functions to expose OS descriptors they need to be made aware of OS descriptors. This involves extending the "options" structure and setting up appropriate associations. Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com> Acked-by: Michal Nazarewicz <mina86@mina86.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
		
					parent
					
						
							
								37a3a53342
							
						
					
				
			
			
				commit
				
					
						de7a8d2d53
					
				
			
		
					 2 changed files with 24 additions and 3 deletions
				
			
		|  | @ -682,6 +682,15 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) | ||||||
| 
 | 
 | ||||||
| 	rndis_opts = container_of(f->fi, struct f_rndis_opts, func_inst); | 	rndis_opts = container_of(f->fi, struct f_rndis_opts, func_inst); | ||||||
| 
 | 
 | ||||||
|  | 	if (cdev->use_os_string) { | ||||||
|  | 		f->os_desc_table = kzalloc(sizeof(*f->os_desc_table), | ||||||
|  | 					   GFP_KERNEL); | ||||||
|  | 		if (!f->os_desc_table) | ||||||
|  | 			return PTR_ERR(f->os_desc_table); | ||||||
|  | 		f->os_desc_n = 1; | ||||||
|  | 		f->os_desc_table[0].os_desc = &rndis_opts->rndis_os_desc; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * in drivers/usb/gadget/configfs.c:configfs_composite_bind() | 	 * in drivers/usb/gadget/configfs.c:configfs_composite_bind() | ||||||
| 	 * configurations are bound in sequence with list_for_each_entry, | 	 * configurations are bound in sequence with list_for_each_entry, | ||||||
|  | @ -693,14 +702,16 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) | ||||||
| 		gether_set_gadget(rndis_opts->net, cdev->gadget); | 		gether_set_gadget(rndis_opts->net, cdev->gadget); | ||||||
| 		status = gether_register_netdev(rndis_opts->net); | 		status = gether_register_netdev(rndis_opts->net); | ||||||
| 		if (status) | 		if (status) | ||||||
| 			return status; | 			goto fail; | ||||||
| 		rndis_opts->bound = true; | 		rndis_opts->bound = true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	us = usb_gstrings_attach(cdev, rndis_strings, | 	us = usb_gstrings_attach(cdev, rndis_strings, | ||||||
| 				 ARRAY_SIZE(rndis_string_defs)); | 				 ARRAY_SIZE(rndis_string_defs)); | ||||||
| 	if (IS_ERR(us)) | 	if (IS_ERR(us)) { | ||||||
| 		return PTR_ERR(us); | 		status = PTR_ERR(us); | ||||||
|  | 		goto fail; | ||||||
|  | 	} | ||||||
| 	rndis_control_intf.iInterface = us[0].id; | 	rndis_control_intf.iInterface = us[0].id; | ||||||
| 	rndis_data_intf.iInterface = us[1].id; | 	rndis_data_intf.iInterface = us[1].id; | ||||||
| 	rndis_iad_descriptor.iFunction = us[2].id; | 	rndis_iad_descriptor.iFunction = us[2].id; | ||||||
|  | @ -802,6 +813,8 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) | ||||||
| 	return 0; | 	return 0; | ||||||
| 
 | 
 | ||||||
| fail: | fail: | ||||||
|  | 	kfree(f->os_desc_table); | ||||||
|  | 	f->os_desc_n = 0; | ||||||
| 	usb_free_all_descriptors(f); | 	usb_free_all_descriptors(f); | ||||||
| 
 | 
 | ||||||
| 	if (rndis->notify_req) { | 	if (rndis->notify_req) { | ||||||
|  | @ -892,6 +905,8 @@ static struct usb_function_instance *rndis_alloc_inst(void) | ||||||
| 	opts = kzalloc(sizeof(*opts), GFP_KERNEL); | 	opts = kzalloc(sizeof(*opts), GFP_KERNEL); | ||||||
| 	if (!opts) | 	if (!opts) | ||||||
| 		return ERR_PTR(-ENOMEM); | 		return ERR_PTR(-ENOMEM); | ||||||
|  | 	opts->rndis_os_desc.ext_compat_id = opts->rndis_ext_compat_id; | ||||||
|  | 
 | ||||||
| 	mutex_init(&opts->lock); | 	mutex_init(&opts->lock); | ||||||
| 	opts->func_inst.free_func_inst = rndis_free_inst; | 	opts->func_inst.free_func_inst = rndis_free_inst; | ||||||
| 	opts->net = gether_setup_default(); | 	opts->net = gether_setup_default(); | ||||||
|  | @ -900,6 +915,7 @@ static struct usb_function_instance *rndis_alloc_inst(void) | ||||||
| 		kfree(opts); | 		kfree(opts); | ||||||
| 		return ERR_CAST(net); | 		return ERR_CAST(net); | ||||||
| 	} | 	} | ||||||
|  | 	INIT_LIST_HEAD(&opts->rndis_os_desc.ext_prop); | ||||||
| 
 | 
 | ||||||
| 	config_group_init_type_name(&opts->func_inst.group, "", | 	config_group_init_type_name(&opts->func_inst.group, "", | ||||||
| 				    &rndis_func_type); | 				    &rndis_func_type); | ||||||
|  | @ -925,6 +941,8 @@ static void rndis_unbind(struct usb_configuration *c, struct usb_function *f) | ||||||
| { | { | ||||||
| 	struct f_rndis		*rndis = func_to_rndis(f); | 	struct f_rndis		*rndis = func_to_rndis(f); | ||||||
| 
 | 
 | ||||||
|  | 	kfree(f->os_desc_table); | ||||||
|  | 	f->os_desc_n = 0; | ||||||
| 	usb_free_all_descriptors(f); | 	usb_free_all_descriptors(f); | ||||||
| 
 | 
 | ||||||
| 	kfree(rndis->notify_req->buf); | 	kfree(rndis->notify_req->buf); | ||||||
|  |  | ||||||
|  | @ -26,6 +26,9 @@ struct f_rndis_opts { | ||||||
| 	bool				bound; | 	bool				bound; | ||||||
| 	bool				borrowed_net; | 	bool				borrowed_net; | ||||||
| 
 | 
 | ||||||
|  | 	struct usb_os_desc		rndis_os_desc; | ||||||
|  | 	char				rndis_ext_compat_id[16]; | ||||||
|  | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * Read/write access to configfs attributes is handled by configfs. | 	 * Read/write access to configfs attributes is handled by configfs. | ||||||
| 	 * | 	 * | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andrzej Pietrasiewicz
				Andrzej Pietrasiewicz