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

📄 rndis.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		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));	resp = (rndis_keepalive_cmplt_type *) r->buf;	if (!resp) return -ENOMEM;			resp->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;	resp->MessageLength = 16;	resp->RequestID = buf->RequestID;	resp->Status = 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;	if (!resp) return -ENOMEM;		resp->MessageType = REMOTE_NDIS_INDICATE_STATUS_MSG;	resp->MessageLength = 20;	resp->Status = status;	resp->StatusBufferLength = 0;	resp->StatusBufferOffset = 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_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, *tmp;	struct rndis_params		*params;		if (!buf)		return -ENOMEM;		tmp = (u32 *) buf; 	MsgType = *tmp;	MsgLength = *(tmp + 1);		if (configNr >= RNDIS_MAX_CONFIGS)		return -ENOTSUPP;	params = &rndis_per_dev_params [configNr];		/* For USB: responses may take up to 10 seconds */	switch (MsgType)	{	case REMOTE_NDIS_INITIALIZE_MSG:		DEBUG(KERN_INFO "%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(KERN_INFO "%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:		DEBUG(KERN_INFO "%s: REMOTE_NDIS_QUERY_MSG\n", 			__FUNCTION__ );		return rndis_query_response (configNr, 					     (rndis_query_msg_type *) buf);			case REMOTE_NDIS_SET_MSG:		DEBUG(KERN_INFO "%s: REMOTE_NDIS_SET_MSG\n", 			__FUNCTION__ );		return rndis_set_response (configNr, 					   (rndis_set_msg_type *) buf);			case REMOTE_NDIS_RESET_MSG:		DEBUG(KERN_INFO "%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 */		DEBUG(KERN_INFO "%s: REMOTE_NDIS_KEEPALIVE_MSG\n", 			__FUNCTION__ );		return rndis_keepalive_response (configNr,						 (rndis_keepalive_msg_type *) 						 buf);			default: 		printk (KERN_ERR "%s: unknown RNDIS Message Type 0x%08X\n", 			__FUNCTION__ , MsgType);		break;	}		return -ENOTSUPP;}int rndis_register (int (* rndis_control_ack) (struct net_device *)){	u8 i;	DEBUG("%s: ", __FUNCTION__ );		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("configNr = %d\n", 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){	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;		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:\n", __FUNCTION__ );	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){	if (!skb) return;	skb_push (skb, sizeof (struct rndis_packet_msg_type));	memset (skb->data, 0, sizeof (struct rndis_packet_msg_type));	*((u32 *) skb->data) = 1;	*((u32 *) skb->data + 1) = skb->len;	*((u32 *) skb->data + 2) = 36;	*((u32 *) skb->data + 3) = skb->len - 44;		return;}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;		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 (u8 *buf, u32 *length){	u32 i, messageLen, dataOffset;		if (!buf || !length) return -1;	if (*((u32 *) buf) != 1) return -1;		messageLen = *((u32 *) buf + 1);		dataOffset = *((u32 *) buf + 2) + 8;	if (messageLen < dataOffset || messageLen > *length) return -1;		for (i = dataOffset; i < messageLen; i++)		buf [i - dataOffset] = buf [i];			*length = messageLen - dataOffset;		return 0;}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;}int rndis_proc_write (struct file *file, const char *buffer, 		      unsigned long count, void *data){	u32 speed = 0;	int i, fl_speed = 0;		for (i = 0; i < count; i++) {		switch (*buffer) {		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 + *buffer - '0';			break;		case 'C':		case 'c':			rndis_signal_connect (((rndis_params *) data)				->confignr);			break;		case 'D':		case 'd':			rndis_signal_disconnect (((rndis_params *) data)				->confignr);			break;		default: 			if (fl_speed) ((rndis_params *) data)->speed = speed;			else DEBUG ("%c is not valid\n", *buffer);			break;		}				buffer++;	}		return count;}int __init rndis_init (void){	u8 i;	char name [4];	/* FIXME this should probably be /proc/driver/rndis,	 * and only if debugging is enabled	 */		if (!(rndis_connect_dir =  proc_mkdir ("rndis", NULL))) {		printk (KERN_ERR "%s: couldn't create /proc/rndis entry", 			__FUNCTION__);		return -EIO;	}		for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {		sprintf (name, "%03d", i);		if (!(rndis_connect_state [i]				= create_proc_entry (name, 0660,						rndis_connect_dir))) 		{			DEBUG ("%s :remove entries", __FUNCTION__);			for (i--; i > 0; i--) {				sprintf (name, "%03d", i);				remove_proc_entry (name, rndis_connect_dir);			}			DEBUG ("\n");						remove_proc_entry ("000", rndis_connect_dir);			remove_proc_entry ("rndis", NULL);			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);		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){	u8 i;	char name [4];		for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {		sprintf (name, "%03d", i);		remove_proc_entry (name, rndis_connect_dir);	}	remove_proc_entry ("rndis", NULL);	return;}

⌨️ 快捷键说明

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