⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ether.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * ether.c -- Ethernet gadget driver, with CDC and non-CDC options * * Copyright (C) 2003-2005 David Brownell * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger * * 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 */// #define DEBUG 1// #define VERBOSE#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/ioport.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/smp_lock.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/timer.h>#include <linux/list.h>#include <linux/interrupt.h>#include <linux/utsname.h>#include <linux/device.h>#include <linux/moduleparam.h>#include <linux/ctype.h>#include <asm/byteorder.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/system.h>#include <asm/uaccess.h>#include <asm/unaligned.h>#include <linux/usb_ch9.h>#include <linux/usb_cdc.h>#include <linux/usb_gadget.h>#include <linux/random.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/ethtool.h>#include "gadget_chips.h"/*-------------------------------------------------------------------------*//* * Ethernet gadget driver -- with CDC and non-CDC options * Builds on hardware support for a full duplex link. * * CDC Ethernet is the standard USB solution for sending Ethernet frames * using USB.  Real hardware tends to use the same framing protocol but look * different for control features.  This driver strongly prefers to use * this USB-IF standard as its open-systems interoperability solution; * most host side USB stacks (except from Microsoft) support it. * * There's some hardware that can't talk CDC.  We make that hardware * implement a "minimalist" vendor-agnostic CDC core:  same framing, but * link-level setup only requires activating the configuration. * Linux supports it, but other host operating systems may not. * (This is a subset of CDC Ethernet.) * * A third option is also in use.  Rather than CDC Ethernet, or something * simpler, Microsoft pushes their own approach: RNDIS.  The published * RNDIS specs are ambiguous and appear to be incomplete, and are also * needlessly complex. */#define DRIVER_DESC		"Ethernet Gadget"#define DRIVER_VERSION		"May Day 2005"static const char shortname [] = "ether";static const char driver_desc [] = DRIVER_DESC;#define RX_EXTRA	20		/* guard against rx overflows */#include "rndis.h"#ifndef	CONFIG_USB_ETH_RNDIS#define rndis_uninit(x)		do{}while(0)#define rndis_deregister(c)	do{}while(0)#define rndis_exit()		do{}while(0)#endif/* CDC and RNDIS support the same host-chosen outgoing packet filters. */#define	DEFAULT_FILTER	(USB_CDC_PACKET_TYPE_BROADCAST \ 			|USB_CDC_PACKET_TYPE_ALL_MULTICAST \ 			|USB_CDC_PACKET_TYPE_PROMISCUOUS \ 			|USB_CDC_PACKET_TYPE_DIRECTED)/*-------------------------------------------------------------------------*/struct eth_dev {	spinlock_t		lock;	struct usb_gadget	*gadget;	struct usb_request	*req;		/* for control responses */	struct usb_request	*stat_req;	/* for cdc & rndis status */	u8			config;	struct usb_ep		*in_ep, *out_ep, *status_ep;	const struct usb_endpoint_descriptor				*in, *out, *status;	struct list_head	tx_reqs, rx_reqs;	struct net_device	*net;	struct net_device_stats	stats;	atomic_t		tx_qlen;	struct work_struct	work;	unsigned		zlp:1;	unsigned		cdc:1;	unsigned		rndis:1;	unsigned		suspended:1;	u16			cdc_filter;	unsigned long		todo;#define	WORK_RX_MEMORY		0	int			rndis_config;	u8			host_mac [ETH_ALEN];};/* This version autoconfigures as much as possible at run-time. * * It also ASSUMES a self-powered device, without remote wakeup, * although remote wakeup support would make sense. *//*-------------------------------------------------------------------------*//* DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!! * Instead:  allocate your own, using normal USB-IF procedures. *//* Thanks to NetChip Technologies for donating this product ID. * It's for devices with only CDC Ethernet configurations. */#define CDC_VENDOR_NUM	0x0525		/* NetChip */#define CDC_PRODUCT_NUM	0xa4a1		/* Linux-USB Ethernet Gadget *//* For hardware that can't talk CDC, we use the same vendor ID that * ARM Linux has used for ethernet-over-usb, both with sa1100 and * with pxa250.  We're protocol-compatible, if the host-side drivers * use the endpoint descriptors.  bcdDevice (version) is nonzero, so * drivers that need to hard-wire endpoint numbers have a hook. * * The protocol is a minimal subset of CDC Ether, which works on any bulk * hardware that's not deeply broken ... even on hardware that can't talk * RNDIS (like SA-1100, with no interrupt endpoint, or anything that * doesn't handle control-OUT). */#define	SIMPLE_VENDOR_NUM	0x049f#define	SIMPLE_PRODUCT_NUM	0x505a/* For hardware that can talk RNDIS and either of the above protocols, * use this ID ... the windows INF files will know it.  Unless it's * used with CDC Ethernet, Linux 2.4 hosts will need updates to choose * the non-RNDIS configuration. */#define RNDIS_VENDOR_NUM	0x0525	/* NetChip */#define RNDIS_PRODUCT_NUM	0xa4a2	/* Ethernet/RNDIS Gadget *//* Some systems will want different product identifers published in the * device descriptor, either numbers or strings or both.  These string * parameters are in UTF-8 (superset of ASCII's 7 bit characters). */static ushort __initdata idVendor;module_param(idVendor, ushort, S_IRUGO);MODULE_PARM_DESC(idVendor, "USB Vendor ID");static ushort __initdata idProduct;module_param(idProduct, ushort, S_IRUGO);MODULE_PARM_DESC(idProduct, "USB Product ID");static ushort __initdata bcdDevice;module_param(bcdDevice, ushort, S_IRUGO);MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");static char *__initdata iManufacturer;module_param(iManufacturer, charp, S_IRUGO);MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");static char *__initdata iProduct;module_param(iProduct, charp, S_IRUGO);MODULE_PARM_DESC(iProduct, "USB Product string");/* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */static char *__initdata dev_addr;module_param(dev_addr, charp, S_IRUGO);MODULE_PARM_DESC(dev_addr, "Device Ethernet Address");/* this address is invisible to ifconfig */static char *__initdata host_addr;module_param(host_addr, charp, S_IRUGO);MODULE_PARM_DESC(host_addr, "Host Ethernet Address");/*-------------------------------------------------------------------------*//* Include CDC support if we could run on CDC-capable hardware. */#ifdef CONFIG_USB_GADGET_NET2280#define	DEV_CONFIG_CDC#endif#ifdef CONFIG_USB_GADGET_DUMMY_HCD#define	DEV_CONFIG_CDC#endif#ifdef CONFIG_USB_GADGET_GOKU#define	DEV_CONFIG_CDC#endif#ifdef CONFIG_USB_GADGET_LH7A40X#define DEV_CONFIG_CDC#endif#ifdef CONFIG_USB_GADGET_MQ11XX#define	DEV_CONFIG_CDC#endif#ifdef CONFIG_USB_GADGET_OMAP#define	DEV_CONFIG_CDC#endif#ifdef CONFIG_USB_GADGET_N9604#define	DEV_CONFIG_CDC#endif#ifdef CONFIG_USB_GADGET_PXA27X#define DEV_CONFIG_CDC#endif#ifdef CONFIG_USB_GADGET_AT91#define DEV_CONFIG_CDC#endif/* For CDC-incapable hardware, choose the simple cdc subset. * Anything that talks bulk (without notable bugs) can do this. */#ifdef CONFIG_USB_GADGET_PXA2XX#define	DEV_CONFIG_SUBSET#endif#ifdef CONFIG_USB_GADGET_SH#define	DEV_CONFIG_SUBSET#endif#ifdef CONFIG_USB_GADGET_SA1100/* use non-CDC for backwards compatibility */#define	DEV_CONFIG_SUBSET#endif#ifdef CONFIG_USB_GADGET_S3C2410#define DEV_CONFIG_CDC#endif/*-------------------------------------------------------------------------*//* "main" config is either CDC, or its simple subset */static inline int is_cdc(struct eth_dev *dev){#if	!defined(DEV_CONFIG_SUBSET)	return 1;		/* only cdc possible */#elif	!defined (DEV_CONFIG_CDC)	return 0;		/* only subset possible */#else	return dev->cdc;	/* depends on what hardware we found */#endif}/* "secondary" RNDIS config may sometimes be activated */static inline int rndis_active(struct eth_dev *dev){#ifdef	CONFIG_USB_ETH_RNDIS	return dev->rndis;#else	return 0;#endif}#define	subset_active(dev)	(!is_cdc(dev) && !rndis_active(dev))#define	cdc_active(dev)		( is_cdc(dev) && !rndis_active(dev))#define DEFAULT_QLEN	2	/* double buffering by default *//* peak bulk transfer bits-per-second */#define	HS_BPS 		(13 * 512 * 8 * 1000 * 8)#define	FS_BPS		(19 *  64 * 1 * 1000 * 8)#ifdef CONFIG_USB_GADGET_DUALSPEED#define	DEVSPEED	USB_SPEED_HIGHstatic unsigned qmult = 5;module_param (qmult, uint, S_IRUGO|S_IWUSR);/* for dual-speed hardware, use deeper queues at highspeed */#define qlen(gadget) \	(DEFAULT_QLEN*((gadget->speed == USB_SPEED_HIGH) ? qmult : 1))/* also defer IRQs on highspeed TX */#define TX_DELAY	qmultstatic inline int BITRATE(struct usb_gadget *g){	return (g->speed == USB_SPEED_HIGH) ? HS_BPS : FS_BPS;}#else	/* full speed (low speed doesn't do bulk) */#define	DEVSPEED	USB_SPEED_FULL#define qlen(gadget) DEFAULT_QLENstatic inline int BITRATE(struct usb_gadget *g){	return FS_BPS;}#endif/*-------------------------------------------------------------------------*/#define xprintk(d,level,fmt,args...) \	printk(level "%s: " fmt , (d)->net->name , ## args)#ifdef DEBUG#undef DEBUG#define DEBUG(dev,fmt,args...) \	xprintk(dev , KERN_DEBUG , fmt , ## args)#else#define DEBUG(dev,fmt,args...) \	do { } while (0)#endif /* DEBUG */#ifdef VERBOSE#define VDEBUG	DEBUG#else#define VDEBUG(dev,fmt,args...) \	do { } while (0)#endif /* DEBUG */#define ERROR(dev,fmt,args...) \	xprintk(dev , KERN_ERR , fmt , ## args)#define WARN(dev,fmt,args...) \	xprintk(dev , KERN_WARNING , fmt , ## args)#define INFO(dev,fmt,args...) \	xprintk(dev , KERN_INFO , fmt , ## args)/*-------------------------------------------------------------------------*//* USB DRIVER HOOKUP (to the hardware driver, below us), mostly * ep0 implementation:  descriptors, config management, setup(). * also optional class-specific notification interrupt transfer. *//* * DESCRIPTORS ... most are static, but strings and (full) configuration * descriptors are built on demand.  For now we do either full CDC, or * our simple subset, with RNDIS as an optional second configuration. * * RNDIS includes some CDC ACM descriptors ... like CDC Ethernet.  But * the class descriptors match a modem (they're ignored; it's really just * Ethernet functionality), they don't need the NOP altsetting, and the * status transfer endpoint isn't optional. */#define STRING_MANUFACTURER		1#define STRING_PRODUCT			2#define STRING_ETHADDR			3#define STRING_DATA			4#define STRING_CONTROL			5#define STRING_RNDIS_CONTROL		6#define STRING_CDC			7#define STRING_SUBSET			8#define STRING_RNDIS			9/* holds our biggest descriptor (or RNDIS response) */#define USB_BUFSIZ	256/* * This device advertises one configuration, eth_config, unless RNDIS * is enabled (rndis_config) on hardware supporting at least two configs. * * NOTE:  Controllers like superh_udc should probably be able to use * an RNDIS-only configuration. * * FIXME define some higher-powered configurations to make it easier * to recharge batteries ... */#define DEV_CONFIG_VALUE	1	/* cdc or subset */#define DEV_RNDIS_CONFIG_VALUE	2	/* rndis; optional */static struct usb_device_descriptordevice_desc = {	.bLength =		sizeof device_desc,	.bDescriptorType =	USB_DT_DEVICE,	.bcdUSB =		__constant_cpu_to_le16 (0x0200),	.bDeviceClass =		USB_CLASS_COMM,	.bDeviceSubClass =	0,	.bDeviceProtocol =	0,	.idVendor =		__constant_cpu_to_le16 (CDC_VENDOR_NUM),	.idProduct =		__constant_cpu_to_le16 (CDC_PRODUCT_NUM),	.iManufacturer =	STRING_MANUFACTURER,	.iProduct =		STRING_PRODUCT,	.bNumConfigurations =	1,};static struct usb_otg_descriptorotg_descriptor = {	.bLength =		sizeof otg_descriptor,	.bDescriptorType =	USB_DT_OTG,	.bmAttributes =		USB_OTG_SRP,};static struct usb_config_descriptoreth_config = {	.bLength =		sizeof eth_config,	.bDescriptorType =	USB_DT_CONFIG,	/* compute wTotalLength on the fly */	.bNumInterfaces =	2,	.bConfigurationValue =	DEV_CONFIG_VALUE,	.iConfiguration =	STRING_CDC,	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,	.bMaxPower =		50,};#ifdef	CONFIG_USB_ETH_RNDISstatic struct usb_config_descriptor rndis_config = {	.bLength =              sizeof rndis_config,	.bDescriptorType =      USB_DT_CONFIG,	/* compute wTotalLength on the fly */	.bNumInterfaces =       2,	.bConfigurationValue =  DEV_RNDIS_CONFIG_VALUE,	.iConfiguration =       STRING_RNDIS,	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,	.bMaxPower =            50,};#endif/* * Compared to the simple CDC subset, the full CDC Ethernet model adds * three class descriptors, two interface descriptors, optional status * endpoint.  Both have a "data" interface and two bulk endpoints. * There are also differences in how control requests are handled. * * RNDIS shares a lot with CDC-Ethernet, since it's a variant of * the CDC-ACM (modem) spec. */#ifdef	DEV_CONFIG_CDCstatic struct usb_interface_descriptorcontrol_intf = {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -