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

📄 rndis.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 3 页
字号:
	case OID_GEN_DIRECTED_BYTES_RCV:		DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__);		*outbuf = __constant_cpu_to_le32 (0);		retval = 0;		break;			case OID_GEN_DIRECTED_FRAMES_RCV:		DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__);		*outbuf = __constant_cpu_to_le32 (0);		retval = 0;		break;			case OID_GEN_MULTICAST_BYTES_RCV:		DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__);		if (rndis_per_dev_params [configNr].stats) {			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]					.stats->multicast * 1111);			retval = 0;		}		break;			case OID_GEN_MULTICAST_FRAMES_RCV:		DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__);		if (rndis_per_dev_params [configNr].stats) {			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]					.stats->multicast);			retval = 0;		}		break;			case OID_GEN_BROADCAST_BYTES_RCV:		DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__);		if (rndis_per_dev_params [configNr].stats) {			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]					.stats->rx_packets/42*255);			retval = 0;		}		break;			case OID_GEN_BROADCAST_FRAMES_RCV:		DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__);		if (rndis_per_dev_params [configNr].stats) {			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]					.stats->rx_packets/42);			retval = 0;		}		break;			case OID_GEN_RCV_CRC_ERROR:		DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__);		if (rndis_per_dev_params [configNr].stats) {			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]					.stats->rx_crc_errors);			retval = 0;		}		break;			case OID_GEN_TRANSMIT_QUEUE_LENGTH:		DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__);		*outbuf = __constant_cpu_to_le32 (0);		retval = 0;		break;#endif	/* RNDIS_OPTIONAL_STATS */	/* ieee802.3 OIDs (table 4-3) */	/* mandatory */	case OID_802_3_PERMANENT_ADDRESS:		DEBUG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__);		if (rndis_per_dev_params [configNr].dev) {			length = ETH_ALEN;			memcpy (outbuf,				rndis_per_dev_params [configNr].host_mac,				length);			retval = 0;		}		break;			/* mandatory */	case OID_802_3_CURRENT_ADDRESS:		DEBUG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__);		if (rndis_per_dev_params [configNr].dev) {			length = ETH_ALEN;			memcpy (outbuf,				rndis_per_dev_params [configNr].host_mac,				length);			retval = 0;		}		break;			/* mandatory */	case OID_802_3_MULTICAST_LIST:		DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);		/* Multicast base address only */		*outbuf = __constant_cpu_to_le32 (0xE0000000);		retval = 0;		break;			/* mandatory */	case OID_802_3_MAXIMUM_LIST_SIZE:		DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__);		/* Multicast base address only */		*outbuf = __constant_cpu_to_le32 (1);		retval = 0;		break;			case OID_802_3_MAC_OPTIONS:		DEBUG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__);		break;	/* ieee802.3 statistics OIDs (table 4-4) */	/* mandatory */	case OID_802_3_RCV_ERROR_ALIGNMENT:		DEBUG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__);		if (rndis_per_dev_params [configNr].stats) {			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]					.stats->rx_frame_errors);			retval = 0;		}		break;			/* mandatory */	case OID_802_3_XMIT_ONE_COLLISION:		DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__);		*outbuf = __constant_cpu_to_le32 (0);		retval = 0;		break;			/* mandatory */	case OID_802_3_XMIT_MORE_COLLISIONS:		DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__);		*outbuf = __constant_cpu_to_le32 (0);		retval = 0;		break;		#ifdef	RNDIS_OPTIONAL_STATS	case OID_802_3_XMIT_DEFERRED:		DEBUG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__);		/* TODO */		break;			case OID_802_3_XMIT_MAX_COLLISIONS:		DEBUG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__);		/* TODO */		break;			case OID_802_3_RCV_OVERRUN:		DEBUG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__);		/* TODO */		break;			case OID_802_3_XMIT_UNDERRUN:		DEBUG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__);		/* TODO */		break;			case OID_802_3_XMIT_HEARTBEAT_FAILURE:		DEBUG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__);		/* TODO */		break;			case OID_802_3_XMIT_TIMES_CRS_LOST:		DEBUG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__);		/* TODO */		break;			case OID_802_3_XMIT_LATE_COLLISIONS:		DEBUG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__);		/* TODO */		break;		#endif	/* RNDIS_OPTIONAL_STATS */#ifdef	RNDIS_PM	/* power management OIDs (table 4-5) */	case OID_PNP_CAPABILITIES:		DEBUG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__);		/* for now, no wakeup capabilities */		length = sizeof (struct NDIS_PNP_CAPABILITIES);		memset(outbuf, 0, length);		retval = 0;		break;	case OID_PNP_QUERY_POWER:		DEBUG("%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__,				le32_to_cpup((__le32 *) buf) - 1);		/* only suspend is a real power state, and		 * it can't be entered by OID_PNP_SET_POWER...		 */		length = 0;		retval = 0;		break;#endif	default:		printk (KERN_WARNING "%s: query unknown OID 0x%08X\n", 			 __FUNCTION__, OID);	}	if (retval < 0)		length = 0;		resp->InformationBufferLength = cpu_to_le32 (length);	r->length = length + sizeof *resp;	resp->MessageLength = cpu_to_le32 (r->length);	return retval;}static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, 			      rndis_resp_t *r){	rndis_set_cmplt_type		*resp;	int 				i, retval = -ENOTSUPP;	struct rndis_params		*params;	if (!r)		return -ENOMEM;	resp = (rndis_set_cmplt_type *) r->buf;	if (!resp)		return -ENOMEM;	if (buf_len && rndis_debug > 1) {		DEBUG("set OID %08x value, len %d:\n", OID, buf_len);		for (i = 0; i < buf_len; i += 16) {			DEBUG ("%03d: %08x %08x %08x %08x\n", i,				le32_to_cpup((__le32 *)&buf[i]),				le32_to_cpup((__le32 *)&buf[i + 4]),				le32_to_cpup((__le32 *)&buf[i + 8]),				le32_to_cpup((__le32 *)&buf[i + 12]));		}	}	params = &rndis_per_dev_params [configNr];	switch (OID) {	case OID_GEN_CURRENT_PACKET_FILTER:		/* these NDIS_PACKET_TYPE_* bitflags are shared with		 * cdc_filter; it's not RNDIS-specific		 * NDIS_PACKET_TYPE_x == USB_CDC_PACKET_TYPE_x for x in:		 *	PROMISCUOUS, DIRECTED,		 *	MULTICAST, ALL_MULTICAST, BROADCAST		 */		*params->filter = (u16) le32_to_cpup((__le32 *)buf);		DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",			__FUNCTION__, *params->filter);		/* this call has a significant side effect:  it's		 * what makes the packet flow start and stop, like		 * activating the CDC Ethernet altsetting.		 */#ifdef	RNDIS_PMupdate_linkstate:#endif		retval = 0;		if (*params->filter) {			params->state = RNDIS_DATA_INITIALIZED;			netif_carrier_on(params->dev);			if (netif_running(params->dev))				netif_wake_queue (params->dev);		} else {			params->state = RNDIS_INITIALIZED;			netif_carrier_off (params->dev);			netif_stop_queue (params->dev);		}		break;			case OID_802_3_MULTICAST_LIST:		/* I think we can ignore this */				DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);		retval = 0;		break;#if 0	case OID_GEN_RNDIS_CONFIG_PARAMETER:		{		struct rndis_config_parameter	*param;		param = (struct rndis_config_parameter *) buf;		DEBUG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n",			__FUNCTION__,			min(cpu_to_le32(param->ParameterNameLength),80),			buf + param->ParameterNameOffset);		retval = 0;		}		break;#endif#ifdef	RNDIS_PM	case OID_PNP_SET_POWER:		/* The only real power state is USB suspend, and RNDIS requests		 * can't enter it; this one isn't really about power.  After		 * resuming, Windows forces a reset, and then SET_POWER D0.		 * FIXME ... then things go batty; Windows wedges itself.		 */		i = le32_to_cpup((__force __le32 *)buf);		DEBUG("%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1);		switch (i) {		case NdisDeviceStateD0:			*params->filter = params->saved_filter;			goto update_linkstate;		case NdisDeviceStateD3:		case NdisDeviceStateD2:		case NdisDeviceStateD1:			params->saved_filter = *params->filter;			retval = 0;			break;		}		break;#ifdef	RNDIS_WAKEUP	// no wakeup support advertised, so wakeup OIDs always fail:	//  - OID_PNP_ENABLE_WAKE_UP	//  - OID_PNP_{ADD,REMOVE}_WAKE_UP_PATTERN#endif#endif	/* RNDIS_PM */	default:		printk (KERN_WARNING "%s: set unknown OID 0x%08X, size %d\n", 			 __FUNCTION__, OID, buf_len);	}		return retval;}/*  * Response Functions  */static int rndis_init_response (int configNr, rndis_init_msg_type *buf){	rndis_init_cmplt_type	*resp; 	rndis_resp_t            *r;		if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;		r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type));	if (!r)		return -ENOMEM;	resp = (rndis_init_cmplt_type *) r->buf;		resp->MessageType = __constant_cpu_to_le32 (			REMOTE_NDIS_INITIALIZE_CMPLT);	resp->MessageLength = __constant_cpu_to_le32 (52);	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */	resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);	resp->MajorVersion = __constant_cpu_to_le32 (RNDIS_MAJOR_VERSION);	resp->MinorVersion = __constant_cpu_to_le32 (RNDIS_MINOR_VERSION);	resp->DeviceFlags = __constant_cpu_to_le32 (RNDIS_DF_CONNECTIONLESS);	resp->Medium = __constant_cpu_to_le32 (RNDIS_MEDIUM_802_3);	resp->MaxPacketsPerTransfer = __constant_cpu_to_le32 (1);	resp->MaxTransferSize = cpu_to_le32 (		  rndis_per_dev_params [configNr].dev->mtu		+ sizeof (struct ethhdr)		+ sizeof (struct rndis_packet_msg_type)		+ 22);	resp->PacketAlignmentFactor = __constant_cpu_to_le32 (0);	resp->AFListOffset = __constant_cpu_to_le32 (0);	resp->AFListSize = __constant_cpu_to_le32 (0);		if (rndis_per_dev_params [configNr].ack)	    rndis_per_dev_params [configNr].ack (	    		rndis_per_dev_params [configNr].dev);		return 0;}static int rndis_query_response (int configNr, rndis_query_msg_type *buf){	rndis_query_cmplt_type *resp;	rndis_resp_t            *r;		// DEBUG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID));	if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;		/* 	 * we need more memory: 	 * oid_supported_list is the largest answer 	 */	r = rndis_add_response (configNr, sizeof (oid_supported_list));	if (!r)		return -ENOMEM;	resp = (rndis_query_cmplt_type *) r->buf;		resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_QUERY_CMPLT);	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */  		if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID),			le32_to_cpu(buf->InformationBufferOffset)					+ 8 + (u8 *) buf,			le32_to_cpu(buf->InformationBufferLength),			r)) {		/* OID not supported */		resp->Status = __constant_cpu_to_le32 (				RNDIS_STATUS_NOT_SUPPORTED);		resp->MessageLength = __constant_cpu_to_le32 (sizeof *resp);		resp->InformationBufferLength = __constant_cpu_to_le32 (0);		resp->InformationBufferOffset = __constant_cpu_to_le32 (0);	} else		resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);		if (rndis_per_dev_params [configNr].ack)	    rndis_per_dev_params [configNr].ack (	    		rndis_per_dev_params [configNr].dev);	return 0;}static int rndis_set_response (int configNr, rndis_set_msg_type *buf){	u32			BufLength, BufOffset;	rndis_set_cmplt_type	*resp;	rndis_resp_t		*r;		r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type));	if (!r)		return -ENOMEM;	resp = (rndis_set_cmplt_type *) r->buf;	BufLength = le32_to_cpu (buf->InformationBufferLength);	BufOffset = le32_to_cpu (buf->InformationBufferOffset);#ifdef	VERBOSE	DEBUG("%s: Length: %d\n", __FUNCTION__, BufLength);	DEBUG("%s: Offset: %d\n", __FUNCTION__, BufOffset);	DEBUG("%s: InfoBuffer: ", __FUNCTION__);		for (i = 0; i < BufLength; i++) {		DEBUG ("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));	}		DEBUG ("\n");#endif		resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT);	resp->MessageLength = __constant_cpu_to_le32 (16);	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */	if (gen_ndis_set_resp (configNr, le32_to_cpu (buf->OID), 			       ((u8 *) buf) + 8 + BufOffset, BufLength, r))	    resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED);	else resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);		if (rndis_per_dev_params [configNr].ack)	    rndis_per_dev_params [configNr].ack (	    		rndis_per_dev_params [configNr].dev);		return 0;}static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf){	rndis_reset_cmplt_type	*resp;	rndis_resp_t		*r;		r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type));	if (!r)		return -ENOMEM;	resp = (rndis_reset_cmplt_type *) r->buf;		resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_RESET_CMPLT);	resp->MessageLength = __constant_cpu_to_le32 (16);	resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);	/* resent information */	resp->AddressingReset = __constant_cpu_to_le32 (1);		if (rndis_per_dev_params [configNr].ack)	    rndis_per_dev_params [configNr].ack (	    		rndis_per_dev_params [configNr].dev);	return 0;}static int rndis_keepalive_response (int configNr,				     rndis_keepalive_msg_type *buf){	rndis_keepalive_cmplt_type	*resp;	rndis_resp_t			*r;	/* host "should" check only in RNDIS_DATA_INITIALIZED state */	r = rndis_add_response (configNr, sizeof (rndis_keepalive_cmplt_type));	if (!r)		return -ENOMEM;	resp = (rndis_keepalive_cmplt_type *) r->buf;			resp->MessageType = __constant_cpu_to_le32 (			REMOTE_NDIS_KEEPALIVE_CMPLT);	resp->MessageLength = __constant_cpu_to_le32 (16);

⌨️ 快捷键说明

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