Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: gadget: add RNDIS configfs options for class/subclass/protocol

This adds 3 new options to the RNDIS gadget function configs. It allows
overriding the default USB interface class/subclass/protocol.

The motivation for this is that if you set the values to "ef" (Misc),
"04" (RNDIS), "01" (Ethernet) respectively, then the device will be
recognized by the rndiscmp.inf file in Windows Vista and newer and will
cause Windows to load the correct RNDIS driver without the need for a
custom (signed) .inf file.

Signed-off-by: David Lechner <david@lechnology.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>

authored by

David Lechner and committed by
Felipe Balbi
73517cf4 6cea1449

+62
+3
Documentation/ABI/testing/configfs-usb-gadget-rndis
··· 12 12 Ethernet over USB link 13 13 dev_addr - MAC address of device's end of this 14 14 Ethernet over USB link 15 + class - USB interface class, default is 02 (hex) 16 + subclass - USB interface subclass, default is 06 (hex) 17 + protocol - USB interface protocol, default is 00 (hex)
+20
drivers/usb/gadget/function/f_rndis.c
··· 691 691 f->os_desc_table[0].os_desc = &rndis_opts->rndis_os_desc; 692 692 } 693 693 694 + rndis_iad_descriptor.bFunctionClass = rndis_opts->class; 695 + rndis_iad_descriptor.bFunctionSubClass = rndis_opts->subclass; 696 + rndis_iad_descriptor.bFunctionProtocol = rndis_opts->protocol; 697 + 694 698 /* 695 699 * in drivers/usb/gadget/configfs.c:configfs_composite_bind() 696 700 * configurations are bound in sequence with list_for_each_entry, ··· 870 866 /* f_rndis_opts_ifname */ 871 867 USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(rndis); 872 868 869 + /* f_rndis_opts_class */ 870 + USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(rndis, class); 871 + 872 + /* f_rndis_opts_subclass */ 873 + USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(rndis, subclass); 874 + 875 + /* f_rndis_opts_protocol */ 876 + USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(rndis, protocol); 877 + 873 878 static struct configfs_attribute *rndis_attrs[] = { 874 879 &rndis_opts_attr_dev_addr, 875 880 &rndis_opts_attr_host_addr, 876 881 &rndis_opts_attr_qmult, 877 882 &rndis_opts_attr_ifname, 883 + &rndis_opts_attr_class, 884 + &rndis_opts_attr_subclass, 885 + &rndis_opts_attr_protocol, 878 886 NULL, 879 887 }; 880 888 ··· 931 915 return ERR_CAST(net); 932 916 } 933 917 INIT_LIST_HEAD(&opts->rndis_os_desc.ext_prop); 918 + 919 + opts->class = rndis_iad_descriptor.bFunctionClass; 920 + opts->subclass = rndis_iad_descriptor.bFunctionSubClass; 921 + opts->protocol = rndis_iad_descriptor.bFunctionProtocol; 934 922 935 923 descs[0] = &opts->rndis_os_desc; 936 924 names[0] = "rndis";
+35
drivers/usb/gadget/function/u_ether_configfs.h
··· 153 153 \ 154 154 CONFIGFS_ATTR_RO(_f_##_opts_, ifname) 155 155 156 + #define USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(_f_, _n_) \ 157 + static ssize_t _f_##_opts_##_n_##_show(struct config_item *item,\ 158 + char *page) \ 159 + { \ 160 + struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ 161 + int ret; \ 162 + \ 163 + mutex_lock(&opts->lock); \ 164 + ret = sprintf(page, "%02x\n", opts->_n_); \ 165 + mutex_unlock(&opts->lock); \ 166 + \ 167 + return ret; \ 168 + } \ 169 + \ 170 + static ssize_t _f_##_opts_##_n_##_store(struct config_item *item,\ 171 + const char *page, \ 172 + size_t len) \ 173 + { \ 174 + struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ 175 + int ret; \ 176 + u8 val; \ 177 + \ 178 + mutex_lock(&opts->lock); \ 179 + ret = sscanf(page, "%02hhx", &val); \ 180 + if (ret > 0) { \ 181 + opts->_n_ = val; \ 182 + ret = len; \ 183 + } \ 184 + mutex_unlock(&opts->lock); \ 185 + \ 186 + return ret; \ 187 + } \ 188 + \ 189 + CONFIGFS_ATTR(_f_##_opts_, _n_) 190 + 156 191 #endif /* __U_ETHER_CONFIGFS_H */
+4
drivers/usb/gadget/function/u_rndis.h
··· 29 29 struct usb_os_desc rndis_os_desc; 30 30 char rndis_ext_compat_id[16]; 31 31 32 + u8 class; 33 + u8 subclass; 34 + u8 protocol; 35 + 32 36 /* 33 37 * Read/write access to configfs attributes is handled by configfs. 34 38 *