18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2002 Pavel Machek <pavel@ucw.cz> 48c2ecf20Sopenharmony_ci * Copyright (C) 2002-2005 by David Brownell 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci// #define DEBUG // error path messages, extra info 88c2ecf20Sopenharmony_ci// #define VERBOSE // more; success messages 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/module.h> 118c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 128c2ecf20Sopenharmony_ci#include <linux/ethtool.h> 138c2ecf20Sopenharmony_ci#include <linux/workqueue.h> 148c2ecf20Sopenharmony_ci#include <linux/mii.h> 158c2ecf20Sopenharmony_ci#include <linux/crc32.h> 168c2ecf20Sopenharmony_ci#include <linux/usb.h> 178c2ecf20Sopenharmony_ci#include <linux/usb/cdc.h> 188c2ecf20Sopenharmony_ci#include <linux/usb/usbnet.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci/* 228c2ecf20Sopenharmony_ci * All known Zaurii lie about their standards conformance. At least 238c2ecf20Sopenharmony_ci * the earliest SA-1100 models lie by saying they support CDC Ethernet. 248c2ecf20Sopenharmony_ci * Some later models (especially PXA-25x and PXA-27x based ones) lie 258c2ecf20Sopenharmony_ci * and say they support CDC MDLM (for access to cell phone modems). 268c2ecf20Sopenharmony_ci * 278c2ecf20Sopenharmony_ci * There are non-Zaurus products that use these same protocols too. 288c2ecf20Sopenharmony_ci * 298c2ecf20Sopenharmony_ci * The annoying thing is that at the same time Sharp was developing 308c2ecf20Sopenharmony_ci * that annoying standards-breaking software, the Linux community had 318c2ecf20Sopenharmony_ci * a simple "CDC Subset" working reliably on the same SA-1100 hardware. 328c2ecf20Sopenharmony_ci * That is, the same functionality but not violating standards. 338c2ecf20Sopenharmony_ci * 348c2ecf20Sopenharmony_ci * The CDC Ethernet nonconformance points are troublesome to hosts 358c2ecf20Sopenharmony_ci * with a true CDC Ethernet implementation: 368c2ecf20Sopenharmony_ci * - Framing appends a CRC, which the spec says drivers "must not" do; 378c2ecf20Sopenharmony_ci * - Transfers data in altsetting zero, instead of altsetting 1; 388c2ecf20Sopenharmony_ci * - All these peripherals use the same ethernet address. 398c2ecf20Sopenharmony_ci * 408c2ecf20Sopenharmony_ci * The CDC MDLM nonconformance is less immediately troublesome, since all 418c2ecf20Sopenharmony_ci * MDLM implementations are quasi-proprietary anyway. 428c2ecf20Sopenharmony_ci */ 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cistatic struct sk_buff * 458c2ecf20Sopenharmony_cizaurus_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) 468c2ecf20Sopenharmony_ci{ 478c2ecf20Sopenharmony_ci int padlen; 488c2ecf20Sopenharmony_ci struct sk_buff *skb2; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci padlen = 2; 518c2ecf20Sopenharmony_ci if (!skb_cloned(skb)) { 528c2ecf20Sopenharmony_ci int tailroom = skb_tailroom(skb); 538c2ecf20Sopenharmony_ci if ((padlen + 4) <= tailroom) 548c2ecf20Sopenharmony_ci goto done; 558c2ecf20Sopenharmony_ci } 568c2ecf20Sopenharmony_ci skb2 = skb_copy_expand(skb, 0, 4 + padlen, flags); 578c2ecf20Sopenharmony_ci dev_kfree_skb_any(skb); 588c2ecf20Sopenharmony_ci skb = skb2; 598c2ecf20Sopenharmony_ci if (skb) { 608c2ecf20Sopenharmony_ci u32 fcs; 618c2ecf20Sopenharmony_cidone: 628c2ecf20Sopenharmony_ci fcs = crc32_le(~0, skb->data, skb->len); 638c2ecf20Sopenharmony_ci fcs = ~fcs; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci skb_put_u8(skb, fcs & 0xff); 668c2ecf20Sopenharmony_ci skb_put_u8(skb, (fcs >> 8) & 0xff); 678c2ecf20Sopenharmony_ci skb_put_u8(skb, (fcs >> 16) & 0xff); 688c2ecf20Sopenharmony_ci skb_put_u8(skb, (fcs >> 24) & 0xff); 698c2ecf20Sopenharmony_ci } 708c2ecf20Sopenharmony_ci return skb; 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistatic int zaurus_bind(struct usbnet *dev, struct usb_interface *intf) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci /* Belcarra's funky framing has other options; mostly 768c2ecf20Sopenharmony_ci * TRAILERS (!) with 4 bytes CRC, and maybe 2 pad bytes. 778c2ecf20Sopenharmony_ci */ 788c2ecf20Sopenharmony_ci dev->net->hard_header_len += 6; 798c2ecf20Sopenharmony_ci dev->rx_urb_size = dev->net->hard_header_len + dev->net->mtu; 808c2ecf20Sopenharmony_ci return usbnet_generic_cdc_bind(dev, intf); 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci/* PDA style devices are always connected if present */ 848c2ecf20Sopenharmony_cistatic int always_connected (struct usbnet *dev) 858c2ecf20Sopenharmony_ci{ 868c2ecf20Sopenharmony_ci return 0; 878c2ecf20Sopenharmony_ci} 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cistatic const struct driver_info zaurus_sl5x00_info = { 908c2ecf20Sopenharmony_ci .description = "Sharp Zaurus SL-5x00", 918c2ecf20Sopenharmony_ci .flags = FLAG_POINTTOPOINT | FLAG_FRAMING_Z, 928c2ecf20Sopenharmony_ci .check_connect = always_connected, 938c2ecf20Sopenharmony_ci .bind = zaurus_bind, 948c2ecf20Sopenharmony_ci .unbind = usbnet_cdc_unbind, 958c2ecf20Sopenharmony_ci .tx_fixup = zaurus_tx_fixup, 968c2ecf20Sopenharmony_ci}; 978c2ecf20Sopenharmony_ci#define ZAURUS_STRONGARM_INFO ((unsigned long)&zaurus_sl5x00_info) 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistatic const struct driver_info zaurus_pxa_info = { 1008c2ecf20Sopenharmony_ci .description = "Sharp Zaurus, PXA-2xx based", 1018c2ecf20Sopenharmony_ci .flags = FLAG_POINTTOPOINT | FLAG_FRAMING_Z, 1028c2ecf20Sopenharmony_ci .check_connect = always_connected, 1038c2ecf20Sopenharmony_ci .bind = zaurus_bind, 1048c2ecf20Sopenharmony_ci .unbind = usbnet_cdc_unbind, 1058c2ecf20Sopenharmony_ci .tx_fixup = zaurus_tx_fixup, 1068c2ecf20Sopenharmony_ci}; 1078c2ecf20Sopenharmony_ci#define ZAURUS_PXA_INFO ((unsigned long)&zaurus_pxa_info) 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_cistatic const struct driver_info olympus_mxl_info = { 1108c2ecf20Sopenharmony_ci .description = "Olympus R1000", 1118c2ecf20Sopenharmony_ci .flags = FLAG_POINTTOPOINT | FLAG_FRAMING_Z, 1128c2ecf20Sopenharmony_ci .check_connect = always_connected, 1138c2ecf20Sopenharmony_ci .bind = zaurus_bind, 1148c2ecf20Sopenharmony_ci .unbind = usbnet_cdc_unbind, 1158c2ecf20Sopenharmony_ci .tx_fixup = zaurus_tx_fixup, 1168c2ecf20Sopenharmony_ci}; 1178c2ecf20Sopenharmony_ci#define OLYMPUS_MXL_INFO ((unsigned long)&olympus_mxl_info) 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci/* Some more recent products using Lineo/Belcarra code will wrongly claim 1218c2ecf20Sopenharmony_ci * CDC MDLM conformance. They aren't conformant: data endpoints live 1228c2ecf20Sopenharmony_ci * in the control interface, there's no data interface, and it's not used 1238c2ecf20Sopenharmony_ci * to talk to a cell phone radio. But at least we can detect these two 1248c2ecf20Sopenharmony_ci * pseudo-classes, rather than growing this product list with entries for 1258c2ecf20Sopenharmony_ci * each new nonconformant product (sigh). 1268c2ecf20Sopenharmony_ci */ 1278c2ecf20Sopenharmony_cistatic const u8 safe_guid[16] = { 1288c2ecf20Sopenharmony_ci 0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6, 1298c2ecf20Sopenharmony_ci 0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f, 1308c2ecf20Sopenharmony_ci}; 1318c2ecf20Sopenharmony_cistatic const u8 blan_guid[16] = { 1328c2ecf20Sopenharmony_ci 0x74, 0xf0, 0x3d, 0xbd, 0x1e, 0xc1, 0x44, 0x70, 1338c2ecf20Sopenharmony_ci 0xa3, 0x67, 0x71, 0x34, 0xc9, 0xf5, 0x54, 0x37, 1348c2ecf20Sopenharmony_ci}; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistatic int blan_mdlm_bind(struct usbnet *dev, struct usb_interface *intf) 1378c2ecf20Sopenharmony_ci{ 1388c2ecf20Sopenharmony_ci u8 *buf = intf->cur_altsetting->extra; 1398c2ecf20Sopenharmony_ci int len = intf->cur_altsetting->extralen; 1408c2ecf20Sopenharmony_ci struct usb_cdc_mdlm_desc *desc = NULL; 1418c2ecf20Sopenharmony_ci struct usb_cdc_mdlm_detail_desc *detail = NULL; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci while (len > 3) { 1448c2ecf20Sopenharmony_ci if (buf [1] != USB_DT_CS_INTERFACE) 1458c2ecf20Sopenharmony_ci goto next_desc; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci /* use bDescriptorSubType, and just verify that we get a 1488c2ecf20Sopenharmony_ci * "BLAN" (or "SAFE") descriptor. 1498c2ecf20Sopenharmony_ci */ 1508c2ecf20Sopenharmony_ci switch (buf [2]) { 1518c2ecf20Sopenharmony_ci case USB_CDC_MDLM_TYPE: 1528c2ecf20Sopenharmony_ci if (desc) { 1538c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "extra MDLM\n"); 1548c2ecf20Sopenharmony_ci goto bad_desc; 1558c2ecf20Sopenharmony_ci } 1568c2ecf20Sopenharmony_ci desc = (void *) buf; 1578c2ecf20Sopenharmony_ci if (desc->bLength != sizeof *desc) { 1588c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "MDLM len %u\n", 1598c2ecf20Sopenharmony_ci desc->bLength); 1608c2ecf20Sopenharmony_ci goto bad_desc; 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci /* expect bcdVersion 1.0, ignore */ 1638c2ecf20Sopenharmony_ci if (memcmp(&desc->bGUID, blan_guid, 16) && 1648c2ecf20Sopenharmony_ci memcmp(&desc->bGUID, safe_guid, 16)) { 1658c2ecf20Sopenharmony_ci /* hey, this one might _really_ be MDLM! */ 1668c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "MDLM guid\n"); 1678c2ecf20Sopenharmony_ci goto bad_desc; 1688c2ecf20Sopenharmony_ci } 1698c2ecf20Sopenharmony_ci break; 1708c2ecf20Sopenharmony_ci case USB_CDC_MDLM_DETAIL_TYPE: 1718c2ecf20Sopenharmony_ci if (detail) { 1728c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "extra MDLM detail\n"); 1738c2ecf20Sopenharmony_ci goto bad_desc; 1748c2ecf20Sopenharmony_ci } 1758c2ecf20Sopenharmony_ci detail = (void *) buf; 1768c2ecf20Sopenharmony_ci switch (detail->bGuidDescriptorType) { 1778c2ecf20Sopenharmony_ci case 0: /* "SAFE" */ 1788c2ecf20Sopenharmony_ci if (detail->bLength != (sizeof *detail + 2)) 1798c2ecf20Sopenharmony_ci goto bad_detail; 1808c2ecf20Sopenharmony_ci break; 1818c2ecf20Sopenharmony_ci case 1: /* "BLAN" */ 1828c2ecf20Sopenharmony_ci if (detail->bLength != (sizeof *detail + 3)) 1838c2ecf20Sopenharmony_ci goto bad_detail; 1848c2ecf20Sopenharmony_ci break; 1858c2ecf20Sopenharmony_ci default: 1868c2ecf20Sopenharmony_ci goto bad_detail; 1878c2ecf20Sopenharmony_ci } 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci /* assuming we either noticed BLAN already, or will 1908c2ecf20Sopenharmony_ci * find it soon, there are some data bytes here: 1918c2ecf20Sopenharmony_ci * - bmNetworkCapabilities (unused) 1928c2ecf20Sopenharmony_ci * - bmDataCapabilities (bits, see below) 1938c2ecf20Sopenharmony_ci * - bPad (ignored, for PADAFTER -- BLAN-only) 1948c2ecf20Sopenharmony_ci * bits are: 1958c2ecf20Sopenharmony_ci * - 0x01 -- Zaurus framing (add CRC) 1968c2ecf20Sopenharmony_ci * - 0x02 -- PADBEFORE (CRC includes some padding) 1978c2ecf20Sopenharmony_ci * - 0x04 -- PADAFTER (some padding after CRC) 1988c2ecf20Sopenharmony_ci * - 0x08 -- "fermat" packet mangling (for hw bugs) 1998c2ecf20Sopenharmony_ci * the PADBEFORE appears not to matter; we interop 2008c2ecf20Sopenharmony_ci * with devices that use it and those that don't. 2018c2ecf20Sopenharmony_ci */ 2028c2ecf20Sopenharmony_ci if ((detail->bDetailData[1] & ~0x02) != 0x01) { 2038c2ecf20Sopenharmony_ci /* bmDataCapabilities == 0 would be fine too, 2048c2ecf20Sopenharmony_ci * but framing is minidriver-coupled for now. 2058c2ecf20Sopenharmony_ci */ 2068c2ecf20Sopenharmony_cibad_detail: 2078c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, 2088c2ecf20Sopenharmony_ci "bad MDLM detail, %d %d %d\n", 2098c2ecf20Sopenharmony_ci detail->bLength, 2108c2ecf20Sopenharmony_ci detail->bDetailData[0], 2118c2ecf20Sopenharmony_ci detail->bDetailData[2]); 2128c2ecf20Sopenharmony_ci goto bad_desc; 2138c2ecf20Sopenharmony_ci } 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci /* same extra framing as for non-BLAN mode */ 2168c2ecf20Sopenharmony_ci dev->net->hard_header_len += 6; 2178c2ecf20Sopenharmony_ci dev->rx_urb_size = dev->net->hard_header_len 2188c2ecf20Sopenharmony_ci + dev->net->mtu; 2198c2ecf20Sopenharmony_ci break; 2208c2ecf20Sopenharmony_ci } 2218c2ecf20Sopenharmony_cinext_desc: 2228c2ecf20Sopenharmony_ci len -= buf [0]; /* bLength */ 2238c2ecf20Sopenharmony_ci buf += buf [0]; 2248c2ecf20Sopenharmony_ci } 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci if (!desc || !detail) { 2278c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "missing cdc mdlm %s%sdescriptor\n", 2288c2ecf20Sopenharmony_ci desc ? "" : "func ", 2298c2ecf20Sopenharmony_ci detail ? "" : "detail "); 2308c2ecf20Sopenharmony_ci goto bad_desc; 2318c2ecf20Sopenharmony_ci } 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci /* There's probably a CDC Ethernet descriptor there, but we can't 2348c2ecf20Sopenharmony_ci * rely on the Ethernet address it provides since not all vendors 2358c2ecf20Sopenharmony_ci * bother to make it unique. Likewise there's no point in tracking 2368c2ecf20Sopenharmony_ci * of the CDC event notifications. 2378c2ecf20Sopenharmony_ci */ 2388c2ecf20Sopenharmony_ci return usbnet_get_endpoints(dev, intf); 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_cibad_desc: 2418c2ecf20Sopenharmony_ci dev_info(&dev->udev->dev, "unsupported MDLM descriptors\n"); 2428c2ecf20Sopenharmony_ci return -ENODEV; 2438c2ecf20Sopenharmony_ci} 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_cistatic const struct driver_info bogus_mdlm_info = { 2468c2ecf20Sopenharmony_ci .description = "pseudo-MDLM (BLAN) device", 2478c2ecf20Sopenharmony_ci .flags = FLAG_POINTTOPOINT | FLAG_FRAMING_Z, 2488c2ecf20Sopenharmony_ci .check_connect = always_connected, 2498c2ecf20Sopenharmony_ci .tx_fixup = zaurus_tx_fixup, 2508c2ecf20Sopenharmony_ci .bind = blan_mdlm_bind, 2518c2ecf20Sopenharmony_ci}; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_cistatic const struct usb_device_id products [] = { 2548c2ecf20Sopenharmony_ci#define ZAURUS_MASTER_INTERFACE \ 2558c2ecf20Sopenharmony_ci .bInterfaceClass = USB_CLASS_COMM, \ 2568c2ecf20Sopenharmony_ci .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \ 2578c2ecf20Sopenharmony_ci .bInterfaceProtocol = USB_CDC_PROTO_NONE 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci#define ZAURUS_FAKE_INTERFACE \ 2608c2ecf20Sopenharmony_ci .bInterfaceClass = USB_CLASS_COMM, \ 2618c2ecf20Sopenharmony_ci .bInterfaceSubClass = USB_CDC_SUBCLASS_MDLM, \ 2628c2ecf20Sopenharmony_ci .bInterfaceProtocol = USB_CDC_PROTO_NONE 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci/* SA-1100 based Sharp Zaurus ("collie"), or compatible. */ 2658c2ecf20Sopenharmony_ci{ 2668c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 2678c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 2688c2ecf20Sopenharmony_ci .idVendor = 0x04DD, 2698c2ecf20Sopenharmony_ci .idProduct = 0x8004, 2708c2ecf20Sopenharmony_ci ZAURUS_MASTER_INTERFACE, 2718c2ecf20Sopenharmony_ci .driver_info = ZAURUS_STRONGARM_INFO, 2728c2ecf20Sopenharmony_ci}, 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci/* PXA-2xx based models are also lying-about-cdc. If you add any 2758c2ecf20Sopenharmony_ci * more devices that claim to be CDC Ethernet, make sure they get 2768c2ecf20Sopenharmony_ci * added to the blacklist in cdc_ether too. 2778c2ecf20Sopenharmony_ci * 2788c2ecf20Sopenharmony_ci * NOTE: OpenZaurus versions with 2.6 kernels won't use these entries, 2798c2ecf20Sopenharmony_ci * unlike the older ones with 2.4 "embedix" kernels. 2808c2ecf20Sopenharmony_ci */ 2818c2ecf20Sopenharmony_ci{ 2828c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 2838c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 2848c2ecf20Sopenharmony_ci .idVendor = 0x04DD, 2858c2ecf20Sopenharmony_ci .idProduct = 0x8005, /* A-300 */ 2868c2ecf20Sopenharmony_ci ZAURUS_MASTER_INTERFACE, 2878c2ecf20Sopenharmony_ci .driver_info = ZAURUS_PXA_INFO, 2888c2ecf20Sopenharmony_ci}, { 2898c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 2908c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 2918c2ecf20Sopenharmony_ci .idVendor = 0x04DD, 2928c2ecf20Sopenharmony_ci .idProduct = 0x8005, /* A-300 */ 2938c2ecf20Sopenharmony_ci ZAURUS_FAKE_INTERFACE, 2948c2ecf20Sopenharmony_ci .driver_info = (unsigned long)&bogus_mdlm_info, 2958c2ecf20Sopenharmony_ci}, { 2968c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 2978c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 2988c2ecf20Sopenharmony_ci .idVendor = 0x04DD, 2998c2ecf20Sopenharmony_ci .idProduct = 0x8006, /* B-500/SL-5600 */ 3008c2ecf20Sopenharmony_ci ZAURUS_MASTER_INTERFACE, 3018c2ecf20Sopenharmony_ci .driver_info = ZAURUS_PXA_INFO, 3028c2ecf20Sopenharmony_ci}, { 3038c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 3048c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 3058c2ecf20Sopenharmony_ci .idVendor = 0x04DD, 3068c2ecf20Sopenharmony_ci .idProduct = 0x8006, /* B-500/SL-5600 */ 3078c2ecf20Sopenharmony_ci ZAURUS_FAKE_INTERFACE, 3088c2ecf20Sopenharmony_ci .driver_info = (unsigned long)&bogus_mdlm_info, 3098c2ecf20Sopenharmony_ci}, { 3108c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 3118c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 3128c2ecf20Sopenharmony_ci .idVendor = 0x04DD, 3138c2ecf20Sopenharmony_ci .idProduct = 0x8007, /* C-700 */ 3148c2ecf20Sopenharmony_ci ZAURUS_MASTER_INTERFACE, 3158c2ecf20Sopenharmony_ci .driver_info = ZAURUS_PXA_INFO, 3168c2ecf20Sopenharmony_ci}, { 3178c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 3188c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 3198c2ecf20Sopenharmony_ci .idVendor = 0x04DD, 3208c2ecf20Sopenharmony_ci .idProduct = 0x8007, /* C-700 */ 3218c2ecf20Sopenharmony_ci ZAURUS_FAKE_INTERFACE, 3228c2ecf20Sopenharmony_ci .driver_info = (unsigned long)&bogus_mdlm_info, 3238c2ecf20Sopenharmony_ci}, { 3248c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 3258c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 3268c2ecf20Sopenharmony_ci .idVendor = 0x04DD, 3278c2ecf20Sopenharmony_ci .idProduct = 0x9031, /* C-750 C-760 */ 3288c2ecf20Sopenharmony_ci ZAURUS_MASTER_INTERFACE, 3298c2ecf20Sopenharmony_ci .driver_info = ZAURUS_PXA_INFO, 3308c2ecf20Sopenharmony_ci}, { 3318c2ecf20Sopenharmony_ci /* C-750/C-760/C-860/SL-C3000 PDA in MDLM mode */ 3328c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(0x04DD, 0x9031, USB_CLASS_COMM, 3338c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), 3348c2ecf20Sopenharmony_ci .driver_info = (unsigned long) &bogus_mdlm_info, 3358c2ecf20Sopenharmony_ci}, { 3368c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 3378c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 3388c2ecf20Sopenharmony_ci .idVendor = 0x04DD, 3398c2ecf20Sopenharmony_ci .idProduct = 0x9032, /* SL-6000 */ 3408c2ecf20Sopenharmony_ci ZAURUS_MASTER_INTERFACE, 3418c2ecf20Sopenharmony_ci .driver_info = ZAURUS_PXA_INFO, 3428c2ecf20Sopenharmony_ci}, { 3438c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 3448c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 3458c2ecf20Sopenharmony_ci .idVendor = 0x04DD, 3468c2ecf20Sopenharmony_ci .idProduct = 0x9032, /* SL-6000 */ 3478c2ecf20Sopenharmony_ci ZAURUS_FAKE_INTERFACE, 3488c2ecf20Sopenharmony_ci .driver_info = (unsigned long)&bogus_mdlm_info, 3498c2ecf20Sopenharmony_ci}, { 3508c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 3518c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 3528c2ecf20Sopenharmony_ci .idVendor = 0x04DD, 3538c2ecf20Sopenharmony_ci /* reported with some C860 units */ 3548c2ecf20Sopenharmony_ci .idProduct = 0x9050, /* C-860 */ 3558c2ecf20Sopenharmony_ci ZAURUS_MASTER_INTERFACE, 3568c2ecf20Sopenharmony_ci .driver_info = ZAURUS_PXA_INFO, 3578c2ecf20Sopenharmony_ci}, 3588c2ecf20Sopenharmony_ci{ 3598c2ecf20Sopenharmony_ci /* Motorola Rokr E6 */ 3608c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6027, USB_CLASS_COMM, 3618c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), 3628c2ecf20Sopenharmony_ci .driver_info = (unsigned long) &bogus_mdlm_info, 3638c2ecf20Sopenharmony_ci}, { 3648c2ecf20Sopenharmony_ci /* Motorola MOTOMAGX phones */ 3658c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6425, USB_CLASS_COMM, 3668c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), 3678c2ecf20Sopenharmony_ci .driver_info = (unsigned long) &bogus_mdlm_info, 3688c2ecf20Sopenharmony_ci}, 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci/* Olympus has some models with a Zaurus-compatible option. 3718c2ecf20Sopenharmony_ci * R-1000 uses a FreeScale i.MXL cpu (ARMv4T) 3728c2ecf20Sopenharmony_ci */ 3738c2ecf20Sopenharmony_ci{ 3748c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 3758c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 3768c2ecf20Sopenharmony_ci .idVendor = 0x07B4, 3778c2ecf20Sopenharmony_ci .idProduct = 0x0F02, /* R-1000 */ 3788c2ecf20Sopenharmony_ci ZAURUS_MASTER_INTERFACE, 3798c2ecf20Sopenharmony_ci .driver_info = OLYMPUS_MXL_INFO, 3808c2ecf20Sopenharmony_ci}, 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci/* Logitech Harmony 900 - uses the pseudo-MDLM (BLAN) driver */ 3838c2ecf20Sopenharmony_ci{ 3848c2ecf20Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(0x046d, 0xc11f, USB_CLASS_COMM, 3858c2ecf20Sopenharmony_ci USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), 3868c2ecf20Sopenharmony_ci .driver_info = (unsigned long) &bogus_mdlm_info, 3878c2ecf20Sopenharmony_ci}, 3888c2ecf20Sopenharmony_ci { }, // END 3898c2ecf20Sopenharmony_ci}; 3908c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(usb, products); 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_cistatic struct usb_driver zaurus_driver = { 3938c2ecf20Sopenharmony_ci .name = "zaurus", 3948c2ecf20Sopenharmony_ci .id_table = products, 3958c2ecf20Sopenharmony_ci .probe = usbnet_probe, 3968c2ecf20Sopenharmony_ci .disconnect = usbnet_disconnect, 3978c2ecf20Sopenharmony_ci .suspend = usbnet_suspend, 3988c2ecf20Sopenharmony_ci .resume = usbnet_resume, 3998c2ecf20Sopenharmony_ci .disable_hub_initiated_lpm = 1, 4008c2ecf20Sopenharmony_ci}; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_cimodule_usb_driver(zaurus_driver); 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ciMODULE_AUTHOR("Pavel Machek, David Brownell"); 4058c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Sharp Zaurus PDA, and compatible products"); 4068c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 407