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