www.pudn.com > src.rar > main.c, change:2013-12-18,size:68372b


#include <stdio.h> 
#include <string.h> 
#include <sys/types.h> 
#include <errno.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <unistd.h> 
#include <termio.h> 
#include <sys/signal.h> 
#include <pthread.h> 
#include <time.h> 
#include <stdlib.h> 
#include <sys/ioctl.h> 
#include <sys/select.h> 
#include <time.h> 
#include <pthread.h> 
 
#include <sys/socket.h> 
#include <dirent.h> 
#include  <netinet/in.h> 
#include <netinet/tcp.h> 
#include  <sys/wait.h> 
#include  <arpa/inet.h> 
#include  <netdb.h> 
#include <net/if.h> 
#include <stdbool.h> 
 
#include <libxml/parser.h> 
#include <libxml/tree.h> 
 
 
#include "lib.h" 
#include "inifile.h" 
#include "list.h" 
#include "iec_103.h" 
#include "iec_103appdata.h" 
 
#define DEBUG_ON 1 
 
#define UART_RCV_SIZE 250 
#define MAX_BUF_SIZE 1000 
 
 
#define SEND_CONFIRM_FRAME(acd, dfc, addr) send_response_frame(acd, dfc, SLAVE_FUNNO_CONFIRM, addr) 
#define SEND_BUSY_FRAME(acd, dfc, addr) send_response_frame(acd, dfc, SLAVE_FUNNO_BUSY, addr) 
#define SEND_NO_DATA_FRAME(acd, dfc, addr) send_response_frame(acd, dfc, SLAVE_FUNNO_NO_DATA, addr) 
#define SEND_LINK_STATE_FRAME(acd, dfc, addr) send_response_frame(acd, dfc, SLAVE_FUNNO_LINK_STATE, addr) 
 
uint8 ISA351G_YC_INF[]={92, 93, 94, 99, 100, 101, 106, 107, 109}; 
uint8 ISA347G_YC_INF[]={92, 93, 105, 108}; 
uint8 ISA381G_YC_INF[]={92, 93, 103, 106}; 
 
uint8 ISA351G_YX_INF[]={150, 172}; 
uint8 ISA347G_YX_INF[]={150, 172}; 
uint8 ISA381G_YX_INF[]={150, 175}; 
 
 
 
 
static int speed_arr[] =  
{ 
	921600, 460800, 230400, 115200,  
	57600,  38400,  19200,  9600,  
	4800,   2400,   1800,   1200, 
	600,    300,    150,    110,  
	75,     50 
}; 
 
static int baudflag_arr[] =  
{ 
	B921600, B460800, B230400, B115200,  
	B57600,  B38400,  B19200,  B9600,  
	B4800,   B2400,   B1800,   B1200, 
	B600,    B300,    B150,    B110,  
	B75,     B50 
}; 
 
typedef struct  
{ 
	char name[MAX_BUF_SIZE]; 
	uint32 baud; 
	uint8 data_bits; 
	uint8 parity; 
	uint8 stop_bits; 
	uint16 recv_delay; 
} uart_para; 
 
 
PCL_INFO pcl_info; 
 
 
static uint16 max_modaddr = 0; 
uint16 *YC_REG; 
uint8   *YX_REG; 
static int com_fd; 
static int tcp_fd = 4096; 
static uart_para MY_COM; 
static pthread_t modbus_scan_thread; 
 
static pthread_mutex_t MUTEX_SCAN = PTHREAD_MUTEX_INITIALIZER; 
static pthread_mutex_t MUTEX_SEND = PTHREAD_MUTEX_INITIALIZER; 
static pthread_mutex_t MUTEX_WRITE = PTHREAD_MUTEX_INITIALIZER; 
static pthread_t COM_THREAD; 
 
static uint16 crc16_check(uint8 * puchMsg, uint16 usDataLen) 
{ 
	uint8 uchCRCHi = 0xFF ;  
	uint8 uchCRCLo = 0xFF ;  
	uint8 uIndex ; 
  
	while (usDataLen--)  
	{ 
		uIndex = uchCRCHi ^ (*(puchMsg++)) ; /* ����CRC */ 
		uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ; 
		uchCRCLo = auchCRCLo[uIndex] ; 
	} 
	 
	return (uchCRCHi << 8 | uchCRCLo) ; 
} 
 
static int uart_send(const int fd, const uint8 *buf, uint8 len)	 
{ 
	int sended = 0; 
	int i; 
 
	if(fd <= 0) 	return -1; 
	if(NULL == buf)	return -1; 
	if(len <= 0)	return -1; 
	 
	pthread_mutex_lock(&MUTEX_SEND); 
 
	sended = write(fd, buf, len);	 
	if( sended <= 0) { 
		printf("--Port send [%d] error.\n ", sended); 
	} 
 
	pthread_mutex_unlock(&MUTEX_SEND); 
 
#if DEBUG_ON 
	printf("UART SEND [%03d] Bytes --> ", len); 
	for(i=0; i < len; i++){ 
		printf("%02x ", buf[i]); 
	} 
	printf("\n"); 
#endif	 
	 
	return sended; 
} 
 
static int uart_recv(const int fd, uint8 *buf)	 
{ 
	int len = 0; 
	int i; 
	if(fd <= 0) 	return -1; 
	if(NULL == buf)	return -1; 
		 
	len = read(fd, buf, MAX_BUF_SIZE);	 
#if DEBUG_ON 
	if(len <= 0){ 
		printf("--Port recv [%d] error.\n", len); 
	} 
	else { 
		printf("UART RECV [%03d] Bytes <-- ", len); 
		for(i=0; i < len; i++){ 
			printf("%02x ", buf[i]); 
		} 
		printf("\n"); 
	} 
#endif	 
	return len; 
} 
 
 
 
static int uart_recv2(const int fd, uint8 *buf, int timeout)	 
{ 
	int len = 0; 
	int total= 0; 
	int i; 
	time_t timep; 
	fd_set fdset; 
	int ret; 
	struct timeval tm; 
	 
	 
	if(fd <= 0) 	return -1; 
	if(NULL == buf)	return -1; 
 
	FD_ZERO(&fdset); 
	FD_SET(fd, &fdset); 
 
	tm.tv_sec = timeout / 1000; 
	tm.tv_usec = (timeout % 1000) * 1000; 
	 
	ret = select(fd + 1, &fdset, NULL, NULL, &tm); 
	if(ret < 0){ 
		if(EINTR == errno){ 
			printf("select interrupt !\n"); 
			return -1; 
		} 
		else{ 
			perror("--select failued "); 
			return -2; 
		} 
	}else if(ret == 0){ 
		printf("--select timeout !\n"); 
		return -3; 
	}else { 
		if(FD_ISSET(fd, &fdset)){ 
			while(1){ 
				len = read(fd, buf + total, MAX_BUF_SIZE);	 
				if(len > 0){ 
					total += len; 
					usleep(20000); 
					continue; 
				} 
				break; 
			} 
		} 
	} 
#if DEBUG_ON 
	if( total <= 0){ 
		printf("--Port recv [%d] error.\n", total); 
	} 
	else { 
		printf("UART RECV [%03d] Bytes <-- ", total); 
		for(i=0; i < total; i++){ 
			printf("%02x ", buf[i]); 
		} 
		printf("\n"); 
	} 
#endif		 
	return total; 
} 
 
 
/* У */                                         
uint8 Makecrc(uint8 *str,uint8 nSize) 
{ 
	uint8  i; 
	uint8 J; 
	J=0; 
	for(i=0;i < nSize;i++) 
	{ 
		J+=str[i]; 
	} 
	 
	return J;  
} 
 
int IsOverTime(struct timer *tmr) 
{ 
	struct timeval cur; 
	 
	gettimeofday(&cur, NULL); 
	if((cur.tv_sec - tmr->time_base.tv_sec) * 1000 + \ 
	(cur.tv_usec - tmr->time_base.tv_usec) / 1000 > tmr->time_out) 
	{ 
		return 1; 
	} 
	return 0; 
} 
 
void start_timer(struct timer *tmr) 
{ 
	gettimeofday(&tmr->time_base, NULL); 
} 
 
 
static int ini_rd_str(const char *section, const char *key, char *value) 
{ 
	int ret; 
 
	ret = read_profile_string(section, key, value, MAX_BUF_SIZE, "", ini_file_name); 
 
	if(ret)	return 0; 
	else	return -1;	 
} 
 
static int ini_rd_int(const char *section, const char *key) 
{ 
	int ret; 
 
	ret = read_profile_int(section, key, -1, ini_file_name); 
	//printf("INI read int ret = [%d]\n", ret); 
	return ret; 
} 
 
 
static int ini_com_read(uart_para *port) 
{ 
	uart_para *com = port; 
 
	if(NULL == com)	return -1; 
	 
	if(ini_rd_str(ini_section[0], ini_key_com[0], com->name) < 0) { 
		printf("--INI file read KEY: [%s] failure.\n", ini_key_com[0]); 
		strcpy(com->name, PORT_DEFAULT); 
	}	 
	 
	com->baud = ini_rd_int(ini_section[0], ini_key_com[1]); 
	if((com->baud < 300) || (com->baud > 115200)) { 
		printf("--INI file read KEY: [%s] failure.\n", ini_key_com[1]); 
		com->baud = BAUD_DEFAULT; 
	} 
 
	com->data_bits = ini_rd_int(ini_section[0], ini_key_com[2]); 
	if((com->data_bits < 5) || (com->data_bits > 8)) { 
		printf("--INI file read KEY: [%s] failure.\n", ini_key_com[2]); 
		com->data_bits = DATA_BITS_DEFAULT; 
	} 
 
	com->parity = ini_rd_int(ini_section[0], ini_key_com[3]); 
	if((com->parity < 0) || (com->parity > 4)) { 
		printf("--INI file read KEY: [%s] failure.\n", ini_key_com[3]); 
		com->parity = PARITY_DEFAULT; 
	} 
 
	com->stop_bits = ini_rd_int(ini_section[0], ini_key_com[4]); 
	if((com->stop_bits < 1) || (com->stop_bits > 2)) { 
		printf("--INI file read KEY: [%s] failure.\n", ini_key_com[4]); 
		com->stop_bits = STOP_BITS_DEFAULT; 
	}	 
 
	com->recv_delay= ini_rd_int(ini_section[0], ini_key_com[5]); 
	if((com->recv_delay< 0) || (com->recv_delay> 10000)) { 
		printf("--INI file read KEY: [%s] failure.\n", ini_key_com[5]); 
		com->recv_delay = RECV_DELAY_DEFAULT; 
	}	 
	 
	return 0; 
} 
 
static int port_open(uart_para *port) 
{ 
	int fd = 0; 
	uart_para *com = port; 
 
	if(NULL == com)	return -1; 
	 
	//打开串口设备 
	fd = open(com->name, O_RDWR|O_NOCTTY|O_NONBLOCK); 
	if(fd < 0) { 
		printf("--Open PORT: [%s] failure.\n", com->name); 
	} 
	return fd; 
} 
 
