Re: [PATCH 1/2] usb: gadget: f_ncm: Add OS descriptor support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Ping ?

Did I do something wrong with submission or is it queued for later ?
4.19 is missing these which make USB NCM unusable with Win >= 10. 

 Jocke

On Wed, 2023-05-31 at 19:33 +0200, Joakim Tjernlund wrote:
> From: Romain Izard <romain.izard.pro@xxxxxxxxx>
> 
> To be able to use the default USB class drivers available in Microsoft
> Windows, we need to add OS descriptors to the exported USB gadget to
> tell the OS that we are compatible with the built-in drivers.
> 
> Copy the OS descriptor support from f_rndis into f_ncm. As a result,
> using the WINNCM compatible ID, the UsbNcm driver is loaded on
> enumeration without the need for a custom driver or inf file.
> 
> Signed-off-by: Romain Izard <romain.izard.pro@xxxxxxxxx>
> Signed-off-by: Felipe Balbi <felipe.balbi@xxxxxxxxxxxxxxx>
> Signed-off-by: Joakim Tjernlund <joakim.tjernlund@xxxxxxxxxxxx>
> Cc: stable@xxxxxxxxxxxxxxx # v4.19
> ---
> 
>  Seems to have been forgotten when backporting NCM fixes.
>  Needed to make Win10 accept Linux NCM gadget ethernet
> 
>  drivers/usb/gadget/function/f_ncm.c | 47 +++++++++++++++++++++++++++--
>  drivers/usb/gadget/function/u_ncm.h |  3 ++
>  2 files changed, 47 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c
> index e4aa370e86a9..b4571633f7b5 100644
> --- a/drivers/usb/gadget/function/f_ncm.c
> +++ b/drivers/usb/gadget/function/f_ncm.c
> @@ -23,6 +23,7 @@
>  #include "u_ether.h"
>  #include "u_ether_configfs.h"
>  #include "u_ncm.h"
> +#include "configfs.h"
>  
>  /*
>   * This function is a "CDC Network Control Model" (CDC NCM) Ethernet link.
> @@ -1432,6 +1433,16 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
>  		return -EINVAL;
>  
>  	ncm_opts = container_of(f->fi, struct f_ncm_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 = &ncm_opts->ncm_os_desc;
> +	}
> +
>  	/*
>  	 * in drivers/usb/gadget/configfs.c:configfs_composite_bind()
>  	 * configurations are bound in sequence with list_for_each_entry,
> @@ -1445,13 +1456,15 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
>  		status = gether_register_netdev(ncm_opts->net);
>  		mutex_unlock(&ncm_opts->lock);
>  		if (status)
> -			return status;
> +			goto fail;
>  		ncm_opts->bound = true;
>  	}
>  	us = usb_gstrings_attach(cdev, ncm_strings,
>  				 ARRAY_SIZE(ncm_string_defs));
> -	if (IS_ERR(us))
> -		return PTR_ERR(us);
> +	if (IS_ERR(us)) {
> +		status = PTR_ERR(us);
> +		goto fail;
> +	}
>  	ncm_control_intf.iInterface = us[STRING_CTRL_IDX].id;
>  	ncm_data_nop_intf.iInterface = us[STRING_DATA_IDX].id;
>  	ncm_data_intf.iInterface = us[STRING_DATA_IDX].id;
> @@ -1468,6 +1481,10 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
>  	ncm_control_intf.bInterfaceNumber = status;
>  	ncm_union_desc.bMasterInterface0 = status;
>  
> +	if (cdev->use_os_string)
> +		f->os_desc_table[0].if_id =
> +			ncm_iad_desc.bFirstInterface;
> +
>  	status = usb_interface_id(c, f);
>  	if (status < 0)
>  		goto fail;
> @@ -1547,6 +1564,9 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
>  	return 0;
>  
>  fail:
> +	kfree(f->os_desc_table);
> +	f->os_desc_n = 0;
> +
>  	if (ncm->notify_req) {
>  		kfree(ncm->notify_req->buf);
>  		usb_ep_free_request(ncm->notify, ncm->notify_req);
> @@ -1601,16 +1621,22 @@ static void ncm_free_inst(struct usb_function_instance *f)
>  		gether_cleanup(netdev_priv(opts->net));
>  	else
>  		free_netdev(opts->net);
> +	kfree(opts->ncm_interf_group);
>  	kfree(opts);
>  }
>  
>  static struct usb_function_instance *ncm_alloc_inst(void)
>  {
>  	struct f_ncm_opts *opts;
> +	struct usb_os_desc *descs[1];
> +	char *names[1];
> +	struct config_group *ncm_interf_group;
>  
>  	opts = kzalloc(sizeof(*opts), GFP_KERNEL);
>  	if (!opts)
>  		return ERR_PTR(-ENOMEM);
> +	opts->ncm_os_desc.ext_compat_id = opts->ncm_ext_compat_id;
> +
>  	mutex_init(&opts->lock);
>  	opts->func_inst.free_func_inst = ncm_free_inst;
>  	opts->net = gether_setup_default();
> @@ -1619,8 +1645,20 @@ static struct usb_function_instance *ncm_alloc_inst(void)
>  		kfree(opts);
>  		return ERR_CAST(net);
>  	}
> +	INIT_LIST_HEAD(&opts->ncm_os_desc.ext_prop);
> +
> +	descs[0] = &opts->ncm_os_desc;
> +	names[0] = "ncm";
>  
>  	config_group_init_type_name(&opts->func_inst.group, "", &ncm_func_type);
> +	ncm_interf_group =
> +		usb_os_desc_prepare_interf_dir(&opts->func_inst.group, 1, descs,
> +					       names, THIS_MODULE);
> +	if (IS_ERR(ncm_interf_group)) {
> +		ncm_free_inst(&opts->func_inst);
> +		return ERR_CAST(ncm_interf_group);
> +	}
> +	opts->ncm_interf_group = ncm_interf_group;
>  
>  	return &opts->func_inst;
>  }
> @@ -1646,6 +1684,9 @@ static void ncm_unbind(struct usb_configuration *c, struct usb_function *f)
>  
>  	hrtimer_cancel(&ncm->task_timer);
>  
> +	kfree(f->os_desc_table);
> +	f->os_desc_n = 0;
> +
>  	ncm_string_defs[0].id = 0;
>  	usb_free_all_descriptors(f);
>  
> diff --git a/drivers/usb/gadget/function/u_ncm.h b/drivers/usb/gadget/function/u_ncm.h
> index 67324f983343..dfd75ad61b3f 100644
> --- a/drivers/usb/gadget/function/u_ncm.h
> +++ b/drivers/usb/gadget/function/u_ncm.h
> @@ -20,6 +20,9 @@ struct f_ncm_opts {
>  	struct net_device		*net;
>  	bool				bound;
>  
> +	struct config_group		*ncm_interf_group;
> +	struct usb_os_desc		ncm_os_desc;
> +	char				ncm_ext_compat_id[16];
>  	/*
>  	 * Read/write access to configfs attributes is handled by configfs.
>  	 *





[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux