162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Simple "CDC Subset" USB Networking Links 462306a36Sopenharmony_ci * Copyright (C) 2000-2005 by David Brownell 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/module.h> 862306a36Sopenharmony_ci#include <linux/kmod.h> 962306a36Sopenharmony_ci#include <linux/netdevice.h> 1062306a36Sopenharmony_ci#include <linux/etherdevice.h> 1162306a36Sopenharmony_ci#include <linux/ethtool.h> 1262306a36Sopenharmony_ci#include <linux/workqueue.h> 1362306a36Sopenharmony_ci#include <linux/mii.h> 1462306a36Sopenharmony_ci#include <linux/usb.h> 1562306a36Sopenharmony_ci#include <linux/usb/usbnet.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* 1962306a36Sopenharmony_ci * This supports simple USB network links that don't require any special 2062306a36Sopenharmony_ci * framing or hardware control operations. The protocol used here is a 2162306a36Sopenharmony_ci * strict subset of CDC Ethernet, with three basic differences reflecting 2262306a36Sopenharmony_ci * the goal that almost any hardware should run it: 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci * - Minimal runtime control: one interface, no altsettings, and 2562306a36Sopenharmony_ci * no vendor or class specific control requests. If a device is 2662306a36Sopenharmony_ci * configured, it is allowed to exchange packets with the host. 2762306a36Sopenharmony_ci * Fancier models would mean not working on some hardware. 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * - Minimal manufacturing control: no IEEE "Organizationally 3062306a36Sopenharmony_ci * Unique ID" required, or an EEPROMs to store one. Each host uses 3162306a36Sopenharmony_ci * one random "locally assigned" Ethernet address instead, which can 3262306a36Sopenharmony_ci * of course be overridden using standard tools like "ifconfig". 3362306a36Sopenharmony_ci * (With 2^46 such addresses, same-net collisions are quite rare.) 3462306a36Sopenharmony_ci * 3562306a36Sopenharmony_ci * - There is no additional framing data for USB. Packets are written 3662306a36Sopenharmony_ci * exactly as in CDC Ethernet, starting with an Ethernet header and 3762306a36Sopenharmony_ci * terminated by a short packet. However, the host will never send a 3862306a36Sopenharmony_ci * zero length packet; some systems can't handle those robustly. 3962306a36Sopenharmony_ci * 4062306a36Sopenharmony_ci * Anything that can transmit and receive USB bulk packets can implement 4162306a36Sopenharmony_ci * this protocol. That includes both smart peripherals and quite a lot 4262306a36Sopenharmony_ci * of "host-to-host" USB cables (which embed two devices back-to-back). 4362306a36Sopenharmony_ci * 4462306a36Sopenharmony_ci * Note that although Linux may use many of those host-to-host links 4562306a36Sopenharmony_ci * with this "cdc_subset" framing, that doesn't mean there may not be a 4662306a36Sopenharmony_ci * better approach. Handling the "other end unplugs/replugs" scenario 4762306a36Sopenharmony_ci * well tends to require chip-specific vendor requests. Also, Windows 4862306a36Sopenharmony_ci * peers at the other end of host-to-host cables may expect their own 4962306a36Sopenharmony_ci * framing to be used rather than this "cdc_subset" model. 5062306a36Sopenharmony_ci */ 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci#if defined(CONFIG_USB_EPSON2888) || defined(CONFIG_USB_ARMLINUX) 5362306a36Sopenharmony_ci/* PDA style devices are always connected if present */ 5462306a36Sopenharmony_cistatic int always_connected (struct usbnet *dev) 5562306a36Sopenharmony_ci{ 5662306a36Sopenharmony_ci return 0; 5762306a36Sopenharmony_ci} 5862306a36Sopenharmony_ci#endif 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci#ifdef CONFIG_USB_ALI_M5632 6162306a36Sopenharmony_ci#define HAVE_HARDWARE 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci/*------------------------------------------------------------------------- 6462306a36Sopenharmony_ci * 6562306a36Sopenharmony_ci * ALi M5632 driver ... does high speed 6662306a36Sopenharmony_ci * 6762306a36Sopenharmony_ci * NOTE that the MS-Windows drivers for this chip use some funky and 6862306a36Sopenharmony_ci * (naturally) undocumented 7-byte prefix to each packet, so this is a 6962306a36Sopenharmony_ci * case where we don't currently interoperate. Also, once you unplug 7062306a36Sopenharmony_ci * one end of the cable, you need to replug the other end too ... since 7162306a36Sopenharmony_ci * chip docs are unavailable, there's no way to reset the relevant state 7262306a36Sopenharmony_ci * short of a power cycle. 7362306a36Sopenharmony_ci * 7462306a36Sopenharmony_ci *-------------------------------------------------------------------------*/ 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cistatic void m5632_recover(struct usbnet *dev) 7762306a36Sopenharmony_ci{ 7862306a36Sopenharmony_ci struct usb_device *udev = dev->udev; 7962306a36Sopenharmony_ci struct usb_interface *intf = dev->intf; 8062306a36Sopenharmony_ci int r; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci r = usb_lock_device_for_reset(udev, intf); 8362306a36Sopenharmony_ci if (r < 0) 8462306a36Sopenharmony_ci return; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci usb_reset_device(udev); 8762306a36Sopenharmony_ci usb_unlock_device(udev); 8862306a36Sopenharmony_ci} 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_cistatic const struct driver_info ali_m5632_info = { 9162306a36Sopenharmony_ci .description = "ALi M5632", 9262306a36Sopenharmony_ci .flags = FLAG_POINTTOPOINT, 9362306a36Sopenharmony_ci .recover = m5632_recover, 9462306a36Sopenharmony_ci}; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci#endif 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci#ifdef CONFIG_USB_AN2720 9962306a36Sopenharmony_ci#define HAVE_HARDWARE 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci/*------------------------------------------------------------------------- 10262306a36Sopenharmony_ci * 10362306a36Sopenharmony_ci * AnchorChips 2720 driver ... http://www.cypress.com 10462306a36Sopenharmony_ci * 10562306a36Sopenharmony_ci * This doesn't seem to have a way to detect whether the peer is 10662306a36Sopenharmony_ci * connected, or need any reset handshaking. It's got pretty big 10762306a36Sopenharmony_ci * internal buffers (handles most of a frame's worth of data). 10862306a36Sopenharmony_ci * Chip data sheets don't describe any vendor control messages. 10962306a36Sopenharmony_ci * 11062306a36Sopenharmony_ci *-------------------------------------------------------------------------*/ 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic const struct driver_info an2720_info = { 11362306a36Sopenharmony_ci .description = "AnchorChips/Cypress 2720", 11462306a36Sopenharmony_ci .flags = FLAG_POINTTOPOINT, 11562306a36Sopenharmony_ci // no reset available! 11662306a36Sopenharmony_ci // no check_connect available! 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci .in = 2, .out = 2, // direction distinguishes these 11962306a36Sopenharmony_ci}; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci#endif /* CONFIG_USB_AN2720 */ 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci#ifdef CONFIG_USB_BELKIN 12562306a36Sopenharmony_ci#define HAVE_HARDWARE 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci/*------------------------------------------------------------------------- 12862306a36Sopenharmony_ci * 12962306a36Sopenharmony_ci * Belkin F5U104 ... two NetChip 2280 devices + Atmel AVR microcontroller 13062306a36Sopenharmony_ci * 13162306a36Sopenharmony_ci * ... also two eTEK designs, including one sold as "Advance USBNET" 13262306a36Sopenharmony_ci * 13362306a36Sopenharmony_ci *-------------------------------------------------------------------------*/ 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistatic const struct driver_info belkin_info = { 13662306a36Sopenharmony_ci .description = "Belkin, eTEK, or compatible", 13762306a36Sopenharmony_ci .flags = FLAG_POINTTOPOINT, 13862306a36Sopenharmony_ci}; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci#endif /* CONFIG_USB_BELKIN */ 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci#ifdef CONFIG_USB_EPSON2888 14562306a36Sopenharmony_ci#define HAVE_HARDWARE 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci/*------------------------------------------------------------------------- 14862306a36Sopenharmony_ci * 14962306a36Sopenharmony_ci * EPSON USB clients 15062306a36Sopenharmony_ci * 15162306a36Sopenharmony_ci * This is the same idea as Linux PDAs (below) except the firmware in the 15262306a36Sopenharmony_ci * device might not be Tux-powered. Epson provides reference firmware that 15362306a36Sopenharmony_ci * implements this interface. Product developers can reuse or modify that 15462306a36Sopenharmony_ci * code, such as by using their own product and vendor codes. 15562306a36Sopenharmony_ci * 15662306a36Sopenharmony_ci * Support was from Juro Bystricky <bystricky.juro@erd.epson.com> 15762306a36Sopenharmony_ci * 15862306a36Sopenharmony_ci *-------------------------------------------------------------------------*/ 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistatic const struct driver_info epson2888_info = { 16162306a36Sopenharmony_ci .description = "Epson USB Device", 16262306a36Sopenharmony_ci .check_connect = always_connected, 16362306a36Sopenharmony_ci .flags = FLAG_POINTTOPOINT, 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci .in = 4, .out = 3, 16662306a36Sopenharmony_ci}; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci#endif /* CONFIG_USB_EPSON2888 */ 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci/*------------------------------------------------------------------------- 17262306a36Sopenharmony_ci * 17362306a36Sopenharmony_ci * info from Jonathan McDowell <noodles@earth.li> 17462306a36Sopenharmony_ci * 17562306a36Sopenharmony_ci *-------------------------------------------------------------------------*/ 17662306a36Sopenharmony_ci#ifdef CONFIG_USB_KC2190 17762306a36Sopenharmony_ci#define HAVE_HARDWARE 17862306a36Sopenharmony_cistatic const struct driver_info kc2190_info = { 17962306a36Sopenharmony_ci .description = "KC Technology KC-190", 18062306a36Sopenharmony_ci .flags = FLAG_POINTTOPOINT, 18162306a36Sopenharmony_ci}; 18262306a36Sopenharmony_ci#endif /* CONFIG_USB_KC2190 */ 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci#ifdef CONFIG_USB_ARMLINUX 18662306a36Sopenharmony_ci#define HAVE_HARDWARE 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci/*------------------------------------------------------------------------- 18962306a36Sopenharmony_ci * 19062306a36Sopenharmony_ci * Intel's SA-1100 chip integrates basic USB support, and is used 19162306a36Sopenharmony_ci * in PDAs like some iPaqs, the Yopy, some Zaurus models, and more. 19262306a36Sopenharmony_ci * When they run Linux, arch/arm/mach-sa1100/usb-eth.c may be used to 19362306a36Sopenharmony_ci * network using minimal USB framing data. 19462306a36Sopenharmony_ci * 19562306a36Sopenharmony_ci * This describes the driver currently in standard ARM Linux kernels. 19662306a36Sopenharmony_ci * The Zaurus uses a different driver (see later). 19762306a36Sopenharmony_ci * 19862306a36Sopenharmony_ci * PXA25x and PXA210 use XScale cores (ARM v5TE) with better USB support 19962306a36Sopenharmony_ci * and different USB endpoint numbering than the SA1100 devices. The 20062306a36Sopenharmony_ci * mach-pxa/usb-eth.c driver re-uses the device ids from mach-sa1100 20162306a36Sopenharmony_ci * so we rely on the endpoint descriptors. 20262306a36Sopenharmony_ci * 20362306a36Sopenharmony_ci *-------------------------------------------------------------------------*/ 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_cistatic const struct driver_info linuxdev_info = { 20662306a36Sopenharmony_ci .description = "Linux Device", 20762306a36Sopenharmony_ci .check_connect = always_connected, 20862306a36Sopenharmony_ci .flags = FLAG_POINTTOPOINT, 20962306a36Sopenharmony_ci}; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_cistatic const struct driver_info yopy_info = { 21262306a36Sopenharmony_ci .description = "Yopy", 21362306a36Sopenharmony_ci .check_connect = always_connected, 21462306a36Sopenharmony_ci .flags = FLAG_POINTTOPOINT, 21562306a36Sopenharmony_ci}; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_cistatic const struct driver_info blob_info = { 21862306a36Sopenharmony_ci .description = "Boot Loader OBject", 21962306a36Sopenharmony_ci .check_connect = always_connected, 22062306a36Sopenharmony_ci .flags = FLAG_POINTTOPOINT, 22162306a36Sopenharmony_ci}; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci#endif /* CONFIG_USB_ARMLINUX */ 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci/*-------------------------------------------------------------------------*/ 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci#ifndef HAVE_HARDWARE 22962306a36Sopenharmony_ci#warning You need to configure some hardware for this driver 23062306a36Sopenharmony_ci#endif 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci/* 23362306a36Sopenharmony_ci * chip vendor names won't normally be on the cables, and 23462306a36Sopenharmony_ci * may not be on the device. 23562306a36Sopenharmony_ci */ 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_cistatic const struct usb_device_id products [] = { 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci#ifdef CONFIG_USB_ALI_M5632 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci USB_DEVICE (0x0402, 0x5632), // ALi defaults 24262306a36Sopenharmony_ci .driver_info = (unsigned long) &ali_m5632_info, 24362306a36Sopenharmony_ci}, 24462306a36Sopenharmony_ci{ 24562306a36Sopenharmony_ci USB_DEVICE (0x182d,0x207c), // SiteCom CN-124 24662306a36Sopenharmony_ci .driver_info = (unsigned long) &ali_m5632_info, 24762306a36Sopenharmony_ci}, 24862306a36Sopenharmony_ci#endif 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci#ifdef CONFIG_USB_AN2720 25162306a36Sopenharmony_ci{ 25262306a36Sopenharmony_ci USB_DEVICE (0x0547, 0x2720), // AnchorChips defaults 25362306a36Sopenharmony_ci .driver_info = (unsigned long) &an2720_info, 25462306a36Sopenharmony_ci}, { 25562306a36Sopenharmony_ci USB_DEVICE (0x0547, 0x2727), // Xircom PGUNET 25662306a36Sopenharmony_ci .driver_info = (unsigned long) &an2720_info, 25762306a36Sopenharmony_ci}, 25862306a36Sopenharmony_ci#endif 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci#ifdef CONFIG_USB_BELKIN 26162306a36Sopenharmony_ci{ 26262306a36Sopenharmony_ci USB_DEVICE (0x050d, 0x0004), // Belkin 26362306a36Sopenharmony_ci .driver_info = (unsigned long) &belkin_info, 26462306a36Sopenharmony_ci}, { 26562306a36Sopenharmony_ci USB_DEVICE (0x056c, 0x8100), // eTEK 26662306a36Sopenharmony_ci .driver_info = (unsigned long) &belkin_info, 26762306a36Sopenharmony_ci}, { 26862306a36Sopenharmony_ci USB_DEVICE (0x0525, 0x9901), // Advance USBNET (eTEK) 26962306a36Sopenharmony_ci .driver_info = (unsigned long) &belkin_info, 27062306a36Sopenharmony_ci}, 27162306a36Sopenharmony_ci#endif 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci#ifdef CONFIG_USB_EPSON2888 27462306a36Sopenharmony_ci{ 27562306a36Sopenharmony_ci USB_DEVICE (0x0525, 0x2888), // EPSON USB client 27662306a36Sopenharmony_ci .driver_info = (unsigned long) &epson2888_info, 27762306a36Sopenharmony_ci}, 27862306a36Sopenharmony_ci#endif 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci#ifdef CONFIG_USB_KC2190 28162306a36Sopenharmony_ci{ 28262306a36Sopenharmony_ci USB_DEVICE (0x050f, 0x0190), // KC-190 28362306a36Sopenharmony_ci .driver_info = (unsigned long) &kc2190_info, 28462306a36Sopenharmony_ci}, 28562306a36Sopenharmony_ci#endif 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci#ifdef CONFIG_USB_ARMLINUX 28862306a36Sopenharmony_ci/* 28962306a36Sopenharmony_ci * SA-1100 using standard ARM Linux kernels, or compatible. 29062306a36Sopenharmony_ci * Often used when talking to Linux PDAs (iPaq, Yopy, etc). 29162306a36Sopenharmony_ci * The sa-1100 "usb-eth" driver handles the basic framing. 29262306a36Sopenharmony_ci * 29362306a36Sopenharmony_ci * PXA25x or PXA210 ... these use a "usb-eth" driver much like 29462306a36Sopenharmony_ci * the sa1100 one, but hardware uses different endpoint numbers. 29562306a36Sopenharmony_ci * 29662306a36Sopenharmony_ci * Or the Linux "Ethernet" gadget on hardware that can't talk 29762306a36Sopenharmony_ci * CDC Ethernet (e.g., no altsettings), in either of two modes: 29862306a36Sopenharmony_ci * - acting just like the old "usb-eth" firmware, though 29962306a36Sopenharmony_ci * the implementation is different 30062306a36Sopenharmony_ci * - supporting RNDIS as the first/default configuration for 30162306a36Sopenharmony_ci * MS-Windows interop; Linux needs to use the other config 30262306a36Sopenharmony_ci */ 30362306a36Sopenharmony_ci{ 30462306a36Sopenharmony_ci // 1183 = 0x049F, both used as hex values? 30562306a36Sopenharmony_ci // Compaq "Itsy" vendor/product id 30662306a36Sopenharmony_ci USB_DEVICE (0x049F, 0x505A), // usb-eth, or compatible 30762306a36Sopenharmony_ci .driver_info = (unsigned long) &linuxdev_info, 30862306a36Sopenharmony_ci}, { 30962306a36Sopenharmony_ci USB_DEVICE (0x0E7E, 0x1001), // G.Mate "Yopy" 31062306a36Sopenharmony_ci .driver_info = (unsigned long) &yopy_info, 31162306a36Sopenharmony_ci}, { 31262306a36Sopenharmony_ci USB_DEVICE (0x8086, 0x07d3), // "blob" bootloader 31362306a36Sopenharmony_ci .driver_info = (unsigned long) &blob_info, 31462306a36Sopenharmony_ci}, { 31562306a36Sopenharmony_ci USB_DEVICE (0x1286, 0x8001), // "blob" bootloader 31662306a36Sopenharmony_ci .driver_info = (unsigned long) &blob_info, 31762306a36Sopenharmony_ci}, { 31862306a36Sopenharmony_ci // Linux Ethernet/RNDIS gadget, mostly on PXA, second config 31962306a36Sopenharmony_ci // e.g. Gumstix, current OpenZaurus, ... or anything else 32062306a36Sopenharmony_ci // that just enables this gadget option. 32162306a36Sopenharmony_ci USB_DEVICE (0x0525, 0xa4a2), 32262306a36Sopenharmony_ci .driver_info = (unsigned long) &linuxdev_info, 32362306a36Sopenharmony_ci}, 32462306a36Sopenharmony_ci#endif 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci { }, // END 32762306a36Sopenharmony_ci}; 32862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(usb, products); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci/*-------------------------------------------------------------------------*/ 33162306a36Sopenharmony_cistatic int dummy_prereset(struct usb_interface *intf) 33262306a36Sopenharmony_ci{ 33362306a36Sopenharmony_ci return 0; 33462306a36Sopenharmony_ci} 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_cistatic int dummy_postreset(struct usb_interface *intf) 33762306a36Sopenharmony_ci{ 33862306a36Sopenharmony_ci return 0; 33962306a36Sopenharmony_ci} 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_cistatic struct usb_driver cdc_subset_driver = { 34262306a36Sopenharmony_ci .name = "cdc_subset", 34362306a36Sopenharmony_ci .probe = usbnet_probe, 34462306a36Sopenharmony_ci .suspend = usbnet_suspend, 34562306a36Sopenharmony_ci .resume = usbnet_resume, 34662306a36Sopenharmony_ci .pre_reset = dummy_prereset, 34762306a36Sopenharmony_ci .post_reset = dummy_postreset, 34862306a36Sopenharmony_ci .disconnect = usbnet_disconnect, 34962306a36Sopenharmony_ci .id_table = products, 35062306a36Sopenharmony_ci .disable_hub_initiated_lpm = 1, 35162306a36Sopenharmony_ci}; 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_cimodule_usb_driver(cdc_subset_driver); 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ciMODULE_AUTHOR("David Brownell"); 35662306a36Sopenharmony_ciMODULE_DESCRIPTION("Simple 'CDC Subset' USB networking links"); 35762306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 358