ChangeSet 1.781, 2002/12/05 14:20:12-08:00, david-b@pacbell.net [PATCH] usbnet talks to Zaurus This more or less syncs the 2.4 version with the 2.5 one. It teaches "usbnet" how to talk to the SL-5000D/SL-5500, and the A-300. It's got some cleanups of how it talks to other StrongArm PDAs -- which is most of the patch by volume, other than making the GPL explicit. This will make Zaurus interop easier, folk won't need to find and install the "usbdnet" version which, as Pavel put it, "eats disks". diff -Nru a/drivers/usb/usbnet.c b/drivers/usb/usbnet.c --- a/drivers/usb/usbnet.c Thu Dec 5 14:48:44 2002 +++ b/drivers/usb/usbnet.c Thu Dec 5 14:48:44 2002 @@ -1,6 +1,21 @@ /* * USB Host-to-Host Links * Copyright (C) 2000-2002 by David Brownell + * Copyright (C) 2002 Pavel Machek + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* @@ -18,13 +33,15 @@ * - Belkin, eTEK (interops with Win32 drivers) * - EPSON USB clients * - GeneSys GL620USB-A - * - "Linux Devices" (like iPaq and similar SA-1100 based PDAs) * - NetChip 1080 (interoperates with NetChip Win32 drivers) * - Prolific PL-2301/2302 (replaces "plusb" driver) + * - SA-1100 (and similar) Linux PDAs like iPaq, Yopy, and Zaurus * * USB devices can implement their side of this protocol at the cost * of two bulk endpoints; it's not restricted to "cable" applications. - * See the LINUXDEV or EPSON device/client support. + * See the SA1110, Zaurus, or EPSON device/client support in this driver; + * slave/target drivers such as "usb-eth" (on most SA-1100 PDAs) are + * used inside USB slave/target devices. * * * Status: @@ -37,10 +54,6 @@ * handshaking; it'd be worth implementing those as "carrier detect". * Prefer generic hooks, not minidriver-specific hacks. * - * - Linux devices ... the www.handhelds.org SA-1100 support works nicely, - * but the Sharp Zaurus uses an incompatible protocol (extra checksums). - * No reason not to merge the Zaurus protocol here too (got patch? :) - * * - For Netchip, should use keventd to poll via control requests to detect * hardware level "carrier detect". * @@ -48,11 +61,16 @@ * sheets, sometimes it's not needed and sometimes it hangs. Prolific has * not responded to repeated support/information requests. * + * - SA-1100 PDAs ... the standard ARM Linux SA-1100 support works nicely, + * as found in www.handhelds.org and other kernels. The Sharp/Lineo + * kernels use different drivers, which also work here, but they've made + * "uhci-hcd" (2.5) die. + * * Interop with more Win32 drivers may be a good thing. * * Seems like reporting "peer connected" (carrier present) events may end - * up going through the netlink event system, not hotplug ... that may be - * awkward in terms of automatic configuration though. + * up going through the netlink event system, not hotplug ... so new links + * would likely be handled with a link monitoring thread in some daemon. * * There are reports that bridging gives lower-than-usual throughput. * @@ -100,6 +118,7 @@ * 07-may-2002 Generalize/cleanup keventd support, handling rx stalls (mostly * for USB 2.0 TTs) and memory shortages (potential) too. (db) * Use "locally assigned" IEEE802 address space. (Brad Hards) + * 18-oct-2002 Support for Zaurus (Pavel Machek), related cleanup (db). * *-------------------------------------------------------------------------*/ @@ -139,12 +158,13 @@ #define CONFIG_USB_BELKIN #define CONFIG_USB_EPSON2888 #define CONFIG_USB_GENESYS -#define CONFIG_USB_LINUXDEV #define CONFIG_USB_NET1080 #define CONFIG_USB_PL2301 +#define CONFIG_USB_SA1110 +#define CONFIG_USB_ZAURUS -#define DRIVER_VERSION "17-Jul-2002" +#define DRIVER_VERSION "18-Oct-2002" /*-------------------------------------------------------------------------*/ @@ -277,6 +297,12 @@ #define RUN_CONTEXT (in_irq () ? "in_irq" \ : (in_interrupt () ? "in_interrupt" : "can sleep")) +/* mostly for PDA style devices, which are always present */ +static int always_connected (struct usbnet *dev) +{ + return 0; +} + /*-------------------------------------------------------------------------*/ #ifdef DEBUG @@ -345,7 +371,7 @@ * * EPSON USB clients * - * This is the same idea as "linuxdev" (below) except the firmware in the + * This is the same idea as Linux PDAs (below) except the firmware in the * device might not be Tux-powered. Epson provides reference firmware that * implements this interface. Product developers can reuse or modify that * code, such as by using their own product and vendor codes. @@ -354,6 +380,7 @@ static const struct driver_info epson2888_info = { .description = "Epson USB Device", + .check_connect = always_connected, .in = 4, .out = 3, .epsize = 64, @@ -439,10 +466,28 @@ { int status = urb->status; + switch (status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", + __FUNCTION__, status); + return; + default: + dbg("%s - nonzero urb status received: %d", + __FUNCTION__, urb->status); + } + + // NOTE: 2.4 still has automagic resubmit, so this would be + // wrong ... but this code has never worked, is always disabled. + status = usb_submit_urb (urb, GFP_ATOMIC); if (status) - dbg ("gl_interrupt_complete fail - %X", status); - else - dbg ("gl_interrupt_complete success..."); + err ("%s - usb_submit_urb failed with result %d", + __FUNCTION__, status); } static int gl_interrupt_read (struct usbnet *dev) @@ -682,34 +727,6 @@ -#ifdef CONFIG_USB_LINUXDEV - -/*------------------------------------------------------------------------- - * - * This could talk to a device that uses Linux, such as a PDA or - * an embedded system, or in fact to any "smart" device using this - * particular mapping of USB and Ethernet. - * - * Such a Linux host would need a "USB Device Controller" hardware - * (not "USB Host Controller"), and a network driver talking to that - * hardware. - * - * One example is Intel's SA-1100 chip, which integrates basic USB - * support (arch/arm/sa1100/usb-eth.c); it's used in the iPaq PDA. - * And others too, like the Yopy. - * - *-------------------------------------------------------------------------*/ - -static const struct driver_info linuxdev_info = { - .description = "Linux Device", - - .in = 2, .out = 1, - .epsize = 64, -}; - -#endif /* CONFIG_USB_LINUXDEV */ - - #ifdef CONFIG_USB_NET1080 /*------------------------------------------------------------------------- @@ -1228,6 +1245,153 @@ +#ifdef CONFIG_USB_SA1100 + +/*------------------------------------------------------------------------- + * + * Intel's SA-1100 chip integrates basic USB support, and is used + * in PDAs like some iPaqs, the Yopy, some Zaurus models, and more. + * When they run Linux, arch/arm/sa1100/usb-eth.c may be used to + * network using minimal USB framing data. + * + * This describes the driver currently in standard ARM Linux kernels. + * The Zaurus uses a different driver (see later). + * + *-------------------------------------------------------------------------*/ + +static const struct driver_info linuxdev_info = { + .description = "SA-1100 Linux Device", + .check_connect = always_connected, + + .in = 2, .out = 1, + .epsize = 64, +}; + +static const struct driver_info yopy_info = { + .description = "Yopy", + .check_connect = always_connected, + + .in = 2, .out = 1, + .epsize = 64, +}; + +#endif /* CONFIG_USB_SA1100 */ + + +#ifdef CONFIG_USB_ZAURUS + +/*------------------------------------------------------------------------- + * + * Zaurus is also a SA-1110 based PDA, but one using a different driver + * for its USB slave/target controller than the case above. + * + * The key differences are that (a) it's got a msft-friendly configuration, + * and (b) the linux-friendly framing adds a crc32 to cope with some + * memory corruption observed with usb-to-memory DMA in some cases. + * (SA-1100 has a lot of nasty USB errata that need working around.) + * + *-------------------------------------------------------------------------*/ + +// FIXME try instead + +static const u32 crc32_table [256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +#define CRC32_INITFCS 0xffffffff // Initial FCS value +#define CRC32_FCS(fcs, c) (((fcs) >> 8) ^ crc32_table[((fcs) ^ (c)) & 0xff]) + +/* fcs_compute32 - memcpy and calculate fcs + * Perform a memcpy and calculate fcs using ppp 32bit CRC algorithm. + */ +static inline u32 fcs_compute32 (unsigned char *sp, int len, u32 fcs) +{ + for (;len-- > 0; fcs = CRC32_FCS (fcs, *sp++)) + continue; + return fcs; +} + +static struct sk_buff * +zaurus_tx_fixup (struct usbnet *dev, struct sk_buff *skb, int flags) +{ + int padlen; + struct sk_buff *skb2; + + padlen = 2; + if (!skb_cloned (skb)) { + int tailroom = skb_tailroom (skb); + if ((padlen + 4) <= tailroom) + goto done; + } + skb2 = skb_copy_expand (skb, 0, 4 + padlen, flags); + dev_kfree_skb_any (skb); + skb = skb2; + if (skb) { + u32 fcs; +done: + fcs = fcs_compute32 (skb->data, skb->len, CRC32_INITFCS); + fcs = ~fcs; + + *skb_put (skb, 1) = fcs & 0xff; + *skb_put (skb, 1) = (fcs>> 8) & 0xff; + *skb_put (skb, 1) = (fcs>>16) & 0xff; + *skb_put (skb, 1) = (fcs>>24) & 0xff; + } + return skb; +} + +static const struct driver_info zaurus_sl5x00_info = { + .description = "Sharp Zaurus SL-5x00", + .check_connect = always_connected, + .tx_fixup = zaurus_tx_fixup, + + // SA-1100 fixed function endpoints + .in = 2, .out = 1, + .epsize = 64, +}; +static const struct driver_info zaurus_sla300_info = { + .description = "Sharp Zaurus SL-A300", + .check_connect = always_connected, + .tx_fixup = zaurus_tx_fixup, + + // two of the many PXA-250 fixed function endpoints + .in = 1, .out = 2, + .epsize = 64, +}; +#endif + + /*------------------------------------------------------------------------- * * Network Device Driver (peer link to "Host Device", from USB host) @@ -1662,7 +1826,7 @@ /* could also map RINGPARAM to RX/TX QLEN */ } - /* Note that the ethtool user space code requires EOPNOTSUPP */ + /* Note that the ethtool user space code requires EOPNOTSUPP */ return -EOPNOTSUPP; } @@ -1982,21 +2146,26 @@ { struct usbnet *dev; struct net_device *net; - struct usb_interface_descriptor *interface; struct driver_info *info; int altnum = 0; info = (struct driver_info *) prod->driver_info; - // sanity check; expect dedicated interface/devices for now. - interface = &udev->actconfig->interface [ifnum].altsetting [altnum]; - if (udev->descriptor.bNumConfigurations != 1 - || udev->config[0].bNumInterfaces != 1 -// || interface->bInterfaceClass != USB_CLASS_VENDOR_SPEC - ) { - dbg ("Bogus config info"); - return 0; +#ifdef CONFIG_USB_ZAURUS + if (info == &zaurus_sl5x00_info) { + int status; + + /* old ROMs have more than one config + * so we have to make sure config="1" (?) + */ + status = usb_set_configuration (udev, 1); + if (status < 0) { + err ("set_config failed, %d", status); + return 0; + } + altnum = 1; } +#endif // more sanity (unless the device is broken) if (!(info->flags & FLAG_NO_SETINT)) { @@ -2099,7 +2268,7 @@ #ifdef CONFIG_USB_EPSON2888 { USB_DEVICE (0x0525, 0x2888), // EPSON USB client - driver_info: (unsigned long) &epson2888_info, + .driver_info = (unsigned long) &epson2888_info, }, #endif @@ -2113,23 +2282,6 @@ */ #endif -#ifdef CONFIG_USB_LINUXDEV -/* - * for example, this can be a host side talk-to-PDA driver. - * this driver is NOT what runs _inside_ a Linux device !! - */ -{ - // 1183 = 0x049F, both used as hex values? - USB_DEVICE (0x049F, 0x505A), // Compaq "Itsy" - .driver_info = (unsigned long) &linuxdev_info, -}, { - USB_DEVICE (0x0E7E, 0x1001), // G.Mate "Yopy" - .driver_info = (unsigned long) &linuxdev_info, -}, - // NOTE: the Sharp Zaurus uses a modified version of - // this driver, which is not interoperable with this. -#endif - #ifdef CONFIG_USB_NET1080 { USB_DEVICE (0x0525, 0x1080), // NetChip ref design @@ -2147,6 +2299,49 @@ }, { USB_DEVICE (0x067b, 0x0001), // PL-2302 .driver_info = (unsigned long) &prolific_info, +}, +#endif + +#ifdef CONFIG_USB_SA1100 +/* + * SA-1100 using standard ARM Linux kernels, or compatible. + * Often used when talking to Linux PDAs (iPaq, Yopy, etc). + * The sa-1100 "usb-eth" driver handles the basic framing. + */ +{ + // 1183 = 0x049F, both used as hex values? + USB_DEVICE (0x049F, 0x505A), // iPaq: Compaq "Itsy" + .driver_info = (unsigned long) &linuxdev_info, +}, { + USB_DEVICE (0x0E7E, 0x1001), // G.Mate "Yopy" + .driver_info = (unsigned long) &yopy_info, +}, +#endif + +#ifdef CONFIG_USB_ZAURUS +/* + * SA-1100 based Sharp Zaurus ("collie"), or compatible. + * Same idea as above, but different framing. + */ +{ + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x04DD, + .idProduct = 0x8004, + .bInterfaceClass = 0x0a, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, + .driver_info = (unsigned long) &zaurus_sl5x00_info, +}, +{ + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x04DD, + .idProduct = 0x8005, + .bInterfaceClass = 0x02, + .bInterfaceSubClass = 0x0a, + .bInterfaceProtocol = 0x00, + .driver_info = (unsigned long) &zaurus_sla300_info, }, #endif