18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * CDC Ethernet based networking peripherals 48c2ecf20Sopenharmony_ci * Copyright (C) 2003-2005 by David Brownell 58c2ecf20Sopenharmony_ci * Copyright (C) 2006 by Ole Andre Vadla Ravnas (ActiveSync) 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci// #define DEBUG // error path messages, extra info 98c2ecf20Sopenharmony_ci// #define VERBOSE // more; success messages 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/module.h> 128c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 138c2ecf20Sopenharmony_ci#include <linux/etherdevice.h> 148c2ecf20Sopenharmony_ci#include <linux/ethtool.h> 158c2ecf20Sopenharmony_ci#include <linux/workqueue.h> 168c2ecf20Sopenharmony_ci#include <linux/mii.h> 178c2ecf20Sopenharmony_ci#include <linux/usb.h> 188c2ecf20Sopenharmony_ci#include <linux/usb/cdc.h> 198c2ecf20Sopenharmony_ci#include <linux/usb/usbnet.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_USB_NET_RNDIS_HOST) 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistatic int is_rndis(struct usb_interface_descriptor *desc) 258c2ecf20Sopenharmony_ci{ 268c2ecf20Sopenharmony_ci return (desc->bInterfaceClass == USB_CLASS_COMM && 278c2ecf20Sopenharmony_ci desc->bInterfaceSubClass == 2 && 288c2ecf20Sopenharmony_ci desc->bInterfaceProtocol == 0xff); 298c2ecf20Sopenharmony_ci} 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic int is_activesync(struct usb_interface_descriptor *desc) 328c2ecf20Sopenharmony_ci{ 338c2ecf20Sopenharmony_ci return (desc->bInterfaceClass == USB_CLASS_MISC && 348c2ecf20Sopenharmony_ci desc->bInterfaceSubClass == 1 && 358c2ecf20Sopenharmony_ci desc->bInterfaceProtocol == 1); 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic int is_wireless_rndis(struct usb_interface_descriptor *desc) 398c2ecf20Sopenharmony_ci{ 408c2ecf20Sopenharmony_ci return (desc->bInterfaceClass == USB_CLASS_WIRELESS_CONTROLLER && 418c2ecf20Sopenharmony_ci desc->bInterfaceSubClass == 1 && 428c2ecf20Sopenharmony_ci desc->bInterfaceProtocol == 3); 438c2ecf20Sopenharmony_ci} 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic int is_novatel_rndis(struct usb_interface_descriptor *desc) 468c2ecf20Sopenharmony_ci{ 478c2ecf20Sopenharmony_ci return (desc->bInterfaceClass == USB_CLASS_MISC && 488c2ecf20Sopenharmony_ci desc->bInterfaceSubClass == 4 && 498c2ecf20Sopenharmony_ci desc->bInterfaceProtocol == 1); 508c2ecf20Sopenharmony_ci} 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci#else 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci#define is_rndis(desc) 0 558c2ecf20Sopenharmony_ci#define is_activesync(desc) 0 568c2ecf20Sopenharmony_ci#define is_wireless_rndis(desc) 0 578c2ecf20Sopenharmony_ci#define is_novatel_rndis(desc) 0 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci#endif 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic const u8 mbm_guid[16] = { 628c2ecf20Sopenharmony_ci 0xa3, 0x17, 0xa8, 0x8b, 0x04, 0x5e, 0x4f, 0x01, 638c2ecf20Sopenharmony_ci 0xa6, 0x07, 0xc0, 0xff, 0xcb, 0x7e, 0x39, 0x2a, 648c2ecf20Sopenharmony_ci}; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_civoid usbnet_cdc_update_filter(struct usbnet *dev) 678c2ecf20Sopenharmony_ci{ 688c2ecf20Sopenharmony_ci struct net_device *net = dev->net; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci u16 cdc_filter = USB_CDC_PACKET_TYPE_DIRECTED 718c2ecf20Sopenharmony_ci | USB_CDC_PACKET_TYPE_BROADCAST; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci /* filtering on the device is an optional feature and not worth 748c2ecf20Sopenharmony_ci * the hassle so we just roughly care about snooping and if any 758c2ecf20Sopenharmony_ci * multicast is requested, we take every multicast 768c2ecf20Sopenharmony_ci */ 778c2ecf20Sopenharmony_ci if (net->flags & IFF_PROMISC) 788c2ecf20Sopenharmony_ci cdc_filter |= USB_CDC_PACKET_TYPE_PROMISCUOUS; 798c2ecf20Sopenharmony_ci if (!netdev_mc_empty(net) || (net->flags & IFF_ALLMULTI)) 808c2ecf20Sopenharmony_ci cdc_filter |= USB_CDC_PACKET_TYPE_ALL_MULTICAST; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci usb_control_msg(dev->udev, 838c2ecf20Sopenharmony_ci usb_sndctrlpipe(dev->udev, 0), 848c2ecf20Sopenharmony_ci USB_CDC_SET_ETHERNET_PACKET_FILTER, 858c2ecf20Sopenharmony_ci USB_TYPE_CLASS | USB_RECIP_INTERFACE, 868c2ecf20Sopenharmony_ci cdc_filter, 878c2ecf20Sopenharmony_ci dev->intf->cur_altsetting->desc.bInterfaceNumber, 888c2ecf20Sopenharmony_ci NULL, 898c2ecf20Sopenharmony_ci 0, 908c2ecf20Sopenharmony_ci USB_CTRL_SET_TIMEOUT 918c2ecf20Sopenharmony_ci ); 928c2ecf20Sopenharmony_ci} 938c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usbnet_cdc_update_filter); 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci/* probes control interface, claims data interface, collects the bulk 968c2ecf20Sopenharmony_ci * endpoints, activates data interface (if needed), maybe sets MTU. 978c2ecf20Sopenharmony_ci * all pure cdc, except for certain firmware workarounds, and knowing 988c2ecf20Sopenharmony_ci * that rndis uses one different rule. 998c2ecf20Sopenharmony_ci */ 1008c2ecf20Sopenharmony_ciint usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) 1018c2ecf20Sopenharmony_ci{ 1028c2ecf20Sopenharmony_ci u8 *buf = intf->cur_altsetting->extra; 1038c2ecf20Sopenharmony_ci int len = intf->cur_altsetting->extralen; 1048c2ecf20Sopenharmony_ci struct usb_interface_descriptor *d; 1058c2ecf20Sopenharmony_ci struct cdc_state *info = (void *) &dev->data; 1068c2ecf20Sopenharmony_ci int status; 1078c2ecf20Sopenharmony_ci int rndis; 1088c2ecf20Sopenharmony_ci bool android_rndis_quirk = false; 1098c2ecf20Sopenharmony_ci struct usb_driver *driver = driver_of(intf); 1108c2ecf20Sopenharmony_ci struct usb_cdc_parsed_header header; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci if (sizeof(dev->data) < sizeof(*info)) 1138c2ecf20Sopenharmony_ci return -EDOM; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci /* expect strict spec conformance for the descriptors, but 1168c2ecf20Sopenharmony_ci * cope with firmware which stores them in the wrong place 1178c2ecf20Sopenharmony_ci */ 1188c2ecf20Sopenharmony_ci if (len == 0 && dev->udev->actconfig->extralen) { 1198c2ecf20Sopenharmony_ci /* Motorola SB4100 (and others: Brad Hards says it's 1208c2ecf20Sopenharmony_ci * from a Broadcom design) put CDC descriptors here 1218c2ecf20Sopenharmony_ci */ 1228c2ecf20Sopenharmony_ci buf = dev->udev->actconfig->extra; 1238c2ecf20Sopenharmony_ci len = dev->udev->actconfig->extralen; 1248c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "CDC descriptors on config\n"); 1258c2ecf20Sopenharmony_ci } 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci /* Maybe CDC descriptors are after the endpoint? This bug has 1288c2ecf20Sopenharmony_ci * been seen on some 2Wire Inc RNDIS-ish products. 1298c2ecf20Sopenharmony_ci */ 1308c2ecf20Sopenharmony_ci if (len == 0) { 1318c2ecf20Sopenharmony_ci struct usb_host_endpoint *hep; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci hep = intf->cur_altsetting->endpoint; 1348c2ecf20Sopenharmony_ci if (hep) { 1358c2ecf20Sopenharmony_ci buf = hep->extra; 1368c2ecf20Sopenharmony_ci len = hep->extralen; 1378c2ecf20Sopenharmony_ci } 1388c2ecf20Sopenharmony_ci if (len) 1398c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, 1408c2ecf20Sopenharmony_ci "CDC descriptors on endpoint\n"); 1418c2ecf20Sopenharmony_ci } 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci /* this assumes that if there's a non-RNDIS vendor variant 1448c2ecf20Sopenharmony_ci * of cdc-acm, it'll fail RNDIS requests cleanly. 1458c2ecf20Sopenharmony_ci */ 1468c2ecf20Sopenharmony_ci rndis = (is_rndis(&intf->cur_altsetting->desc) || 1478c2ecf20Sopenharmony_ci is_activesync(&intf->cur_altsetting->desc) || 1488c2ecf20Sopenharmony_ci is_wireless_rndis(&intf->cur_altsetting->desc) || 1498c2ecf20Sopenharmony_ci is_novatel_rndis(&intf->cur_altsetting->desc)); 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci memset(info, 0, sizeof(*info)); 1528c2ecf20Sopenharmony_ci info->control = intf; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci cdc_parse_cdc_header(&header, intf, buf, len); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci info->u = header.usb_cdc_union_desc; 1578c2ecf20Sopenharmony_ci info->header = header.usb_cdc_header_desc; 1588c2ecf20Sopenharmony_ci info->ether = header.usb_cdc_ether_desc; 1598c2ecf20Sopenharmony_ci if (!info->u) { 1608c2ecf20Sopenharmony_ci if (rndis) 1618c2ecf20Sopenharmony_ci goto skip; 1628c2ecf20Sopenharmony_ci else /* in that case a quirk is mandatory */ 1638c2ecf20Sopenharmony_ci goto bad_desc; 1648c2ecf20Sopenharmony_ci } 1658c2ecf20Sopenharmony_ci /* we need a master/control interface (what we're 1668c2ecf20Sopenharmony_ci * probed with) and a slave/data interface; union 1678c2ecf20Sopenharmony_ci * descriptors sort this all out. 1688c2ecf20Sopenharmony_ci */ 1698c2ecf20Sopenharmony_ci info->control = usb_ifnum_to_if(dev->udev, info->u->bMasterInterface0); 1708c2ecf20Sopenharmony_ci info->data = usb_ifnum_to_if(dev->udev, info->u->bSlaveInterface0); 1718c2ecf20Sopenharmony_ci if (!info->control || !info->data) { 1728c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, 1738c2ecf20Sopenharmony_ci "master #%u/%p slave #%u/%p\n", 1748c2ecf20Sopenharmony_ci info->u->bMasterInterface0, 1758c2ecf20Sopenharmony_ci info->control, 1768c2ecf20Sopenharmony_ci info->u->bSlaveInterface0, 1778c2ecf20Sopenharmony_ci info->data); 1788c2ecf20Sopenharmony_ci /* fall back to hard-wiring for RNDIS */ 1798c2ecf20Sopenharmony_ci if (rndis) { 1808c2ecf20Sopenharmony_ci android_rndis_quirk = true; 1818c2ecf20Sopenharmony_ci goto skip; 1828c2ecf20Sopenharmony_ci } 1838c2ecf20Sopenharmony_ci goto bad_desc; 1848c2ecf20Sopenharmony_ci } 1858c2ecf20Sopenharmony_ci if (info->control != intf) { 1868c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "bogus CDC Union\n"); 1878c2ecf20Sopenharmony_ci /* Ambit USB Cable Modem (and maybe others) 1888c2ecf20Sopenharmony_ci * interchanges master and slave interface. 1898c2ecf20Sopenharmony_ci */ 1908c2ecf20Sopenharmony_ci if (info->data == intf) { 1918c2ecf20Sopenharmony_ci info->data = info->control; 1928c2ecf20Sopenharmony_ci info->control = intf; 1938c2ecf20Sopenharmony_ci } else 1948c2ecf20Sopenharmony_ci goto bad_desc; 1958c2ecf20Sopenharmony_ci } 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci /* some devices merge these - skip class check */ 1988c2ecf20Sopenharmony_ci if (info->control == info->data) 1998c2ecf20Sopenharmony_ci goto skip; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci /* a data interface altsetting does the real i/o */ 2028c2ecf20Sopenharmony_ci d = &info->data->cur_altsetting->desc; 2038c2ecf20Sopenharmony_ci if (d->bInterfaceClass != USB_CLASS_CDC_DATA) { 2048c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "slave class %u\n", d->bInterfaceClass); 2058c2ecf20Sopenharmony_ci goto bad_desc; 2068c2ecf20Sopenharmony_ci } 2078c2ecf20Sopenharmony_ciskip: 2088c2ecf20Sopenharmony_ci /* Communcation class functions with bmCapabilities are not 2098c2ecf20Sopenharmony_ci * RNDIS. But some Wireless class RNDIS functions use 2108c2ecf20Sopenharmony_ci * bmCapabilities for their own purpose. The failsafe is 2118c2ecf20Sopenharmony_ci * therefore applied only to Communication class RNDIS 2128c2ecf20Sopenharmony_ci * functions. The rndis test is redundant, but a cheap 2138c2ecf20Sopenharmony_ci * optimization. 2148c2ecf20Sopenharmony_ci */ 2158c2ecf20Sopenharmony_ci if (rndis && is_rndis(&intf->cur_altsetting->desc) && 2168c2ecf20Sopenharmony_ci header.usb_cdc_acm_descriptor && 2178c2ecf20Sopenharmony_ci header.usb_cdc_acm_descriptor->bmCapabilities) { 2188c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, 2198c2ecf20Sopenharmony_ci "ACM capabilities %02x, not really RNDIS?\n", 2208c2ecf20Sopenharmony_ci header.usb_cdc_acm_descriptor->bmCapabilities); 2218c2ecf20Sopenharmony_ci goto bad_desc; 2228c2ecf20Sopenharmony_ci } 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci if (header.usb_cdc_ether_desc && info->ether->wMaxSegmentSize) { 2258c2ecf20Sopenharmony_ci dev->hard_mtu = le16_to_cpu(info->ether->wMaxSegmentSize); 2268c2ecf20Sopenharmony_ci /* because of Zaurus, we may be ignoring the host 2278c2ecf20Sopenharmony_ci * side link address we were given. 2288c2ecf20Sopenharmony_ci */ 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci if (header.usb_cdc_mdlm_desc && 2328c2ecf20Sopenharmony_ci memcmp(header.usb_cdc_mdlm_desc->bGUID, mbm_guid, 16)) { 2338c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "GUID doesn't match\n"); 2348c2ecf20Sopenharmony_ci goto bad_desc; 2358c2ecf20Sopenharmony_ci } 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci if (header.usb_cdc_mdlm_detail_desc && 2388c2ecf20Sopenharmony_ci header.usb_cdc_mdlm_detail_desc->bLength < 2398c2ecf20Sopenharmony_ci (sizeof(struct usb_cdc_mdlm_detail_desc) + 1)) { 2408c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "Descriptor too short\n"); 2418c2ecf20Sopenharmony_ci goto bad_desc; 2428c2ecf20Sopenharmony_ci } 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci /* Microsoft ActiveSync based and some regular RNDIS devices lack the 2478c2ecf20Sopenharmony_ci * CDC descriptors, so we'll hard-wire the interfaces and not check 2488c2ecf20Sopenharmony_ci * for descriptors. 2498c2ecf20Sopenharmony_ci * 2508c2ecf20Sopenharmony_ci * Some Android RNDIS devices have a CDC Union descriptor pointing 2518c2ecf20Sopenharmony_ci * to non-existing interfaces. Ignore that and attempt the same 2528c2ecf20Sopenharmony_ci * hard-wired 0 and 1 interfaces. 2538c2ecf20Sopenharmony_ci */ 2548c2ecf20Sopenharmony_ci if (rndis && (!info->u || android_rndis_quirk)) { 2558c2ecf20Sopenharmony_ci info->control = usb_ifnum_to_if(dev->udev, 0); 2568c2ecf20Sopenharmony_ci info->data = usb_ifnum_to_if(dev->udev, 1); 2578c2ecf20Sopenharmony_ci if (!info->control || !info->data || info->control != intf) { 2588c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, 2598c2ecf20Sopenharmony_ci "rndis: master #0/%p slave #1/%p\n", 2608c2ecf20Sopenharmony_ci info->control, 2618c2ecf20Sopenharmony_ci info->data); 2628c2ecf20Sopenharmony_ci goto bad_desc; 2638c2ecf20Sopenharmony_ci } 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci } else if (!info->header || (!rndis && !info->ether)) { 2668c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "missing cdc %s%s%sdescriptor\n", 2678c2ecf20Sopenharmony_ci info->header ? "" : "header ", 2688c2ecf20Sopenharmony_ci info->u ? "" : "union ", 2698c2ecf20Sopenharmony_ci info->ether ? "" : "ether "); 2708c2ecf20Sopenharmony_ci goto bad_desc; 2718c2ecf20Sopenharmony_ci } 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci /* claim data interface and set it up ... with side effects. 2748c2ecf20Sopenharmony_ci * network traffic can't flow until an altsetting is enabled. 2758c2ecf20Sopenharmony_ci */ 2768c2ecf20Sopenharmony_ci if (info->data != info->control) { 2778c2ecf20Sopenharmony_ci status = usb_driver_claim_interface(driver, info->data, dev); 2788c2ecf20Sopenharmony_ci if (status < 0) 2798c2ecf20Sopenharmony_ci return status; 2808c2ecf20Sopenharmony_ci } 2818c2ecf20Sopenharmony_ci status = usbnet_get_endpoints(dev, info->data); 2828c2ecf20Sopenharmony_ci if (status < 0) { 2838c2ecf20Sopenharmony_ci /* ensure immediate exit from usbnet_disconnect */ 2848c2ecf20Sopenharmony_ci usb_set_intfdata(info->data, NULL); 2858c2ecf20Sopenharmony_ci if (info->data != info->control) 2868c2ecf20Sopenharmony_ci usb_driver_release_interface(driver, info->data); 2878c2ecf20Sopenharmony_ci return status; 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci /* status endpoint: optional for CDC Ethernet, not RNDIS (or ACM) */ 2918c2ecf20Sopenharmony_ci if (info->data != info->control) 2928c2ecf20Sopenharmony_ci dev->status = NULL; 2938c2ecf20Sopenharmony_ci if (info->control->cur_altsetting->desc.bNumEndpoints == 1) { 2948c2ecf20Sopenharmony_ci struct usb_endpoint_descriptor *desc; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci dev->status = &info->control->cur_altsetting->endpoint[0]; 2978c2ecf20Sopenharmony_ci desc = &dev->status->desc; 2988c2ecf20Sopenharmony_ci if (!usb_endpoint_is_int_in(desc) || 2998c2ecf20Sopenharmony_ci (le16_to_cpu(desc->wMaxPacketSize) 3008c2ecf20Sopenharmony_ci < sizeof(struct usb_cdc_notification)) || 3018c2ecf20Sopenharmony_ci !desc->bInterval) { 3028c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "bad notification endpoint\n"); 3038c2ecf20Sopenharmony_ci dev->status = NULL; 3048c2ecf20Sopenharmony_ci } 3058c2ecf20Sopenharmony_ci } 3068c2ecf20Sopenharmony_ci if (rndis && !dev->status) { 3078c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "missing RNDIS status endpoint\n"); 3088c2ecf20Sopenharmony_ci usb_set_intfdata(info->data, NULL); 3098c2ecf20Sopenharmony_ci usb_driver_release_interface(driver, info->data); 3108c2ecf20Sopenharmony_ci return -ENODEV; 3118c2ecf20Sopenharmony_ci } 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci return 0; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_cibad_desc: 3168c2ecf20Sopenharmony_ci dev_info(&dev->udev->dev, "bad CDC descriptors\n"); 3178c2ecf20Sopenharmony_ci return -ENODEV; 3188c2ecf20Sopenharmony_ci} 3198c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usbnet_generic_cdc_bind); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci/* like usbnet_generic_cdc_bind() but handles filter initialization 3238c2ecf20Sopenharmony_ci * correctly 3248c2ecf20Sopenharmony_ci */ 3258c2ecf20Sopenharmony_ciint usbnet_ether_cdc_bind(struct usbnet *dev, struct usb_interface *intf) 3268c2ecf20Sopenharmony_ci{ 3278c2ecf20Sopenharmony_ci int rv; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci rv = usbnet_generic_cdc_bind(dev, intf); 3308c2ecf20Sopenharmony_ci if (rv < 0) 3318c2ecf20Sopenharmony_ci goto bail_out; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci /* Some devices don't initialise properly. In particular 3348c2ecf20Sopenharmony_ci * the packet filter is not reset. There are devices that 3358c2ecf20Sopenharmony_ci * don't do reset all the way. So the packet filter should 3368c2ecf20Sopenharmony_ci * be set to a sane initial value. 3378c2ecf20Sopenharmony_ci */ 3388c2ecf20Sopenharmony_ci usbnet_cdc_update_filter(dev); 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_cibail_out: 3418c2ecf20Sopenharmony_ci return rv; 3428c2ecf20Sopenharmony_ci} 3438c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usbnet_ether_cdc_bind); 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_civoid usbnet_cdc_unbind(struct usbnet *dev, struct usb_interface *intf) 3468c2ecf20Sopenharmony_ci{ 3478c2ecf20Sopenharmony_ci struct cdc_state *info = (void *) &dev->data; 3488c2ecf20Sopenharmony_ci struct usb_driver *driver = driver_of(intf); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci /* combined interface - nothing to do */ 3518c2ecf20Sopenharmony_ci if (info->data == info->control) 3528c2ecf20Sopenharmony_ci return; 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci /* disconnect master --> disconnect slave */ 3558c2ecf20Sopenharmony_ci if (intf == info->control && info->data) { 3568c2ecf20Sopenharmony_ci /* ensure immediate exit from usbnet_disconnect */ 3578c2ecf20Sopenharmony_ci usb_set_intfdata(info->data, NULL); 3588c2ecf20Sopenharmony_ci usb_driver_release_interface(driver, info->data); 3598c2ecf20Sopenharmony_ci info->data = NULL; 3608c2ecf20Sopenharmony_ci } 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci /* and vice versa (just in case) */ 3638c2ecf20Sopenharmony_ci else if (intf == info->data && info->control) { 3648c2ecf20Sopenharmony_ci /* ensure immediate exit from usbnet_disconnect */ 3658c2ecf20Sopenharmony_ci usb_set_intfdata(info->control, NULL); 3668c2ecf20Sopenharmony_ci usb_driver_release_interface(driver, info->control); 3678c2ecf20Sopenharmony_ci info->control = NULL; 3688c2ecf20Sopenharmony_ci } 3698c2ecf20Sopenharmony_ci} 3708c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usbnet_cdc_unbind); 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci/* Communications Device Class, Ethernet Control model 3738c2ecf20Sopenharmony_ci * 3748c2ecf20Sopenharmony_ci * Takes two interfaces. The DATA interface is inactive till an altsetting 3758c2ecf20Sopenharmony_ci * is selected. Configuration data includes class descriptors. There's 3768c2ecf20Sopenharmony_ci * an optional status endpoint on the control interface. 3778c2ecf20Sopenharmony_ci * 3788c2ecf20Sopenharmony_ci * This should interop with whatever the 2.4 "CDCEther.c" driver 3798c2ecf20Sopenharmony_ci * (by Brad Hards) talked with, with more functionality. 3808c2ecf20Sopenharmony_ci */ 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_cistatic void dumpspeed(struct usbnet *dev, __le32 *speeds) 3838c2ecf20Sopenharmony_ci{ 3848c2ecf20Sopenharmony_ci netif_info(dev, timer, dev->net, 3858c2ecf20Sopenharmony_ci "link speeds: %u kbps up, %u kbps down\n", 3868c2ecf20Sopenharmony_ci __le32_to_cpu(speeds[0]) / 1000, 3878c2ecf20Sopenharmony_ci __le32_to_cpu(speeds[1]) / 1000); 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_civoid usbnet_cdc_status(struct usbnet *dev, struct urb *urb) 3918c2ecf20Sopenharmony_ci{ 3928c2ecf20Sopenharmony_ci struct usb_cdc_notification *event; 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci if (urb->actual_length < sizeof(*event)) 3958c2ecf20Sopenharmony_ci return; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci /* SPEED_CHANGE can get split into two 8-byte packets */ 3988c2ecf20Sopenharmony_ci if (test_and_clear_bit(EVENT_STS_SPLIT, &dev->flags)) { 3998c2ecf20Sopenharmony_ci dumpspeed(dev, (__le32 *) urb->transfer_buffer); 4008c2ecf20Sopenharmony_ci return; 4018c2ecf20Sopenharmony_ci } 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci event = urb->transfer_buffer; 4048c2ecf20Sopenharmony_ci switch (event->bNotificationType) { 4058c2ecf20Sopenharmony_ci case USB_CDC_NOTIFY_NETWORK_CONNECTION: 4068c2ecf20Sopenharmony_ci netif_dbg(dev, timer, dev->net, "CDC: carrier %s\n", 4078c2ecf20Sopenharmony_ci event->wValue ? "on" : "off"); 4088c2ecf20Sopenharmony_ci usbnet_link_change(dev, !!event->wValue, 0); 4098c2ecf20Sopenharmony_ci break; 4108c2ecf20Sopenharmony_ci case USB_CDC_NOTIFY_SPEED_CHANGE: /* tx/rx rates */ 4118c2ecf20Sopenharmony_ci netif_dbg(dev, timer, dev->net, "CDC: speed change (len %d)\n", 4128c2ecf20Sopenharmony_ci urb->actual_length); 4138c2ecf20Sopenharmony_ci if (urb->actual_length != (sizeof(*event) + 8)) 4148c2ecf20Sopenharmony_ci set_bit(EVENT_STS_SPLIT, &dev->flags); 4158c2ecf20Sopenharmony_ci else 4168c2ecf20Sopenharmony_ci dumpspeed(dev, (__le32 *) &event[1]); 4178c2ecf20Sopenharmony_ci break; 4188c2ecf20Sopenharmony_ci /* USB_CDC_NOTIFY_RESPONSE_AVAILABLE can happen too (e.g. RNDIS), 4198c2ecf20Sopenharmony_ci * but there are no standard formats for the response data. 4208c2ecf20Sopenharmony_ci */ 4218c2ecf20Sopenharmony_ci default: 4228c2ecf20Sopenharmony_ci netdev_err(dev->net, "CDC: unexpected notification %02x!\n", 4238c2ecf20Sopenharmony_ci event->bNotificationType); 4248c2ecf20Sopenharmony_ci break; 4258c2ecf20Sopenharmony_ci } 4268c2ecf20Sopenharmony_ci} 4278c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usbnet_cdc_status); 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ciint usbnet_cdc_bind(struct usbnet *dev, struct usb_interface *intf) 4308c2ecf20Sopenharmony_ci{ 4318c2ecf20Sopenharmony_ci int status; 4328c2ecf20Sopenharmony_ci struct cdc_state *info = (void *) &dev->data; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) 4358c2ecf20Sopenharmony_ci < sizeof(struct cdc_state))); 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci status = usbnet_ether_cdc_bind(dev, intf); 4388c2ecf20Sopenharmony_ci if (status < 0) 4398c2ecf20Sopenharmony_ci return status; 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci status = usbnet_get_ethernet_addr(dev, info->ether->iMACAddress); 4428c2ecf20Sopenharmony_ci if (status < 0) { 4438c2ecf20Sopenharmony_ci usb_set_intfdata(info->data, NULL); 4448c2ecf20Sopenharmony_ci usb_driver_release_interface(driver_of(intf), info->data); 4458c2ecf20Sopenharmony_ci return status; 4468c2ecf20Sopenharmony_ci } 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci return 0; 4498c2ecf20Sopenharmony_ci} 4508c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usbnet_cdc_bind); 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_cistatic int usbnet_cdc_zte_bind(struct usbnet *dev, struct usb_interface *intf) 4538c2ecf20Sopenharmony_ci{ 4548c2ecf20Sopenharmony_ci int status = usbnet_cdc_bind(dev, intf); 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci if (!status && (dev->net->dev_addr[0] & 0x02)) 4578c2ecf20Sopenharmony_ci eth_hw_addr_random(dev->net); 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci return status; 4608c2ecf20Sopenharmony_ci} 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci/* Make sure packets have correct destination MAC address 4638c2ecf20Sopenharmony_ci * 4648c2ecf20Sopenharmony_ci * A firmware bug observed on some devices (ZTE MF823/831/910) is that the 4658c2ecf20Sopenharmony_ci * device sends packets with a static, bogus, random MAC address (event if 4668c2ecf20Sopenharmony_ci * device MAC address has been updated). Always set MAC address to that of the 4678c2ecf20Sopenharmony_ci * device. 4688c2ecf20Sopenharmony_ci */ 4698c2ecf20Sopenharmony_cistatic int usbnet_cdc_zte_rx_fixup(struct usbnet *dev, struct sk_buff *skb) 4708c2ecf20Sopenharmony_ci{ 4718c2ecf20Sopenharmony_ci if (skb->len < ETH_HLEN || !(skb->data[0] & 0x02)) 4728c2ecf20Sopenharmony_ci return 1; 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci skb_reset_mac_header(skb); 4758c2ecf20Sopenharmony_ci ether_addr_copy(eth_hdr(skb)->h_dest, dev->net->dev_addr); 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci return 1; 4788c2ecf20Sopenharmony_ci} 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci/* Ensure correct link state 4818c2ecf20Sopenharmony_ci * 4828c2ecf20Sopenharmony_ci * Some devices (ZTE MF823/831/910) export two carrier on notifications when 4838c2ecf20Sopenharmony_ci * connected. This causes the link state to be incorrect. Work around this by 4848c2ecf20Sopenharmony_ci * always setting the state to off, then on. 4858c2ecf20Sopenharmony_ci */ 4868c2ecf20Sopenharmony_cistatic void usbnet_cdc_zte_status(struct usbnet *dev, struct urb *urb) 4878c2ecf20Sopenharmony_ci{ 4888c2ecf20Sopenharmony_ci struct usb_cdc_notification *event; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci if (urb->actual_length < sizeof(*event)) 4918c2ecf20Sopenharmony_ci return; 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci event = urb->transfer_buffer; 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci if (event->bNotificationType != USB_CDC_NOTIFY_NETWORK_CONNECTION) { 4968c2ecf20Sopenharmony_ci usbnet_cdc_status(dev, urb); 4978c2ecf20Sopenharmony_ci return; 4988c2ecf20Sopenharmony_ci } 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci netif_dbg(dev, timer, dev->net, "CDC: carrier %s\n", 5018c2ecf20Sopenharmony_ci event->wValue ? "on" : "off"); 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci if (event->wValue && 5048c2ecf20Sopenharmony_ci netif_carrier_ok(dev->net)) 5058c2ecf20Sopenharmony_ci netif_carrier_off(dev->net); 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci usbnet_link_change(dev, !!event->wValue, 0); 5088c2ecf20Sopenharmony_ci} 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_cistatic const struct driver_info cdc_info = { 5118c2ecf20Sopenharmony_ci .description = "CDC Ethernet Device", 5128c2ecf20Sopenharmony_ci .flags = FLAG_ETHER | FLAG_POINTTOPOINT, 5138c2ecf20Sopenharmony_ci .bind = usbnet_cdc_bind, 5148c2ecf20Sopenharmony_ci .unbind = usbnet_cdc_unbind, 5158c2ecf20Sopenharmony_ci .status = usbnet_cdc_status, 5168c2ecf20Sopenharmony_ci .set_rx_mode = usbnet_cdc_update_filter, 5178c2ecf20Sopenharmony_ci .manage_power = usbnet_manage_power, 5188c2ecf20Sopenharmony_ci}; 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_cistatic const struct driver_info zte_cdc_info = { 5218c2ecf20Sopenharmony_ci .description = "ZTE CDC Ethernet Device", 5228c2ecf20Sopenharmony_ci .flags = FLAG_ETHER | FLAG_POINTTOPOINT, 5238c2ecf20Sopenharmony_ci .bind = usbnet_cdc_zte_bind, 5248c2ecf20Sopenharmony_ci .unbind = usbnet_cdc_unbind, 5258c2ecf20Sopenharmony_ci .status = usbnet_cdc_zte_status, 5268c2ecf20Sopenharmony_ci .set_rx_mode = usbnet_cdc_update_filter, 5278c2ecf20Sopenharmony_ci .manage_power = usbnet_manage_power, 5288c2ecf20Sopenharmony_ci .rx_fixup = usbnet_cdc_zte_rx_fixup, 5298c2ecf20Sopenharmony_ci}; 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_cistatic const struct driver_info wwan_info = { 5328c2ecf20Sopenharmony_ci .description = "Mobile Broadband Network Device", 5338c2ecf20Sopenharmony_ci .flags = FLAG_WWAN, 5348c2ecf20Sopenharmony_ci .bind = usbnet_cdc_bind, 5358c2ecf20Sopenharmony_ci .unbind = usbnet_cdc_unbind, 5368c2ecf20Sopenharmony_ci .status = usbnet_cdc_status, 5378c2ecf20Sopenharmony_ci .set_rx_mode = usbnet_cdc_update_filter, 5388c2ecf20Sopenharmony_ci .manage_power = usbnet_manage_power, 5398c2ecf20Sopenharmony_ci}; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci/*-------------------------------------------------------------------------*/ 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci#define HUAWEI_VENDOR_ID 0x12D1 5448c2ecf20Sopenharmony_ci#define NOVATEL_VENDOR_ID 0x1410 5458c2ecf20Sopenharmony_ci#define ZTE_VENDOR_ID 0x19D2 5468c2ecf20Sopenharmony_ci#define DELL_VENDOR_ID 0x413C 5478c2ecf20Sopenharmony_ci#define REALTEK_VENDOR_ID 0x0bda 5488c2ecf20Sopenharmony_ci#define SAMSUNG_VENDOR_ID 0x04e8 5498c2ecf20Sopenharmony_ci#define LENOVO_VENDOR_ID 0x17ef 5508c2ecf20Sopenharmony_ci#define LINKSYS_VENDOR_ID 0x13b1 5518c2ecf20Sopenharmony_ci#define NVIDIA_VENDOR_ID 0x0955 5528c2ecf20Sopenharmony_ci#define HP_VENDOR_ID 0x03f0 5538c2ecf20Sopenharmony_ci#define MICROSOFT_VENDOR_ID 0x045e 5548c2ecf20Sopenharmony_ci#define UBLOX_VENDOR_ID 0x1546 5558c2ecf20Sopenharmony_ci#define TPLINK_VENDOR_ID 0x2357 5568c2ecf20Sopenharmony_ci#define AQUANTIA_VENDOR_ID 0x2eca 5578c2ecf20Sopenharmony_ci#define ASIX_VENDOR_ID 0x0b95 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_cistatic const struct usb_device_id products[] = { 5608c2ecf20Sopenharmony_ci/* BLACKLIST !! 5618c2ecf20Sopenharmony_ci * 5628c2ecf20Sopenharmony_ci * First blacklist any products that are egregiously nonconformant 5638c2ecf20Sopenharmony_ci * with the CDC Ethernet specs. Minor braindamage we cope with; when 5648c2ecf20Sopenharmony_ci * they're not even trying, needing a separate driver is only the first 5658c2ecf20Sopenharmony_ci * of the differences to show up. 5668c2ecf20Sopenharmony_ci */ 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci#define ZAURUS_MASTER_INTERFACE \ 5698c2ecf20Sopenharmony_ci .bInterfaceClass = USB_CLASS_COMM, \ 5708c2ecf20Sopenharmony_ci .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \ 5718c2ecf20Sopenharmony_ci .bInterfaceProtocol = USB_CDC_PROTO_NONE 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci#define ZAURUS_FAKE_INTERFACE \ 5748c2ecf20Sopenharmony_ci .bInterfaceClass = USB_CLASS_COMM, \ 5758c2ecf20Sopenharmony_ci .bInterfaceSubClass = USB_CDC_SUBCLASS_MDLM, \ 5768c2ecf20Sopenharmony_ci .bInterfaceProtocol = USB_CDC_PROTO_NONE 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci/* SA-1100 based Sharp Zaurus ("collie"), or compatible; 5798c2ecf20Sopenharmony_ci * wire-incompatible with true CDC Ethernet implementations. 5808c2ecf20Sopenharmony_ci * (And, it seems, needlessly so...) 5818c2ecf20Sopenharmony_ci */ 5828c2ecf20Sopenharmony_ci{ 5838c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 5848c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 5858c2ecf20Sopenharmony_ci .idVendor = 0x04DD, 5868c2ecf20Sopenharmony_ci .idProduct = 0x8004, 5878c2ecf20Sopenharmony_ci ZAURUS_MASTER_INTERFACE, 5888c2ecf20Sopenharmony_ci .driver_info = 0, 5898c2ecf20Sopenharmony_ci}, 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci/* PXA-25x based Sharp Zaurii. Note that it seems some of these 5928c2ecf20Sopenharmony_ci * (later models especially) may have shipped only with firmware 5938c2ecf20Sopenharmony_ci * advertising false "CDC MDLM" compatibility ... but we're not 5948c2ecf20Sopenharmony_ci * clear which models did that, so for now let's assume the worst. 5958c2ecf20Sopenharmony_ci */ 5968c2ecf20Sopenharmony_ci{ 5978c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 5988c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 5998c2ecf20Sopenharmony_ci .idVendor = 0x04DD, 6008c2ecf20Sopenharmony_ci .idProduct = 0x8005, /* A-300 */ 6018c2ecf20Sopenharmony_ci ZAURUS_MASTER_INTERFACE, 6028c2ecf20Sopenharmony_ci .driver_info = 0, 6038c2ecf20Sopenharmony_ci}, { 6048c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 6058c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 6068c2ecf20Sopenharmony_ci .idVendor = 0x04DD, 6078c2ecf20Sopenharmony_ci .idProduct = 0x8005, /* A-300 */ 6088c2ecf20Sopenharmony_ci ZAURUS_FAKE_INTERFACE, 6098c2ecf20Sopenharmony_ci .driver_info = 0, 6108c2ecf20Sopenharmony_ci}, { 6118c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 6128c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 6138c2ecf20Sopenharmony_ci .idVendor = 0x04DD, 6148c2ecf20Sopenharmony_ci .idProduct = 0x8006, /* B-500/SL-5600 */ 6158c2ecf20Sopenharmony_ci ZAURUS_MASTER_INTERFACE, 6168c2ecf20Sopenharmony_ci .driver_info = 0, 6178c2ecf20Sopenharmony_ci}, { 6188c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 6198c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 6208c2ecf20Sopenharmony_ci .idVendor = 0x04DD, 6218c2ecf20Sopenharmony_ci .idProduct = 0x8006, /* B-500/SL-5600 */ 6228c2ecf20Sopenharmony_ci ZAURUS_FAKE_INTERFACE, 6238c2ecf20Sopenharmony_ci .driver_info = 0, 6248c2ecf20Sopenharmony_ci}, { 6258c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 6268c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 6278c2ecf20Sopenharmony_ci .idVendor = 0x04DD, 6288c2ecf20Sopenharmony_ci .idProduct = 0x8007, /* C-700 */ 6298c2ecf20Sopenharmony_ci ZAURUS_MASTER_INTERFACE, 6308c2ecf20Sopenharmony_ci .driver_info = 0, 6318c2ecf20Sopenharmony_ci}, { 6328c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 6338c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 6348c2ecf20Sopenharmony_ci .idVendor = 0x04DD, 6358c2ecf20Sopenharmony_ci .idProduct = 0x8007, /* C-700 */ 6368c2ecf20Sopenharmony_ci ZAURUS_FAKE_INTERFACE, 6378c2ecf20Sopenharmony_ci .driver_info = 0, 6388c2ecf20Sopenharmony_ci}, { 6398c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 6408c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 6418c2ecf20Sopenharmony_ci .idVendor = 0x04DD, 6428c2ecf20Sopenharmony_ci .idProduct = 0x9031, /* C-750 C-760 */ 6438c2ecf20Sopenharmony_ci ZAURUS_MASTER_INTERFACE, 6448c2ecf20Sopenharmony_ci .driver_info = 0, 6458c2ecf20Sopenharmony_ci}, { 6468c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 6478c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 6488c2ecf20Sopenharmony_ci .idVendor = 0x04DD, 6498c2ecf20Sopenharmony_ci .idProduct = 0x9032, /* SL-6000 */ 6508c2ecf20Sopenharmony_ci ZAURUS_MASTER_INTERFACE, 6518c2ecf20Sopenharmony_ci .driver_info = 0, 6528c2ecf20Sopenharmony_ci}, { 6538c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 6548c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 6558c2ecf20Sopenharmony_ci .idVendor = 0x04DD, 6568c2ecf20Sopenharmony_ci .idProduct = 0x9032, /* SL-6000 */ 6578c2ecf20Sopenharmony_ci ZAURUS_FAKE_INTERFACE, 6588c2ecf20Sopenharmony_ci .driver_info = 0, 6598c2ecf20Sopenharmony_ci}, { 6608c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 6618c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 6628c2ecf20Sopenharmony_ci .idVendor = 0x04DD, 6638c2ecf20Sopenharmony_ci /* reported with some C860 units */ 6648c2ecf20Sopenharmony_ci .idProduct = 0x9050, /* C-860 */ 6658c2ecf20Sopenharmony_ci ZAURUS_MASTER_INTERFACE, 6668c2ecf20Sopenharmony_ci .driver_info = 0, 6678c2ecf20Sopenharmony_ci}, 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci/* Olympus has some models with a Zaurus-compatible option. 6708c2ecf20Sopenharmony_ci * R-1000 uses a FreeScale i.MXL cpu (ARMv4T) 6718c2ecf20Sopenharmony_ci */ 6728c2ecf20Sopenharmony_ci{ 6738c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 6748c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 6758c2ecf20Sopenharmony_ci .idVendor = 0x07B4, 6768c2ecf20Sopenharmony_ci .idProduct = 0x0F02, /* R-1000 */ 6778c2ecf20Sopenharmony_ci ZAURUS_MASTER_INTERFACE, 6788c2ecf20Sopenharmony_ci .driver_info = 0, 6798c2ecf20Sopenharmony_ci}, 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci/* LG Electronics VL600 wants additional headers on every frame */ 6828c2ecf20Sopenharmony_ci{ 6838c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(0x1004, 0x61aa, USB_CLASS_COMM, 6848c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 6858c2ecf20Sopenharmony_ci .driver_info = 0, 6868c2ecf20Sopenharmony_ci}, 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci/* Logitech Harmony 900 - uses the pseudo-MDLM (BLAN) driver */ 6898c2ecf20Sopenharmony_ci{ 6908c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(0x046d, 0xc11f, USB_CLASS_COMM, 6918c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), 6928c2ecf20Sopenharmony_ci .driver_info = 0, 6938c2ecf20Sopenharmony_ci}, 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci/* Novatel USB551L and MC551 - handled by qmi_wwan */ 6968c2ecf20Sopenharmony_ci{ 6978c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(NOVATEL_VENDOR_ID, 0xB001, USB_CLASS_COMM, 6988c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 6998c2ecf20Sopenharmony_ci .driver_info = 0, 7008c2ecf20Sopenharmony_ci}, 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci/* Novatel E362 - handled by qmi_wwan */ 7038c2ecf20Sopenharmony_ci{ 7048c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(NOVATEL_VENDOR_ID, 0x9010, USB_CLASS_COMM, 7058c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 7068c2ecf20Sopenharmony_ci .driver_info = 0, 7078c2ecf20Sopenharmony_ci}, 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci/* Dell Wireless 5800 (Novatel E362) - handled by qmi_wwan */ 7108c2ecf20Sopenharmony_ci{ 7118c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, 0x8195, USB_CLASS_COMM, 7128c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 7138c2ecf20Sopenharmony_ci .driver_info = 0, 7148c2ecf20Sopenharmony_ci}, 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci/* Dell Wireless 5800 (Novatel E362) - handled by qmi_wwan */ 7178c2ecf20Sopenharmony_ci{ 7188c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, 0x8196, USB_CLASS_COMM, 7198c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 7208c2ecf20Sopenharmony_ci .driver_info = 0, 7218c2ecf20Sopenharmony_ci}, 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci/* Dell Wireless 5804 (Novatel E371) - handled by qmi_wwan */ 7248c2ecf20Sopenharmony_ci{ 7258c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, 0x819b, USB_CLASS_COMM, 7268c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 7278c2ecf20Sopenharmony_ci .driver_info = 0, 7288c2ecf20Sopenharmony_ci}, 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci/* Novatel Expedite E371 - handled by qmi_wwan */ 7318c2ecf20Sopenharmony_ci{ 7328c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(NOVATEL_VENDOR_ID, 0x9011, USB_CLASS_COMM, 7338c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 7348c2ecf20Sopenharmony_ci .driver_info = 0, 7358c2ecf20Sopenharmony_ci}, 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci/* HP lt2523 (Novatel E371) - handled by qmi_wwan */ 7388c2ecf20Sopenharmony_ci{ 7398c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(HP_VENDOR_ID, 0x421d, USB_CLASS_COMM, 7408c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 7418c2ecf20Sopenharmony_ci .driver_info = 0, 7428c2ecf20Sopenharmony_ci}, 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci/* AnyDATA ADU960S - handled by qmi_wwan */ 7458c2ecf20Sopenharmony_ci{ 7468c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(0x16d5, 0x650a, USB_CLASS_COMM, 7478c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 7488c2ecf20Sopenharmony_ci .driver_info = 0, 7498c2ecf20Sopenharmony_ci}, 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci/* Huawei E1820 - handled by qmi_wwan */ 7528c2ecf20Sopenharmony_ci{ 7538c2ecf20Sopenharmony_ci USB_DEVICE_INTERFACE_NUMBER(HUAWEI_VENDOR_ID, 0x14ac, 1), 7548c2ecf20Sopenharmony_ci .driver_info = 0, 7558c2ecf20Sopenharmony_ci}, 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_ci/* Realtek RTL8152 Based USB 2.0 Ethernet Adapters */ 7588c2ecf20Sopenharmony_ci{ 7598c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8152, USB_CLASS_COMM, 7608c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 7618c2ecf20Sopenharmony_ci .driver_info = 0, 7628c2ecf20Sopenharmony_ci}, 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci/* Realtek RTL8153 Based USB 3.0 Ethernet Adapters */ 7658c2ecf20Sopenharmony_ci{ 7668c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8153, USB_CLASS_COMM, 7678c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 7688c2ecf20Sopenharmony_ci .driver_info = 0, 7698c2ecf20Sopenharmony_ci}, 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_ci/* Samsung USB Ethernet Adapters */ 7728c2ecf20Sopenharmony_ci{ 7738c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, 0xa101, USB_CLASS_COMM, 7748c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 7758c2ecf20Sopenharmony_ci .driver_info = 0, 7768c2ecf20Sopenharmony_ci}, 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_USB_RTL8152) 7798c2ecf20Sopenharmony_ci/* Linksys USB3GIGV1 Ethernet Adapter */ 7808c2ecf20Sopenharmony_ci{ 7818c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(LINKSYS_VENDOR_ID, 0x0041, USB_CLASS_COMM, 7828c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 7838c2ecf20Sopenharmony_ci .driver_info = 0, 7848c2ecf20Sopenharmony_ci}, 7858c2ecf20Sopenharmony_ci#endif 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci/* Lenovo ThinkPad OneLink+ Dock (based on Realtek RTL8153) */ 7888c2ecf20Sopenharmony_ci{ 7898c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3054, USB_CLASS_COMM, 7908c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 7918c2ecf20Sopenharmony_ci .driver_info = 0, 7928c2ecf20Sopenharmony_ci}, 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_ci/* ThinkPad USB-C Dock (based on Realtek RTL8153) */ 7958c2ecf20Sopenharmony_ci{ 7968c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3062, USB_CLASS_COMM, 7978c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 7988c2ecf20Sopenharmony_ci .driver_info = 0, 7998c2ecf20Sopenharmony_ci}, 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci/* ThinkPad Thunderbolt 3 Dock (based on Realtek RTL8153) */ 8028c2ecf20Sopenharmony_ci{ 8038c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3069, USB_CLASS_COMM, 8048c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 8058c2ecf20Sopenharmony_ci .driver_info = 0, 8068c2ecf20Sopenharmony_ci}, 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci/* ThinkPad Thunderbolt 3 Dock Gen 2 (based on Realtek RTL8153) */ 8098c2ecf20Sopenharmony_ci{ 8108c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3082, USB_CLASS_COMM, 8118c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 8128c2ecf20Sopenharmony_ci .driver_info = 0, 8138c2ecf20Sopenharmony_ci}, 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci/* Lenovo Thinkpad USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ 8168c2ecf20Sopenharmony_ci{ 8178c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x7205, USB_CLASS_COMM, 8188c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 8198c2ecf20Sopenharmony_ci .driver_info = 0, 8208c2ecf20Sopenharmony_ci}, 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_ci/* Lenovo USB C to Ethernet Adapter (based on Realtek RTL8153) */ 8238c2ecf20Sopenharmony_ci{ 8248c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x720c, USB_CLASS_COMM, 8258c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 8268c2ecf20Sopenharmony_ci .driver_info = 0, 8278c2ecf20Sopenharmony_ci}, 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci/* Lenovo USB-C Travel Hub (based on Realtek RTL8153) */ 8308c2ecf20Sopenharmony_ci{ 8318c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x7214, USB_CLASS_COMM, 8328c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 8338c2ecf20Sopenharmony_ci .driver_info = 0, 8348c2ecf20Sopenharmony_ci}, 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci/* Lenovo Powered USB-C Travel Hub (4X90S92381, based on Realtek RTL8153) */ 8378c2ecf20Sopenharmony_ci{ 8388c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x721e, USB_CLASS_COMM, 8398c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 8408c2ecf20Sopenharmony_ci .driver_info = 0, 8418c2ecf20Sopenharmony_ci}, 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci/* ThinkPad USB-C Dock Gen 2 (based on Realtek RTL8153) */ 8448c2ecf20Sopenharmony_ci{ 8458c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0xa387, USB_CLASS_COMM, 8468c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 8478c2ecf20Sopenharmony_ci .driver_info = 0, 8488c2ecf20Sopenharmony_ci}, 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci/* NVIDIA Tegra USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ 8518c2ecf20Sopenharmony_ci{ 8528c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(NVIDIA_VENDOR_ID, 0x09ff, USB_CLASS_COMM, 8538c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 8548c2ecf20Sopenharmony_ci .driver_info = 0, 8558c2ecf20Sopenharmony_ci}, 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci/* Microsoft Surface 2 dock (based on Realtek RTL8152) */ 8588c2ecf20Sopenharmony_ci{ 8598c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x07ab, USB_CLASS_COMM, 8608c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 8618c2ecf20Sopenharmony_ci .driver_info = 0, 8628c2ecf20Sopenharmony_ci}, 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci/* Microsoft Surface Ethernet Adapter (based on Realtek RTL8153) */ 8658c2ecf20Sopenharmony_ci{ 8668c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x07c6, USB_CLASS_COMM, 8678c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 8688c2ecf20Sopenharmony_ci .driver_info = 0, 8698c2ecf20Sopenharmony_ci}, 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci/* Microsoft Surface Ethernet Adapter (based on Realtek RTL8153B) */ 8728c2ecf20Sopenharmony_ci{ 8738c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x0927, USB_CLASS_COMM, 8748c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 8758c2ecf20Sopenharmony_ci .driver_info = 0, 8768c2ecf20Sopenharmony_ci}, 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci/* TP-LINK UE300 USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ 8798c2ecf20Sopenharmony_ci{ 8808c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(TPLINK_VENDOR_ID, 0x0601, USB_CLASS_COMM, 8818c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 8828c2ecf20Sopenharmony_ci .driver_info = 0, 8838c2ecf20Sopenharmony_ci}, 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci/* Aquantia AQtion USB to 5GbE Controller (based on AQC111U) */ 8868c2ecf20Sopenharmony_ci{ 8878c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(AQUANTIA_VENDOR_ID, 0xc101, 8888c2ecf20Sopenharmony_ci USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET, 8898c2ecf20Sopenharmony_ci USB_CDC_PROTO_NONE), 8908c2ecf20Sopenharmony_ci .driver_info = 0, 8918c2ecf20Sopenharmony_ci}, 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci/* ASIX USB 3.1 Gen1 to 5G Multi-Gigabit Ethernet Adapter(based on AQC111U) */ 8948c2ecf20Sopenharmony_ci{ 8958c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(ASIX_VENDOR_ID, 0x2790, USB_CLASS_COMM, 8968c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, 8978c2ecf20Sopenharmony_ci USB_CDC_PROTO_NONE), 8988c2ecf20Sopenharmony_ci .driver_info = 0, 8998c2ecf20Sopenharmony_ci}, 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci/* ASIX USB 3.1 Gen1 to 2.5G Multi-Gigabit Ethernet Adapter(based on AQC112U) */ 9028c2ecf20Sopenharmony_ci{ 9038c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(ASIX_VENDOR_ID, 0x2791, USB_CLASS_COMM, 9048c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, 9058c2ecf20Sopenharmony_ci USB_CDC_PROTO_NONE), 9068c2ecf20Sopenharmony_ci .driver_info = 0, 9078c2ecf20Sopenharmony_ci}, 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci/* USB-C 3.1 to 5GBASE-T Ethernet Adapter (based on AQC111U) */ 9108c2ecf20Sopenharmony_ci{ 9118c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0xe05a, USB_CLASS_COMM, 9128c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, 9138c2ecf20Sopenharmony_ci USB_CDC_PROTO_NONE), 9148c2ecf20Sopenharmony_ci .driver_info = 0, 9158c2ecf20Sopenharmony_ci}, 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci/* QNAP QNA-UC5G1T USB to 5GbE Adapter (based on AQC111U) */ 9188c2ecf20Sopenharmony_ci{ 9198c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(0x1c04, 0x0015, USB_CLASS_COMM, 9208c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, 9218c2ecf20Sopenharmony_ci USB_CDC_PROTO_NONE), 9228c2ecf20Sopenharmony_ci .driver_info = 0, 9238c2ecf20Sopenharmony_ci}, 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_ci/* WHITELIST!!! 9268c2ecf20Sopenharmony_ci * 9278c2ecf20Sopenharmony_ci * CDC Ether uses two interfaces, not necessarily consecutive. 9288c2ecf20Sopenharmony_ci * We match the main interface, ignoring the optional device 9298c2ecf20Sopenharmony_ci * class so we could handle devices that aren't exclusively 9308c2ecf20Sopenharmony_ci * CDC ether. 9318c2ecf20Sopenharmony_ci * 9328c2ecf20Sopenharmony_ci * NOTE: this match must come AFTER entries blacklisting devices 9338c2ecf20Sopenharmony_ci * because of bugs/quirks in a given product (like Zaurus, above). 9348c2ecf20Sopenharmony_ci */ 9358c2ecf20Sopenharmony_ci{ 9368c2ecf20Sopenharmony_ci /* ZTE (Vodafone) K3805-Z */ 9378c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1003, USB_CLASS_COMM, 9388c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, 9398c2ecf20Sopenharmony_ci USB_CDC_PROTO_NONE), 9408c2ecf20Sopenharmony_ci .driver_info = (unsigned long)&wwan_info, 9418c2ecf20Sopenharmony_ci}, { 9428c2ecf20Sopenharmony_ci /* ZTE (Vodafone) K3806-Z */ 9438c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1015, USB_CLASS_COMM, 9448c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, 9458c2ecf20Sopenharmony_ci USB_CDC_PROTO_NONE), 9468c2ecf20Sopenharmony_ci .driver_info = (unsigned long)&wwan_info, 9478c2ecf20Sopenharmony_ci}, { 9488c2ecf20Sopenharmony_ci /* ZTE (Vodafone) K4510-Z */ 9498c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1173, USB_CLASS_COMM, 9508c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, 9518c2ecf20Sopenharmony_ci USB_CDC_PROTO_NONE), 9528c2ecf20Sopenharmony_ci .driver_info = (unsigned long)&wwan_info, 9538c2ecf20Sopenharmony_ci}, { 9548c2ecf20Sopenharmony_ci /* ZTE (Vodafone) K3770-Z */ 9558c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1177, USB_CLASS_COMM, 9568c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, 9578c2ecf20Sopenharmony_ci USB_CDC_PROTO_NONE), 9588c2ecf20Sopenharmony_ci .driver_info = (unsigned long)&wwan_info, 9598c2ecf20Sopenharmony_ci}, { 9608c2ecf20Sopenharmony_ci /* ZTE (Vodafone) K3772-Z */ 9618c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1181, USB_CLASS_COMM, 9628c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, 9638c2ecf20Sopenharmony_ci USB_CDC_PROTO_NONE), 9648c2ecf20Sopenharmony_ci .driver_info = (unsigned long)&wwan_info, 9658c2ecf20Sopenharmony_ci}, { 9668c2ecf20Sopenharmony_ci /* Telit modules */ 9678c2ecf20Sopenharmony_ci USB_VENDOR_AND_INTERFACE_INFO(0x1bc7, USB_CLASS_COMM, 9688c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 9698c2ecf20Sopenharmony_ci .driver_info = (kernel_ulong_t) &wwan_info, 9708c2ecf20Sopenharmony_ci}, { 9718c2ecf20Sopenharmony_ci /* Dell DW5580 modules */ 9728c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, 0x81ba, USB_CLASS_COMM, 9738c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), 9748c2ecf20Sopenharmony_ci .driver_info = (kernel_ulong_t)&wwan_info, 9758c2ecf20Sopenharmony_ci}, { 9768c2ecf20Sopenharmony_ci /* Huawei ME906 and ME909 */ 9778c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x15c1, USB_CLASS_COMM, 9788c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, 9798c2ecf20Sopenharmony_ci USB_CDC_PROTO_NONE), 9808c2ecf20Sopenharmony_ci .driver_info = (unsigned long)&wwan_info, 9818c2ecf20Sopenharmony_ci}, { 9828c2ecf20Sopenharmony_ci /* ZTE modules */ 9838c2ecf20Sopenharmony_ci USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, USB_CLASS_COMM, 9848c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, 9858c2ecf20Sopenharmony_ci USB_CDC_PROTO_NONE), 9868c2ecf20Sopenharmony_ci .driver_info = (unsigned long)&zte_cdc_info, 9878c2ecf20Sopenharmony_ci}, { 9888c2ecf20Sopenharmony_ci /* U-blox TOBY-L2 */ 9898c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(UBLOX_VENDOR_ID, 0x1143, USB_CLASS_COMM, 9908c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, 9918c2ecf20Sopenharmony_ci USB_CDC_PROTO_NONE), 9928c2ecf20Sopenharmony_ci .driver_info = (unsigned long)&wwan_info, 9938c2ecf20Sopenharmony_ci}, { 9948c2ecf20Sopenharmony_ci /* U-blox SARA-U2 */ 9958c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(UBLOX_VENDOR_ID, 0x1104, USB_CLASS_COMM, 9968c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, 9978c2ecf20Sopenharmony_ci USB_CDC_PROTO_NONE), 9988c2ecf20Sopenharmony_ci .driver_info = (unsigned long)&wwan_info, 9998c2ecf20Sopenharmony_ci}, { 10008c2ecf20Sopenharmony_ci /* Cinterion PLS8 modem by GEMALTO */ 10018c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(0x1e2d, 0x0061, USB_CLASS_COMM, 10028c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, 10038c2ecf20Sopenharmony_ci USB_CDC_PROTO_NONE), 10048c2ecf20Sopenharmony_ci .driver_info = (unsigned long)&wwan_info, 10058c2ecf20Sopenharmony_ci}, { 10068c2ecf20Sopenharmony_ci /* Cinterion AHS3 modem by GEMALTO */ 10078c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(0x1e2d, 0x0055, USB_CLASS_COMM, 10088c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, 10098c2ecf20Sopenharmony_ci USB_CDC_PROTO_NONE), 10108c2ecf20Sopenharmony_ci .driver_info = (unsigned long)&wwan_info, 10118c2ecf20Sopenharmony_ci}, { 10128c2ecf20Sopenharmony_ci USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET, 10138c2ecf20Sopenharmony_ci USB_CDC_PROTO_NONE), 10148c2ecf20Sopenharmony_ci .driver_info = (unsigned long) &cdc_info, 10158c2ecf20Sopenharmony_ci}, { 10168c2ecf20Sopenharmony_ci USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM, 10178c2ecf20Sopenharmony_ci USB_CDC_PROTO_NONE), 10188c2ecf20Sopenharmony_ci .driver_info = (unsigned long)&wwan_info, 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ci}, { 10218c2ecf20Sopenharmony_ci /* Various Huawei modems with a network port like the UMG1831 */ 10228c2ecf20Sopenharmony_ci USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_COMM, 10238c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_ETHERNET, 255), 10248c2ecf20Sopenharmony_ci .driver_info = (unsigned long)&wwan_info, 10258c2ecf20Sopenharmony_ci}, 10268c2ecf20Sopenharmony_ci { }, /* END */ 10278c2ecf20Sopenharmony_ci}; 10288c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(usb, products); 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_cistatic struct usb_driver cdc_driver = { 10318c2ecf20Sopenharmony_ci .name = "cdc_ether", 10328c2ecf20Sopenharmony_ci .id_table = products, 10338c2ecf20Sopenharmony_ci .probe = usbnet_probe, 10348c2ecf20Sopenharmony_ci .disconnect = usbnet_disconnect, 10358c2ecf20Sopenharmony_ci .suspend = usbnet_suspend, 10368c2ecf20Sopenharmony_ci .resume = usbnet_resume, 10378c2ecf20Sopenharmony_ci .reset_resume = usbnet_resume, 10388c2ecf20Sopenharmony_ci .supports_autosuspend = 1, 10398c2ecf20Sopenharmony_ci .disable_hub_initiated_lpm = 1, 10408c2ecf20Sopenharmony_ci}; 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_cimodule_usb_driver(cdc_driver); 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_ciMODULE_AUTHOR("David Brownell"); 10458c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("USB CDC Ethernet devices"); 10468c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1047