static int speed_to_flag(int speed) 
{ 
	int i; 
	int cnt = 0; 
 
	for (i = 0; i < sizeof(speed_arr)/sizeof(int); i++) { 
		cnt = (speed - speed_arr[i]); 
		//printf("cnt = %d\n", cnt); 
        	if ( cnt == 0)  
        		return baudflag_arr[i]; 
		//else 
			//printf("speed_arr[%d] = %d\n", i, speed_arr[i]); 
    	} 
 
    	printf("--Unsupported baudrate, use 9600 instead!\n"); 
    	return B9600; 
} 
 
static int port_setup(int fd, uart_para *port) 
{ 
	uart_para *com = port; 
	struct termios old_tio, new_tio; 
	int baud_rate = 0; 
 
	if(fd < 0)		return -1; 
	if(NULL == com)		return -1; 
 
	tcgetattr(fd, &old_tio); 
	bzero(&new_tio, sizeof(struct termios)); 
	new_tio.c_cflag |= (CLOCAL | CREAD); 
 
	//设置波特率 
	baud_rate = speed_to_flag(com->baud); 
	new_tio.c_cflag |= baud_rate;  
	//设置停止位 
	switch(com->stop_bits) { 
		case 1: 
			new_tio.c_cflag &= ~CSTOPB; 
		break; 
		case 2: 
			new_tio.c_cflag |= CSTOPB; 
		break; 
		default: 
			printf("--PORT stop bits set error. use default.\n"); 
			new_tio.c_cflag &= ~CSTOPB; 
		break; 
	} 
 
	//设置奇偶校验 
	switch(com->parity) { 
		case 0://无校验 
			new_tio.c_cflag &= ~PARENB; 
		break; 
		case 1://奇校验 
			new_tio.c_cflag |= (PARENB | PARODD); 
		break; 
		case 2://偶校验 
			new_tio.c_cflag |= PARENB; 
			new_tio.c_cflag &= ~PARODD; 
		break; 
		case 3://MARK校验 
			new_tio.c_cflag |= (PARENB | PARODD); 
			new_tio.c_cflag |= CMSPAR; 
		break; 
		case 4://SPACE校验 
			new_tio.c_cflag |= PARENB; 
			new_tio.c_cflag &= ~PARODD; 
			new_tio.c_cflag |= CMSPAR; 
		break; 
		default: 
			printf("--PORT parity set error. use default.\n"); 
			new_tio.c_cflag &= ~PARENB; 
		break; 
	} 
	new_tio.c_cflag &= ~CSIZE; 
	switch(com->data_bits) { 
		case 5: 
			new_tio.c_cflag |= CS5; 
		break; 
		case 6: 
			new_tio.c_cflag |= CS6; 
		break; 
		case 7: 
			new_tio.c_cflag |= CS7; 
		break; 
		case 8: 
			new_tio.c_cflag |= CS8; 
		break; 
		default: 
			printf("--PORT data bits set error. use default.\n"); 
			new_tio.c_cflag |= CS8; 
		break; 
	} 
 
	//设置无硬件流控 
	new_tio.c_cflag &= ~CRTSCTS; 
	new_tio.c_lflag = 0; 
	new_tio.c_oflag = 0; 
	new_tio.c_cc[VMIN] = 4; 
	new_tio.c_cc[VTIME] = 0; 
	new_tio.c_iflag &= ~(IXON | IXOFF | IXANY); 
 
	cfsetispeed(&new_tio, baud_rate); 
	cfsetospeed(&new_tio, baud_rate); 
	tcsetattr(fd, TCSANOW, &new_tio); 
	tcflush(fd, TCIFLUSH); 
	 
	return 0; 
} 
 
 
DBL_LNK *list_find_prev (DBL_LNK *list_head_ptr, DBL_LNK *cur_node) 
{ 
	DBL_LNK *prev_node = NULL; 
 
	if (list_head_ptr == NULL){ 
		printf ("err: ATTEMPT TO REFERENCE A NULL LIST\n"); 
	} 
	else if (cur_node == NULL){ 
		printf ("err: ATTEMPT TO REFERENCE THROUGH A NULL PTR\n"); 
	} 
	else if (cur_node != list_head_ptr){ 
		prev_node = cur_node->prev; 
	} 
	return (prev_node); 
} 
 
DBL_LNK *list_find_last (DBL_LNK *list_head_ptr) 
{ 
	DBL_LNK *last_node; 
 
	if (list_head_ptr) 
		last_node = list_head_ptr->prev; 
	else{	/* head is NULL (i.e. list is empty) so last is NULL too.	*/ 
		last_node = NULL; 
	} 
	return (last_node); 
} 
 
int list_add_first (DBL_LNK **list_head_ptr, DBL_LNK *node_ptr) 
{ 
	DBL_LNK *list_tail_ptr; 
 
	if (node_ptr == NULL){ 
		printf ("err: ATTEMPT TO ADD A NULL ADDRESS TO A LIST"); 
		return -1; 
	} 
 
	/* If list checking is enabled and we get to here we have valid 	*/ 
	/* arguments 								*/ 
 
	/* will this be the only node?	*/ 
	if (*list_head_ptr == NULL) { 
		node_ptr->next = node_ptr; 
		node_ptr->prev = node_ptr; 
	} 
	else{ 
		list_tail_ptr = (*list_head_ptr)->prev; 
		node_ptr->next = *list_head_ptr; 
		node_ptr->prev = list_tail_ptr; 
		list_tail_ptr->next = node_ptr; 
		(*list_head_ptr)->prev = node_ptr; 
	} 
	*list_head_ptr = node_ptr;		/* assign the new head of list	*/ 
	return 0; 
	  
} 
 
PCL_MODADDR *pcl_modaddr_add(PCL_INFO *pcl_info) 
{ 
	PCL_MODADDR *pcl_modaddr = NULL; 
	pcl_modaddr = (PCL_MODADDR *)calloc(1, sizeof(PCL_MODADDR)); 
	list_add_first(&pcl_info->portHead->devHead->modaddrHead, pcl_modaddr); 
	return pcl_modaddr; 
} 
 
 
PCL_DEV *pcl_dev_add(PCL_INFO *pcl_info) 
{ 
	PCL_DEV *pcl_dev = NULL; 
	if(pcl_info->portHead){ 
		pcl_dev = (PCL_DEV *)calloc(1, sizeof(PCL_DEV)); 
		if(pcl_dev) 
			list_add_first(&pcl_info->portHead->devHead, pcl_dev); 
		else 
			printf("alloc dev_addr space failed !\n"); 
	}else 
		printf("add dev_addr failed !\n"); 
	return pcl_dev; 
} 
 
PCL_PORT *pcl_port_add(PCL_INFO *pcl_info) 
{ 
	PCL_PORT *pcl_port = NULL; 
	if(pcl_info){ 
		pcl_port = (PCL_PORT *)calloc(1, sizeof(PCL_PORT)); 
		list_add_first(&pcl_info->portHead, pcl_port); 
	}else 
		printf("add port failed !\n"); 
	return pcl_port; 
} 
 
int parse_xml(char *filename, PCL_INFO *info) 
{ 
	xmlDocPtr Doc; 
	xmlNodePtr curNode; 
	xmlNodePtr portNode; 
	xmlNodePtr devaddrNode; 
	xmlNodePtr funNode; 
	xmlNodePtr regaddrNode; 
	xmlNodePtr saddrNode; 
	 
	PCL_INFO *pcl_info = info; 
	PCL_PORT *pcl_port; 
	PCL_DEV *pcl_dev; 
	PCL_MODADDR *pcl_modaddr; 
	PCL_REG_ADDR *pcl_reg_addr; 
	PCL_SADDR *pcl_saddr; 
	xmlChar * szAttr; 
 
	xmlNodePtr propNodePtr; 
	xmlAttrPtr attrPtr; 
	 
	Doc = xmlReadFile(filename, "GB2312", XML_PARSE_RECOVER); 
	if(NULL == Doc){ 
		fprintf(stderr, "Document not parsed successfully\n"); 
		return -1; 
	} 
	curNode = xmlDocGetRootElement(Doc); 
	if(NULL == curNode){ 
		fprintf(stderr, "empty Document\n"); 
		xmlFreeDoc(Doc); 
		return -1; 
	} 
	if(xmlStrcmp(curNode->name, BAD_CAST "PCL")){ 
		fprintf(stderr, "document of the wront type, root node != PCL\n"); 
		xmlFreeDoc(Doc); 
		return -1; 
	} 
 
	printf("\n		          parse file success !\n\n"); 
	printf("---------------------------------------------------------------------\n"); 
	portNode = curNode->xmlChildrenNode; 
	while(portNode != NULL){ 
		if(!(xmlStrcmp(portNode->name, BAD_CAST "PORT"))){ 
			pcl_port = pcl_port_add(pcl_info); 
			propNodePtr = portNode; 
			attrPtr = propNodePtr->properties; 
			while(attrPtr != NULL){ 
				if(!xmlStrcmp(attrPtr->name, BAD_CAST "portno")){ 
					szAttr = xmlGetProp(propNodePtr, BAD_CAST "portno"); 
					pcl_port->portno = atoi(szAttr); 
				} 
 
				if(!xmlStrcmp(attrPtr->name, BAD_CAST "baud")){ 
					szAttr = xmlGetProp(propNodePtr, BAD_CAST "baud"); 
					pcl_port->baud = atoi(szAttr); 
				} 
 
				if(!xmlStrcmp(attrPtr->name, BAD_CAST "data_bits")){ 
					szAttr = xmlGetProp(propNodePtr, BAD_CAST "data_bits"); 
					pcl_port->data_bits = atoi(szAttr); 
				} 
 
				if(!xmlStrcmp(attrPtr->name, BAD_CAST "parity")){ 
					szAttr = xmlGetProp(propNodePtr, BAD_CAST "parity"); 
					pcl_port->parity = atoi(szAttr); 
				} 
 
				if(!xmlStrcmp(attrPtr->name, BAD_CAST "stop_bits")){ 
					szAttr = xmlGetProp(propNodePtr, BAD_CAST "stop_bits"); 
					pcl_port->stop_bits = atoi(szAttr); 
				} 
				if(!xmlStrcmp(attrPtr->name, BAD_CAST "poll_interval")){ 
					szAttr = xmlGetProp(propNodePtr, BAD_CAST "poll_interval"); 
					pcl_port->poll_interval= atoi(szAttr); 
				}	 
 
				if(!xmlStrcmp(attrPtr->name, BAD_CAST "frame_timeout")){ 
					szAttr = xmlGetProp(propNodePtr, BAD_CAST "frame_timeout"); 
					pcl_port->frame_timeout = atoi(szAttr); 
				} 
				if(!xmlStrcmp(attrPtr->name, BAD_CAST "query_timeout")){ 
					szAttr = xmlGetProp(propNodePtr, BAD_CAST "query_timeout"); 
					pcl_port->query_timeout = atoi(szAttr); 
				} 
				if(!xmlStrcmp(attrPtr->name, BAD_CAST "synctm_timeout")){ 
					szAttr = xmlGetProp(propNodePtr, BAD_CAST "synctm_timeout"); 
					pcl_port->synctm_timeout = atoi(szAttr); 
				} 
				if(!xmlStrcmp(attrPtr->name, BAD_CAST "modbus_srv")){ 
					szAttr = xmlGetProp(propNodePtr, BAD_CAST "modbus_srv"); 
					pcl_port->modbus_srv = atoi(szAttr); 
				} 
				 
				attrPtr = attrPtr->next; 
			} 
			printf("<portno=%d, baud=%d, data_bits=%d, parity=%d, stop_bits=%d, modbus_srv=%d >\n", \ 
				pcl_port->portno, pcl_port->baud, pcl_port->data_bits, pcl_port->parity, pcl_port->stop_bits,pcl_port->modbus_srv); 
			 
			devaddrNode = portNode->xmlChildrenNode; 
			while(devaddrNode != NULL){ 
				if(!(xmlStrcmp(devaddrNode->name, BAD_CAST "DEVICE"))){ 
					pcl_dev = pcl_dev_add(pcl_info); 
					propNodePtr = devaddrNode; 
					attrPtr = propNodePtr->properties; 
					while(attrPtr != NULL){ 
						if(!xmlStrcmp(attrPtr->name, BAD_CAST "devaddr")){ 
							szAttr = xmlGetProp(propNodePtr, BAD_CAST "devaddr"); 
							pcl_dev->devaddr = atoi(szAttr); 
						} 
						if(!xmlStrcmp(attrPtr->name, BAD_CAST "devname")){ 
							pcl_dev->devname = (char *)xmlGetProp(propNodePtr, BAD_CAST "devname"); 
						} 
						if(!xmlStrcmp(attrPtr->name, BAD_CAST "yc_addr")){ 
							szAttr = xmlGetProp(propNodePtr, BAD_CAST "yc_addr"); 
							pcl_dev->yc_addr = atoi(szAttr); 
							if(pcl_dev->yc_addr < 0) 
								pcl_dev->yc_addr == 0xffff; 
						} 
						if(!xmlStrcmp(attrPtr->name, BAD_CAST "yx_addr")){ 
							szAttr = xmlGetProp(propNodePtr, BAD_CAST "yx_addr"); 
							pcl_dev->yx_addr = atoi(szAttr); 
							if(pcl_dev->yx_addr < 0) 
								pcl_dev->yx_addr == 0xffff; 
						} 
						attrPtr = attrPtr->next; 
					} 
					printf("    <devaddr=%d, devname=%s, yc_addr=%d, yx_addr=%d>\n", pcl_dev->devaddr, pcl_dev->devname, pcl_dev->yc_addr, pcl_dev->yx_addr); 
					 
				} 
				devaddrNode = devaddrNode->next; 
			} 
		} 
		portNode = portNode->next; 
	} 
	printf("---------------------------------------------------------------------\n"); 
	xmlFreeDoc(Doc); 
	return 0; 
	 
} 
 
int response_err(int fd, uint8 dev, uint8 err_no) 
{ 
	uint16 crc; 
	uint8 buf[5]; 
	buf[0] = dev; 
	buf[1] = 0x83; 
	buf[2] = err_no; 
	crc = crc16_check(buf, 3); 
	buf[3] = (uint8)(crc >> 8); 
	buf[4] = (uint8)(crc); 
	uart_send(fd, buf, 5); 
	return 0; 
} 
 
int response_yc(int fd, uint8 dev, uint16 *reg_addr, uint8 reg_num) 
{ 
	int i; 
	uint16 crc; 
	uint8 buf[MAX_BUF_SIZE]; 
	uint8 *p = buf; 
	if(reg_addr == NULL || reg_num > (MAX_BUF_SIZE - 5) / 2) 
		return -1; 
	*p++ = dev; 
	*p++ = 0x03; 
	*p++ = reg_num * 2; 
	pthread_mutex_lock(&MUTEX_WRITE); 
	for(i = 0; i < reg_num; i++){ 
		*p++ = (uint8)(reg_addr[i] >> 8); 
		*p++ = (uint8)(reg_addr[i]); 
	} 
	pthread_mutex_unlock(&MUTEX_WRITE); 
	crc = crc16_check(buf, p - buf); 
	*p++ = (uint8)(crc >> 8); 
	*p++ = (uint8)(crc); 
	uart_send(fd, buf, p - buf); 
	return 0; 
} 
 
int response_yx(int fd, uint8 dev, uint8 *reg_addr, uint8 reg_num) 
{ 
	int i, j; 
	int ret; 
	uint16 crc; 
	uint8 buf[MAX_BUF_SIZE]; 
	uint8 *p = buf; 
	uint8 *q = reg_addr; 
	uint8 tmp; 
	if(reg_addr == NULL || reg_num > 1000) 
		return -1; 
 
	memset(buf, 0, sizeof(buf)); 
	 
	*p++ = dev; 
	*p++ = 2; 
	*p++ = (reg_num - 1) / 8 + 1; 
	pthread_mutex_lock(&MUTEX_WRITE); 
	for(i = 0; i < (reg_num - 1) / 8 + 1; i++){ 
		for(j = 0; j < 8; j++){ 
			tmp = (*q++) ? 1 : 0; 
			*p |= ((q - reg_addr > reg_num) ? 0 : tmp) << j; 
		} 
		p++; 
	} 
	pthread_mutex_unlock(&MUTEX_WRITE); 
	crc = crc16_check(buf, p - buf); 
	*p++ = (uint8)(crc >> 8); 
	*p++ = (uint8)(crc); 
	uart_send(fd, buf, p - buf); 
	ret = uart_send(fd, buf, p - buf); 
	return 0; 
} 
 
int modbus_handle(int fd, uint8 *buf, int len) 
{ 
	uint16 crc; 
	uint8 dev_addr; 
	uint8 fun_no; 
	uint16 reg_addr; 
	uint16 reg_num; 
	int i; 
	if(len <= 0 || buf == NULL) 
		return -1; 
	crc = crc16_check(buf, len - 2); 
	if((crc >> 8) != buf[len -2] || (crc & 0x00ff) != buf[len -1]) 
		return -1; 
	dev_addr = buf[0]; 
	fun_no= buf[1]; 
	reg_addr = buf[2] * 0x100 + buf[3]; 
	reg_num = buf[4] * 0x100 + buf[5]; 
	if(dev_addr < 1 || dev_addr > 8) 
		return -1; 
	if(fun_no != READ_HOLDING_REGISTER_FUN && fun_no != READ_INPUT_STATUS_FUN){ 
		response_err(fd, dev_addr, MODBUS_ERR_ILLEGAL_FC); 
		return -1; 
	} 
	if(reg_addr < 0x0 || reg_addr > 0xffff){ 
		response_err(fd, dev_addr, MODBUS_ERR_ILLEGAL_ADDR); 
		return -1; 
	} 
	if(reg_num < 0 || reg_num > 0xffff){ 
		response_err(fd, dev_addr, MODBUS_ERR_ILLEGAL_ADDR); 
		return -1; 
	} 
	printf("proces.....\n"); 
	if(fun_no == READ_HOLDING_REGISTER_FUN) 
		response_yc(fd, dev_addr, &YC_REG[reg_addr], reg_num); 
	else if(fun_no == READ_INPUT_STATUS_FUN) 
		response_yx(fd, dev_addr, &YX_REG[reg_addr], reg_num); 
} 
 
void modbus_server_thread_func(char *arg) 
{ 
	uint8 buf[256]; 
	int yc_max = 65536; 
	int yx_max = 65536; 
	int i, j, k = 0, l, n = 0; 
	int len; 
	uint16 tmp; 
	float current_val; 
	uint16 q_val; 
	time_t tv; 
	uint8 *p; 
	float *q; 
	int ret; 
	int (*reg)[58]; 
	fd_set client;  
	int com_fd = *((int *)arg); 
	 
	YC_REG = (uint16 *)malloc(yc_max * sizeof(uint16)); 
	memset(YC_REG, 0, yc_max * sizeof(uint16)); 
 
	YX_REG = (uint8 *)malloc(yx_max * sizeof(uint8)); 
	memset(YX_REG, 0, yx_max * sizeof(uint8)); 
	 
	 
	 
	while(1){ 
		FD_ZERO(&client); 
		FD_SET(com_fd, &client); 
		ret = select(com_fd + 1, &client, NULL, NULL, NULL); 
		if(ret <= 0) 
			continue; 
		usleep(1000 * 50); 
		if(FD_ISSET(com_fd, &client)){ 
			len = uart_recv(com_fd, buf); 
			if(len > 0){ 
				modbus_handle(com_fd, buf, len); 
			} 
		} 
		 
	} 
		 
} 
 
void saveYCtoREG(uint16 addr, short value) 
{ 
	pthread_mutex_lock(&MUTEX_WRITE); 
	YC_REG[addr] = value; 
	pthread_mutex_unlock(&MUTEX_WRITE); 
} 
 
void saveYXtoREG(uint16 addr, uint8 value) 
{ 
	pthread_mutex_lock(&MUTEX_WRITE); 
	YX_REG[addr] = value; 
	pthread_mutex_unlock(&MUTEX_WRITE); 
} 
 
int GetnIndexbyFuninf(char *devname, struct FunInf funinf) 
{ 
	int i; 
	if(!strcmp(devname, "ISA351G")){ 
		if(funinf.inf < 149){ 
			for(i = 0; i < sizeof(ISA351G_YC_INF); i++){ 
				if(ISA351G_YC_INF[i] == funinf.inf) 
					return i; 
			} 
		}else{ 
			for(i = 0; i < sizeof(ISA351G_YX_INF); i++){ 
				if(ISA351G_YX_INF[i] == funinf.inf) 
					return i; 
			} 
		} 
	} 
	else if(!strcmp(devname, "ISA347G")){ 
		if(funinf.inf < 149){ 
			for(i = 0; i < sizeof(ISA347G_YC_INF); i++){ 
				if(ISA347G_YC_INF[i] == funinf.inf) 
					return i; 
			} 
		}else{ 
			for(i = 0; i < sizeof(ISA351G_YX_INF); i++){ 
				if(ISA351G_YX_INF[i] == funinf.inf) 
					return i; 
			} 
		} 
	} 
	else if(!strcmp(devname, "ISA381G")){ 
		if(funinf.inf < 149){ 
			for(i = 0; i < sizeof(ISA381G_YC_INF); i++){ 
				if(ISA351G_YC_INF[i] == funinf.inf) 
					return i; 
			} 
		}else{ 
			for(i = 0; i < sizeof(ISA351G_YX_INF); i++){ 
				if(ISA381G_YX_INF[i] == funinf.inf) 
					return i; 
			} 
		} 
	} 
	return -1; 
} 
void PackLPDU (struct PtlData103 *ptl103, struct RealRunIED *pDevRun, unsigned char code)    
{    
    if(!pDevRun)    
        return;    
    
    struct LinkCtrl linkCtrl;    
    linkCtrl.funcode = code;    
    linkCtrl.res = 0;    
    linkCtrl.prm = 1;    
    
    switch(code)     
    {    
    case ResCU_code:    
    case ResFcb_code:    
        ptl103->m_lnkSvrCls = SendConfirm;    
        linkCtrl.fcvDfc = 0;    
        break;    
    
    case NoReply_code:    
        ptl103->m_lnkSvrCls = SendNoreply;    
        linkCtrl.fcvDfc = 0;    
        break;    
    
    case QueryLink_code:    
        ptl103->m_lnkSvrCls = RequestRespond;    
        linkCtrl.fcvDfc = 0;    
        break;    
    
    case SendCon_code:    
        ptl103->m_lnkSvrCls = SendConfirm;    
        linkCtrl.fcvDfc = 1;    
        break;    
    
    case CallClass1_code:    
    case CallClass2_code:    
        ptl103->m_lnkSvrCls = RequestRespond;    
        linkCtrl.fcvDfc = 1;    
        break;    
    default:    
        break;    
    }    
    // ·֡    
    linkCtrl.fcbAcd = 0;    
    if (linkCtrl.fcvDfc)     
    {    
        pDevRun->fcb = ~pDevRun->fcb;    
        linkCtrl.fcbAcd = pDevRun->fcb;    
    }    
    
    if (0 == ptl103->m_wSendNum)    
    { // ̶֡    
        struct LPDU_Fix_Fmt *pFmt = (struct LPDU_Fix_Fmt *)(ptl103->m_bySend);    
        pFmt->head = 0x10;    
        pFmt->ctrl = linkCtrl;    
        pFmt->addr = pDevRun->byAddr;    
        pFmt->sum = pFmt->ctrl.lnkCtrl + pFmt->addr;    
        pFmt->tail = 0x16;    
    
        ptl103->m_wSendNum = sizeof(struct LPDU_Fix_Fmt);    
    }else {    
        struct LPDU_Vol_Head *pHead = (struct LPDU_Vol_Head *)(ptl103->m_bySend);    
        pHead->head1 = pHead->head2 = 0x68;    
        pHead->len1 = pHead->len2 = ptl103->m_wSendNum + 2;    
        pHead->ctrl = linkCtrl;    
        pHead->addr = pDevRun->byAddr;    
    
        ptl103->m_wSendNum += sizeof(struct LPDU_Vol_Head);    
        ptl103->m_bySend[ptl103->m_wSendNum ++] = Makecrc(ptl103->m_bySend + 4, pHead->len1);    
        ptl103->m_bySend[ptl103->m_wSendNum ++] = 0x16;    
    }    
}    
 
 
// ̶֡·֡    
void PackLPDU_Fix(struct PtlData103 *ptl103, struct RealRunIED *pDevRun, unsigned char byCode)    
{    
//  if(ptl103->m_frmOver.IsOverTime(m_nCnt))    
    {    
        PackLPDU(ptl103, pDevRun, byCode);    
    }    
}    
    
//asdu7    
void Pack_Asdu_7(struct PtlData103 *ptl103, struct RealRunIED *pDevRun, uint8 byAddr)    
{    
    
    struct ASDU_7_Fmt *pFmt = (struct ASDU_7_Fmt *)(ptl103->m_bySend + sizeof(struct LPDU_Vol_Head));    
    pFmt->head.type = 7;    
    pFmt->head.vsq.vsq = 0x81;    
    pFmt->head.cot = 9;    
    pFmt->head.addr = byAddr;    
    pFmt->head.fun = 0xff;    
    pFmt->head.inf = 0;    
    pFmt->scn = ptl103->m_bySin ++;    
    
    ptl103->m_wSendNum = sizeof(struct ASDU_7_Fmt);    
    PackLPDU(ptl103, pDevRun, SendCon_code);    
}    
 
 
// ·㴫    
// 1. վʼ    
// 2. ·״̬        
unsigned char PackLinkCmm(struct PtlData103 *ptl103, struct RealRunIED *pDevRun)    
{    
    if(!pDevRun)    
        return 0;    
    if (!pDevRun->linkQuery && !pDevRun->linkRes)    
        return 0;    
    
    if (pDevRun->linkRes) { // ʼ    
        PackLPDU_Fix(ptl103, pDevRun, ResCU_code);    
    
        pDevRun->bCommInitFlag = 1;    
        pDevRun->nASDU5Cnt = 0;    
        pDevRun->step = eInitStart;    
    }else if (pDevRun->linkQuery){  // ·״̬    
        PackLPDU_Fix(ptl103, pDevRun, QueryLink_code);    
    }    
 
    return 1;    
}    
 
unsigned char gettask() 
{ 
	return 0; 
} 
    
//֡    
unsigned char PackTask(struct PtlData103 *ptl103)    
{    
 
    return 0;    
}    
 
//վУʱ 
uint8 SlaveAdjustTime103(struct PtlData103 *ptl103, uint8 byaddr)    
{    
	struct tm *tp; 
	struct timeval tv; 
	 
    struct ASDU_6_Fmt *pFmt = (struct ASDU_6_Fmt *)(ptl103->m_bySend + sizeof(struct LPDU_Vol_Head));    
    memset(pFmt, 0, sizeof(struct ASDU_6_Fmt));    
    pFmt->head.type = 6;    
    pFmt->head.vsq.vsq = 0x81;    
    pFmt->head.cot = 8;    
    pFmt->head.addr = byaddr;    
    pFmt->head.fun = 0xff;    
    pFmt->head.inf = 0;    
    
    gettimeofday(&tv, NULL); 
	tp = localtime(&(tv.tv_sec)); 
	 
    pFmt->dataTime.year = (tp->tm_year + 1900) % 100;    
    pFmt->dataTime.month = tp->tm_mon + 1;    
    pFmt->dataTime.bay = tp->tm_mday;    
    pFmt->dataTime.week = 0;    
    pFmt->dataTime.time.Hours = tp->tm_hour;    
    pFmt->dataTime.time.Minutes = tp->tm_min;    
    uint16 wtmp = tp->tm_sec * 1000 + tv.tv_usec / 1000;    
    pFmt->dataTime.time.byLowMs = (uint8)(wtmp);    
    pFmt->dataTime.time.byHighMs = (uint8)(wtmp >> 8);    
    
    struct LPDU_Vol_Head *pHead = (struct LPDU_Vol_Head *)ptl103->m_bySend;    
    memset(pHead, 0, sizeof(struct LPDU_Vol_Head));    
    pHead->head1 = pHead->head2 = 0x68;    
    pHead->len1 = pHead->len2 = ASDU6Fmt_LEN + 2;    
    
    if(byaddr == 0xff)    
        pHead->ctrl.funcode = NoReply_code;    
    else    
        pHead->ctrl.funcode = SendCon_code;    
    
    pHead->ctrl.prm = 1;    
    pHead->addr = byaddr;    
    
    ptl103->m_wSendNum = sizeof(struct LPDU_Vol_Head) + ASDU6Fmt_LEN;    
    ptl103->m_bySend[ptl103->m_wSendNum ++] = Makecrc(ptl103->m_bySend + 4, pHead->len1);    
    ptl103->m_bySend[ptl103->m_wSendNum ++] = 0x16;    
    
    return 1;    
}    
    
//㲥 Уʱ    
uint8 BroadcastAdjustTime103(struct PtlData103 *ptl103)    
{    
	struct tm *tp; 
	struct timeval tv; 
	 
    struct ASDU_6_Fmt *pFmt = (struct ASDU_6_Fmt *)(ptl103->m_bySend + sizeof(struct LPDU_Vol_Head));    
    memset(pFmt, 0, sizeof(struct ASDU_6_Fmt));    
    pFmt->head.type = 6;    
    pFmt->head.vsq.vsq = 0x81;    
    pFmt->head.cot = 8;    
    pFmt->head.addr = 0xff;    
    pFmt->head.fun = 0xff;    
    pFmt->head.inf = 0;    
    
    gettimeofday(&tv, NULL); 
	tp = localtime(&(tv.tv_sec)); 
	 
    pFmt->dataTime.year = (tp->tm_year + 1900) % 100;    
    pFmt->dataTime.month = tp->tm_mon + 1;    
    pFmt->dataTime.bay = tp->tm_mday;    
    pFmt->dataTime.week = 0;    
    pFmt->dataTime.time.Hours = tp->tm_hour;    
    pFmt->dataTime.time.Minutes = tp->tm_min;    
    uint16 wtmp = tp->tm_sec * 1000 + tv.tv_usec / 1000;    
    pFmt->dataTime.time.byLowMs = (uint8)(wtmp);    
    pFmt->dataTime.time.byHighMs = (uint8)(wtmp >> 8);    
    
    struct LPDU_Vol_Head *pHead = (struct LPDU_Vol_Head *)ptl103->m_bySend;    
    memset(pHead, 0, sizeof(struct LPDU_Vol_Head));    
    pHead->head1 = pHead->head2 = 0x68;    
    pHead->len1 = pHead->len2 = ASDU6Fmt_LEN + 2;    
    pHead->ctrl.funcode = NoReply_code;    
    pHead->ctrl.prm = 1;    
    pHead->addr = 0xff;    
    
    ptl103->m_wSendNum = sizeof(struct LPDU_Vol_Head) + ASDU6Fmt_LEN;    
    ptl103->m_bySend[ptl103->m_wSendNum ++] = Makecrc(ptl103->m_bySend + 4, pHead->len1);    
    ptl103->m_bySend[ptl103->m_wSendNum ++] = 0x16;    
    
    return 1;    
}    
 
 
void QueryRecvLPDU(struct PtlData103 *ptl103)  
{  
	ptl103->m_wLinkLen = 0;  
}  
 
