diff options
Diffstat (limited to 'drivers/usb/gadget/f_rndis.c')
| -rw-r--r-- | drivers/usb/gadget/f_rndis.c | 131 | 
1 files changed, 54 insertions, 77 deletions
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index 717ed7f9563..9c41e9515b8 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -27,6 +27,7 @@  #include "u_ether_configfs.h"  #include "u_rndis.h"  #include "rndis.h" +#include "configfs.h"  /*   * This function is an RNDIS Ethernet port -- a Microsoft protocol that's @@ -377,7 +378,7 @@ static struct sk_buff *rndis_add_header(struct gether *port,  	if (skb2)  		rndis_add_hdr(skb2); -	dev_kfree_skb_any(skb); +	dev_kfree_skb(skb);  	return skb2;  } @@ -675,7 +676,6 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)  	int			status;  	struct usb_ep		*ep; -#ifndef USB_FRNDIS_INCLUDED  	struct f_rndis_opts *rndis_opts;  	if (!can_support_rndis(c)) @@ -683,6 +683,15 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)  	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 -ENOMEM; +		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()  	 * configurations are bound in sequence with list_for_each_entry, @@ -694,14 +703,16 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)  		gether_set_gadget(rndis_opts->net, cdev->gadget);  		status = gether_register_netdev(rndis_opts->net);  		if (status) -			return status; +			goto fail;  		rndis_opts->bound = true;  	} -#endif +  	us = usb_gstrings_attach(cdev, rndis_strings,  				 ARRAY_SIZE(rndis_string_defs)); -	if (IS_ERR(us)) -		return PTR_ERR(us); +	if (IS_ERR(us)) { +		status = PTR_ERR(us); +		goto fail; +	}  	rndis_control_intf.iInterface = us[0].id;  	rndis_data_intf.iInterface = us[1].id;  	rndis_iad_descriptor.iFunction = us[2].id; @@ -782,13 +793,6 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)  	rndis->port.open = rndis_open;  	rndis->port.close = rndis_close; -#ifdef USB_FRNDIS_INCLUDED -	status = rndis_register(rndis_response_available, rndis); -	if (status < 0) -		goto fail; -	rndis->config = status; -#endif -  	rndis_set_param_medium(rndis->config, RNDIS_MEDIUM_802_3, 0);  	rndis_set_host_mac(rndis->config, rndis->ethaddr); @@ -810,6 +814,8 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)  	return 0;  fail: +	kfree(f->os_desc_table); +	f->os_desc_n = 0;  	usb_free_all_descriptors(f);  	if (rndis->notify_req) { @@ -830,66 +836,6 @@ fail:  	return status;  } -#ifdef USB_FRNDIS_INCLUDED - -static void -rndis_old_unbind(struct usb_configuration *c, struct usb_function *f) -{ -	struct f_rndis		*rndis = func_to_rndis(f); - -	rndis_deregister(rndis->config); - -	usb_free_all_descriptors(f); - -	kfree(rndis->notify_req->buf); -	usb_ep_free_request(rndis->notify, rndis->notify_req); - -	kfree(rndis); -} - -int -rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], -		u32 vendorID, const char *manufacturer, struct eth_dev *dev) -{ -	struct f_rndis	*rndis; -	int		status; - -	/* allocate and initialize one new instance */ -	status = -ENOMEM; -	rndis = kzalloc(sizeof *rndis, GFP_KERNEL); -	if (!rndis) -		goto fail; - -	memcpy(rndis->ethaddr, ethaddr, ETH_ALEN); -	rndis->vendorID = vendorID; -	rndis->manufacturer = manufacturer; - -	rndis->port.ioport = dev; -	/* RNDIS activates when the host changes this filter */ -	rndis->port.cdc_filter = 0; - -	/* RNDIS has special (and complex) framing */ -	rndis->port.header_len = sizeof(struct rndis_packet_msg_type); -	rndis->port.wrap = rndis_add_header; -	rndis->port.unwrap = rndis_rm_hdr; - -	rndis->port.func.name = "rndis"; -	/* descriptors are per-instance copies */ -	rndis->port.func.bind = rndis_bind; -	rndis->port.func.unbind = rndis_old_unbind; -	rndis->port.func.set_alt = rndis_set_alt; -	rndis->port.func.setup = rndis_setup; -	rndis->port.func.disable = rndis_disable; - -	status = usb_add_function(c, &rndis->port.func); -	if (status) -		kfree(rndis); -fail: -	return status; -} - -#else -  void rndis_borrow_net(struct usb_function_instance *f, struct net_device *net)  {  	struct f_rndis_opts *opts; @@ -902,7 +848,7 @@ void rndis_borrow_net(struct usb_function_instance *f, struct net_device *net)  	opts->borrowed_net = opts->bound = true;  	opts->net = net;  } -EXPORT_SYMBOL(rndis_borrow_net); +EXPORT_SYMBOL_GPL(rndis_borrow_net);  static inline struct f_rndis_opts *to_f_rndis_opts(struct config_item *item)  { @@ -950,16 +896,22 @@ static void rndis_free_inst(struct usb_function_instance *f)  		else  			free_netdev(opts->net);  	} + +	kfree(opts->rndis_os_desc.group.default_groups); /* single VLA chunk */  	kfree(opts);  }  static struct usb_function_instance *rndis_alloc_inst(void)  {  	struct f_rndis_opts *opts; +	struct usb_os_desc *descs[1]; +	char *names[1];  	opts = kzalloc(sizeof(*opts), GFP_KERNEL);  	if (!opts)  		return ERR_PTR(-ENOMEM); +	opts->rndis_os_desc.ext_compat_id = opts->rndis_ext_compat_id; +  	mutex_init(&opts->lock);  	opts->func_inst.free_func_inst = rndis_free_inst;  	opts->net = gether_setup_default(); @@ -968,7 +920,12 @@ static struct usb_function_instance *rndis_alloc_inst(void)  		kfree(opts);  		return ERR_CAST(net);  	} +	INIT_LIST_HEAD(&opts->rndis_os_desc.ext_prop); +	descs[0] = &opts->rndis_os_desc; +	names[0] = "rndis"; +	usb_os_desc_prepare_interf_dir(&opts->func_inst.group, 1, descs, +				       names, THIS_MODULE);  	config_group_init_type_name(&opts->func_inst.group, "",  				    &rndis_func_type); @@ -993,6 +950,8 @@ static void rndis_unbind(struct usb_configuration *c, struct usb_function *f)  {  	struct f_rndis		*rndis = func_to_rndis(f); +	kfree(f->os_desc_table); +	f->os_desc_n = 0;  	usb_free_all_descriptors(f);  	kfree(rndis->notify_req->buf); @@ -1047,8 +1006,26 @@ static struct usb_function *rndis_alloc(struct usb_function_instance *fi)  	return &rndis->port.func;  } -DECLARE_USB_FUNCTION_INIT(rndis, rndis_alloc_inst, rndis_alloc); +DECLARE_USB_FUNCTION(rndis, rndis_alloc_inst, rndis_alloc); + +static int __init rndis_mod_init(void) +{ +	int ret; + +	ret = rndis_init(); +	if (ret) +		return ret; + +	return usb_function_register(&rndisusb_func); +} +module_init(rndis_mod_init); + +static void __exit rndis_mod_exit(void) +{ +	usb_function_unregister(&rndisusb_func); +	rndis_exit(); +} +module_exit(rndis_mod_exit); +  MODULE_LICENSE("GPL");  MODULE_AUTHOR("David Brownell"); - -#endif  | 
