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

📄 rndis_host.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Host Side support for RNDIS Networking Links * Copyright (C) 2005 by David Brownell * * 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			// error path messages, extra info// #define	VERBOSE			// more; success messages#include <linux/config.h>#include <linux/module.h>#include <linux/sched.h>#include <linux/init.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/ethtool.h>#include <linux/workqueue.h>#include <linux/mii.h>#include <linux/usb.h>#include <linux/usb_cdc.h>#include "usbnet.h"/* * RNDIS is NDIS remoted over USB.  It's a MSFT variant of CDC ACM ... of * course ACM was intended for modems, not Ethernet links!  USB's standard * for Ethernet links is "CDC Ethernet", which is significantly simpler. *//* * CONTROL uses CDC "encapsulated commands" with funky notifications. *  - control-out:  SEND_ENCAPSULATED *  - interrupt-in:  RESPONSE_AVAILABLE *  - control-in:  GET_ENCAPSULATED * * We'll try to ignore the RESPONSE_AVAILABLE notifications. */struct rndis_msg_hdr {	__le32	msg_type;			/* RNDIS_MSG_* */	__le32	msg_len;	// followed by data that varies between messages	__le32	request_id;	__le32	status;	// ... and more} __attribute__ ((packed));/* RNDIS defines this (absurdly huge) control timeout */#define	RNDIS_CONTROL_TIMEOUT_MS	(10 * 1000)#define ccpu2 __constant_cpu_to_le32#define RNDIS_MSG_COMPLETION	ccpu2(0x80000000)/* codes for "msg_type" field of rndis messages; * only the data channel uses packet messages (maybe batched); * everything else goes on the control channel. */#define RNDIS_MSG_PACKET	ccpu2(0x00000001)	/* 1-N packets */#define RNDIS_MSG_INIT		ccpu2(0x00000002)#define RNDIS_MSG_INIT_C 	(RNDIS_MSG_INIT|RNDIS_MSG_COMPLETION)#define RNDIS_MSG_HALT		ccpu2(0x00000003)#define RNDIS_MSG_QUERY		ccpu2(0x00000004)#define RNDIS_MSG_QUERY_C 	(RNDIS_MSG_QUERY|RNDIS_MSG_COMPLETION)#define RNDIS_MSG_SET		ccpu2(0x00000005)#define RNDIS_MSG_SET_C 	(RNDIS_MSG_SET|RNDIS_MSG_COMPLETION)#define RNDIS_MSG_RESET		ccpu2(0x00000006)#define RNDIS_MSG_RESET_C 	(RNDIS_MSG_RESET|RNDIS_MSG_COMPLETION)#define RNDIS_MSG_INDICATE	ccpu2(0x00000007)#define RNDIS_MSG_KEEPALIVE	ccpu2(0x00000008)#define RNDIS_MSG_KEEPALIVE_C 	(RNDIS_MSG_KEEPALIVE|RNDIS_MSG_COMPLETION)/* codes for "status" field of completion messages */#define	RNDIS_STATUS_SUCCESS		ccpu2(0x00000000)#define	RNDIS_STATUS_FAILURE		ccpu2(0xc0000001)#define	RNDIS_STATUS_INVALID_DATA	ccpu2(0xc0010015)#define	RNDIS_STATUS_NOT_SUPPORTED	ccpu2(0xc00000bb)#define	RNDIS_STATUS_MEDIA_CONNECT	ccpu2(0x4001000b)#define	RNDIS_STATUS_MEDIA_DISCONNECT	ccpu2(0x4001000c)struct rndis_data_hdr {	__le32	msg_type;		/* RNDIS_MSG_PACKET */	__le32	msg_len;		// rndis_data_hdr + data_len + pad	__le32	data_offset;		// 36 -- right after header	__le32	data_len;		// ... real packet size	__le32	oob_data_offset;	// zero	__le32	oob_data_len;		// zero	__le32	num_oob;		// zero	__le32	packet_data_offset;	// zero	__le32	packet_data_len;	// zero	__le32	vc_handle;		// zero	__le32	reserved;		// zero} __attribute__ ((packed));struct rndis_init {		/* OUT */	// header and:	__le32	msg_type;			/* RNDIS_MSG_INIT */	__le32	msg_len;			// 24	__le32	request_id;	__le32	major_version;			// of rndis (1.0)	__le32	minor_version;	__le32	max_transfer_size;} __attribute__ ((packed));struct rndis_init_c {		/* IN */	// header and:	__le32	msg_type;			/* RNDIS_MSG_INIT_C */	__le32	msg_len;	__le32	request_id;	__le32	status;	__le32	major_version;			// of rndis (1.0)	__le32	minor_version;	__le32	device_flags;	__le32	medium;				// zero == 802.3	__le32	max_packets_per_message;	__le32	max_transfer_size;	__le32	packet_alignment;		// max 7; (1<<n) bytes	__le32	af_list_offset;			// zero	__le32	af_list_size;			// zero} __attribute__ ((packed));struct rndis_halt {		/* OUT (no reply) */	// header and:	__le32	msg_type;			/* RNDIS_MSG_HALT */	__le32	msg_len;	__le32	request_id;} __attribute__ ((packed));struct rndis_query {		/* OUT */	// header and:	__le32	msg_type;			/* RNDIS_MSG_QUERY */	__le32	msg_len;	__le32	request_id;	__le32	oid;	__le32	len;	__le32	offset;/*?*/	__le32	handle;				// zero} __attribute__ ((packed));struct rndis_query_c {		/* IN */	// header and:	__le32	msg_type;			/* RNDIS_MSG_QUERY_C */	__le32	msg_len;	__le32	request_id;	__le32	status;	__le32	len;	__le32	offset;} __attribute__ ((packed));struct rndis_set {		/* OUT */	// header and:	__le32	msg_type;			/* RNDIS_MSG_SET */	__le32	msg_len;	__le32	request_id;	__le32	oid;	__le32	len;	__le32	offset;/*?*/	__le32	handle;				// zero} __attribute__ ((packed));struct rndis_set_c {		/* IN */	// header and:	__le32	msg_type;			/* RNDIS_MSG_SET_C */	__le32	msg_len;	__le32	request_id;	__le32	status;} __attribute__ ((packed));struct rndis_reset {		/* IN */	// header and:	__le32	msg_type;			/* RNDIS_MSG_RESET */	__le32	msg_len;	__le32	reserved;} __attribute__ ((packed));struct rndis_reset_c {		/* OUT */	// header and:	__le32	msg_type;			/* RNDIS_MSG_RESET_C */	__le32	msg_len;	__le32	status;	__le32	addressing_lost;} __attribute__ ((packed));struct rndis_indicate {		/* IN (unrequested) */	// header and:	__le32	msg_type;			/* RNDIS_MSG_INDICATE */	__le32	msg_len;	__le32	status;	__le32	length;	__le32	offset;/**/	__le32	diag_status;	__le32	error_offset;/**/	__le32	message;} __attribute__ ((packed));struct rndis_keepalive {	/* OUT (optionally IN) */	// header and:	__le32	msg_type;			/* RNDIS_MSG_KEEPALIVE */	__le32	msg_len;	__le32	request_id;} __attribute__ ((packed));struct rndis_keepalive_c {	/* IN (optionally OUT) */	// header and:	__le32	msg_type;			/* RNDIS_MSG_KEEPALIVE_C */	__le32	msg_len;	__le32	request_id;	__le32	status;} __attribute__ ((packed));/* NOTE:  about 30 OIDs are "mandatory" for peripherals to support ... and * there are gobs more that may optionally be supported.  We'll avoid as much * of that mess as possible. */#define OID_802_3_PERMANENT_ADDRESS	ccpu2(0x01010101)#define OID_GEN_CURRENT_PACKET_FILTER	ccpu2(0x0001010e)/* * RNDIS notifications from device: command completion; "reverse" * keepalives; etc */static void rndis_status(struct usbnet *dev, struct urb *urb){	devdbg(dev, "rndis status urb, len %d stat %d",		urb->actual_length, urb->status);	// FIXME for keepalives, respond immediately (asynchronously)	// if not an RNDIS status, do like cdc_status(dev,urb) does}/* * RPC done RNDIS-style.  Caller guarantees: * - message is properly byteswapped * - there's no other request pending * - buf can hold up to 1KB response (required by RNDIS spec) * On return, the first few entries are already byteswapped. * * Call context is likely probe(), before interface name is known, * which is why we won't try to use it in the diagnostics. */static int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf){	struct cdc_state	*info = (void *) &dev->data;	int			retval;	unsigned		count;	__le32			rsp;	u32			xid = 0, msg_len, request_id;	/* REVISIT when this gets called from contexts other than probe() or	 * disconnect(): either serialize, or dispatch responses on xid	 */	/* Issue the request; don't bother byteswapping our xid */	if (likely(buf->msg_type != RNDIS_MSG_HALT			&& buf->msg_type != RNDIS_MSG_RESET)) {		xid = dev->xid++;		if (!xid)			xid = dev->xid++;		buf->request_id = (__force __le32) xid;	}	retval = usb_control_msg(dev->udev,		usb_sndctrlpipe(dev->udev, 0),		USB_CDC_SEND_ENCAPSULATED_COMMAND,		USB_TYPE_CLASS | USB_RECIP_INTERFACE,		0, info->u->bMasterInterface0,		buf, le32_to_cpu(buf->msg_len),		RNDIS_CONTROL_TIMEOUT_MS);	if (unlikely(retval < 0 || xid == 0))		return retval;	// FIXME Seems like some devices discard responses when	// we time out and cancel our "get response" requests...	// so, this is fragile.  Probably need to poll for status.	/* ignore status endpoint, just poll the control channel;	 * the request probably completed immediately	 */	rsp = buf->msg_type | RNDIS_MSG_COMPLETION;	for (count = 0; count < 10; count++) {		memset(buf, 0, 1024);		retval = usb_control_msg(dev->udev,			usb_rcvctrlpipe(dev->udev, 0),			USB_CDC_GET_ENCAPSULATED_RESPONSE,			USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,			0, info->u->bMasterInterface0,			buf, 1024,			RNDIS_CONTROL_TIMEOUT_MS);		if (likely(retval >= 8)) {			msg_len = le32_to_cpu(buf->msg_len);			request_id = (__force u32) buf->request_id;			if (likely(buf->msg_type == rsp)) {

⌨️ 快捷键说明

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