//·    
int PtlSendLPDU(struct PtlData103 *ptl103)    
{    
    start_timer(&ptl103->frame_timer);    
    
    // ׼    
    QueryRecvLPDU(ptl103);    
            
    // תӦò֡    
    if (SendNoreply == ptl103->m_lnkSvrCls)    
        ptl103->m_runStep = PtlRun_PackASDU;    
    else    
        ptl103->m_runStep = PtlRun_RecvLPDU;    
    
    return ptl103->m_wSendNum;    
}    
    
	   
// ·ݽ	  
void NoLPDU(struct PtlData103 *ptl103)	 
{    
   uint8 *pSend = ptl103->m_bySend;    
	int i; 
   uint8 addr = 0; 
    
   if (0x10 == pSend[0])    
   {    
	   struct LPDU_Fix_Fmt *pFmt = (struct LPDU_Fix_Fmt *)pSend;	  
	   addr = pFmt->addr;	 
   }    
   else    
   {    
	   struct LPDU_Vol_Head *pHead = (struct LPDU_Vol_Head *)pSend;	 
	   addr = pHead->addr;	  
   }    
 
  	uint8 byNodeID = ptl103->m_addrtoID[addr];    
    struct RealRunIED *pRunIed = ptl103->m_RunIed[byNodeID];  
	 
   if (pRunIed)    
   {    
	   pRunIed->linkRes = 1;    
	   pRunIed->lnkNoRecvCnt ++;    
	   if (pRunIed->lnkNoRecvCnt > 5)	 
	   {    
		   
	   }    
   }    
}    
//ѭѯ֡    
/****   
*PackCyc - ѭѯ֡   
*   
*ܣ   
*   1ܲѯ   
*   2¼   
*   3ͨ÷ܲѯ   
*   4ͨ2ݲѯ   
*   
****/    
void PackCyc(struct PtlData103 *ptl103)    
{    
    struct RealRunIED *pDevRun = ptl103->m_RunIed[ptl103->m_byCycCnt];    
    if (pDevRun)    
    {    
        if (!PackLinkCmm(ptl103, pDevRun))     
        {   // ·֡    
            /*   
            * Ӧò֡   
            *   
            *ȼ   
            * 1Ŷݴ   
            * 2ͨ÷ܲѯ   
            * 3ٻ   
            * 4ܲѯ(ٻ)   
            * 5ѭѯ2   
            **/    
            if(pDevRun->bCommInitFlag  && !pDevRun->acd)    
            {    
                if(eInitTime == pDevRun->step && pDevRun->nASDU5Cnt>=2)//Уʱ    
                {    
                    SlaveAdjustTime103(ptl103, pDevRun->byAddr);    
                }else if(eInitGenAsk == pDevRun->step)//ٻ    
                {    
                    Pack_Asdu_7(ptl103, pDevRun, pDevRun->byAddr);    
                }else    
                {    
                    unsigned char Code = CallClass2_code;    
                    PackLPDU_Fix(ptl103, pDevRun, Code);    
                }    
            }else if (!pDevRun->acd && pDevRun->query && !pDevRun->bCommInitFlag)     
            {    
               // if (!pDevRun->queryFull)    
               // { 
                		// ٻ    
                    //if(pDevRun->pDevData->m_IEDConfig.nDdNum > 0)    
                      //  Pack_Asdu_88(ptl103->m_byCycCnt);    
               // }else// ٻ    
                    Pack_Asdu_7(ptl103, pDevRun, pDevRun->byAddr);    
    
                // ѯ־    
                pDevRun->query = 0;    
            }else if(IsOverTime(&ptl103->synctm_timer)&& !pDevRun->bCommInitFlag)//Уʱ    
            {    
                start_timer(&ptl103->synctm_timer);    
                unsigned char byaddr = 0xff;    
                SlaveAdjustTime103(ptl103, byaddr);    
                ptl103->AdjustTimeFlag = 1;    
            }    
            else    
            {                       // ͨòѯ    
                unsigned char byCode = CallClass2_code;    
                if (pDevRun->acd)     
                    byCode = CallClass1_code;    
    
                PackLPDU_Fix(ptl103, pDevRun, byCode);    
            }           
        }       
    }    
    ptl103->m_byCycCnt = (ptl103->m_byCycCnt+1) % CH_MAX_IED_NUM;    
}    
    
//֡    
int Frame(struct PtlData103 *ptl103, unsigned char *SendBuf, int Len)    
{    
	int nret = -1; 
	int i; 
	 
   // ٻ/ٻʱ    
    if (IsOverTime(&ptl103->query_timer))    
    {    
        start_timer(&ptl103->query_timer);    
        for (i = 0; i < CH_MAX_IED_NUM; i++)    
        {    
            struct RealRunIED *pRunIED = ptl103->m_RunIed[i];    
            if(pRunIED)    
            {    
                pRunIED->queryFull ^= 1; // ѯ־ȡ    
                pRunIED->query = 1;    
            }    
        }    
    }   
	 
    /*Ӧò֡   
    * 1) ͨ   
    * 2) ͨѭ   
    */    
    if (PtlRun_PackASDU == ptl103->m_runStep)    
    {    
        // Ҫ֡    
        ptl103->m_wSendNum = 0;    
        ptl103->m_wLinkLen = 0;    
    
        // ʼԭ    
        memset(&ptl103->m_prmSend, 0, sizeof(struct CommPrim));    
        memset(&ptl103->m_prmRecv, 0, sizeof(struct CommPrim));    
    
        // ͨ    
        if (!PackTask(ptl103))     
        {       
            PackCyc(ptl103);              // ѭѯ    
        }    
        // ת·֡͹    
        ptl103->m_bySendCnt = 0;    
        if (ptl103->m_wSendNum > 0)    
            ptl103->m_runStep = PtlRun_SendLPDU;    
    }    
    
    // ֱת·չ    
    /*if (!lpCh->m_pDevDB->GetCcsModule( ))   
    {   
        pPtlData->m_runStep = PtlRun_RecvLPDU;   
        QueryRecvLPDU(lpCh);   
    }*/    
    
    // ȴ·    
    if (PtlRun_RecvLPDU == ptl103->m_runStep)    
    {    
        if (IsOverTime(&ptl103->frame_timer))    
        {    
            ptl103->m_bySendCnt ++;    
            if (ptl103->m_bySendCnt > 2)    
            {    
                NoLPDU(ptl103);    
                ptl103->m_runStep = PtlRun_PackASDU;    
            }    
            else    
                ptl103->m_runStep = PtlRun_SendLPDU;    
        }    
		nret = 0; 
    }    
    
    // ·㷢    
    if (PtlRun_SendLPDU == ptl103->m_runStep)    
    {    
        // ,    
        //if (lpCh->m_pDevDB->GetCcsModule( ))    
        //{    
            // ȴʱ     
            if(ptl103->AdjustTimeFlag)    
            {    
                ptl103->AdjustTimeFlag = 0;    
                ptl103->m_runStep = PtlRun_PackASDU;    
                nret = ptl103->m_wSendNum;    
            }else    
                nret = PtlSendLPDU(ptl103);    
			 
            memcpy(SendBuf, ptl103->m_bySend, nret);    
        //}    
    }   
	//printf("nret=%d\n", nret); 
    return nret;    
}   
    
// ʱı()    
void Unpack_Asdu_1(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
#if 0 
    int nIndex;    
    TASK *pTask = NULL;    
    CIED *pIED = pRunIed->pDevData;    
    uint8 byNodeID = pIED->m_IEDConfig.byNodeID;    
    
    ASDU_1_Fmt *pFmt = (ASDU_1_Fmt *)buf;    
    //ʱ    
    WB_UNION wb;    
    wb.bwUnion.byVal[0] = pFmt->tm.byHighMs;    
    wb.bwUnion.byVal[1] = pFmt->tm.byLowMs;    
    
    uint8 yxBit = (pFmt->dpi & 0x03) >> 1;    
    // ȷϱ(϶/)    
    if (M_AFM_ORD == pFmt->head.cot || M_NEG_ORD == pFmt->head.cot)     
    {    
        if((WatchTask(pTask, taskCmdYkSelect, byNodeID) ||    
            WatchTask(pTask, taskCmdYkExecute, byNodeID) ||    
            WatchTask(pTask, taskCmdYkCancel, byNodeID)) && pTask)    
        {    
            // ң    
            YK_COMMAND *pCommand = (YK_COMMAND *)pTask->iUserData;    
            nIndex = GetnIndexbyFuninf(pIED, dataYk, pFmt->head.funInf);    
            if(nIndex >= 0)    
            {    
                if (nIndex != pCommand->byYkNode || M_NEG_ORD == pFmt->head.cot)     
                {    
                    if (pCommand->byAction == yk_PrevH ||pCommand->byAction == yk_PrevF)    
                        pCommand->eReturn = fj_wrong;    
                    else    
                        pCommand->eReturn = act_wrong;    
                    pTask->eTaskReturn=retWrong;    
                }    
                else    
                {    
                    if (pCommand->byAction == yk_PrevH ||pCommand->byAction == yk_PrevF)    
                        pCommand->eReturn = fj_right;    
                    else    
                        pCommand->eReturn = act_right;    
                    pTask->eTaskReturn=retRight;    
                }    
                pTask->eRespType = taskCmdYkReturn;    
                m_pCH->TaskResp(pTask);    
                //m_pCH->m_pTaskQue->UnLockTask();    
            }    
        }    
        else if(WatchTask(pTask, taskCmdBhReset, byNodeID) && pTask)    
        {//     
        /*  if (M_NEG_ORD == pFmt->head.cot)   
                pTask->iUserData[0] = retWrong;   
            else   
                pTask->iUserData[0] = retRight;   
   
            pTask->eRespType = taskRespBhReset;   
            m_pCH->TaskResp(pTask);   
            m_pCH->m_pTaskQue->UnLockTask();   
        */}    
        // ͨ()    
        else if(WatchTask(pTask, taskChThree, byNodeID) && pTask)     
        {    
            /*   
            *    
            *=======================================================   
            *                     ƫ             ռλռ       
            *-------------------------------------------------------   
            *   Ӧܳ         01             2   
            *   **103ܸ֡N        23             2   
            *-------------------------------------------------------   
            *   **103֡1ܳL1  4                   1   
            *   **103֡1           5L1+5              L1   
            *   **103֡2ܳL2  L1+6                1   
            *   **103֡2           L17L178     L2   
            *   **       
            *   **103֡2ܳLN  X                   1   
            *   **103֡N           XXLN          LN   
            */    
            pTask->pbyBuff = g_pTaskDataBuff->QueryBuf(pTask->byDataBufIndex);//ռ    
            if(pTask->pbyBuff == NULL)    
                return;    
            pTask->nDataBufLen = 0;    
            pTask->bWithDataF = 1;    
            if(SaveTaskRespFmt(buf - sizeof(struct LPDU_Vol_Head), len + 8, pTask))    
            {    
                pTask->eRespType = taskZF;    
                m_pCH->TaskResp(pTask);    
                //m_pCH->m_pTaskQue->UnLockTask();    
            }    
        }    
    }    
    // ͨݴ    
    else     
    {    
        // /ģʽ(洢)    
        uint8 bStateChg = 0;    
        eDataSort data;    
        nIndex = GetnIndexbyFuninf(pIED, dataYx, pFmt->head.funInf);//ȡʵңŵ    
        data = dataYx;    
        if(nIndex == -1)    
        {    
            nIndex = GetnIndexbyFuninf(pIED, dataBhYx, pFmt->head.funInf);//ȡң    
            data = dataBhYx;    
        }    
        TIME_STRUCT sysTime;    
        g_pMainApp->GetSystime(&sysTime);    
        if(data == dataBhYx)    
        {    
            //    
            BHEVENT_STRUCT bhevent;    
            bhevent.eDS=(eDataSource)m_pCH->m_ChConfig.eDS;          // Դ    
            bhevent.nIEDType=iedXUJI103;                            // װ    
            bhevent.eEventType=dataBh;                              // (    
            bhevent.nEventNode=nIndex;                              //     
            bhevent.nNode=pIED->m_IEDConfig.byNodeID;    
            bhevent.nEventVal=0x10;    
            if(yxBit == 1)    
                bhevent.nEventVal = 0x01;    
            bhevent.nFunCode=bhevent.nEventVal;// ֵ    
    
            bhevent.TimeStamp.nMs = wb.bwUnion.wVal % 1000;    
            bhevent.TimeStamp.bySecond = wb.bwUnion.wVal / 1000;    
            bhevent.TimeStamp.byMinute = pFmt->tm.Minutes;    
            bhevent.TimeStamp.byHour     = pFmt->tm.Hours;    
            bhevent.TimeStamp.byDay    = sysTime.byDay;    
            bhevent.TimeStamp.byMonth  = sysTime.byMonth;    
            bhevent.TimeStamp.nYear    = sysTime.nYear;    
    
            memcpy(bhevent.byUserData, buf, len);                   //    
            bhevent.nUserDataLen = len;                         //¼ݻ    
    
            m_pCH->m_pBhSoeQue->Add(bhevent);    
    
            if(!m_IEC103PtlPara.bEventVirtualYX)//,Ҫתң    
                return;    
        }    
        // ңűλб    
        uint8 byYXRecvVal = pIED->GetDataRecvVal(data,0,nIndex);    
        if (nIndex >= 0)     
        {    
            if (byYXRecvVal != yxBit)    
                bStateChg = 1;    
        }    
        
        // ңŴ洢    
        if (nIndex >= 0)//ңֵ    
            pIED->SetDataRecvVal(data,0,nIndex,yxBit);    
        // 洢ȴ    
        if (bStateChg)     
        {       
            // ңűλ洢    
            // 洢    
            EVENT_STRUCT bhent;    
    
            bhent.eDS        = (eDataSource)m_pCH->m_ChConfig.eDS;   // Դ    
            bhent.eEventType = data;                    // (ࣩ    
            bhent.nEventNode = nIndex;                  //     
            bhent.nEventVal  = 0x10;                    // ֵ    
            if(yxBit == 1)    
                bhent.nEventVal = 0x01;    
            bhent.nNode      = pIED->m_IEDConfig.byNodeID;// 豸ڵ    
            bhent.TimeStamp.nMs = wb.bwUnion.wVal % 1000;    
            bhent.TimeStamp.bySecond = wb.bwUnion.wVal / 1000;    
            bhent.TimeStamp.byMinute = pFmt->tm.Minutes;    
            bhent.TimeStamp.byHour   = pFmt->tm.Hours;    
            bhent.TimeStamp.byDay    = sysTime.byDay;    
            bhent.TimeStamp.byMonth  = sysTime.byMonth;    
            bhent.TimeStamp.nYear    = sysTime.nYear;    
                
            m_pCH->m_pYxbwSoeQue->Add(bhent);    
            m_pCH->m_pYxSoeQue->Add(bhent);       
        }    
    }    
	#endif 
}    
    
// ʱʱ걨,103DZ    
void Unpack_Asdu_2(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
#if 0	 
    ASDU_2_Fmt *pFmt = (ASDU_2_Fmt *)buf;    
    TIME_STRUCT sysTime;    
    g_pMainApp->GetSystime(&sysTime);    
    //ֵ    
    WB_UNION wb;    
    wb.bwUnion.byVal[0] = pFmt->ret.byHigh;    
    wb.bwUnion.byVal[1] = pFmt->ret.byLow;    
    
    wb.bwUnion.byVal[0] = pFmt->fan.byHigh;    
    wb.bwUnion.byVal[1] = pFmt->fan.byLow;    
    
    
    CIED *pIED = pRunIed->pDevData;    
    if(pIED == NULL)    
        return;    
    
    eDataSort data;    
    int nIndex = GetnIndexbyFuninf(pIED, dataBhYx, pFmt->head.funInf);//ȡң    
    data = dataBhYx;    
    if(nIndex == -1)    
        return;    
    
    uint8 yxBit = (pFmt->dpi & 0x03) >> 1;//ң    
    
    //    
    BHEVENT_STRUCT bhevent;    
    bhevent.eDS=(eDataSource)m_pCH->m_ChConfig.eDS;          // Դ    
    bhevent.nIEDType=iedXUJI103;                            // װ    
    bhevent.eEventType=dataBh;                              // (    
    bhevent.nEventNode=nIndex;                              //     
    bhevent.nNode=pIED->m_IEDConfig.byNodeID;    
    bhevent.nEventVal=0x10;    
    if(yxBit == 1)    
        bhevent.nEventVal = 0x01;    
    bhevent.nFunCode=bhevent.nEventVal;// ֵ    
    
    wb.bwUnion.byVal[0] = pFmt->tm.byHighMs;    
    wb.bwUnion.byVal[1] = pFmt->tm.byLowMs;    
    
    bhevent.TimeStamp.nMs = wb.bwUnion.wVal % 1000;    
    bhevent.TimeStamp.bySecond = wb.bwUnion.wVal / 1000;    
    bhevent.TimeStamp.byMinute = pFmt->tm.Minutes;    
    bhevent.TimeStamp.byHour     = pFmt->tm.Hours;    
    bhevent.TimeStamp.byDay    = sysTime.byDay;    
    bhevent.TimeStamp.byMonth  = sysTime.byMonth;    
    bhevent.TimeStamp.nYear    = sysTime.nYear;    
    
    memcpy(bhevent.byUserData, buf, len);                   //    
    bhevent.nUserDataLen = len;                         //¼ݻ    
    
    m_pCH->m_pBhSoeQue->Add(bhevent);    
    
    if(!m_IEC103PtlPara.bEventVirtualYX)//,Ҫתң    
        return;    
    
    uint8 byYXRecvVal = pIED->GetDataRecvVal(data,0,nIndex);    
    //  if(byYXRecvVal != yxbit)    
    {    
        //ñң״̬    
        pIED->SetDataRecvVal(data,0,nIndex,yxBit);    
        // 洢    
        EVENT_STRUCT bhent;    
    
        bhent.eDS        = (eDataSource)m_pCH->m_ChConfig.eDS;   // Դ    
        bhent.eEventType = data;                    // (ࣩ    
        bhent.nEventNode = nIndex;                  //     
        bhent.nEventVal  = 0x10;                    // ֵ    
        if(yxBit == 1)    
            bhent.nEventVal = 0x01;    
        bhent.nNode      = pIED->m_IEDConfig.byNodeID;// 豸ڵ    
        bhent.TimeStamp.nMs = wb.bwUnion.wVal % 1000;    
        bhent.TimeStamp.bySecond = wb.bwUnion.wVal / 1000;    
        bhent.TimeStamp.byMinute = pFmt->tm.Minutes;    
        bhent.TimeStamp.byHour   = pFmt->tm.Hours;    
        bhent.TimeStamp.byDay    = sysTime.byDay;    
        bhent.TimeStamp.byMonth  = sysTime.byMonth;    
        bhent.TimeStamp.nYear    = sysTime.nYear;    
            
        m_pCH->m_pYxbwSoeQue->Add(bhent);    
        m_pCH->m_pYxSoeQue->Add(bhent);       
    }    
#endif 
}    
    
