📄 usbnet.c
字号:
/* * USB Host-to-Host Links * Copyright (C) 2000-2002 by David Brownell <dbrownell@users.sourceforge.net> *//* * This is used for "USB networking", connecting USB hosts as peers. * * It can be used with USB "network cables", for IP-over-USB communications; * Ethernet speeds without the Ethernet. USB devices (including some PDAs) * can support such links directly, replacing device-specific protocols * with Internet standard ones. * * The links can be bridged using the Ethernet bridging (net/bridge) * support as appropriate. Devices currently supported include: * * - AnchorChip 2720 * - 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) * * 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. * * * Status: * * - AN2720 ... not widely available, but reportedly works well * * - Belkin/eTEK ... no known issues * * - Both GeneSys and PL-230x use interrupt transfers for driver-to-driver * 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". * * - PL-230x ... the initialization protocol doesn't seem to match chip data * sheets, sometimes it's not needed and sometimes it hangs. Prolific has * not responded to repeated support/information requests. * * 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. * * There are reports that bridging gives lower-than-usual throughput. * * Need smarter hotplug policy scripts ... ones that know how to arrange * bridging with "brctl", and can handle static and dynamic ("pump") setups. * Use those eventual "peer connected" events, and zeroconf. * * * CHANGELOG: * * 13-sep-2000 experimental, new * 10-oct-2000 usb_device_id table created. * 28-oct-2000 misc fixes; mostly, discard more TTL-mangled rx packets. * 01-nov-2000 usb_device_id table and probing api update by * Adam J. Richter <adam@yggdrasil.com>. * 18-dec-2000 (db) tx watchdog, "net1080" renaming to "usbnet", device_info * and prolific support, isolate net1080-specific bits, cleanup. * fix unlink_urbs oops in D3 PM resume code path. * * 02-feb-2001 (db) fix tx skb sharing, packet length, match_flags, ... * 08-feb-2001 stubbed in "linuxdev", maybe the SA-1100 folk can use it; * AnchorChips 2720 support (from spec) for testing; * fix bit-ordering problem with ethernet multicast addr * 19-feb-2001 Support for clearing halt conditions. SA1100 UDC support * updates. Oleg Drokin (green@iXcelerator.com) * 25-mar-2001 More SA-1100 updates, including workaround for ip problem * expecting cleared skb->cb and framing change to match latest * handhelds.org version (Oleg). Enable device IDs from the * Win32 Belkin driver; other cleanups (db). * 16-jul-2001 Bugfixes for uhci oops-on-unplug, Belkin support, various * cleanups for problems not yet seen in the field. (db) * 17-oct-2001 Handle "Advance USBNET" product, like Belkin/eTEK devices, * from Ioannis Mavroukakis <i.mavroukakis@btinternet.com>; * rx unlinks somehow weren't async; minor cleanup. * 03-nov-2001 Merged GeneSys driver; original code from Jiun-Jie Huang * <huangjj@genesyslogic.com.tw>, updated by Stanislav Brabec * <utx@penguin.cz>. Made framing options (NetChip/GeneSys) * tie mostly to (sub)driver info. Workaround some PL-2302 * chips that seem to reject SET_INTERFACE requests. * * 06-apr-2002 Added ethtool support, based on a patch from Brad Hards. * Level of diagnostics is more configurable; they use device * location (usb_device->devpath) instead of address (2.5). * For tx_fixup, memflags can't be NOIO. * 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) * *-------------------------------------------------------------------------*/#include <linux/config.h>#include <linux/module.h>#include <linux/kmod.h>#include <linux/sched.h>#include <linux/init.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/random.h>#include <linux/ethtool.h>#include <linux/tqueue.h>#include <asm/uaccess.h>#include <asm/unaligned.h>// #define DEBUG // error path messages, extra info// #define VERBOSE // more; success messages// #define REALLY_QUEUE#if !defined (DEBUG) && defined (CONFIG_USB_DEBUG)# define DEBUG#endif#include <linux/usb.h>/* in 2.5 these standard usb ops take mem_flags */#define ALLOC_URB(n,flags) usb_alloc_urb(n)#define SUBMIT_URB(u,flags) usb_submit_urb(u)/* and these got renamed (may move to usb.h) */#define usb_get_dev usb_inc_dev_use#define usb_put_dev usb_dec_dev_use/* minidrivers _could_ be individually configured */#define CONFIG_USB_AN2720#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 DRIVER_VERSION "17-Jul-2002"/*-------------------------------------------------------------------------*//* * Nineteen USB 1.1 max size bulk transactions per frame (ms), max. * Several dozen bytes of IPv4 data can fit in two such transactions. * One maximum size Ethernet packet takes twenty four of them. */#ifdef REALLY_QUEUE#define RX_QLEN 4#define TX_QLEN 4#else#define RX_QLEN 1#define TX_QLEN 1#endif// packets are always ethernet inside// ... except they can be bigger (limit of 64K with NetChip framing)#define MIN_PACKET sizeof(struct ethhdr)#define MAX_PACKET 32768// reawaken network queue this soon after stopping; else watchdog barks#define TX_TIMEOUT_JIFFIES (5*HZ)// for vendor-specific control operations#define CONTROL_TIMEOUT_MS (500) /* msec */#define CONTROL_TIMEOUT_JIFFIES ((CONTROL_TIMEOUT_MS * HZ)/1000)// between wakeups#define UNLINK_TIMEOUT_JIFFIES ((3 /*ms*/ * HZ)/1000)/*-------------------------------------------------------------------------*/// list of all devices we managestatic DECLARE_MUTEX (usbnet_mutex);static LIST_HEAD (usbnet_list);// randomly generated ethernet addressstatic u8 node_id [ETH_ALEN];// state we keep for each device we handlestruct usbnet { // housekeeping struct usb_device *udev; struct driver_info *driver_info; struct semaphore mutex; struct list_head dev_list; wait_queue_head_t *wait; // protocol/interface state struct net_device net; struct net_device_stats stats; int msg_level;#ifdef CONFIG_USB_NET1080 u16 packet_id;#endif // various kinds of pending driver work struct sk_buff_head rxq; struct sk_buff_head txq; struct sk_buff_head done; struct tasklet_struct bh; struct tq_struct kevent; unsigned long flags;# define EVENT_TX_HALT 0# define EVENT_RX_HALT 1# define EVENT_RX_MEMORY 2};// device-specific info used by the driverstruct driver_info { char *description; int flags;#define FLAG_FRAMING_NC 0x0001 /* guard against device dropouts */ #define FLAG_FRAMING_GL 0x0002 /* genelink batches packets */#define FLAG_NO_SETINT 0x0010 /* device can't set_interface() */ /* reset device ... can sleep */ int (*reset)(struct usbnet *); /* see if peer is connected ... can sleep */ int (*check_connect)(struct usbnet *); /* fixup rx packet (strip framing) */ int (*rx_fixup)(struct usbnet *dev, struct sk_buff *skb); /* fixup tx packet (add framing) */ struct sk_buff *(*tx_fixup)(struct usbnet *dev, struct sk_buff *skb, int flags); // FIXME -- also an interrupt mechanism // useful for at least PL2301/2302 and GL620USB-A /* framework currently "knows" bulk EPs talk packets */ int in; /* rx endpoint */ int out; /* tx endpoint */ int epsize;};#define EP_SIZE(usbnet) ((usbnet)->driver_info->epsize)// we record the state for each of our queued skbsenum skb_state { illegal = 0, tx_start, tx_done, rx_start, rx_done, rx_cleanup};struct skb_data { // skb->cb is one of these struct urb *urb; struct usbnet *dev; enum skb_state state; size_t length;};static const char driver_name [] = "usbnet";/* use ethtool to change the level for any given device */static int msg_level = 1;MODULE_PARM (msg_level, "i");MODULE_PARM_DESC (msg_level, "Initial message level (default = 1)");#define mutex_lock(x) down(x)#define mutex_unlock(x) up(x)#define RUN_CONTEXT (in_irq () ? "in_irq" \ : (in_interrupt () ? "in_interrupt" : "can sleep"))/*-------------------------------------------------------------------------*/#ifdef DEBUG#define devdbg(usbnet, fmt, arg...) \ printk(KERN_DEBUG "%s: " fmt "\n" , (usbnet)->net.name, ## arg)#else#define devdbg(usbnet, fmt, arg...) do {} while(0)#endif#define devinfo(usbnet, fmt, arg...) \ do { if ((usbnet)->msg_level >= 1) \ printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net.name, ## arg); \ } while (0)#ifdef CONFIG_USB_AN2720/*------------------------------------------------------------------------- * * AnchorChips 2720 driver ... http://www.cypress.com * * This doesn't seem to have a way to detect whether the peer is * connected, or need any reset handshaking. It's got pretty big * internal buffers (handles most of a frame's worth of data). * Chip data sheets don't describe any vendor control messages. * *-------------------------------------------------------------------------*/static const struct driver_info an2720_info = { .description = "AnchorChips/Cypress 2720", // no reset available! // no check_connect available! .in = 2, .out = 2, // direction distinguishes these .epsize =64,};#endif /* CONFIG_USB_AN2720 */#ifdef CONFIG_USB_BELKIN/*------------------------------------------------------------------------- * * Belkin F5U104 ... two NetChip 2280 devices + Atmel microcontroller * * ... also two eTEK designs, including one sold as "Advance USBNET" * *-------------------------------------------------------------------------*/static const struct driver_info belkin_info = { .description = "Belkin, eTEK, or compatible", .in = 1, .out = 1, // direction distinguishes these .epsize =64,};#endif /* CONFIG_USB_BELKIN */#ifdef CONFIG_USB_EPSON2888/*------------------------------------------------------------------------- * * EPSON USB clients * * This is the same idea as "linuxdev" (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. * *-------------------------------------------------------------------------*/static const struct driver_info epson2888_info = { .description = "Epson USB Device", .in = 4, .out = 3, .epsize = 64,};#endif /* CONFIG_USB_EPSON2888 */#ifdef CONFIG_USB_GENESYS/*------------------------------------------------------------------------- * * GeneSys GL620USB-A (www.genesyslogic.com.tw) * * ... should partially interop with the Win32 driver for this hardware * The GeneSys docs imply there's some NDIS issue motivating this framing. * * Some info from GeneSys: * - GL620USB-A is full duplex; GL620USB is only half duplex for bulk. * (Some cables, like the BAFO-100c, use the half duplex version.) * - For the full duplex model, the low bit of the version code says * which side is which ("left/right"). * - For the half duplex type, a control/interrupt handshake settles * the transfer direction. (That's disabled here, partially coded.) * A control URB would block until other side writes an interrupt. * *-------------------------------------------------------------------------*/// control msg write command#define GENELINK_CONNECT_WRITE 0xF0// interrupt pipe index#define GENELINK_INTERRUPT_PIPE 0x03// interrupt read buffer size#define INTERRUPT_BUFSIZE 0x08// interrupt pipe interval value#define GENELINK_INTERRUPT_INTERVAL 0x10// max transmit packet number per transmit#define GL_MAX_TRANSMIT_PACKETS 32// max packet length#define GL_MAX_PACKET_LEN 1514// max receive buffer size #define GL_RCV_BUF_SIZE \ (((GL_MAX_PACKET_LEN + 4) * GL_MAX_TRANSMIT_PACKETS) + 4)struct gl_packet { u32 packet_length; char packet_data [1];};struct gl_header { u32 packet_count; struct gl_packet packets;};#ifdef GENLINK_ACK// FIXME: this code is incomplete, not debugged; it doesn't// handle interrupts correctly. interrupts should be generic// code like all other device I/O, anyway.struct gl_priv { struct urb *irq_urb; char irq_buf [INTERRUPT_BUFSIZE];};static inline int gl_control_write (struct usbnet *dev, u8 request, u16 value){ int retval; retval = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0), request, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, value, 0, // index 0, // data buffer 0, // size CONTROL_TIMEOUT_JIFFIES); return retval;}static void gl_interrupt_complete (struct urb *urb){ int status = urb->status; if (status) dbg ("gl_interrupt_complete fail - %X", status); else dbg ("gl_interrupt_complete success...");}static int gl_interrupt_read (struct usbnet *dev){ struct gl_priv *priv = dev->priv_data; int retval; // issue usb interrupt read if (priv && priv->irq_urb) { // submit urb if ((retval = SUBMIT_URB (priv->irq_urb, GFP_KERNEL)) != 0) dbg ("gl_interrupt_read: submit fail - %X...", retval); else dbg ("gl_interrupt_read: submit success..."); } return 0;}// check whether another side is connectedstatic int genelink_check_connect (struct usbnet *dev){ int retval; dbg ("genelink_check_connect..."); // detect whether another side is connected if ((retval = gl_control_write (dev, GENELINK_CONNECT_WRITE, 0)) != 0) { dbg ("%s: genelink_check_connect write fail - %X", dev->net.name, retval); return retval; } // usb interrupt read to ack another side if ((retval = gl_interrupt_read (dev)) != 0) { dbg ("%s: genelink_check_connect read fail - %X", dev->net.name, retval); return retval; } dbg ("%s: genelink_check_connect read success", dev->net.name); return 0;}// allocate and initialize the private data for genelinkstatic int genelink_init (struct usbnet *dev){ struct gl_priv *priv; // allocate the private data structure if ((priv = kmalloc (sizeof *priv, GFP_KERNEL)) == 0) { dbg ("%s: cannot allocate private data per device", dev->net.name); return -ENOMEM; } // allocate irq urb if ((priv->irq_urb = ALLOC_URB (0, GFP_KERNEL)) == 0) { dbg ("%s: cannot allocate private irq urb per device", dev->net.name); kfree (priv); return -ENOMEM; } // fill irq urb FILL_INT_URB (priv->irq_urb, dev->udev, usb_rcvintpipe (dev->udev, GENELINK_INTERRUPT_PIPE), priv->irq_buf, INTERRUPT_BUFSIZE, gl_interrupt_complete, 0, GENELINK_INTERRUPT_INTERVAL); // set private data pointer dev->priv_data = priv; return 0;}// release the private datastatic int genelink_free (struct usbnet *dev){ struct gl_priv *priv = dev->priv_data; if (!priv) return 0;// FIXME: can't cancel here; it's synchronous, and// should have happened earlier in any case (interrupt// handling needs to be generic) // cancel irq urb first usb_unlink_urb (priv->irq_urb); // free irq urb usb_free_urb (priv->irq_urb); // free the private data structure kfree (priv); return 0;}#endifstatic int genelink_rx_fixup (struct usbnet *dev, struct sk_buff *skb){ struct gl_header *header; struct gl_packet *packet; struct sk_buff *gl_skb; int status; u32 size;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -