| Start/ | End/ | |||
| True | False | - | Line | Source |
| 1 | /* | |||
| 2 | * ether.c -- Ethernet gadget driver, with CDC and non-CDC options | |||
| 3 | * | |||
| 4 | * Copyright (C) 2003-2005 David Brownell | |||
| 5 | * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger | |||
| 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 | * This program is distributed in the hope that it will be useful, | |||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| 15 | * GNU General Public License for more details. | |||
| 16 | * | |||
| 17 | * You should have received a copy of the GNU General Public License | |||
| 18 | * along with this program; if not, write to the Free Software | |||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
| 20 | */ | |||
| 21 | ||||
| 22 | ||||
| 23 | // #define DEBUG 1 | |||
| 24 | // #define VERBOSE | |||
| 25 | ||||
| 26 | #include <linux/config.h> | |||
| 27 | #include <linux/module.h> | |||
| 28 | #include <linux/kernel.h> | |||
| 29 | #include <linux/delay.h> | |||
| 30 | #include <linux/ioport.h> | |||
| 31 | #include <linux/sched.h> | |||
| 32 | #include <linux/slab.h> | |||
| 33 | #include <linux/smp_lock.h> | |||
| 34 | #include <linux/errno.h> | |||
| 35 | #include <linux/init.h> | |||
| 36 | #include <linux/timer.h> | |||
| 37 | #include <linux/list.h> | |||
| 38 | #include <linux/interrupt.h> | |||
| 39 | #include <linux/utsname.h> | |||
| 40 | #include <linux/device.h> | |||
| 41 | #include <linux/moduleparam.h> | |||
| 42 | #include <linux/ctype.h> | |||
| 43 | ||||
| 44 | #include <asm/byteorder.h> | |||
| 45 | #include <asm/io.h> | |||
| 46 | #include <asm/irq.h> | |||
| 47 | #include <asm/system.h> | |||
| 48 | #include <asm/uaccess.h> | |||
| 49 | #include <asm/unaligned.h> | |||
| 50 | ||||
| 51 | #include <linux/usb_ch9.h> | |||
| 52 | #include <linux/usb_cdc.h> | |||
| 53 | #include <linux/usb_gadget.h> | |||
| 54 | ||||
| 55 | #include <linux/random.h> | |||
| 56 | #include <linux/netdevice.h> | |||
| 57 | #include <linux/etherdevice.h> | |||
| 58 | #include <linux/ethtool.h> | |||
| 59 | ||||
| 60 | #include "gadget_chips.h" | |||
| 61 | ||||
| 62 | /*-------------------------------------------------------------------------*/ | |||
| 63 | ||||
| 64 | /* | |||
| 65 | * Ethernet gadget driver -- with CDC and non-CDC options | |||
| 66 | * Builds on hardware support for a full duplex link. | |||
| 67 | * | |||
| 68 | * CDC Ethernet is the standard USB solution for sending Ethernet frames | |||
| 69 | * using USB. Real hardware tends to use the same framing protocol but look | |||
| 70 | * different for control features. This driver strongly prefers to use | |||
| 71 | * this USB-IF standard as its open-systems interoperability solution; | |||
| 72 | * most host side USB stacks (except from Microsoft) support it. | |||
| 73 | * | |||
| 74 | * There's some hardware that can't talk CDC. We make that hardware | |||
| 75 | * implement a "minimalist" vendor-agnostic CDC core: same framing, but | |||
| 76 | * link-level setup only requires activating the configuration. | |||
| 77 | * Linux supports it, but other host operating systems may not. | |||
| 78 | * (This is a subset of CDC Ethernet.) | |||
| 79 | * | |||
| 80 | * A third option is also in use. Rather than CDC Ethernet, or something | |||
| 81 | * simpler, Microsoft pushes their own approach: RNDIS. The published | |||
| 82 | * RNDIS specs are ambiguous and appear to be incomplete, and are also | |||
| 83 | * needlessly complex. | |||
| 84 | */ | |||
| 85 | ||||
| 86 | #define DRIVER_DESC "Ethernet Gadget" | |||
| 87 | #define DRIVER_VERSION "May Day 2005" | |||
| 88 | ||||
| 89 | static const char shortname [] = "ether"; | |||
| 90 | static const char driver_desc [] = DRIVER_DESC; | |||
| 91 | ||||
| 92 | #define RX_EXTRA 20 /* guard against rx overflows */ | |||
| 93 | ||||
| 94 | #include "rndis.h" | |||
| 95 | ||||
| 96 | #ifndef CONFIG_USB_ETH_RNDIS | |||
| 97 | #define rndis_uninit(x) do{}while(0) | |||
| 98 | #define rndis_deregister(c) do{}while(0) | |||
| 99 | #define rndis_exit() do{}while(0) | |||
| 100 | #endif | |||
| 101 | ||||
| 102 | /* CDC and RNDIS support the same host-chosen outgoing packet filters. */ | |||
| 103 | #define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \ | |||
| 104 | |USB_CDC_PACKET_TYPE_ALL_MULTICAST \ | |||
| 105 | |USB_CDC_PACKET_TYPE_PROMISCUOUS \ | |||
| 106 | |USB_CDC_PACKET_TYPE_DIRECTED) | |||
| 107 | ||||
| 108 | ||||
| 109 | /*-------------------------------------------------------------------------*/ | |||
| 110 | ||||
| 111 | struct eth_dev { | |||
| 112 | spinlock_t lock; | |||
| 113 | struct usb_gadget *gadget; | |||
| 114 | struct usb_request *req; /* for control responses */ | |||
| 115 | struct usb_request *stat_req; /* for cdc & rndis status */ | |||
| 116 | ||||
| 117 | u8 config; | |||
| 118 | struct usb_ep *in_ep, *out_ep, *status_ep; | |||
| 119 | const struct usb_endpoint_descriptor | |||
| 120 | *in, *out, *status; | |||
| 121 | struct list_head tx_reqs, rx_reqs; | |||
| 122 | ||||
| 123 | struct net_device *net; | |||
| 124 | struct net_device_stats stats; | |||
| 125 | atomic_t tx_qlen; | |||
| 126 | ||||
| 127 | struct work_struct work; | |||
| 128 | unsigned zlp:1; | |||
| 129 | unsigned cdc:1; | |||
| 130 | unsigned rndis:1; | |||
| 131 | unsigned suspended:1; | |||
| 132 | u16 cdc_filter; | |||
| 133 | unsigned long todo; | |||
| 134 | #define WORK_RX_MEMORY 0 | |||
| 135 | int rndis_config; | |||
| 136 | u8 host_mac [ETH_ALEN]; | |||
| 137 | }; | |||
| 138 | ||||
| 139 | /* This version autoconfigures as much as possible at run-time. | |||
| 140 | * | |||
| 141 | * It also ASSUMES a self-powered device, without remote wakeup, | |||
| 142 | * although remote wakeup support would make sense. | |||
| 143 | */ | |||
| 144 | ||||
| 145 | /*-------------------------------------------------------------------------*/ | |||
| 146 | ||||
| 147 | /* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! | |||
| 148 | * Instead: allocate your own, using normal USB-IF procedures. | |||
| 149 | */ | |||
| 150 | ||||
| 151 | /* Thanks to NetChip Technologies for donating this product ID. | |||
| 152 | * It's for devices with only CDC Ethernet configurations. | |||
| 153 | */ | |||
| 154 | #define CDC_VENDOR_NUM 0x0525 /* NetChip */ | |||
| 155 | #define CDC_PRODUCT_NUM 0xa4a1 /* Linux-USB Ethernet Gadget */ | |||
| 156 | ||||
| 157 | /* For hardware that can't talk CDC, we use the same vendor ID that | |||
| 158 | * ARM Linux has used for ethernet-over-usb, both with sa1100 and | |||
| 159 | * with pxa250. We're protocol-compatible, if the host-side drivers | |||
| 160 | * use the endpoint descriptors. bcdDevice (version) is nonzero, so | |||
| 161 | * drivers that need to hard-wire endpoint numbers have a hook. | |||
| 162 | * | |||
| 163 | * The protocol is a minimal subset of CDC Ether, which works on any bulk | |||
| 164 | * hardware that's not deeply broken ... even on hardware that can't talk | |||
| 165 | * RNDIS (like SA-1100, with no interrupt endpoint, or anything that | |||
| 166 | * doesn't handle control-OUT). | |||
| 167 | */ | |||
| 168 | #define SIMPLE_VENDOR_NUM 0x049f | |||
| 169 | #define SIMPLE_PRODUCT_NUM 0x505a | |||
| 170 | ||||
| 171 | /* For hardware that can talk RNDIS and either of the above protocols, | |||
| 172 | * use this ID ... the windows INF files will know it. Unless it's | |||
| 173 | * used with CDC Ethernet, Linux 2.4 hosts will need updates to choose | |||
| 174 | * the non-RNDIS configuration. | |||
| 175 | */ | |||
| 176 | #define RNDIS_VENDOR_NUM 0x0525 /* NetChip */ | |||
| 177 | #define RNDIS_PRODUCT_NUM 0xa4a2 /* Ethernet/RNDIS Gadget */ | |||
| 178 | ||||
| 179 | ||||
| 180 | /* Some systems will want different product identifers published in the | |||
| 181 | * device descriptor, either numbers or strings or both. These string | |||
| 182 | * parameters are in UTF-8 (superset of ASCII's 7 bit characters). | |||
| 183 | */ | |||
| 184 | ||||
| 185 | static ushort __initdata idVendor; | |||
| 0 | 0 | - | 186 | module_param(idVendor, ushort, S_IRUGO); |
| 0 | - | 186 | return ( & ( idVendor ) ) | |
| 187 | MODULE_PARM_DESC(idVendor, "USB Vendor ID"); | |||
| 188 | ||||
| 189 | static ushort __initdata idProduct; | |||
| 0 | 0 | - | 190 | module_param(idProduct, ushort, S_IRUGO); |
| 0 | - | 190 | return ( & ( idProduct ) ) | |
| 191 | MODULE_PARM_DESC(idProduct, "USB Product ID"); | |||
| 192 | ||||
| 193 | static ushort __initdata bcdDevice; | |||
| 0 | 0 | - | 194 | module_param(bcdDevice, ushort, S_IRUGO); |
| 0 | - | 194 | return ( & ( bcdDevice ) ) | |
| 195 | MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)"); | |||
| 196 | ||||
| 197 | static char *__initdata iManufacturer; | |||
| 0 | 0 | - | 198 | module_param(iManufacturer, charp, S_IRUGO); |
| 0 | - | 198 | return ( & ( iManufacturer ) ) | |
| 199 | MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string"); | |||
| 200 | ||||
| 201 | static char *__initdata iProduct; | |||
| 0 | 0 | - | 202 | module_param(iProduct, charp, S_IRUGO); |
| 0 | - | 202 | return ( & ( iProduct ) ) | |
| 203 | MODULE_PARM_DESC(iProduct, "USB Product string"); | |||
| 204 | ||||
| 205 | /* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */ | |||
| 206 | static char *__initdata dev_addr; | |||
| 0 | 0 | - | 207 | module_param(dev_addr, charp, S_IRUGO); |
| 0 | - | 207 | return ( & ( dev_addr ) ) | |
| 208 | MODULE_PARM_DESC(dev_addr, "Device Ethernet Address"); | |||
| 209 | ||||
| 210 | /* this address is invisible to ifconfig */ | |||
| 211 | static char *__initdata host_addr; | |||
| 0 | 0 | - | 212 | module_param(host_addr, charp, S_IRUGO); |
| 0 | - | 212 | return ( & ( host_addr ) ) | |
| 213 | MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); | |||
| 214 | ||||
| 215 | ||||
| 216 | /*-------------------------------------------------------------------------*/ | |||
| 217 | ||||
| 218 | /* Include CDC support if we could run on CDC-capable hardware. */ | |||
| 219 | ||||
| 220 | #ifdef CONFIG_USB_GADGET_NET2280 | |||
| 221 | #define DEV_CONFIG_CDC | |||
| 222 | #endif | |||
| 223 | ||||
| 224 | #ifdef CONFIG_USB_GADGET_DUMMY_HCD | |||
| 225 | #define DEV_CONFIG_CDC | |||
| 226 | #endif | |||
| 227 | ||||
| 228 | #ifdef CONFIG_USB_GADGET_GOKU | |||
| 229 | #define DEV_CONFIG_CDC | |||
| 230 | #endif | |||
| 231 | ||||
| 232 | #ifdef CONFIG_USB_GADGET_LH7A40X | |||
| 233 | #define DEV_CONFIG_CDC | |||
| 234 | #endif | |||
| 235 | ||||
| 236 | #ifdef CONFIG_USB_GADGET_MQ11XX | |||
| 237 | #define DEV_CONFIG_CDC | |||
| 238 | #endif | |||
| 239 | ||||
| 240 | #ifdef CONFIG_USB_GADGET_OMAP | |||
| 241 | #define DEV_CONFIG_CDC | |||
| 242 | #endif | |||
| 243 | ||||
| 244 | #ifdef CONFIG_USB_GADGET_N9604 | |||
| 245 | #define DEV_CONFIG_CDC | |||
| 246 | #endif | |||
| 247 | ||||
| 248 | #ifdef CONFIG_USB_GADGET_PXA27X | |||
| 249 | #define DEV_CONFIG_CDC | |||
| 250 | #endif | |||
| 251 | ||||
| 252 | #ifdef CONFIG_USB_GADGET_AT91 | |||
| 253 | #define DEV_CONFIG_CDC | |||
| 254 | #endif | |||
| 255 | ||||
| 256 | ||||
| 257 | /* For CDC-incapable hardware, choose the simple cdc subset. | |||
| 258 | * Anything that talks bulk (without notable bugs) can do this. | |||
| 259 | */ | |||
| 260 | #ifdef CONFIG_USB_GADGET_PXA2XX | |||
| 261 | #define DEV_CONFIG_SUBSET | |||
| 262 | #endif | |||
| 263 | ||||
| 264 | #ifdef CONFIG_USB_GADGET_SH | |||
| 265 | #define DEV_CONFIG_SUBSET | |||
| 266 | #endif | |||
| 267 | ||||
| 268 | #ifdef CONFIG_USB_GADGET_SA1100 | |||
| 269 | /* use non-CDC for backwards compatibility */ | |||
| 270 | #define DEV_CONFIG_SUBSET | |||
| 271 | #endif | |||
| 272 | ||||
| 273 | #ifdef CONFIG_USB_GADGET_S3C2410 | |||
| 274 | #define DEV_CONFIG_CDC | |||
| 275 | #endif | |||
| 276 | ||||
| 277 | /*-------------------------------------------------------------------------*/ | |||
| 278 | ||||
| 279 | /* "main" config is either CDC, or its simple subset */ | |||
| 0 | 0 | - | 280 | static inline int is_cdc(struct eth_dev *dev) |
| 281 | { | |||
| 282 | #if !defined(DEV_CONFIG_SUBSET) | |||
| 0 | - | 283 | return 1; /* only cdc possible */ | |
| 284 | #elif !defined (DEV_CONFIG_CDC) | |||
| 285 | return 0; /* only subset possible */ | |||
| 286 | #else | |||
| 287 | return dev->cdc; /* depends on what hardware we found */ | |||
| 288 | #endif | |||
| 289 | } | |||
| 290 | ||||
| 291 | /* "secondary" RNDIS config may sometimes be activated */ | |||
| 0 | 0 | - | 292 | static inline int rndis_active(struct eth_dev *dev) |
| 293 | { | |||
| 294 | #ifdef CONFIG_USB_ETH_RNDIS | |||
| 295 | return dev->rndis; | |||
| 296 | #else | |||
| 0 | - | 297 | return 0; | |
| 298 | #endif | |||
| 299 | } | |||
| 300 | ||||
| 301 | #define subset_active(dev) (!is_cdc(dev) && !rndis_active(dev)) | |||
| 302 | #define cdc_active(dev) ( is_cdc(dev) && !rndis_active(dev)) | |||
| 303 | ||||
| 304 | ||||
| 305 | ||||
| 306 | #define DEFAULT_QLEN 2 /* double buffering by default */ | |||
| 307 | ||||
| 308 | /* peak bulk transfer bits-per-second */ | |||
| 309 | #define HS_BPS (13 * 512 * 8 * 1000 * 8) | |||
| 310 | #define FS_BPS (19 * 64 * 1 * 1000 * 8) | |||
| 311 | ||||
| 312 | #ifdef CONFIG_USB_GADGET_DUALSPEED | |||
| 313 | #define DEVSPEED USB_SPEED_HIGH | |||
| 314 | ||||
| 315 | static unsigned qmult = 5; | |||
| 0 | 0 | - | 316 | module_param (qmult, uint, S_IRUGO|S_IWUSR); |
| 0 | - | 316 | return ( & ( qmult ) ) | |
| 317 | ||||
| 318 | ||||
| 319 | /* for dual-speed hardware, use deeper queues at highspeed */ | |||
| 320 | #define qlen(gadget) \ | |||
| 321 | (DEFAULT_QLEN*((gadget->speed == USB_SPEED_HIGH) ? qmult : 1)) | |||
| 322 | ||||
| 323 | /* also defer IRQs on highspeed TX */ | |||
| 324 | #define TX_DELAY qmult | |||
| 325 | ||||
| 0 | 0 | - | 326 | static inline int BITRATE(struct usb_gadget *g) |
| 327 | { | |||
| 328 | return (g->speed == USB_SPEED_HIGH) ? HS_BPS : FS_BPS; | |||
| 0 | 0 | - | 328 | ternary-?: ( g -> speed == USB_SPEED_HIGH ) |
| 0 | - | 328 | return ( g -> speed == USB_SPEED_HIGH ) ? ( 13.. | |
| 329 | } | |||
| 330 | ||||
| 331 | #else /* full speed (low speed doesn't do bulk) */ | |||
| 332 | #define DEVSPEED USB_SPEED_FULL | |||
| 333 | ||||
| 334 | #define qlen(gadget) DEFAULT_QLEN | |||
| 335 | ||||
| 336 | static inline int BITRATE(struct usb_gadget *g) | |||
| 337 | { | |||
| 338 | return FS_BPS; | |||
| 339 | } | |||
| 340 | #endif | |||
| 341 | ||||
| 342 | ||||
| 343 | /*-------------------------------------------------------------------------*/ | |||
| 344 | ||||
| 345 | #define xprintk(d,level,fmt,args...) \ | |||
| 346 | printk(level "%s: " fmt , (d)->net->name , ## args) | |||
| 347 | ||||
| 348 | #ifdef DEBUG | |||
| 349 | #undef DEBUG | |||
| 350 | #define DEBUG(dev,fmt,args...) \ | |||
| 351 | xprintk(dev , KERN_DEBUG , fmt , ## args) | |||
| 352 | #else | |||
| 353 | #define DEBUG(dev,fmt,args...) \ | |||
| 354 | do { } while (0) | |||
| 355 | #endif /* DEBUG */ | |||
| 356 | ||||
| 357 | #ifdef VERBOSE | |||
| 358 | #define VDEBUG DEBUG | |||
| 359 | #else | |||
| 360 | #define VDEBUG(dev,fmt,args...) \ | |||
| 361 | do { } while (0) | |||
| 362 | #endif /* DEBUG */ | |||
| 363 | ||||
| 364 | #define ERROR(dev,fmt,args...) \ | |||
| 365 | xprintk(dev , KERN_ERR , fmt , ## args) | |||
| 366 | #define WARN(dev,fmt,args...) \ | |||
| 367 | xprintk(dev , KERN_WARNING , fmt , ## args) | |||
| 368 | #define INFO(dev,fmt,args...) \ | |||
| 369 | xprintk(dev , KERN_INFO , fmt , ## args) | |||
| 370 | ||||
| 371 | /*-------------------------------------------------------------------------*/ | |||
| 372 | ||||
| 373 | /* USB DRIVER HOOKUP (to the hardware driver, below us), mostly | |||
| 374 | * ep0 implementation: descriptors, config management, setup(). | |||
| 375 | * also optional class-specific notification interrupt transfer. | |||
| 376 | */ | |||
| 377 | ||||
| 378 | /* | |||
| 379 | * DESCRIPTORS ... most are static, but strings and (full) configuration | |||
| 380 | * descriptors are built on demand. For now we do either full CDC, or | |||
| 381 | * our simple subset, with RNDIS as an optional second configuration. | |||
| 382 | * | |||
| 383 | * RNDIS includes some CDC ACM descriptors ... like CDC Ethernet. But | |||
| 384 | * the class descriptors match a modem (they're ignored; it's really just | |||
| 385 | * Ethernet functionality), they don't need the NOP altsetting, and the | |||
| 386 | * status transfer endpoint isn't optional. | |||
| 387 | */ | |||
| 388 | ||||
| 389 | #define STRING_MANUFACTURER 1 | |||
| 390 | #define STRING_PRODUCT 2 | |||
| 391 | #define STRING_ETHADDR 3 | |||
| 392 | #define STRING_DATA 4 | |||
| 393 | #define STRING_CONTROL 5 | |||
| 394 | #define STRING_RNDIS_CONTROL 6 | |||
| 395 | #define STRING_CDC 7 | |||
| 396 | #define STRING_SUBSET 8 | |||
| 397 | #define STRING_RNDIS 9 | |||
| 398 | ||||
| 399 | /* holds our biggest descriptor (or RNDIS response) */ | |||
| 400 | #define USB_BUFSIZ 256 | |||
| 401 | ||||
| 402 | /* | |||
| 403 | * This device advertises one configuration, eth_config, unless RNDIS | |||
| 404 | * is enabled (rndis_config) on hardware supporting at least two configs. | |||
| 405 | * | |||
| 406 | * NOTE: Controllers like superh_udc should probably be able to use | |||
| 407 | * an RNDIS-only configuration. | |||
| 408 | * | |||
| 409 | * FIXME define some higher-powered configurations to make it easier | |||
| 410 | * to recharge batteries ... | |||
| 411 | */ | |||
| 412 | ||||
| 413 | #define DEV_CONFIG_VALUE 1 /* cdc or subset */ | |||
| 414 | #define DEV_RNDIS_CONFIG_VALUE 2 /* rndis; optional */ | |||
| 415 | ||||
| 416 | static struct usb_device_descriptor | |||
| 417 | device_desc = { | |||
| 418 | .bLength = sizeof device_desc, | |||
| 419 | .bDescriptorType = USB_DT_DEVICE, | |||
| 420 | ||||
| 421 | .bcdUSB = __constant_cpu_to_le16 (0x0200), | |||
| 422 | ||||
| 423 | .bDeviceClass = USB_CLASS_COMM, | |||
| 424 | .bDeviceSubClass = 0, | |||
| 425 | .bDeviceProtocol = 0, | |||
| 426 | ||||
| 427 | .idVendor = __constant_cpu_to_le16 (CDC_VENDOR_NUM), | |||
| 428 | .idProduct = __constant_cpu_to_le16 (CDC_PRODUCT_NUM), | |||
| 429 | .iManufacturer = STRING_MANUFACTURER, | |||
| 430 | .iProduct = STRING_PRODUCT, | |||
| 431 | .bNumConfigurations = 1, | |||
| 432 | }; | |||
| 433 | ||||
| 434 | static struct usb_otg_descriptor | |||
| 435 | otg_descriptor = { | |||
| 436 | .bLength = sizeof otg_descriptor, | |||
| 437 | .bDescriptorType = USB_DT_OTG, | |||
| 438 | ||||
| 439 | .bmAttributes = USB_OTG_SRP, | |||
| 440 | }; | |||
| 441 | ||||
| 442 | static struct usb_config_descriptor | |||
| 443 | eth_config = { | |||
| 444 | .bLength = sizeof eth_config, | |||
| 445 | .bDescriptorType = USB_DT_CONFIG, | |||
| 446 | ||||
| 447 | /* compute wTotalLength on the fly */ | |||
| 448 | .bNumInterfaces = 2, | |||
| 449 | .bConfigurationValue = DEV_CONFIG_VALUE, | |||
| 450 | .iConfiguration = STRING_CDC, | |||
| 451 | .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, | |||
| 452 | .bMaxPower = 50, | |||
| 453 | }; | |||
| 454 | ||||
| 455 | #ifdef CONFIG_USB_ETH_RNDIS | |||
| 456 | static struct usb_config_descriptor | |||
| 457 | rndis_config = { | |||
| 458 | .bLength = sizeof rndis_config, | |||
| 459 | .bDescriptorType = USB_DT_CONFIG, | |||
| 460 | ||||
| 461 | /* compute wTotalLength on the fly */ | |||
| 462 | .bNumInterfaces = 2, | |||
| 463 | .bConfigurationValue = DEV_RNDIS_CONFIG_VALUE, | |||
| 464 | .iConfiguration = STRING_RNDIS, | |||
| 465 | .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, | |||
| 466 | .bMaxPower = 50, | |||
| 467 | }; | |||
| 468 | #endif | |||
| 469 | ||||
| 470 | /* | |||
| 471 | * Compared to the simple CDC subset, the full CDC Ethernet model adds | |||
| 472 | * three class descriptors, two interface descriptors, optional status | |||
| 473 | * endpoint. Both have a "data" interface and two bulk endpoints. | |||
| 474 | * There are also differences in how control requests are handled. | |||
| 475 | * | |||
| 476 | * RNDIS shares a lot with CDC-Ethernet, since it's a variant of | |||
| 477 | * the CDC-ACM (modem) spec. | |||
| 478 | */ | |||
| 479 | ||||
| 480 | #ifdef DEV_CONFIG_CDC | |||
| 481 | static struct usb_interface_descriptor | |||
| 482 | control_intf = { | |||
| 483 | .bLength = sizeof control_intf, | |||
| 484 | .bDescriptorType = USB_DT_INTERFACE, | |||
| 485 | ||||
| 486 | .bInterfaceNumber = 0, | |||
| 487 | /* status endpoint is optional; this may be patched later */ | |||
| 488 | .bNumEndpoints = 1, | |||
| 489 | .bInterfaceClass = USB_CLASS_COMM, | |||
| 490 | .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, | |||
| 491 | .bInterfaceProtocol = USB_CDC_PROTO_NONE, | |||
| 492 | .iInterface = STRING_CONTROL, | |||
| 493 | }; | |||
| 494 | #endif | |||
| 495 | ||||
| 496 | #ifdef CONFIG_USB_ETH_RNDIS | |||
| 497 | static const struct usb_interface_descriptor | |||
| 498 | rndis_control_intf = { | |||
| 499 | .bLength = sizeof rndis_control_intf, | |||
| 500 | .bDescriptorType = USB_DT_INTERFACE, | |||
| 501 | ||||
| 502 | .bInterfaceNumber = 0, | |||
| 503 | .bNumEndpoints = 1, | |||
| 504 | .bInterfaceClass = USB_CLASS_COMM, | |||
| 505 | .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, | |||
| 506 | .bInterfaceProtocol = USB_CDC_ACM_PROTO_VENDOR, | |||
| 507 | .iInterface = STRING_RNDIS_CONTROL, | |||
| 508 | }; | |||
| 509 | #endif | |||
| 510 | ||||
| 511 | #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) | |||
| 512 | ||||
| 513 | static const struct usb_cdc_header_desc header_desc = { | |||
| 514 | .bLength = sizeof header_desc, | |||
| 515 | .bDescriptorType = USB_DT_CS_INTERFACE, | |||
| 516 | .bDescriptorSubType = USB_CDC_HEADER_TYPE, | |||
| 517 | ||||
| 518 | .bcdCDC = __constant_cpu_to_le16 (0x0110), | |||
| 519 | }; | |||
| 520 | ||||
| 521 | static const struct usb_cdc_union_desc union_desc = { | |||
| 522 | .bLength = sizeof union_desc, | |||
| 523 | .bDescriptorType = USB_DT_CS_INTERFACE, | |||
| 524 | .bDescriptorSubType = USB_CDC_UNION_TYPE, | |||
| 525 | ||||
| 526 | .bMasterInterface0 = 0, /* index of control interface */ | |||
| 527 | .bSlaveInterface0 = 1, /* index of DATA interface */ | |||
| 528 | }; | |||
| 529 | ||||
| 530 | #endif /* CDC || RNDIS */ | |||
| 531 | ||||
| 532 | #ifdef CONFIG_USB_ETH_RNDIS | |||
| 533 | ||||
| 534 | static const struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor = { | |||
| 535 | .bLength = sizeof call_mgmt_descriptor, | |||
| 536 | .bDescriptorType = USB_DT_CS_INTERFACE, | |||
| 537 | .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE, | |||
| 538 | ||||
| 539 | .bmCapabilities = 0x00, | |||
| 540 | .bDataInterface = 0x01, | |||
| 541 | }; | |||
| 542 | ||||
| 543 | static const struct usb_cdc_acm_descriptor acm_descriptor = { | |||
| 544 | .bLength = sizeof acm_descriptor, | |||
| 545 | .bDescriptorType = USB_DT_CS_INTERFACE, | |||
| 546 | .bDescriptorSubType = USB_CDC_ACM_TYPE, | |||
| 547 | ||||
| 548 | .bmCapabilities = 0x00, | |||
| 549 | }; | |||
| 550 | ||||
| 551 | #endif | |||
| 552 | ||||
| 553 | #ifdef DEV_CONFIG_CDC | |||
| 554 | ||||
| 555 | static const struct usb_cdc_ether_desc ether_desc = { | |||
| 556 | .bLength = sizeof ether_desc, | |||
| 557 | .bDescriptorType = USB_DT_CS_INTERFACE, | |||
| 558 | .bDescriptorSubType = USB_CDC_ETHERNET_TYPE, | |||
| 559 | ||||
| 560 | /* this descriptor actually adds value, surprise! */ | |||
| 561 | .iMACAddress = STRING_ETHADDR, | |||
| 562 | .bmEthernetStatistics = __constant_cpu_to_le32 (0), /* no statistics */ | |||
| 563 | .wMaxSegmentSize = __constant_cpu_to_le16 (ETH_FRAME_LEN), | |||
| 564 | .wNumberMCFilters = __constant_cpu_to_le16 (0), | |||
| 565 | .bNumberPowerFilters = 0, | |||
| 566 | }; | |||
| 567 | ||||
| 568 | #endif | |||
| 569 | ||||
| 570 | #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) | |||
| 571 | ||||
| 572 | /* include the status endpoint if we can, even where it's optional. | |||
| 573 | * use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one | |||
| 574 | * packet, to simplify cancellation; and a big transfer interval, to | |||
| 575 | * waste less bandwidth. | |||
| 576 | * | |||
| 577 | * some drivers (like Linux 2.4 cdc-ether!) "need" it to exist even | |||
| 578 | * if they ignore the connect/disconnect notifications that real aether | |||
| 579 | * can provide. more advanced cdc configurations might want to support | |||
| 580 | * encapsulated commands (vendor-specific, using control-OUT). | |||
| 581 | * | |||
| 582 | * RNDIS requires the status endpoint, since it uses that encapsulation | |||
| 583 | * mechanism for its funky RPC scheme. | |||
| 584 | */ | |||
| 585 | ||||
| 586 | #define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */ | |||
| 587 | #define STATUS_BYTECOUNT 16 /* 8 byte header + data */ | |||
| 588 | ||||
| 589 | static struct usb_endpoint_descriptor | |||
| 590 | fs_status_desc = { | |||
| 591 | .bLength = USB_DT_ENDPOINT_SIZE, | |||
| 592 | .bDescriptorType = USB_DT_ENDPOINT, | |||
| 593 | ||||
| 594 | .bEndpointAddress = USB_DIR_IN, | |||
| 595 | .bmAttributes = USB_ENDPOINT_XFER_INT, | |||
| 596 | .wMaxPacketSize = __constant_cpu_to_le16 (STATUS_BYTECOUNT), | |||
| 597 | .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC, | |||
| 598 | }; | |||
| 599 | #endif | |||
| 600 | ||||
| 601 | #ifdef DEV_CONFIG_CDC | |||
| 602 | ||||
| 603 | /* the default data interface has no endpoints ... */ | |||
| 604 | ||||
| 605 | static const struct usb_interface_descriptor | |||
| 606 | data_nop_intf = { | |||
| 607 | .bLength = sizeof data_nop_intf, | |||