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. > *