// ֵIʽ    
void Unpack_Asdu_3(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{       
}    
    
// ʱʱıֵ,103Уasdu4DZģתҡ    
void Unpack_Asdu_4(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{   
 
}    
    
// ʶ    
void Unpack_Asdu_5(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
}    
    
// ʱͬ    
void Unpack_Asdu_6(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
}    
    
// ܲѯ(ٻ)    
void Unpack_Asdu_8(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
}    
    
// ͨ÷    
void Unpack_Asdu_10(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
     
}    
    
// ͨ÷ʶ    
void Unpack_Asdu_11(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
}    
    
// ¼Ŷ    
void Unpack_Asdu_23(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
}    
    
// Ŷݴ׼    
void Unpack_Asdu_26(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
}    
    
// ¼ͨ׼    
void Unpack_Asdu_27(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
}    
    
// ־״̬λĴ׼    
void Unpack_Asdu_28(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
}    
    
// ־״̬λ    
void Unpack_Asdu_29(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
}    
    
// Ŷֵ    
void Unpack_Asdu_30(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
}    
    
// Ŷݴ    
void Unpack_Asdu_31(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
}    
    
// ʱıֵIII    
void Unpack_Asdu_32(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
}    
    
// ʱıֵIV    
void Unpack_Asdu_33(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
}    
    
// ʱV    
void Unpack_Asdu_34(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
}    
    
// ʱVI    
void Unpack_Asdu_35(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
}    
    
//     
void Unpack_Asdu_36(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
      
}    
    
// ʱĵ    
void Unpack_Asdu_37(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
     
}    
    
// λϢ    
void Unpack_Asdu_38(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
}    
    
// ʱIJλϢ    
void Unpack_Asdu_39(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
     
}    
    
//ҡ    
void Unpack_Asdu_4042(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
#if 0 
 
    int i, nCnt = 0;    
    ASDU_Head *pHead = (ASDU_Head *)buf;    
    uint8 bSPI;    
    uint8 yxBit;    
    if(M_SP_NA_3 == pHead->type)    
        bSPI = 1;    
    else if(M_DP_NA_3 == pHead->type)    
        bSPI = 0;    
    CIED *pIED = pRunIed->pDevData;    
        
    struct FunInf funInf = pHead->funInf;    
    for (i = 0, nCnt = sizeof(ASDU_Head); i < pHead->vsq.num; i++)    
    {    
        if(nCnt >= len)    
            break;    
        if (bSPI)    
            yxBit = (buf[nCnt ++]) & 0x01;    
        else    
            yxBit = (buf[nCnt ++] & 0x03) >> 1;    
    
        SaveCeKongYaoXin(pRunIed, funInf, yxBit);    
        if (pHead->vsq.sq)    
            funInf.inf = buf[nCnt ++];    
        else    
            funInf.inf ++;    
    }   
#endif 
}    
    
//ҡ״̬λʱ    
void Unpack_Asdu_4143(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
      
}    
    
void Unpack_Asdu_4446(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
    int i,j,nCnt=0;    
    uint8 yxBit;    
	uint16 tmp; 
	int nIndex; 
    struct ASDU_Head *pHead = (struct ASDU_Head *)buf;    
    uint8 bSPI;  
	 
	if(pRunIed->yxAddr == 0xffff) 
		return; 
	 
    if(M_SS_NA_3 == pHead->type)    
        bSPI = 1;    
    else if(M_DS_NA_3 == pHead->type)    
        bSPI = 0;    
    
    struct FunInf funInf = pHead->funInf;    
    for (i = 0, nCnt = sizeof(struct ASDU_Head); i < pHead->vsq.num; i++)    
    {    
        if(nCnt >= len)    
            break;    
   
        if (bSPI)    
        {    
            for (j = 0; j < 8; j++)    
            {    
                yxBit = (buf[nCnt] >> j) & 1;   
				nIndex = GetnIndexbyFuninf(pRunIed->devname, funInf); 
				if(nIndex >= 0) 
                	saveYXtoREG(pRunIed->yxAddr + nIndex, yxBit);    
                funInf.inf ++;    
            }    
            for (j = 0; j < 8; j++)    
            {    
                yxBit = (buf[nCnt + 1] >> j) & 1;    
				nIndex = GetnIndexbyFuninf(pRunIed->devname, funInf); 
				if(nIndex >= 0) 
                	saveYXtoREG(pRunIed->yxAddr + nIndex, yxBit);    
                funInf.inf ++;    
            }    
        }    
        
    
        nCnt += sizeof(struct SCD);    
        nCnt += sizeof(struct QDS);    
    }    
}    
    
void Unpack_Asdu_4547(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
     
}    
    
// ˮλ    
void Unpack_Asdu_48(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
}    
    
// IIʽ    
void Unpack_Asdu_9(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{       
     
}    
    
void Unpack_Asdu_50(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
 
    int i,nIndex, nCnt = 0;    
    struct ASDU_Head *pHead = (struct ASDU_Head *)buf;    
    short nVal = 0;    
	uint16 tmp; 
 
    if(pRunIed->ycAddr == 0xffff) 
		return; 
	 
    // ֵ洢    
    struct FunInf funInf = pHead->funInf;    
    for (i = 0, nCnt = sizeof(struct ASDU_Head); i < pHead->vsq.num && nCnt < len; i++)     
    {    
        nIndex = GetnIndexbyFuninf(pRunIed->devname, funInf);    
    
        struct MEA mea;    
		tmp = buf[nCnt + 1] * 256 + buf[nCnt]; 
           
        mea.mea.wVal = tmp;    
        if(mea.mea.wVal & 0x8000)    
            nVal= 0xF000|mea.mea.mval;    
        else    
            nVal=mea.mea.mval;    
            
        if (nIndex >= 0)     
            saveYCtoREG(pRunIed->ycAddr + nIndex, nVal);    
    
        nCnt += sizeof(struct MEA);    
        if (!pHead->vsq.sq)    
            funInf.inf ++;    
        else    
            funInf.inf = *(buf + nCnt++);    
    }    
}    
    
// ң    
void Unpack_Asdu_64(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
    
}    
    
//     
void Unpack_Asdu_65(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
}    
    
// 趨    
void Unpack_Asdu_66(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
}    
    
//     
void Unpack_Asdu_67(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
}    
// 103Уasdu70DZ    
void Unpack_Asdu_70(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
     
}    
    
// ϵͳϢ    
void Unpack_Asdu_88(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
}    
    
//VQCװͱʽ    
void Unpack_Asdu_49(uint8* buf, uint8 len, struct RealRunIED *pRunIed)    
{    
      
}    
/*****   
*UnpackASDU_Ied - Ӧò֡   
*   
*ܣ   
*   Ӧ÷ݵԪ֡    
*   
******/    
void UnpackASDU_Ied(uint8 *pRecvBuf, struct RealRunIED *pRunIed)    
{    
    //     
    if (!pRunIed)    
        return;    
    
    struct ASDU_Head *pHead = (struct ASDU_Head *)(pRecvBuf + sizeof(struct LPDU_Vol_Head));    
    
    uint8 *buf = pRecvBuf + sizeof(struct LPDU_Vol_Head);    
    uint8  len = pRecvBuf[1] - 2;    
	printf("TYPE : %d \n", pHead->type); 
    switch (pHead->type)    
    {    
    case M_TM_TA_3:    
        Unpack_Asdu_1(buf, len, pRunIed);    
        break;    
    case M_TMR_TA_3:    
        Unpack_Asdu_2(buf, len, pRunIed);    
        break;    
    case M_GD_NTA_3:    
        Unpack_Asdu_10(buf, len, pRunIed);    
        break;    
    case M_MEVII_NA_3:    
        Unpack_Asdu_50(buf, len, pRunIed);    
        break;    
    case M_IT_NA_3:    
        Unpack_Asdu_36(buf, len-1, pRunIed);    
        break;    
    case M_IT_TA_3:    
        Unpack_Asdu_37(buf, len-1, pRunIed);    
        break;    
    case M_MEI_NA_3:    
        Unpack_Asdu_3(buf, len, pRunIed);    
        break;    
    case M_TME_TA_3:    
        Unpack_Asdu_4(buf, len, pRunIed);    
        break;    
    case M_IRC_NA_3:    
        {    
            Unpack_Asdu_5(buf, len, pRunIed);    
            if(pRunIed->step == eInitStart)    
            {    
                pRunIed->nASDU5Cnt++;    
                if(pRunIed->nASDU5Cnt >= 2)    
                    pRunIed->step = eInitTime;    
            }    
            break;    
        }    
    case M_SYN_TA_3://ʱͬ    
        Unpack_Asdu_6(buf, len, pRunIed);    
        if(eInitTime == pRunIed->step)    
            pRunIed->step = eInitGenAsk;    
        break;    
    case M_TGI_NA_3://н    
        Unpack_Asdu_8(buf, len, pRunIed);    
        if(eInitGenAsk == pRunIed->step)    
        {    
            pRunIed->step = eInitEnd;    
            pRunIed->bCommInitFlag = 0;    
            pRunIed->nASDU5Cnt = 0;    
        }    
        break;    
    case M_MEII_NA_3:    
        Unpack_Asdu_9(buf, len, pRunIed);    
        break;    
    case M_GI_NTA_3:    
        Unpack_Asdu_11(buf, len, pRunIed);    
        break;    
    case M_LRT_TA_3:    
        Unpack_Asdu_23(buf, len, pRunIed);    
        break;    
    case M_RTD_TA_3:    
        Unpack_Asdu_26(buf, len, pRunIed);    
        break;    
    case M_RTC_NA_3:    
        Unpack_Asdu_27(buf, len, pRunIed);    
        break;    
    case M_RTT_NA_3:    
        Unpack_Asdu_28(buf, len, pRunIed);    
        break;    
    case M_TDT_TA_3:    
        Unpack_Asdu_29(buf, len, pRunIed);    
        break;    
    case M_TDN_NA_3:    
        Unpack_Asdu_30(buf, len, pRunIed);    
        break;    
    case M_EOT_NA_3:    
        Unpack_Asdu_31(buf, len, pRunIed);    
        break;    
    case M_MEIII_TA_3:    
        Unpack_Asdu_32(buf, len, pRunIed);    
        break;    
    case M_MEIV_TA_3:    
        Unpack_Asdu_33(buf, len, pRunIed);    
        break;    
    case M_MEV_TA_3:    
        Unpack_Asdu_34(buf, len, pRunIed);    
        break;    
    case M_MEVI_TA_3:    
        Unpack_Asdu_35(buf, len, pRunIed);    
        break;    
    case M_ST_NA_3:    
        Unpack_Asdu_38(buf, len, pRunIed);    
        break;    
    case M_ST_TA_3:    
        Unpack_Asdu_39(buf, len, pRunIed);    
        break;    
    case M_SP_NA_3:    
    case M_DP_NA_3:    
        Unpack_Asdu_4042(buf, len-1, pRunIed);    
        break;    
    case M_SP_TA_3:    
    case M_DP_TA_3:    
        Unpack_Asdu_4143(buf, len-1, pRunIed);    
        break;    
    case M_SS_NA_3:    
    case M_DS_NA_3:    
        Unpack_Asdu_4446(buf, len-1, pRunIed);    
        break;    
    case M_SS_TA_3:    
    case M_DS_TA_3:    
        Unpack_Asdu_4547(buf, len-1, pRunIed);    
        break;    
    case M_WL_TA_3:    
        Unpack_Asdu_48(buf, len, pRunIed);    
        break;    
    case M_DC_NA_3:    
        Unpack_Asdu_64(buf, len, pRunIed);    
        break;    
    case M_RC_NA_3:             
        Unpack_Asdu_65(buf, len, pRunIed);    
        break;    
    case M_SE_NA_3:    
        Unpack_Asdu_66(buf, len, pRunIed);    
        break;    
    case M_CC_NA_3:    
        Unpack_Asdu_67(buf, len, pRunIed);    
        break;    
    case M_ASDU_70:    
        Unpack_Asdu_70(buf, len, pRunIed);    
        break;    
    case M_CI_NA_3:    
        Unpack_Asdu_88(buf, len, pRunIed);    
        break;    
    case 0x31://VQCװͱʽ    
    //  Unpack_Asdu_49(buf, len, pRunIed);    
    default:    
        break;    
    }    
}    
    
//·֡    
void UnpackLPDU(struct PtlData103 *ptl103, uint8 *pRecvBuf)    
{    
    // ·֡    
    uint8 *pRecv = pRecvBuf;    
        
    struct LinkCtrl lnkCtrl;    
    uint8     addr;  
	 
    // ̶֡    
    if (0x10 == pRecv[0])    
    {       
        struct LPDU_Fix_Fmt *pFmt = (struct LPDU_Fix_Fmt *)pRecv;    
        lnkCtrl = pFmt->ctrl;    
        addr = pFmt->addr;    
    }    
    else    
    {   // ɱ֡    
        struct LPDU_Vol_Head *pHead = (struct LPDU_Vol_Head *)pRecv;    
        lnkCtrl = pHead->ctrl;    
        addr = pHead->addr;    
    }    
        
    uint8 bACD = 0;    
    uint8 byNodeID = ptl103->m_addrtoID[addr];    
    struct RealRunIED *pRunIed = ptl103->m_RunIed[byNodeID];    
    if (pRunIed)    
    {    
        // ·ָ    
        if (pRunIed->linkRes)    
        {    
            pRunIed->linkRes = pRunIed->linkQuery = pRunIed->fcb = 0;    
            pRunIed->queryFull = pRunIed->query = 1;    
    
            // ͨѶָ    
            pRunIed->lnkNoRecvCnt = 0;    
            //CIED *pIED = pRunIed->pDevData;    
            //DevYxPara devYx = pBayDev->GetDevYxPara();    
            //pBayDev->SetYaoXinRecvVal(devYx.wComYxId, 0);    
        }       
        if (0x68 == pRecv[0])    
        {       
            UnpackASDU_Ied(pRecvBuf, pRunIed);    
        }    
    
        pRunIed->acd = lnkCtrl.fcbAcd;    
        pRunIed->linkQuery = lnkCtrl.fcvDfc;    
    
        if(pRunIed->acd)//080905޸ģӦֳҪ1̲ѯٵȵһ    
        {    
            ptl103->m_byCycCnt = byNodeID;    
            bACD = 1;    
        }    
    }    
    //if(!bACD)//080905޸ģӦֳҪ1̲ѯٵȵһ    
    //  ptl103->m_byCycCnt = (ptl103->m_byCycCnt+1) % CH_MAX_IED_NUM;    
    
    // ת֡    
    ptl103->m_runStep = PtlRun_PackASDU;    
}    
    
//Լ    
void PtlSearch(struct PtlData103 *ptl103, uint8 *pRecvBuf, int nLen)    
{       
    uint8 *pbyhead = NULL;   
	int nCnt; 
	 
    for(nCnt=0; nCnt<nLen; nCnt++)    
    {    
        if(0x10 == pRecvBuf[nCnt] || 0x68 == pRecvBuf[nCnt])//֡ͷ    
        {    
            pbyhead = pRecvBuf + nCnt;    
            break;    
        }    
    }    
    uint8 bySum = 0;    
    if(pbyhead != NULL)    
    {    
        uint8 bLnkUnpack = 0;    
        if(0x10 == pbyhead[0])          //̶֡    
        {    
            bySum = pbyhead[1] + pbyhead[2];    
            if(bySum == pbyhead[3] && 0x16 == pbyhead[4])    
            {    
                bLnkUnpack = 1;    
                ptl103->m_wLinkLen = 5;    
            }    
            else    
                ptl103->m_lnkSerialError ++;    
        }else if(0x68 == pbyhead[0])    //ɱ֡    
        {    
            if (pbyhead[3] == pbyhead[0] && pbyhead[1] == pbyhead[2])     
            {    
            	 
                uint8 byLnkLen = pbyhead[1];    
                bySum = Makecrc(pbyhead + 4, pbyhead[1]);    
                if(bySum == pbyhead[byLnkLen + 4] && 0x16 == pbyhead[byLnkLen + 4 + 1])    
                {    
                    bLnkUnpack = 1;    
                    ptl103->m_wLinkLen = 4 + 2 + byLnkLen;     
                }    
                else    
                    ptl103->m_lnkSerialError ++;    
            }    
            else    
                ptl103->m_lnkSerialError ++;    
        }    
        if(bLnkUnpack)              //ʼ֡    
        {    
            // ·֡    
            UnpackLPDU(ptl103, pbyhead);    
            QueryRecvLPDU(ptl103);    
            ptl103->m_lnkSerialError = 0;    
        }    
    }    
}    
 
void UnFrame(struct PtlData103 *ptl103, uint8* pRecvBuf, int nLen)    
{    
    //if (PtlRun_RecvLPDU == ptl103->m_runStep)    
    {    
        PtlSearch(ptl103, pRecvBuf, nLen);       
    }    
}  
uint8 CreateRealRunIED(struct PtlData103 *ptl103, uint8 byNodeId, uint8 addr, uint16 yc_addr, uint16 yx_addr, char *devname)    
{    
    struct RealRunIED *pDevRun = ptl103->m_RunIed[byNodeId];    
 
    if (!pDevRun)    
    {    
        pDevRun = (struct RealRunIED *)malloc(sizeof(struct RealRunIED));;//Լ˳Ҫͷ    
        if (pDevRun)    
            ptl103->m_RunIed[byNodeId] = pDevRun;    
    }    
    
    if (!pDevRun)    
        return -1;    
 
	 
    memset(pDevRun, 0, sizeof(struct RealRunIED));    
   	pDevRun->byAddr = addr; 
	pDevRun->ycAddr = yc_addr; 
	pDevRun->yxAddr = yx_addr; 
	pDevRun->devname = devname; 
	pDevRun->byNodeId = byNodeId;    
	pDevRun->mode = 0;       
	pDevRun->fcb = 0;        
	pDevRun->acd = 0;        
	pDevRun->sendCode = pDevRun->recvCode = 0;    
	pDevRun->linkQuery   = 0;   
	pDevRun->linkRes= 1;    
	pDevRun->query   = 0;    
	pDevRun->queryFull= 0;    
	pDevRun->sin = 0;    
	pDevRun->lnkNoRecvCnt = 0;    
	pDevRun->bCommInitFlag = 1;    
	pDevRun->nASDU5Cnt = 0;    
	pDevRun->step = eInitStart;    
 
   	ptl103->m_addrtoID[addr] = byNodeId; 
    return 0;    
}    
//Լʼ    
struct PtlData103 *InitPtl(void)    
{    
    struct PtlData103 *ptl103; 
	int i; 
	 
	ptl103 = (struct PtlData103 *)malloc(sizeof(struct PtlData103)); 
	memset(ptl103, 0, sizeof(struct PtlData103)); 
	for(i = 0; i < CH_MAX_IED_NUM; i++){ 
		ptl103->m_RunIed[i] == NULL; 
	} 
	 
    // Լв     
    ptl103->m_runStep = PtlRun_PackASDU;    
    
    ptl103->m_byCycCnt = 0;    
     
    // ԭ    
    memset(&ptl103->m_prmSend, 0, sizeof(struct CommPrim));    
    memset(&ptl103->m_prmRecv, 0, sizeof(struct CommPrim));    
        
    // շ    
    ptl103->m_wLinkLen = 0;      
    ptl103->m_wSendNum = 0;    
        
    ptl103->AdjustTimeFlag = 0; 
        
    // ͨݽռӣ    
    ptl103->m_lnkSerialError = 0;    
    ptl103->m_bySendCnt = 0;       
    ptl103->m_bySin = 0;           
    memset(&ptl103->m_OldCmd, 0, sizeof(ptl103->m_OldCmd));    
            
    QueryRecvLPDU(ptl103);    
    
	return ptl103; 
}    
 
void create_103_device(struct PtlData103 *ptl103, PCL_PORT *pcl_port, int com_fd) 
{ 
	PCL_DEV *pcl_dev; 
	PCL_MODADDR *pcl_modaddr; 
	DEVICE *dev; 
	pthread_mutex_t lock; 
	uint8 byNodeId = 0; 
 
	pthread_mutex_init(&lock, NULL); 
	ptl103->lock = &lock; 
	ptl103->fd = com_fd; 
	ptl103->frame_timer.time_out = pcl_port->frame_timeout; 
	ptl103->query_timer.time_out = pcl_port->query_timeout * 1000; 
	ptl103->synctm_timer.time_out = pcl_port->synctm_timeout * 1000; 
	 
	for(pcl_dev = (PCL_DEV *)list_find_last((DBL_LNK *)pcl_port->devHead); 
	      pcl_dev != NULL; 
	      pcl_dev = (PCL_DEV *)list_find_prev((DBL_LNK *)pcl_port->devHead, (DBL_LNK *)pcl_dev)) 
 	{	 
 		 
 		if(byNodeId == CH_MAX_IED_NUM) 
			break; 
		CreateRealRunIED(ptl103, byNodeId++, pcl_dev->devaddr, pcl_dev->yc_addr, pcl_dev->yx_addr, pcl_dev->devname); 
	} 
 
	start_timer(&ptl103->query_timer); 
	start_timer(&ptl103->synctm_timer); 
} 
 
void com_thread_func(char *arg) 
{ 
	PCL_PORT *pcl_port = (PCL_PORT *)arg; 
	int i; 
	int len; 
	uart_para MY_COM; 
	int com_fd; 
	int hn_fd; 
	char hostname[20]; 
	uint8 sbuf[MAX_BUF_SIZE]; 
	uint8 rbuf[MAX_BUF_SIZE]; 
	 
	struct PtlData103 *ptl103; 
 
	hn_fd = open("/proc/sys/kernel/hostname", O_RDWR); 
	if(hn_fd < 0){ 
		printf("--open hostname failed\n"); 
	} 
	len = read(hn_fd, hostname, 20); 
	if(len > 0){ 
		printf("hostname[%d] = %s\n", len, hostname); 
		if(strncmp("cce_d2800", hostname, strlen("cce_d2800")) == 0) 
			sprintf(MY_COM.name, "/dev/tts%d", pcl_port->portno - 1); 
		else if(strncmp("swm61850_mini", hostname, strlen("swm61850_mini")) == 0) 
			sprintf(MY_COM.name, "/dev/ttyS%d", pcl_port->portno); 
		else if(strncmp("swm61850", hostname, strlen("swm61850")) == 0) 
			sprintf(MY_COM.name, "/dev/tts%d", pcl_port->portno - 1); 
		else if(strncmp("CCE3100", hostname, strlen("CCE3100")) == 0) 
			sprintf(MY_COM.name, "/dev/ttyS%d", pcl_port->portno); 
		else 
			sprintf(MY_COM.name, "/dev/tts%d", pcl_port->portno - 1); 
	}else{ 
		sprintf(MY_COM.name, "/dev/tts%d", pcl_port->portno - 1); 
	} 
 
	MY_COM.baud = pcl_port->baud; 
	MY_COM.data_bits = pcl_port->data_bits; 
	MY_COM.parity = pcl_port->parity; 
	MY_COM.stop_bits = pcl_port->stop_bits; 
 
	#if DEBUG_ON 
	printf(" open %s\n",MY_COM.name); 
	#endif 
	com_fd = port_open(&MY_COM); 
	if(com_fd < 0) 
		return; 
	if(port_setup(com_fd, &MY_COM) < 0) { 
		printf("--Setup PORT: [%s] failed.\n", MY_COM.name); 
		return; 
	} 
	pcl_port->com_fd = com_fd; 
 
	if(pcl_port->modbus_srv == 1){ 
		if(pthread_create(&COM_THREAD, NULL, (void *)modbus_server_thread_func, (void *)(&com_fd)) < 0){ 
			printf("--create modbus server thread faile !\n"); 
			return; 
		} 
		printf("create modbus server thread success\n"); 
		pthread_exit(NULL); 
	} 
 
	ptl103 = InitPtl(); 
	create_103_device(ptl103, pcl_port, com_fd); 
	 
	while(1){ 
		len = Frame(ptl103, sbuf, 0); 
		if(len > 0){ 
			uart_send(ptl103->fd, sbuf, len); 
			len = uart_recv2(ptl103->fd, rbuf, ptl103->frame_timer.time_out); 
		} 
		if(len > 0) 
			UnFrame(ptl103, rbuf, len); 
	} 
 
	 
} 
int main(void) 
{ 
	int len; 
	int i; 
	uint8 recv_buf[512]; 
	fd_set fdset; 
	int maxfd; 
	int fd; 
	int connect_num = 0; 
	PCL_PORT *pcl_port; 
	printf("###### 103 transform to ModBus #####\n"); 
	printf("Build at %s, %s.\n", __TIME__, __DATE__); 
	printf("####################################\n"); 
 
	if(parse_xml("protocol.xml", &pcl_info)){ 
		printf("parse xml file failued !\n"); 
		return -1; 
	} 
 
	 
	for(pcl_port = (PCL_PORT *)list_find_last((DBL_LNK *)pcl_info.portHead); 
	      pcl_port != NULL; 
	      pcl_port = (PCL_PORT *)list_find_prev((DBL_LNK *)pcl_info.portHead, (DBL_LNK *)pcl_port)) 
 	{ 
		 
   		if(pthread_create(&COM_THREAD, NULL, (void *)com_thread_func, (void *)(pcl_port)) < 0){ 
			printf("--create client work failed: port = %d\n", pcl_port->portno); 
			return -1; 
		} 
		printf("create work thread success\n"); 
		usleep(1000 * 100); 
	} 
 
	while(1); 
	 
	return 0;	 
}