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

📄 rndis.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 3 页
字号:
	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */	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;}/*  * Device to Host Comunication  */static int rndis_indicate_status_msg (int configNr, u32 status){	rndis_indicate_status_msg_type	*resp;		rndis_resp_t			*r;		if (rndis_per_dev_params [configNr].state == RNDIS_UNINITIALIZED)	    return -ENOTSUPP;		r = rndis_add_response (configNr, 				sizeof (rndis_indicate_status_msg_type));	if (!r)		return -ENOMEM;	resp = (rndis_indicate_status_msg_type *) r->buf;		resp->MessageType = __constant_cpu_to_le32 (			REMOTE_NDIS_INDICATE_STATUS_MSG);	resp->MessageLength = __constant_cpu_to_le32 (20);	resp->Status = cpu_to_le32 (status);	resp->StatusBufferLength = __constant_cpu_to_le32 (0);	resp->StatusBufferOffset = __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;}int rndis_signal_connect (int configNr){	rndis_per_dev_params [configNr].media_state			= NDIS_MEDIA_STATE_CONNECTED;	return rndis_indicate_status_msg (configNr, 					  RNDIS_STATUS_MEDIA_CONNECT);}int rndis_signal_disconnect (int configNr){	rndis_per_dev_params [configNr].media_state			= NDIS_MEDIA_STATE_DISCONNECTED;	return rndis_indicate_status_msg (configNr,					  RNDIS_STATUS_MEDIA_DISCONNECT);}void rndis_uninit (int configNr){	u8 *buf;	u32 length;	if (configNr >= RNDIS_MAX_CONFIGS)		return;	rndis_per_dev_params [configNr].used = 0;	rndis_per_dev_params [configNr].state = RNDIS_UNINITIALIZED;	/* drain the response queue */	while ((buf = rndis_get_next_response(configNr, &length)))		rndis_free_response(configNr, buf);}void rndis_set_host_mac (int configNr, const u8 *addr){	rndis_per_dev_params [configNr].host_mac = addr;}/*  * Message Parser  */int rndis_msg_parser (u8 configNr, u8 *buf){	u32 MsgType, MsgLength;	__le32 *tmp;	struct rndis_params		*params;		if (!buf)		return -ENOMEM;		tmp = (__le32 *) buf; 	MsgType   = le32_to_cpup(tmp++);	MsgLength = le32_to_cpup(tmp++);		if (configNr >= RNDIS_MAX_CONFIGS)		return -ENOTSUPP;	params = &rndis_per_dev_params [configNr];		/* NOTE: RNDIS is *EXTREMELY* chatty ... Windows constantly polls for	 * rx/tx statistics and link status, in addition to KEEPALIVE traffic	 * and normal HC level polling to see if there's any IN traffic.	 */	/* For USB: responses may take up to 10 seconds */	switch (MsgType) {	case REMOTE_NDIS_INITIALIZE_MSG:		DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n", 			__FUNCTION__ );		params->state = RNDIS_INITIALIZED;		return  rndis_init_response (configNr,					     (rndis_init_msg_type *) buf);			case REMOTE_NDIS_HALT_MSG:		DEBUG("%s: REMOTE_NDIS_HALT_MSG\n",			__FUNCTION__ );		params->state = RNDIS_UNINITIALIZED;		if (params->dev) {			netif_carrier_off (params->dev);			netif_stop_queue (params->dev);		}		return 0;			case REMOTE_NDIS_QUERY_MSG:		return rndis_query_response (configNr, 					     (rndis_query_msg_type *) buf);			case REMOTE_NDIS_SET_MSG:		return rndis_set_response (configNr, 					   (rndis_set_msg_type *) buf);			case REMOTE_NDIS_RESET_MSG:		DEBUG("%s: REMOTE_NDIS_RESET_MSG\n", 			__FUNCTION__ );		return rndis_reset_response (configNr,					     (rndis_reset_msg_type *) buf);	case REMOTE_NDIS_KEEPALIVE_MSG:		/* For USB: host does this every 5 seconds */		if (rndis_debug > 1)			DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", 				__FUNCTION__ );		return rndis_keepalive_response (configNr,						 (rndis_keepalive_msg_type *) 						 buf);			default: 		/* At least Windows XP emits some undefined RNDIS messages.		 * In one case those messages seemed to relate to the host		 * suspending itself.		 */		printk (KERN_WARNING			"%s: unknown RNDIS message 0x%08X len %d\n", 			__FUNCTION__ , MsgType, MsgLength);		{			unsigned i;			for (i = 0; i < MsgLength; i += 16) {				DEBUG ("%03d: "					" %02x %02x %02x %02x"					" %02x %02x %02x %02x"					" %02x %02x %02x %02x"					" %02x %02x %02x %02x"					"\n",					i,					buf[i], buf [i+1],						buf[i+2], buf[i+3],					buf[i+4], buf [i+5],						buf[i+6], buf[i+7],					buf[i+8], buf [i+9],						buf[i+10], buf[i+11],					buf[i+12], buf [i+13],						buf[i+14], buf[i+15]);			}		}		break;	}		return -ENOTSUPP;}int rndis_register (int (* rndis_control_ack) (struct net_device *)){	u8 i;		for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {		if (!rndis_per_dev_params [i].used) {			rndis_per_dev_params [i].used = 1;			rndis_per_dev_params [i].ack = rndis_control_ack;			DEBUG("%s: configNr = %d\n", __FUNCTION__, i);			return i;		}	}	DEBUG("failed\n");		return -1;}void rndis_deregister (int configNr){	DEBUG("%s: \n", __FUNCTION__ );		if (configNr >= RNDIS_MAX_CONFIGS) return;	rndis_per_dev_params [configNr].used = 0;		return;}int rndis_set_param_dev (u8 configNr, struct net_device *dev, 			 struct net_device_stats *stats,			 u16 *cdc_filter){	DEBUG("%s:\n", __FUNCTION__ );	if (!dev || !stats) return -1;	if (configNr >= RNDIS_MAX_CONFIGS) return -1;		rndis_per_dev_params [configNr].dev = dev;	rndis_per_dev_params [configNr].stats = stats;	rndis_per_dev_params [configNr].filter = cdc_filter;		return 0;}int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr){	DEBUG("%s:\n", __FUNCTION__ );	if (!vendorDescr) return -1;	if (configNr >= RNDIS_MAX_CONFIGS) return -1;		rndis_per_dev_params [configNr].vendorID = vendorID;	rndis_per_dev_params [configNr].vendorDescr = vendorDescr;		return 0;}int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed){	DEBUG("%s: %u %u\n", __FUNCTION__, medium, speed);	if (configNr >= RNDIS_MAX_CONFIGS) return -1;		rndis_per_dev_params [configNr].medium = medium;	rndis_per_dev_params [configNr].speed = speed;		return 0;}void rndis_add_hdr (struct sk_buff *skb){	struct rndis_packet_msg_type	*header;	if (!skb)		return;	header = (void *) skb_push (skb, sizeof *header);	memset (header, 0, sizeof *header);	header->MessageType = __constant_cpu_to_le32(REMOTE_NDIS_PACKET_MSG);	header->MessageLength = cpu_to_le32(skb->len);	header->DataOffset = __constant_cpu_to_le32 (36);	header->DataLength = cpu_to_le32(skb->len - sizeof *header);}void rndis_free_response (int configNr, u8 *buf){	rndis_resp_t		*r;	struct list_head	*act, *tmp;		list_for_each_safe (act, tmp, 			    &(rndis_per_dev_params [configNr].resp_queue))	{		r = list_entry (act, rndis_resp_t, list);		if (r && r->buf == buf) {			list_del (&r->list);			kfree (r);		}	}}u8 *rndis_get_next_response (int configNr, u32 *length){	rndis_resp_t		*r;	struct list_head 	*act, *tmp;		if (!length) return NULL;		list_for_each_safe (act, tmp, 			    &(rndis_per_dev_params [configNr].resp_queue))	{		r = list_entry (act, rndis_resp_t, list);		if (!r->send) {			r->send = 1;			*length = r->length;			return r->buf;		}	}		return NULL;}static rndis_resp_t *rndis_add_response (int configNr, u32 length){	rndis_resp_t	*r;		/* NOTE:  this gets copied into ether.c USB_BUFSIZ bytes ... */	r = kmalloc (sizeof (rndis_resp_t) + length, GFP_ATOMIC);	if (!r) return NULL;		r->buf = (u8 *) (r + 1);	r->length = length;	r->send = 0;		list_add_tail (&r->list, 		       &(rndis_per_dev_params [configNr].resp_queue));	return r;}int rndis_rm_hdr(struct sk_buff *skb){	/* tmp points to a struct rndis_packet_msg_type */	__le32		*tmp = (void *) skb->data;	/* MessageType, MessageLength */	if (__constant_cpu_to_le32(REMOTE_NDIS_PACKET_MSG)			!= get_unaligned(tmp++))		return -EINVAL;	tmp++;	/* DataOffset, DataLength */	if (!skb_pull(skb, le32_to_cpu(get_unaligned(tmp++))			+ 8 /* offset of DataOffset */))		return -EOVERFLOW;	skb_trim(skb, le32_to_cpu(get_unaligned(tmp++)));	return 0;}#ifdef	CONFIG_USB_GADGET_DEBUG_FILESstatic int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof, 		     void *data){	char *out = page;	int len;	rndis_params *param = (rndis_params *) data;		out += snprintf (out, count, 			 "Config Nr. %d\n"			 "used      : %s\n"			 "state     : %s\n"			 "medium    : 0x%08X\n"			 "speed     : %d\n"			 "cable     : %s\n"			 "vendor ID : 0x%08X\n"			 "vendor    : %s\n", 			 param->confignr, (param->used) ? "y" : "n", 			 ({ char *s = "?";			 switch (param->state) {			 case RNDIS_UNINITIALIZED:				s = "RNDIS_UNINITIALIZED"; break;			 case RNDIS_INITIALIZED:				s = "RNDIS_INITIALIZED"; break;			 case RNDIS_DATA_INITIALIZED:				s = "RNDIS_DATA_INITIALIZED"; break;			}; s; }),			 param->medium, 			 (param->media_state) ? 0 : param->speed*100, 			 (param->media_state) ? "disconnected" : "connected",			 param->vendorID, param->vendorDescr);      		len = out - page;	len -= off;		if (len < count) {		*eof = 1;		if (len <= 0)			return 0;	} else		len = count;		*start = page + off;	return len;}static int rndis_proc_write (struct file *file, const char __user *buffer, 		      unsigned long count, void *data){	rndis_params *p = data;	u32 speed = 0;	int i, fl_speed = 0;		for (i = 0; i < count; i++) {		char c;		if (get_user(c, buffer))			return -EFAULT;		switch (c) {		case '0':		case '1':		case '2':		case '3':		case '4':		case '5':		case '6':		case '7':		case '8':		case '9':			fl_speed = 1;			speed = speed*10 + c - '0';			break;		case 'C':		case 'c':			rndis_signal_connect (p->confignr);			break;		case 'D':		case 'd':			rndis_signal_disconnect(p->confignr);			break;		default: 			if (fl_speed) p->speed = speed;			else DEBUG ("%c is not valid\n", c);			break;		}				buffer++;	}		return count;}#define	NAME_TEMPLATE	"driver/rndis-%03d"static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];#endif	/* CONFIG_USB_GADGET_DEBUG_FILES */int __init rndis_init (void){	u8 i;	for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {#ifdef	CONFIG_USB_GADGET_DEBUG_FILES		char name [20];		sprintf (name, NAME_TEMPLATE, i);		if (!(rndis_connect_state [i]				= create_proc_entry (name, 0660, NULL))) 		{			DEBUG ("%s :remove entries", __FUNCTION__);			while (i) {				sprintf (name, NAME_TEMPLATE, --i);				remove_proc_entry (name, NULL);			}			DEBUG ("\n");			return -EIO;		}		rndis_connect_state [i]->nlink = 1;		rndis_connect_state [i]->write_proc = rndis_proc_write;		rndis_connect_state [i]->read_proc = rndis_proc_read;		rndis_connect_state [i]->data = (void *)				(rndis_per_dev_params + i);#endif		rndis_per_dev_params [i].confignr = i;		rndis_per_dev_params [i].used = 0;		rndis_per_dev_params [i].state = RNDIS_UNINITIALIZED;		rndis_per_dev_params [i].media_state				= NDIS_MEDIA_STATE_DISCONNECTED;		INIT_LIST_HEAD (&(rndis_per_dev_params [i].resp_queue));	}		return 0;}void rndis_exit (void){#ifdef	CONFIG_USB_GADGET_DEBUG_FILES	u8 i;	char name [20];		for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {		sprintf (name, NAME_TEMPLATE, i);		remove_proc_entry (name, NULL);	}#endif}

⌨️ 快捷键说明

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