aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2006-12-11 18:59:04 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2007-02-07 18:44:33 -0500
commit11d5489873facd395653a4ee14669751bfe9bab5 (patch)
tree70d18d4b4452ea546a2d54e1ae278fd20c67d046 /drivers/usb
parent1737bf2c5e78e331ad0a30b8c34edd1016d043c0 (diff)
USB: ethernet gadget interop with MCCI Windows driver
It turns out that minor tweaks to the "CDC Subset" support in the Ethernet gadget driver, just updating a config descriptor, let it be automagically recognized by a Windows driver supported by MCCI. This patch adds those descriptors, so systems using PXA 255 processors (like Gumstix etc) can interop with those commercial MS-Windows drivers. This is a Good Thing since Microsoft's RNDIS code has bugginess issues, which are unfortunately compounded by "won't fix" issues as well as "the published specs are incomplete and wrong" issues. Being able to talk to the MCCI driver gives Windows users another connectivity option. (MCCI also has CDC Ethernet drivers, which can help most non-PXA processors.) Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/gadget/ether.c142
1 files changed, 103 insertions, 39 deletions
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index ca8e0ebc79e8..72e2b65293c8 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -72,9 +72,18 @@
72 * 72 *
73 * There's some hardware that can't talk CDC. We make that hardware 73 * There's some hardware that can't talk CDC. We make that hardware
74 * implement a "minimalist" vendor-agnostic CDC core: same framing, but 74 * implement a "minimalist" vendor-agnostic CDC core: same framing, but
75 * link-level setup only requires activating the configuration. 75 * link-level setup only requires activating the configuration. Only the
76 * Linux supports it, but other host operating systems may not. 76 * endpoint descriptors, and product/vendor IDs, are relevant; no control
77 * (This is a subset of CDC Ethernet.) 77 * operations are available. Linux supports it, but other host operating
78 * systems may not. (This is a subset of CDC Ethernet.)
79 *
80 * It turns out that if you add a few descriptors to that "CDC Subset",
81 * (Windows) host side drivers from MCCI can treat it as one submode of
82 * a proprietary scheme called "SAFE" ... without needing to know about
83 * specific product/vendor IDs. So we do that, making it easier to use
84 * those MS-Windows drivers. Those added descriptors make it resemble a
85 * CDC MDLM device, but they don't change device behavior at all. (See
86 * MCCI Engineering report 950198 "SAFE Networking Functions".)
78 * 87 *
79 * A third option is also in use. Rather than CDC Ethernet, or something 88 * A third option is also in use. Rather than CDC Ethernet, or something
80 * simpler, Microsoft pushes their own approach: RNDIS. The published 89 * simpler, Microsoft pushes their own approach: RNDIS. The published
@@ -254,6 +263,10 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
254#define DEV_CONFIG_CDC 263#define DEV_CONFIG_CDC
255#endif 264#endif
256 265
266#ifdef CONFIG_USB_GADGET_S3C2410
267#define DEV_CONFIG_CDC
268#endif
269
257#ifdef CONFIG_USB_GADGET_AT91 270#ifdef CONFIG_USB_GADGET_AT91
258#define DEV_CONFIG_CDC 271#define DEV_CONFIG_CDC
259#endif 272#endif
@@ -283,9 +296,6 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
283#define DEV_CONFIG_SUBSET 296#define DEV_CONFIG_SUBSET
284#endif 297#endif
285 298
286#ifdef CONFIG_USB_GADGET_S3C2410
287#define DEV_CONFIG_CDC
288#endif
289 299
290/*-------------------------------------------------------------------------*/ 300/*-------------------------------------------------------------------------*/
291 301
@@ -487,8 +497,17 @@ rndis_config = {
487 * endpoint. Both have a "data" interface and two bulk endpoints. 497 * endpoint. Both have a "data" interface and two bulk endpoints.
488 * There are also differences in how control requests are handled. 498 * There are also differences in how control requests are handled.
489 * 499 *
490 * RNDIS shares a lot with CDC-Ethernet, since it's a variant of 500 * RNDIS shares a lot with CDC-Ethernet, since it's a variant of the
491 * the CDC-ACM (modem) spec. 501 * CDC-ACM (modem) spec. Unfortunately MSFT's RNDIS driver is buggy; it
502 * may hang or oops. Since bugfixes (or accurate specs, letting Linux
503 * work around those bugs) are unlikely to ever come from MSFT, you may
504 * wish to avoid using RNDIS.
505 *
506 * MCCI offers an alternative to RNDIS if you need to connect to Windows
507 * but have hardware that can't support CDC Ethernet. We add descriptors
508 * to present the CDC Subset as a (nonconformant) CDC MDLM variant called
509 * "SAFE". That borrows from both CDC Ethernet and CDC MDLM. You can
510 * get those drivers from MCCI, or bundled with various products.
492 */ 511 */
493 512
494#ifdef DEV_CONFIG_CDC 513#ifdef DEV_CONFIG_CDC
@@ -522,8 +541,6 @@ rndis_control_intf = {
522}; 541};
523#endif 542#endif
524 543
525#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
526
527static const struct usb_cdc_header_desc header_desc = { 544static const struct usb_cdc_header_desc header_desc = {
528 .bLength = sizeof header_desc, 545 .bLength = sizeof header_desc,
529 .bDescriptorType = USB_DT_CS_INTERFACE, 546 .bDescriptorType = USB_DT_CS_INTERFACE,
@@ -532,6 +549,8 @@ static const struct usb_cdc_header_desc header_desc = {
532 .bcdCDC = __constant_cpu_to_le16 (0x0110), 549 .bcdCDC = __constant_cpu_to_le16 (0x0110),
533}; 550};
534 551
552#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
553
535static const struct usb_cdc_union_desc union_desc = { 554static const struct usb_cdc_union_desc union_desc = {
536 .bLength = sizeof union_desc, 555 .bLength = sizeof union_desc,
537 .bDescriptorType = USB_DT_CS_INTERFACE, 556 .bDescriptorType = USB_DT_CS_INTERFACE,
@@ -564,7 +583,40 @@ static const struct usb_cdc_acm_descriptor acm_descriptor = {
564 583
565#endif 584#endif
566 585
567#ifdef DEV_CONFIG_CDC 586#ifndef DEV_CONFIG_CDC
587
588/* "SAFE" loosely follows CDC WMC MDLM, violating the spec in various
589 * ways: data endpoints live in the control interface, there's no data
590 * interface, and it's not used to talk to a cell phone radio.
591 */
592
593static const struct usb_cdc_mdlm_desc mdlm_desc = {
594 .bLength = sizeof mdlm_desc,
595 .bDescriptorType = USB_DT_CS_INTERFACE,
596 .bDescriptorSubType = USB_CDC_MDLM_TYPE,
597
598 .bcdVersion = __constant_cpu_to_le16(0x0100),
599 .bGUID = {
600 0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6,
601 0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f,
602 },
603};
604
605/* since "usb_cdc_mdlm_detail_desc" is a variable length structure, we
606 * can't really use its struct. All we do here is say that we're using
607 * the submode of "SAFE" which directly matches the CDC Subset.
608 */
609static const u8 mdlm_detail_desc[] = {
610 6,
611 USB_DT_CS_INTERFACE,
612 USB_CDC_MDLM_DETAIL_TYPE,
613
614 0, /* "SAFE" */
615 0, /* network control capabilities (none) */
616 0, /* network data capabilities ("raw" encapsulation) */
617};
618
619#endif
568 620
569static const struct usb_cdc_ether_desc ether_desc = { 621static const struct usb_cdc_ether_desc ether_desc = {
570 .bLength = sizeof ether_desc, 622 .bLength = sizeof ether_desc,
@@ -579,7 +631,6 @@ static const struct usb_cdc_ether_desc ether_desc = {
579 .bNumberPowerFilters = 0, 631 .bNumberPowerFilters = 0,
580}; 632};
581 633
582#endif
583 634
584#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) 635#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
585 636
@@ -672,6 +723,9 @@ rndis_data_intf = {
672/* 723/*
673 * "Simple" CDC-subset option is a simple vendor-neutral model that most 724 * "Simple" CDC-subset option is a simple vendor-neutral model that most
674 * full speed controllers can handle: one interface, two bulk endpoints. 725 * full speed controllers can handle: one interface, two bulk endpoints.
726 *
727 * To assist host side drivers, we fancy it up a bit, and add descriptors
728 * so some host side drivers will understand it as a "SAFE" variant.
675 */ 729 */
676 730
677static const struct usb_interface_descriptor 731static const struct usb_interface_descriptor
@@ -682,8 +736,8 @@ subset_data_intf = {
682 .bInterfaceNumber = 0, 736 .bInterfaceNumber = 0,
683 .bAlternateSetting = 0, 737 .bAlternateSetting = 0,
684 .bNumEndpoints = 2, 738 .bNumEndpoints = 2,
685 .bInterfaceClass = USB_CLASS_VENDOR_SPEC, 739 .bInterfaceClass = USB_CLASS_COMM,
686 .bInterfaceSubClass = 0, 740 .bInterfaceSubClass = USB_CDC_SUBCLASS_MDLM,
687 .bInterfaceProtocol = 0, 741 .bInterfaceProtocol = 0,
688 .iInterface = STRING_DATA, 742 .iInterface = STRING_DATA,
689}; 743};
@@ -731,10 +785,15 @@ static const struct usb_descriptor_header *fs_eth_function [11] = {
731static inline void __init fs_subset_descriptors(void) 785static inline void __init fs_subset_descriptors(void)
732{ 786{
733#ifdef DEV_CONFIG_SUBSET 787#ifdef DEV_CONFIG_SUBSET
788 /* behavior is "CDC Subset"; extra descriptors say "SAFE" */
734 fs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf; 789 fs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf;
735 fs_eth_function[2] = (struct usb_descriptor_header *) &fs_source_desc; 790 fs_eth_function[2] = (struct usb_descriptor_header *) &header_desc;
736 fs_eth_function[3] = (struct usb_descriptor_header *) &fs_sink_desc; 791 fs_eth_function[3] = (struct usb_descriptor_header *) &mdlm_desc;
737 fs_eth_function[4] = NULL; 792 fs_eth_function[4] = (struct usb_descriptor_header *) &mdlm_detail_desc;
793 fs_eth_function[5] = (struct usb_descriptor_header *) &ether_desc;
794 fs_eth_function[6] = (struct usb_descriptor_header *) &fs_source_desc;
795 fs_eth_function[7] = (struct usb_descriptor_header *) &fs_sink_desc;
796 fs_eth_function[8] = NULL;
738#else 797#else
739 fs_eth_function[1] = NULL; 798 fs_eth_function[1] = NULL;
740#endif 799#endif
@@ -828,10 +887,15 @@ static const struct usb_descriptor_header *hs_eth_function [11] = {
828static inline void __init hs_subset_descriptors(void) 887static inline void __init hs_subset_descriptors(void)
829{ 888{
830#ifdef DEV_CONFIG_SUBSET 889#ifdef DEV_CONFIG_SUBSET
890 /* behavior is "CDC Subset"; extra descriptors say "SAFE" */
831 hs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf; 891 hs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf;
832 hs_eth_function[2] = (struct usb_descriptor_header *) &fs_source_desc; 892 hs_eth_function[2] = (struct usb_descriptor_header *) &header_desc;
833 hs_eth_function[3] = (struct usb_descriptor_header *) &fs_sink_desc; 893 hs_eth_function[3] = (struct usb_descriptor_header *) &mdlm_desc;
834 hs_eth_function[4] = NULL; 894 hs_eth_function[4] = (struct usb_descriptor_header *) &mdlm_detail_desc;
895 hs_eth_function[5] = (struct usb_descriptor_header *) &ether_desc;
896 hs_eth_function[6] = (struct usb_descriptor_header *) &hs_source_desc;
897 hs_eth_function[7] = (struct usb_descriptor_header *) &hs_sink_desc;
898 hs_eth_function[8] = NULL;
835#else 899#else
836 hs_eth_function[1] = NULL; 900 hs_eth_function[1] = NULL;
837#endif 901#endif
@@ -878,10 +942,8 @@ static char manufacturer [50];
878static char product_desc [40] = DRIVER_DESC; 942static char product_desc [40] = DRIVER_DESC;
879static char serial_number [20]; 943static char serial_number [20];
880 944
881#ifdef DEV_CONFIG_CDC
882/* address that the host will use ... usually assigned at random */ 945/* address that the host will use ... usually assigned at random */
883static char ethaddr [2 * ETH_ALEN + 1]; 946static char ethaddr [2 * ETH_ALEN + 1];
884#endif
885 947
886/* static strings, in UTF-8 */ 948/* static strings, in UTF-8 */
887static struct usb_string strings [] = { 949static struct usb_string strings [] = {
@@ -889,9 +951,9 @@ static struct usb_string strings [] = {
889 { STRING_PRODUCT, product_desc, }, 951 { STRING_PRODUCT, product_desc, },
890 { STRING_SERIALNUMBER, serial_number, }, 952 { STRING_SERIALNUMBER, serial_number, },
891 { STRING_DATA, "Ethernet Data", }, 953 { STRING_DATA, "Ethernet Data", },
954 { STRING_ETHADDR, ethaddr, },
892#ifdef DEV_CONFIG_CDC 955#ifdef DEV_CONFIG_CDC
893 { STRING_CDC, "CDC Ethernet", }, 956 { STRING_CDC, "CDC Ethernet", },
894 { STRING_ETHADDR, ethaddr, },
895 { STRING_CONTROL, "CDC Communications Control", }, 957 { STRING_CONTROL, "CDC Communications Control", },
896#endif 958#endif
897#ifdef DEV_CONFIG_SUBSET 959#ifdef DEV_CONFIG_SUBSET
@@ -986,10 +1048,10 @@ set_ether_config (struct eth_dev *dev, gfp_t gfp_flags)
986 } 1048 }
987#endif 1049#endif
988 1050
989 dev->in = ep_desc (dev->gadget, &hs_source_desc, &fs_source_desc); 1051 dev->in = ep_desc(gadget, &hs_source_desc, &fs_source_desc);
990 dev->in_ep->driver_data = dev; 1052 dev->in_ep->driver_data = dev;
991 1053
992 dev->out = ep_desc (dev->gadget, &hs_sink_desc, &fs_sink_desc); 1054 dev->out = ep_desc(gadget, &hs_sink_desc, &fs_sink_desc);
993 dev->out_ep->driver_data = dev; 1055 dev->out_ep->driver_data = dev;
994 1056
995 /* With CDC, the host isn't allowed to use these two data 1057 /* With CDC, the host isn't allowed to use these two data
@@ -2278,10 +2340,10 @@ eth_bind (struct usb_gadget *gadget)
2278 "RNDIS/%s", driver_desc); 2340 "RNDIS/%s", driver_desc);
2279 2341
2280 /* CDC subset ... recognized by Linux since 2.4.10, but Windows 2342 /* CDC subset ... recognized by Linux since 2.4.10, but Windows
2281 * drivers aren't widely available. 2343 * drivers aren't widely available. (That may be improved by
2344 * supporting one submode of the "SAFE" variant of MDLM.)
2282 */ 2345 */
2283 } else if (!cdc) { 2346 } else if (!cdc) {
2284 device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
2285 device_desc.idVendor = 2347 device_desc.idVendor =
2286 __constant_cpu_to_le16(SIMPLE_VENDOR_NUM); 2348 __constant_cpu_to_le16(SIMPLE_VENDOR_NUM);
2287 device_desc.idProduct = 2349 device_desc.idProduct =
@@ -2352,6 +2414,10 @@ autoconf_fail:
2352 if (!cdc) { 2414 if (!cdc) {
2353 eth_config.bNumInterfaces = 1; 2415 eth_config.bNumInterfaces = 1;
2354 eth_config.iConfiguration = STRING_SUBSET; 2416 eth_config.iConfiguration = STRING_SUBSET;
2417
2418 /* use functions to set these up, in case we're built to work
2419 * with multiple controllers and must override CDC Ethernet.
2420 */
2355 fs_subset_descriptors(); 2421 fs_subset_descriptors();
2356 hs_subset_descriptors(); 2422 hs_subset_descriptors();
2357 } 2423 }
@@ -2415,22 +2481,20 @@ autoconf_fail:
2415 2481
2416 /* Module params for these addresses should come from ID proms. 2482 /* Module params for these addresses should come from ID proms.
2417 * The host side address is used with CDC and RNDIS, and commonly 2483 * The host side address is used with CDC and RNDIS, and commonly
2418 * ends up in a persistent config database. 2484 * ends up in a persistent config database. It's not clear if
2485 * host side code for the SAFE thing cares -- its original BLAN
2486 * thing didn't, Sharp never assigned those addresses on Zaurii.
2419 */ 2487 */
2420 if (get_ether_addr(dev_addr, net->dev_addr)) 2488 if (get_ether_addr(dev_addr, net->dev_addr))
2421 dev_warn(&gadget->dev, 2489 dev_warn(&gadget->dev,
2422 "using random %s ethernet address\n", "self"); 2490 "using random %s ethernet address\n", "self");
2423 if (cdc || rndis) { 2491 if (get_ether_addr(host_addr, dev->host_mac))
2424 if (get_ether_addr(host_addr, dev->host_mac)) 2492 dev_warn(&gadget->dev,
2425 dev_warn(&gadget->dev, 2493 "using random %s ethernet address\n", "host");
2426 "using random %s ethernet address\n", "host"); 2494 snprintf (ethaddr, sizeof ethaddr, "%02X%02X%02X%02X%02X%02X",
2427#ifdef DEV_CONFIG_CDC 2495 dev->host_mac [0], dev->host_mac [1],
2428 snprintf (ethaddr, sizeof ethaddr, "%02X%02X%02X%02X%02X%02X", 2496 dev->host_mac [2], dev->host_mac [3],
2429 dev->host_mac [0], dev->host_mac [1], 2497 dev->host_mac [4], dev->host_mac [5]);
2430 dev->host_mac [2], dev->host_mac [3],
2431 dev->host_mac [4], dev->host_mac [5]);
2432#endif
2433 }
2434 2498
2435 if (rndis) { 2499 if (rndis) {
2436 status = rndis_init(); 2500 status = rndis_init();