162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2002 Pavel Machek <pavel@ucw.cz> 462306a36Sopenharmony_ci * Copyright (C) 2002-2005 by David Brownell 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci// #define DEBUG // error path messages, extra info 862306a36Sopenharmony_ci// #define VERBOSE // more; success messages 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/module.h> 1162306a36Sopenharmony_ci#include <linux/netdevice.h> 1262306a36Sopenharmony_ci#include <linux/ethtool.h> 1362306a36Sopenharmony_ci#include <linux/workqueue.h> 1462306a36Sopenharmony_ci#include <linux/mii.h> 1562306a36Sopenharmony_ci#include <linux/crc32.h> 1662306a36Sopenharmony_ci#include <linux/usb.h> 1762306a36Sopenharmony_ci#include <linux/usb/cdc.h> 1862306a36Sopenharmony_ci#include <linux/usb/usbnet.h> 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci/* 2262306a36Sopenharmony_ci * All known Zaurii lie about their standards conformance. At least 2362306a36Sopenharmony_ci * the earliest SA-1100 models lie by saying they support CDC Ethernet. 2462306a36Sopenharmony_ci * Some later models (especially PXA-25x and PXA-27x based ones) lie 2562306a36Sopenharmony_ci * and say they support CDC MDLM (for access to cell phone modems). 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci * There are non-Zaurus products that use these same protocols too. 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * The annoying thing is that at the same time Sharp was developing 3062306a36Sopenharmony_ci * that annoying standards-breaking software, the Linux community had 3162306a36Sopenharmony_ci * a simple "CDC Subset" working reliably on the same SA-1100 hardware. 3262306a36Sopenharmony_ci * That is, the same functionality but not violating standards. 3362306a36Sopenharmony_ci * 3462306a36Sopenharmony_ci * The CDC Ethernet nonconformance points are troublesome to hosts 3562306a36Sopenharmony_ci * with a true CDC Ethernet implementation: 3662306a36Sopenharmony_ci * - Framing appends a CRC, which the spec says drivers "must not" do; 3762306a36Sopenharmony_ci * - Transfers data in altsetting zero, instead of altsetting 1; 3862306a36Sopenharmony_ci * - All these peripherals use the same ethernet address. 3962306a36Sopenharmony_ci * 4062306a36Sopenharmony_ci * The CDC MDLM nonconformance is less immediately troublesome, since all 4162306a36Sopenharmony_ci * MDLM implementations are quasi-proprietary anyway. 4262306a36Sopenharmony_ci */ 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic struct sk_buff * 4562306a36Sopenharmony_cizaurus_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) 4662306a36Sopenharmony_ci{ 4762306a36Sopenharmony_ci int padlen; 4862306a36Sopenharmony_ci struct sk_buff *skb2; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci padlen = 2; 5162306a36Sopenharmony_ci if (!skb_cloned(skb)) { 5262306a36Sopenharmony_ci int tailroom = skb_tailroom(skb); 5362306a36Sopenharmony_ci if ((padlen + 4) <= tailroom) 5462306a36Sopenharmony_ci goto done; 5562306a36Sopenharmony_ci } 5662306a36Sopenharmony_ci skb2 = skb_copy_expand(skb, 0, 4 + padlen, flags); 5762306a36Sopenharmony_ci dev_kfree_skb_any(skb); 5862306a36Sopenharmony_ci skb = skb2; 5962306a36Sopenharmony_ci if (skb) { 6062306a36Sopenharmony_ci u32 fcs; 6162306a36Sopenharmony_cidone: 6262306a36Sopenharmony_ci fcs = crc32_le(~0, skb->data, skb->len); 6362306a36Sopenharmony_ci fcs = ~fcs; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci skb_put_u8(skb, fcs & 0xff); 6662306a36Sopenharmony_ci skb_put_u8(skb, (fcs >> 8) & 0xff); 6762306a36Sopenharmony_ci skb_put_u8(skb, (fcs >> 16) & 0xff); 6862306a36Sopenharmony_ci skb_put_u8(skb, (fcs >> 24) & 0xff); 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_ci return skb; 7162306a36Sopenharmony_ci} 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistatic int zaurus_bind(struct usbnet *dev, struct usb_interface *intf) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci /* Belcarra's funky framing has other options; mostly 7662306a36Sopenharmony_ci * TRAILERS (!) with 4 bytes CRC, and maybe 2 pad bytes. 7762306a36Sopenharmony_ci */ 7862306a36Sopenharmony_ci dev->net->hard_header_len += 6; 7962306a36Sopenharmony_ci dev->rx_urb_size = dev->net->hard_header_len + dev->net->mtu; 8062306a36Sopenharmony_ci return usbnet_generic_cdc_bind(dev, intf); 8162306a36Sopenharmony_ci} 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci/* PDA style devices are always connected if present */ 8462306a36Sopenharmony_cistatic int always_connected (struct usbnet *dev) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci return 0; 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic const struct driver_info zaurus_sl5x00_info = { 9062306a36Sopenharmony_ci .description = "Sharp Zaurus SL-5x00", 9162306a36Sopenharmony_ci .flags = FLAG_POINTTOPOINT | FLAG_FRAMING_Z, 9262306a36Sopenharmony_ci .check_connect = always_connected, 9362306a36Sopenharmony_ci .bind = zaurus_bind, 9462306a36Sopenharmony_ci .unbind = usbnet_cdc_unbind, 9562306a36Sopenharmony_ci .tx_fixup = zaurus_tx_fixup, 9662306a36Sopenharmony_ci}; 9762306a36Sopenharmony_ci#define ZAURUS_STRONGARM_INFO ((unsigned long)&zaurus_sl5x00_info) 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistatic const struct driver_info zaurus_pxa_info = { 10062306a36Sopenharmony_ci .description = "Sharp Zaurus, PXA-2xx based", 10162306a36Sopenharmony_ci .flags = FLAG_POINTTOPOINT | FLAG_FRAMING_Z, 10262306a36Sopenharmony_ci .check_connect = always_connected, 10362306a36Sopenharmony_ci .bind = zaurus_bind, 10462306a36Sopenharmony_ci .unbind = usbnet_cdc_unbind, 10562306a36Sopenharmony_ci .tx_fixup = zaurus_tx_fixup, 10662306a36Sopenharmony_ci}; 10762306a36Sopenharmony_ci#define ZAURUS_PXA_INFO ((unsigned long)&zaurus_pxa_info) 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistatic const struct driver_info olympus_mxl_info = { 11062306a36Sopenharmony_ci .description = "Olympus R1000", 11162306a36Sopenharmony_ci .flags = FLAG_POINTTOPOINT | FLAG_FRAMING_Z, 11262306a36Sopenharmony_ci .check_connect = always_connected, 11362306a36Sopenharmony_ci .bind = zaurus_bind, 11462306a36Sopenharmony_ci .unbind = usbnet_cdc_unbind, 11562306a36Sopenharmony_ci .tx_fixup = zaurus_tx_fixup, 11662306a36Sopenharmony_ci}; 11762306a36Sopenharmony_ci#define OLYMPUS_MXL_INFO ((unsigned long)&olympus_mxl_info) 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci/* Some more recent products using Lineo/Belcarra code will wrongly claim 12162306a36Sopenharmony_ci * CDC MDLM conformance. They aren't conformant: data endpoints live 12262306a36Sopenharmony_ci * in the control interface, there's no data interface, and it's not used 12362306a36Sopenharmony_ci * to talk to a cell phone radio. But at least we can detect these two 12462306a36Sopenharmony_ci * pseudo-classes, rather than growing this product list with entries for 12562306a36Sopenharmony_ci * each new nonconformant product (sigh). 12662306a36Sopenharmony_ci */ 12762306a36Sopenharmony_cistatic const u8 safe_guid[16] = { 12862306a36Sopenharmony_ci 0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6, 12962306a36Sopenharmony_ci 0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f, 13062306a36Sopenharmony_ci}; 13162306a36Sopenharmony_cistatic const u8 blan_guid[16] = { 13262306a36Sopenharmony_ci 0x74, 0xf0, 0x3d, 0xbd, 0x1e, 0xc1, 0x44, 0x70, 13362306a36Sopenharmony_ci 0xa3, 0x67, 0x71, 0x34, 0xc9, 0xf5, 0x54, 0x37, 13462306a36Sopenharmony_ci}; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistatic int blan_mdlm_bind(struct usbnet *dev, struct usb_interface *intf) 13762306a36Sopenharmony_ci{ 13862306a36Sopenharmony_ci u8 *buf = intf->cur_altsetting->extra; 13962306a36Sopenharmony_ci int len = intf->cur_altsetting->extralen; 14062306a36Sopenharmony_ci struct usb_cdc_mdlm_desc *desc = NULL; 14162306a36Sopenharmony_ci struct usb_cdc_mdlm_detail_desc *detail = NULL; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci while (len > 3) { 14462306a36Sopenharmony_ci if (buf [1] != USB_DT_CS_INTERFACE) 14562306a36Sopenharmony_ci goto next_desc; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci /* use bDescriptorSubType, and just verify that we get a 14862306a36Sopenharmony_ci * "BLAN" (or "SAFE") descriptor. 14962306a36Sopenharmony_ci */ 15062306a36Sopenharmony_ci switch (buf [2]) { 15162306a36Sopenharmony_ci case USB_CDC_MDLM_TYPE: 15262306a36Sopenharmony_ci if (desc) { 15362306a36Sopenharmony_ci dev_dbg(&intf->dev, "extra MDLM\n"); 15462306a36Sopenharmony_ci goto bad_desc; 15562306a36Sopenharmony_ci } 15662306a36Sopenharmony_ci desc = (void *) buf; 15762306a36Sopenharmony_ci if (desc->bLength != sizeof *desc) { 15862306a36Sopenharmony_ci dev_dbg(&intf->dev, "MDLM len %u\n", 15962306a36Sopenharmony_ci desc->bLength); 16062306a36Sopenharmony_ci goto bad_desc; 16162306a36Sopenharmony_ci } 16262306a36Sopenharmony_ci /* expect bcdVersion 1.0, ignore */ 16362306a36Sopenharmony_ci if (memcmp(&desc->bGUID, blan_guid, 16) && 16462306a36Sopenharmony_ci memcmp(&desc->bGUID, safe_guid, 16)) { 16562306a36Sopenharmony_ci /* hey, this one might _really_ be MDLM! */ 16662306a36Sopenharmony_ci dev_dbg(&intf->dev, "MDLM guid\n"); 16762306a36Sopenharmony_ci goto bad_desc; 16862306a36Sopenharmony_ci } 16962306a36Sopenharmony_ci break; 17062306a36Sopenharmony_ci case USB_CDC_MDLM_DETAIL_TYPE: 17162306a36Sopenharmony_ci if (detail) { 17262306a36Sopenharmony_ci dev_dbg(&intf->dev, "extra MDLM detail\n"); 17362306a36Sopenharmony_ci goto bad_desc; 17462306a36Sopenharmony_ci } 17562306a36Sopenharmony_ci detail = (void *) buf; 17662306a36Sopenharmony_ci switch (detail->bGuidDescriptorType) { 17762306a36Sopenharmony_ci case 0: /* "SAFE" */ 17862306a36Sopenharmony_ci if (detail->bLength != (sizeof *detail + 2)) 17962306a36Sopenharmony_ci goto bad_detail; 18062306a36Sopenharmony_ci break; 18162306a36Sopenharmony_ci case 1: /* "BLAN" */ 18262306a36Sopenharmony_ci if (detail->bLength != (sizeof *detail + 3)) 18362306a36Sopenharmony_ci goto bad_detail; 18462306a36Sopenharmony_ci break; 18562306a36Sopenharmony_ci default: 18662306a36Sopenharmony_ci goto bad_detail; 18762306a36Sopenharmony_ci } 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci /* assuming we either noticed BLAN already, or will 19062306a36Sopenharmony_ci * find it soon, there are some data bytes here: 19162306a36Sopenharmony_ci * - bmNetworkCapabilities (unused) 19262306a36Sopenharmony_ci * - bmDataCapabilities (bits, see below) 19362306a36Sopenharmony_ci * - bPad (ignored, for PADAFTER -- BLAN-only) 19462306a36Sopenharmony_ci * bits are: 19562306a36Sopenharmony_ci * - 0x01 -- Zaurus framing (add CRC) 19662306a36Sopenharmony_ci * - 0x02 -- PADBEFORE (CRC includes some padding) 19762306a36Sopenharmony_ci * - 0x04 -- PADAFTER (some padding after CRC) 19862306a36Sopenharmony_ci * - 0x08 -- "fermat" packet mangling (for hw bugs) 19962306a36Sopenharmony_ci * the PADBEFORE appears not to matter; we interop 20062306a36Sopenharmony_ci * with devices that use it and those that don't. 20162306a36Sopenharmony_ci */ 20262306a36Sopenharmony_ci if ((detail->bDetailData[1] & ~0x02) != 0x01) { 20362306a36Sopenharmony_ci /* bmDataCapabilities == 0 would be fine too, 20462306a36Sopenharmony_ci * but framing is minidriver-coupled for now. 20562306a36Sopenharmony_ci */ 20662306a36Sopenharmony_cibad_detail: 20762306a36Sopenharmony_ci dev_dbg(&intf->dev, 20862306a36Sopenharmony_ci "bad MDLM detail, %d %d %d\n", 20962306a36Sopenharmony_ci detail->bLength, 21062306a36Sopenharmony_ci detail->bDetailData[0], 21162306a36Sopenharmony_ci detail->bDetailData[2]); 21262306a36Sopenharmony_ci goto bad_desc; 21362306a36Sopenharmony_ci } 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci /* same extra framing as for non-BLAN mode */ 21662306a36Sopenharmony_ci dev->net->hard_header_len += 6; 21762306a36Sopenharmony_ci dev->rx_urb_size = dev->net->hard_header_len 21862306a36Sopenharmony_ci + dev->net->mtu; 21962306a36Sopenharmony_ci break; 22062306a36Sopenharmony_ci } 22162306a36Sopenharmony_cinext_desc: 22262306a36Sopenharmony_ci len -= buf [0]; /* bLength */ 22362306a36Sopenharmony_ci buf += buf [0]; 22462306a36Sopenharmony_ci } 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci if (!desc || !detail) { 22762306a36Sopenharmony_ci dev_dbg(&intf->dev, "missing cdc mdlm %s%sdescriptor\n", 22862306a36Sopenharmony_ci desc ? "" : "func ", 22962306a36Sopenharmony_ci detail ? "" : "detail "); 23062306a36Sopenharmony_ci goto bad_desc; 23162306a36Sopenharmony_ci } 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci /* There's probably a CDC Ethernet descriptor there, but we can't 23462306a36Sopenharmony_ci * rely on the Ethernet address it provides since not all vendors 23562306a36Sopenharmony_ci * bother to make it unique. Likewise there's no point in tracking 23662306a36Sopenharmony_ci * of the CDC event notifications. 23762306a36Sopenharmony_ci */ 23862306a36Sopenharmony_ci return usbnet_get_endpoints(dev, intf); 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_cibad_desc: 24162306a36Sopenharmony_ci dev_info(&dev->udev->dev, "unsupported MDLM descriptors\n"); 24262306a36Sopenharmony_ci return -ENODEV; 24362306a36Sopenharmony_ci} 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_cistatic const struct driver_info bogus_mdlm_info = { 24662306a36Sopenharmony_ci .description = "pseudo-MDLM (BLAN) device", 24762306a36Sopenharmony_ci .flags = FLAG_POINTTOPOINT | FLAG_FRAMING_Z, 24862306a36Sopenharmony_ci .check_connect = always_connected, 24962306a36Sopenharmony_ci .tx_fixup = zaurus_tx_fixup, 25062306a36Sopenharmony_ci .bind = blan_mdlm_bind, 25162306a36Sopenharmony_ci}; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_cistatic const struct usb_device_id products [] = { 25462306a36Sopenharmony_ci#define ZAURUS_MASTER_INTERFACE \ 25562306a36Sopenharmony_ci .bInterfaceClass = USB_CLASS_COMM, \ 25662306a36Sopenharmony_ci .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \ 25762306a36Sopenharmony_ci .bInterfaceProtocol = USB_CDC_PROTO_NONE 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci#define ZAURUS_FAKE_INTERFACE \ 26062306a36Sopenharmony_ci .bInterfaceClass = USB_CLASS_COMM, \ 26162306a36Sopenharmony_ci .bInterfaceSubClass = USB_CDC_SUBCLASS_MDLM, \ 26262306a36Sopenharmony_ci .bInterfaceProtocol = USB_CDC_PROTO_NONE 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci/* SA-1100 based Sharp Zaurus ("collie"), or compatible. */ 26562306a36Sopenharmony_ci{ 26662306a36Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 26762306a36Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 26862306a36Sopenharmony_ci .idVendor = 0x04DD, 26962306a36Sopenharmony_ci .idProduct = 0x8004, 27062306a36Sopenharmony_ci ZAURUS_MASTER_INTERFACE, 27162306a36Sopenharmony_ci .driver_info = ZAURUS_STRONGARM_INFO, 27262306a36Sopenharmony_ci}, 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci/* PXA-2xx based models are also lying-about-cdc. If you add any 27562306a36Sopenharmony_ci * more devices that claim to be CDC Ethernet, make sure they get 27662306a36Sopenharmony_ci * added to the blacklist in cdc_ether too. 27762306a36Sopenharmony_ci * 27862306a36Sopenharmony_ci * NOTE: OpenZaurus versions with 2.6 kernels won't use these entries, 27962306a36Sopenharmony_ci * unlike the older ones with 2.4 "embedix" kernels. 28062306a36Sopenharmony_ci */ 28162306a36Sopenharmony_ci{ 28262306a36Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 28362306a36Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 28462306a36Sopenharmony_ci .idVendor = 0x04DD, 28562306a36Sopenharmony_ci .idProduct = 0x8005, /* A-300 */ 28662306a36Sopenharmony_ci ZAURUS_MASTER_INTERFACE, 28762306a36Sopenharmony_ci .driver_info = ZAURUS_PXA_INFO, 28862306a36Sopenharmony_ci}, { 28962306a36Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 29062306a36Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 29162306a36Sopenharmony_ci .idVendor = 0x04DD, 29262306a36Sopenharmony_ci .idProduct = 0x8005, /* A-300 */ 29362306a36Sopenharmony_ci ZAURUS_FAKE_INTERFACE, 29462306a36Sopenharmony_ci .driver_info = (unsigned long)&bogus_mdlm_info, 29562306a36Sopenharmony_ci}, { 29662306a36Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 29762306a36Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 29862306a36Sopenharmony_ci .idVendor = 0x04DD, 29962306a36Sopenharmony_ci .idProduct = 0x8006, /* B-500/SL-5600 */ 30062306a36Sopenharmony_ci ZAURUS_MASTER_INTERFACE, 30162306a36Sopenharmony_ci .driver_info = ZAURUS_PXA_INFO, 30262306a36Sopenharmony_ci}, { 30362306a36Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 30462306a36Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 30562306a36Sopenharmony_ci .idVendor = 0x04DD, 30662306a36Sopenharmony_ci .idProduct = 0x8006, /* B-500/SL-5600 */ 30762306a36Sopenharmony_ci ZAURUS_FAKE_INTERFACE, 30862306a36Sopenharmony_ci .driver_info = (unsigned long)&bogus_mdlm_info, 30962306a36Sopenharmony_ci}, { 31062306a36Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 31162306a36Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 31262306a36Sopenharmony_ci .idVendor = 0x04DD, 31362306a36Sopenharmony_ci .idProduct = 0x8007, /* C-700 */ 31462306a36Sopenharmony_ci ZAURUS_MASTER_INTERFACE, 31562306a36Sopenharmony_ci .driver_info = ZAURUS_PXA_INFO, 31662306a36Sopenharmony_ci}, { 31762306a36Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 31862306a36Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 31962306a36Sopenharmony_ci .idVendor = 0x04DD, 32062306a36Sopenharmony_ci .idProduct = 0x8007, /* C-700 */ 32162306a36Sopenharmony_ci ZAURUS_FAKE_INTERFACE, 32262306a36Sopenharmony_ci .driver_info = (unsigned long)&bogus_mdlm_info, 32362306a36Sopenharmony_ci}, { 32462306a36Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 32562306a36Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 32662306a36Sopenharmony_ci .idVendor = 0x04DD, 32762306a36Sopenharmony_ci .idProduct = 0x9031, /* C-750 C-760 */ 32862306a36Sopenharmony_ci ZAURUS_MASTER_INTERFACE, 32962306a36Sopenharmony_ci .driver_info = ZAURUS_PXA_INFO, 33062306a36Sopenharmony_ci}, { 33162306a36Sopenharmony_ci /* C-750/C-760/C-860/SL-C3000 PDA in MDLM mode */ 33262306a36Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(0x04DD, 0x9031, USB_CLASS_COMM, 33362306a36Sopenharmony_ci USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), 33462306a36Sopenharmony_ci .driver_info = (unsigned long) &bogus_mdlm_info, 33562306a36Sopenharmony_ci}, { 33662306a36Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 33762306a36Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 33862306a36Sopenharmony_ci .idVendor = 0x04DD, 33962306a36Sopenharmony_ci .idProduct = 0x9032, /* SL-6000 */ 34062306a36Sopenharmony_ci ZAURUS_MASTER_INTERFACE, 34162306a36Sopenharmony_ci .driver_info = ZAURUS_PXA_INFO, 34262306a36Sopenharmony_ci}, { 34362306a36Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 34462306a36Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 34562306a36Sopenharmony_ci .idVendor = 0x04DD, 34662306a36Sopenharmony_ci .idProduct = 0x9032, /* SL-6000 */ 34762306a36Sopenharmony_ci ZAURUS_FAKE_INTERFACE, 34862306a36Sopenharmony_ci .driver_info = (unsigned long)&bogus_mdlm_info, 34962306a36Sopenharmony_ci}, { 35062306a36Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 35162306a36Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 35262306a36Sopenharmony_ci .idVendor = 0x04DD, 35362306a36Sopenharmony_ci /* reported with some C860 units */ 35462306a36Sopenharmony_ci .idProduct = 0x9050, /* C-860 */ 35562306a36Sopenharmony_ci ZAURUS_MASTER_INTERFACE, 35662306a36Sopenharmony_ci .driver_info = ZAURUS_PXA_INFO, 35762306a36Sopenharmony_ci}, 35862306a36Sopenharmony_ci{ 35962306a36Sopenharmony_ci /* Motorola Rokr E6 */ 36062306a36Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6027, USB_CLASS_COMM, 36162306a36Sopenharmony_ci USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), 36262306a36Sopenharmony_ci .driver_info = (unsigned long) &bogus_mdlm_info, 36362306a36Sopenharmony_ci}, { 36462306a36Sopenharmony_ci /* Motorola MOTOMAGX phones */ 36562306a36Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6425, USB_CLASS_COMM, 36662306a36Sopenharmony_ci USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), 36762306a36Sopenharmony_ci .driver_info = (unsigned long) &bogus_mdlm_info, 36862306a36Sopenharmony_ci}, 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci/* Olympus has some models with a Zaurus-compatible option. 37162306a36Sopenharmony_ci * R-1000 uses a FreeScale i.MXL cpu (ARMv4T) 37262306a36Sopenharmony_ci */ 37362306a36Sopenharmony_ci{ 37462306a36Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_INFO 37562306a36Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, 37662306a36Sopenharmony_ci .idVendor = 0x07B4, 37762306a36Sopenharmony_ci .idProduct = 0x0F02, /* R-1000 */ 37862306a36Sopenharmony_ci ZAURUS_MASTER_INTERFACE, 37962306a36Sopenharmony_ci .driver_info = OLYMPUS_MXL_INFO, 38062306a36Sopenharmony_ci}, 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci/* Logitech Harmony 900 - uses the pseudo-MDLM (BLAN) driver */ 38362306a36Sopenharmony_ci{ 38462306a36Sopenharmony_ci USB_DEVICE_AND_INTERFACE_INFO(0x046d, 0xc11f, USB_CLASS_COMM, 38562306a36Sopenharmony_ci USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), 38662306a36Sopenharmony_ci .driver_info = (unsigned long) &bogus_mdlm_info, 38762306a36Sopenharmony_ci}, 38862306a36Sopenharmony_ci { }, // END 38962306a36Sopenharmony_ci}; 39062306a36Sopenharmony_ciMODULE_DEVICE_TABLE(usb, products); 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_cistatic struct usb_driver zaurus_driver = { 39362306a36Sopenharmony_ci .name = "zaurus", 39462306a36Sopenharmony_ci .id_table = products, 39562306a36Sopenharmony_ci .probe = usbnet_probe, 39662306a36Sopenharmony_ci .disconnect = usbnet_disconnect, 39762306a36Sopenharmony_ci .suspend = usbnet_suspend, 39862306a36Sopenharmony_ci .resume = usbnet_resume, 39962306a36Sopenharmony_ci .disable_hub_initiated_lpm = 1, 40062306a36Sopenharmony_ci}; 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_cimodule_usb_driver(zaurus_driver); 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ciMODULE_AUTHOR("Pavel Machek, David Brownell"); 40562306a36Sopenharmony_ciMODULE_DESCRIPTION("Sharp Zaurus PDA, and compatible products"); 40662306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 407