f_subset.c (14793B)
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * f_subset.c -- "CDC Subset" Ethernet link function driver 4 * 5 * Copyright (C) 2003-2005,2008 David Brownell 6 * Copyright (C) 2008 Nokia Corporation 7 */ 8 9#include <linux/slab.h> 10#include <linux/kernel.h> 11#include <linux/module.h> 12#include <linux/device.h> 13#include <linux/etherdevice.h> 14 15#include "u_ether.h" 16#include "u_ether_configfs.h" 17#include "u_gether.h" 18 19/* 20 * This function packages a simple "CDC Subset" Ethernet port with no real 21 * control mechanisms; just raw data transfer over two bulk endpoints. 22 * The data transfer model is exactly that of CDC Ethernet, which is 23 * why we call it the "CDC Subset". 24 * 25 * Because it's not standardized, this has some interoperability issues. 26 * They mostly relate to driver binding, since the data transfer model is 27 * so simple (CDC Ethernet). The original versions of this protocol used 28 * specific product/vendor IDs: byteswapped IDs for Digital Equipment's 29 * SA-1100 "Itsy" board, which could run Linux 2.4 kernels and supported 30 * daughtercards with USB peripheral connectors. (It was used more often 31 * with other boards, using the Itsy identifiers.) Linux hosts recognized 32 * this with CONFIG_USB_ARMLINUX; these devices have only one configuration 33 * and one interface. 34 * 35 * At some point, MCCI defined a (nonconformant) CDC MDLM variant called 36 * "SAFE", which happens to have a mode which is identical to the "CDC 37 * Subset" in terms of data transfer and lack of control model. This was 38 * adopted by later Sharp Zaurus models, and by some other software which 39 * Linux hosts recognize with CONFIG_USB_NET_ZAURUS. 40 * 41 * Because Microsoft's RNDIS drivers are far from robust, we added a few 42 * descriptors to the CDC Subset code, making this code look like a SAFE 43 * implementation. This lets you use MCCI's host side MS-Windows drivers 44 * if you get fed up with RNDIS. It also makes it easier for composite 45 * drivers to work, since they can use class based binding instead of 46 * caring about specific product and vendor IDs. 47 */ 48 49struct f_gether { 50 struct gether port; 51 52 char ethaddr[14]; 53}; 54 55static inline struct f_gether *func_to_geth(struct usb_function *f) 56{ 57 return container_of(f, struct f_gether, port.func); 58} 59 60/*-------------------------------------------------------------------------*/ 61 62/* 63 * "Simple" CDC-subset option is a simple vendor-neutral model that most 64 * full speed controllers can handle: one interface, two bulk endpoints. 65 * To assist host side drivers, we fancy it up a bit, and add descriptors so 66 * some host side drivers will understand it as a "SAFE" variant. 67 * 68 * "SAFE" loosely follows CDC WMC MDLM, violating the spec in various ways. 69 * Data endpoints live in the control interface, there's no data interface. 70 * And it's not used to talk to a cell phone radio. 71 */ 72 73/* interface descriptor: */ 74 75static struct usb_interface_descriptor subset_data_intf = { 76 .bLength = sizeof subset_data_intf, 77 .bDescriptorType = USB_DT_INTERFACE, 78 79 /* .bInterfaceNumber = DYNAMIC */ 80 .bAlternateSetting = 0, 81 .bNumEndpoints = 2, 82 .bInterfaceClass = USB_CLASS_COMM, 83 .bInterfaceSubClass = USB_CDC_SUBCLASS_MDLM, 84 .bInterfaceProtocol = 0, 85 /* .iInterface = DYNAMIC */ 86}; 87 88static struct usb_cdc_header_desc mdlm_header_desc = { 89 .bLength = sizeof mdlm_header_desc, 90 .bDescriptorType = USB_DT_CS_INTERFACE, 91 .bDescriptorSubType = USB_CDC_HEADER_TYPE, 92 93 .bcdCDC = cpu_to_le16(0x0110), 94}; 95 96static struct usb_cdc_mdlm_desc mdlm_desc = { 97 .bLength = sizeof mdlm_desc, 98 .bDescriptorType = USB_DT_CS_INTERFACE, 99 .bDescriptorSubType = USB_CDC_MDLM_TYPE, 100 101 .bcdVersion = cpu_to_le16(0x0100), 102 .bGUID = { 103 0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6, 104 0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f, 105 }, 106}; 107 108/* since "usb_cdc_mdlm_detail_desc" is a variable length structure, we 109 * can't really use its struct. All we do here is say that we're using 110 * the submode of "SAFE" which directly matches the CDC Subset. 111 */ 112static u8 mdlm_detail_desc[] = { 113 6, 114 USB_DT_CS_INTERFACE, 115 USB_CDC_MDLM_DETAIL_TYPE, 116 117 0, /* "SAFE" */ 118 0, /* network control capabilities (none) */ 119 0, /* network data capabilities ("raw" encapsulation) */ 120}; 121 122static struct usb_cdc_ether_desc ether_desc = { 123 .bLength = sizeof ether_desc, 124 .bDescriptorType = USB_DT_CS_INTERFACE, 125 .bDescriptorSubType = USB_CDC_ETHERNET_TYPE, 126 127 /* this descriptor actually adds value, surprise! */ 128 /* .iMACAddress = DYNAMIC */ 129 .bmEthernetStatistics = cpu_to_le32(0), /* no statistics */ 130 .wMaxSegmentSize = cpu_to_le16(ETH_FRAME_LEN), 131 .wNumberMCFilters = cpu_to_le16(0), 132 .bNumberPowerFilters = 0, 133}; 134 135/* full speed support: */ 136 137static struct usb_endpoint_descriptor fs_subset_in_desc = { 138 .bLength = USB_DT_ENDPOINT_SIZE, 139 .bDescriptorType = USB_DT_ENDPOINT, 140 141 .bEndpointAddress = USB_DIR_IN, 142 .bmAttributes = USB_ENDPOINT_XFER_BULK, 143}; 144 145static struct usb_endpoint_descriptor fs_subset_out_desc = { 146 .bLength = USB_DT_ENDPOINT_SIZE, 147 .bDescriptorType = USB_DT_ENDPOINT, 148 149 .bEndpointAddress = USB_DIR_OUT, 150 .bmAttributes = USB_ENDPOINT_XFER_BULK, 151}; 152 153static struct usb_descriptor_header *fs_eth_function[] = { 154 (struct usb_descriptor_header *) &subset_data_intf, 155 (struct usb_descriptor_header *) &mdlm_header_desc, 156 (struct usb_descriptor_header *) &mdlm_desc, 157 (struct usb_descriptor_header *) &mdlm_detail_desc, 158 (struct usb_descriptor_header *) ðer_desc, 159 (struct usb_descriptor_header *) &fs_subset_in_desc, 160 (struct usb_descriptor_header *) &fs_subset_out_desc, 161 NULL, 162}; 163 164/* high speed support: */ 165 166static struct usb_endpoint_descriptor hs_subset_in_desc = { 167 .bLength = USB_DT_ENDPOINT_SIZE, 168 .bDescriptorType = USB_DT_ENDPOINT, 169 170 .bmAttributes = USB_ENDPOINT_XFER_BULK, 171 .wMaxPacketSize = cpu_to_le16(512), 172}; 173 174static struct usb_endpoint_descriptor hs_subset_out_desc = { 175 .bLength = USB_DT_ENDPOINT_SIZE, 176 .bDescriptorType = USB_DT_ENDPOINT, 177 178 .bmAttributes = USB_ENDPOINT_XFER_BULK, 179 .wMaxPacketSize = cpu_to_le16(512), 180}; 181 182static struct usb_descriptor_header *hs_eth_function[] = { 183 (struct usb_descriptor_header *) &subset_data_intf, 184 (struct usb_descriptor_header *) &mdlm_header_desc, 185 (struct usb_descriptor_header *) &mdlm_desc, 186 (struct usb_descriptor_header *) &mdlm_detail_desc, 187 (struct usb_descriptor_header *) ðer_desc, 188 (struct usb_descriptor_header *) &hs_subset_in_desc, 189 (struct usb_descriptor_header *) &hs_subset_out_desc, 190 NULL, 191}; 192 193/* super speed support: */ 194 195static struct usb_endpoint_descriptor ss_subset_in_desc = { 196 .bLength = USB_DT_ENDPOINT_SIZE, 197 .bDescriptorType = USB_DT_ENDPOINT, 198 199 .bmAttributes = USB_ENDPOINT_XFER_BULK, 200 .wMaxPacketSize = cpu_to_le16(1024), 201}; 202 203static struct usb_endpoint_descriptor ss_subset_out_desc = { 204 .bLength = USB_DT_ENDPOINT_SIZE, 205 .bDescriptorType = USB_DT_ENDPOINT, 206 207 .bmAttributes = USB_ENDPOINT_XFER_BULK, 208 .wMaxPacketSize = cpu_to_le16(1024), 209}; 210 211static struct usb_ss_ep_comp_descriptor ss_subset_bulk_comp_desc = { 212 .bLength = sizeof ss_subset_bulk_comp_desc, 213 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, 214 215 /* the following 2 values can be tweaked if necessary */ 216 /* .bMaxBurst = 0, */ 217 /* .bmAttributes = 0, */ 218}; 219 220static struct usb_descriptor_header *ss_eth_function[] = { 221 (struct usb_descriptor_header *) &subset_data_intf, 222 (struct usb_descriptor_header *) &mdlm_header_desc, 223 (struct usb_descriptor_header *) &mdlm_desc, 224 (struct usb_descriptor_header *) &mdlm_detail_desc, 225 (struct usb_descriptor_header *) ðer_desc, 226 (struct usb_descriptor_header *) &ss_subset_in_desc, 227 (struct usb_descriptor_header *) &ss_subset_bulk_comp_desc, 228 (struct usb_descriptor_header *) &ss_subset_out_desc, 229 (struct usb_descriptor_header *) &ss_subset_bulk_comp_desc, 230 NULL, 231}; 232 233/* string descriptors: */ 234 235static struct usb_string geth_string_defs[] = { 236 [0].s = "CDC Ethernet Subset/SAFE", 237 [1].s = "", 238 { } /* end of list */ 239}; 240 241static struct usb_gadget_strings geth_string_table = { 242 .language = 0x0409, /* en-us */ 243 .strings = geth_string_defs, 244}; 245 246static struct usb_gadget_strings *geth_strings[] = { 247 &geth_string_table, 248 NULL, 249}; 250 251/*-------------------------------------------------------------------------*/ 252 253static int geth_set_alt(struct usb_function *f, unsigned intf, unsigned alt) 254{ 255 struct f_gether *geth = func_to_geth(f); 256 struct usb_composite_dev *cdev = f->config->cdev; 257 struct net_device *net; 258 259 /* we know alt == 0, so this is an activation or a reset */ 260 261 if (geth->port.in_ep->enabled) { 262 DBG(cdev, "reset cdc subset\n"); 263 gether_disconnect(&geth->port); 264 } 265 266 DBG(cdev, "init + activate cdc subset\n"); 267 if (config_ep_by_speed(cdev->gadget, f, geth->port.in_ep) || 268 config_ep_by_speed(cdev->gadget, f, geth->port.out_ep)) { 269 geth->port.in_ep->desc = NULL; 270 geth->port.out_ep->desc = NULL; 271 return -EINVAL; 272 } 273 274 net = gether_connect(&geth->port); 275 return PTR_ERR_OR_ZERO(net); 276} 277 278static void geth_disable(struct usb_function *f) 279{ 280 struct f_gether *geth = func_to_geth(f); 281 struct usb_composite_dev *cdev = f->config->cdev; 282 283 DBG(cdev, "net deactivated\n"); 284 gether_disconnect(&geth->port); 285} 286 287/*-------------------------------------------------------------------------*/ 288 289/* serial function driver setup/binding */ 290 291static int 292geth_bind(struct usb_configuration *c, struct usb_function *f) 293{ 294 struct usb_composite_dev *cdev = c->cdev; 295 struct f_gether *geth = func_to_geth(f); 296 struct usb_string *us; 297 int status; 298 struct usb_ep *ep; 299 300 struct f_gether_opts *gether_opts; 301 302 gether_opts = container_of(f->fi, struct f_gether_opts, func_inst); 303 304 /* 305 * in drivers/usb/gadget/configfs.c:configfs_composite_bind() 306 * configurations are bound in sequence with list_for_each_entry, 307 * in each configuration its functions are bound in sequence 308 * with list_for_each_entry, so we assume no race condition 309 * with regard to gether_opts->bound access 310 */ 311 if (!gether_opts->bound) { 312 mutex_lock(&gether_opts->lock); 313 gether_set_gadget(gether_opts->net, cdev->gadget); 314 status = gether_register_netdev(gether_opts->net); 315 mutex_unlock(&gether_opts->lock); 316 if (status) 317 return status; 318 gether_opts->bound = true; 319 } 320 321 us = usb_gstrings_attach(cdev, geth_strings, 322 ARRAY_SIZE(geth_string_defs)); 323 if (IS_ERR(us)) 324 return PTR_ERR(us); 325 326 subset_data_intf.iInterface = us[0].id; 327 ether_desc.iMACAddress = us[1].id; 328 329 /* allocate instance-specific interface IDs */ 330 status = usb_interface_id(c, f); 331 if (status < 0) 332 goto fail; 333 subset_data_intf.bInterfaceNumber = status; 334 335 status = -ENODEV; 336 337 /* allocate instance-specific endpoints */ 338 ep = usb_ep_autoconfig(cdev->gadget, &fs_subset_in_desc); 339 if (!ep) 340 goto fail; 341 geth->port.in_ep = ep; 342 343 ep = usb_ep_autoconfig(cdev->gadget, &fs_subset_out_desc); 344 if (!ep) 345 goto fail; 346 geth->port.out_ep = ep; 347 348 /* support all relevant hardware speeds... we expect that when 349 * hardware is dual speed, all bulk-capable endpoints work at 350 * both speeds 351 */ 352 hs_subset_in_desc.bEndpointAddress = fs_subset_in_desc.bEndpointAddress; 353 hs_subset_out_desc.bEndpointAddress = 354 fs_subset_out_desc.bEndpointAddress; 355 356 ss_subset_in_desc.bEndpointAddress = fs_subset_in_desc.bEndpointAddress; 357 ss_subset_out_desc.bEndpointAddress = 358 fs_subset_out_desc.bEndpointAddress; 359 360 status = usb_assign_descriptors(f, fs_eth_function, hs_eth_function, 361 ss_eth_function, ss_eth_function); 362 if (status) 363 goto fail; 364 365 /* NOTE: all that is done without knowing or caring about 366 * the network link ... which is unavailable to this code 367 * until we're activated via set_alt(). 368 */ 369 370 DBG(cdev, "CDC Subset: %s speed IN/%s OUT/%s\n", 371 gadget_is_superspeed(c->cdev->gadget) ? "super" : 372 gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", 373 geth->port.in_ep->name, geth->port.out_ep->name); 374 return 0; 375 376fail: 377 ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); 378 379 return status; 380} 381 382static inline struct f_gether_opts *to_f_gether_opts(struct config_item *item) 383{ 384 return container_of(to_config_group(item), struct f_gether_opts, 385 func_inst.group); 386} 387 388/* f_gether_item_ops */ 389USB_ETHERNET_CONFIGFS_ITEM(gether); 390 391/* f_gether_opts_dev_addr */ 392USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(gether); 393 394/* f_gether_opts_host_addr */ 395USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(gether); 396 397/* f_gether_opts_qmult */ 398USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(gether); 399 400/* f_gether_opts_ifname */ 401USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(gether); 402 403static struct configfs_attribute *gether_attrs[] = { 404 &gether_opts_attr_dev_addr, 405 &gether_opts_attr_host_addr, 406 &gether_opts_attr_qmult, 407 &gether_opts_attr_ifname, 408 NULL, 409}; 410 411static const struct config_item_type gether_func_type = { 412 .ct_item_ops = &gether_item_ops, 413 .ct_attrs = gether_attrs, 414 .ct_owner = THIS_MODULE, 415}; 416 417static void geth_free_inst(struct usb_function_instance *f) 418{ 419 struct f_gether_opts *opts; 420 421 opts = container_of(f, struct f_gether_opts, func_inst); 422 if (opts->bound) 423 gether_cleanup(netdev_priv(opts->net)); 424 else 425 free_netdev(opts->net); 426 kfree(opts); 427} 428 429static struct usb_function_instance *geth_alloc_inst(void) 430{ 431 struct f_gether_opts *opts; 432 433 opts = kzalloc(sizeof(*opts), GFP_KERNEL); 434 if (!opts) 435 return ERR_PTR(-ENOMEM); 436 mutex_init(&opts->lock); 437 opts->func_inst.free_func_inst = geth_free_inst; 438 opts->net = gether_setup_default(); 439 if (IS_ERR(opts->net)) { 440 struct net_device *net = opts->net; 441 kfree(opts); 442 return ERR_CAST(net); 443 } 444 445 config_group_init_type_name(&opts->func_inst.group, "", 446 &gether_func_type); 447 448 return &opts->func_inst; 449} 450 451static void geth_free(struct usb_function *f) 452{ 453 struct f_gether *eth; 454 455 eth = func_to_geth(f); 456 kfree(eth); 457} 458 459static void geth_unbind(struct usb_configuration *c, struct usb_function *f) 460{ 461 geth_string_defs[0].id = 0; 462 usb_free_all_descriptors(f); 463} 464 465static struct usb_function *geth_alloc(struct usb_function_instance *fi) 466{ 467 struct f_gether *geth; 468 struct f_gether_opts *opts; 469 int status; 470 471 /* allocate and initialize one new instance */ 472 geth = kzalloc(sizeof(*geth), GFP_KERNEL); 473 if (!geth) 474 return ERR_PTR(-ENOMEM); 475 476 opts = container_of(fi, struct f_gether_opts, func_inst); 477 478 mutex_lock(&opts->lock); 479 opts->refcnt++; 480 /* export host's Ethernet address in CDC format */ 481 status = gether_get_host_addr_cdc(opts->net, geth->ethaddr, 482 sizeof(geth->ethaddr)); 483 if (status < 12) { 484 kfree(geth); 485 mutex_unlock(&opts->lock); 486 return ERR_PTR(-EINVAL); 487 } 488 geth_string_defs[1].s = geth->ethaddr; 489 490 geth->port.ioport = netdev_priv(opts->net); 491 mutex_unlock(&opts->lock); 492 geth->port.cdc_filter = DEFAULT_FILTER; 493 494 geth->port.func.name = "cdc_subset"; 495 geth->port.func.bind = geth_bind; 496 geth->port.func.unbind = geth_unbind; 497 geth->port.func.set_alt = geth_set_alt; 498 geth->port.func.disable = geth_disable; 499 geth->port.func.free_func = geth_free; 500 501 return &geth->port.func; 502} 503 504DECLARE_USB_FUNCTION_INIT(geth, geth_alloc_inst, geth_alloc); 505MODULE_LICENSE("GPL"); 506MODULE_AUTHOR("David Brownell");