
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <errno.h>
#include <unistd.h>

#include "Serial.h"
#include "main.h"

//#include "common.h"

//#include "thread.h"
//#include "app_queue.h"
//#include "dev_arp.h"
//#include "net_handle.h"

#include "uart_proto.h"



uart_data_t g_uart_data;
static uint16_t g_temp_data_len = 0;
static uint16_t g_data_len = 0;
static uint16_t g_recv_crc16 = 0;
static uint8_t state = SOP_STATE1;

uint16_t make_crc16(uint8_t *msg, uint16_t len)
{
    uint16_t crc16 = 0xFFFF;
    uint16_t i, j = 0;
    uint8_t c15, bit;

    for (i = 0; i < len ; i++)
    {
        for (j = 0; j < 8; j++)
        {
            c15 = ((crc16 >> 15 & 1) == 1);
            bit = ((msg[i] >> (7 - j) & 1) == 1);
            crc16 <<= 1;

            if (c15 ^ bit)
            {
                crc16 ^= 0x1021;
            }
        }
    }
   // GW_LOG_DBG("crc16 caculate:0x%04x\n",crc16);
    return crc16;
}

uint32_t make_crc32(uint8_t *msg, uint16_t len)
{
    uint32_t crc32 = 0xFFFFFFFF;
    uint16_t i, j = 0;
    uint16_t c15, bit;

    for (i = 0; i < len ; i++)
    {
        for (j = 0; j < 8; j++)
        {
            c15 = ((crc32 >> 31 & 1) == 1);
            bit = ((msg[i] >> (7 - j) & 1) == 1);
            crc32 <<= 1;

            if (c15 ^ bit)
            {
                crc32 ^= 0x10211021;
            }
        }
    }

    return crc32;
}

int kk_execel_cmd(char * cmd,char * buf,int buf_len,int* ret_len)
{
    if(cmd == NULL || buf == NULL || buf_len == 0)
    {
        GW_LOG_ERR("arg error\n");
        return -1;
    }

    memset(buf,0,buf_len);

    FILE *fp = NULL;
     
  	fp = popen(cmd,"r");
  	while(fgets(buf,buf_len,fp)!=NULL){
  		printf("%s return %s",cmd,buf);  
  	}
  	pclose (fp);
    
    *ret_len = strlen(buf);
    return 0;
}

void uart_frame_send(uint8_t *buf, uint32_t len)
{
    int ret = eSerial_WriteBuffer(buf, len);
    if (ret == E_SERIAL_FD_ERROR)
    {
        //eSerial_Init();
    }
}

uint8_t pro_check_uart_frame(uint8_t *data, uint16_t data_len)
{
    uint16_t i;
    uint16_t tmp_len;
    uint16_t tmp_crc;
    //uint8_t gw_mac_flag = 0;
    //uint16_t crc;

    if (data_len < PRO_LINK_PAKCET_SIZE)
    {
        GW_LOG_ERR("PRO: data_len(%d) < (%d)\n", data_len, PRO_APP_PACKET_MIN_SIZE);
        return 0;
    }

    //check header
    i = 0;

    if (data[0] != PRO_SOF_1 || data[1] != PRO_SOF_2)
    {
        GW_LOG_ERR("PRO: sof err (0x%02X 0x%02X)\n", data[0], data[1]);
        return 0;
    }

    i += PRO_SOF_SIZE;

    #if 0
    //check control-field
    if (data[i] < 0x08 && data[i + 1] == 0x30)
    {
        if (gw_mac_flag == 1)
        {
            //gw link ack, don't care
            GW_LOG_DBG("gw link ack\n");
            return 0;
        }

        //forward link ack to ccu
        #if 0
        if (!dev_arp_query_mac_by_ip(data + PRO_SOF_SIZE, dev_mac))
        {
            return 0;
        }
        #endif

        crc = make_crc16(data, data_len - 2);

        data[data_len - 2] = crc >> 8;
        data[data_len - 1] = crc;
        
        GW_LOG_DBG("link ack\n");

        // dev_send_net(NET_SEND_NOT_BC, UDP_MSG_LOCAL, &g_ccu_net_addr, data, data_len);
        //net_handle_send_tcp_data(data, data_len, 0, TCP_FRAME_NORMAL);

        return 0;
    }
    #endif

    //i += PRO_CONTORL_FIELD_SIZE; //jump over control-field

    //check data_size
    tmp_len = ((uint16_t)(data[i]) << 8) + data[i + 1] + PRO_SOF_SIZE + PRO_LEN_SIZE + PRO_CRC_SIZE;

    if (tmp_len != data_len)
    {
        GW_LOG_ERR("PRO: data_len(%d) != (%d)\n", data_len, tmp_len);
        return 0;
    }

    //check crc
    i = data_len - PRO_CRC_SIZE - PRO_SOF_SIZE - PRO_LEN_SIZE;
    tmp_crc = make_crc16(&data[4], i);

    if (tmp_crc != ((((uint16_t)(data[data_len-2])) << 8) + data[data_len - 1]))
    {
        GW_LOG_ERR("PRO: crc err(0x%04X) != (0x%02X%02X)\n", tmp_crc, data[i], data[i + 1]);
        return 0;
    }

    return 1;
}

int get_uart_frame(uint8_t * buf,int len)
{
    uint8_t ch;
    int i = 0;

    GW_LOG_DBG("uart fram len:%d  state:%d\n",len,state);

    for (i = 0 ; i < len ; i++)
    {
        ch = buf[i];

        switch (state)
        {
            case SOP_STATE1:
                if (ch == PRO_SOF_1)
                {
                    state = SOP_STATE2;
                }

                g_temp_data_len = 0;
                g_uart_data.data[g_temp_data_len++] = ch;
                break;

            case SOP_STATE2:
                if (ch == PRO_SOF_2)
                {
                    state = LENGTH_STATE1;
                    g_uart_data.data[g_temp_data_len++] = ch;
                }
                else
                {
                    GW_LOG_ERR("uart data err: SOF2");

                    if (ch == PRO_SOF_1)
                    {
                        state = SOP_STATE2;
                    }
                    else
                    {
                        state = SOP_STATE1;
                    }
                }

                break;

            /* Length 2 bytes */
            case LENGTH_STATE1:
                g_uart_data.data[g_temp_data_len++] = ch;
                state = LENGTH_STATE2;
                g_data_len = ((uint16_t)ch) << 8;
                break;

            case LENGTH_STATE2:
                g_uart_data.data[g_temp_data_len++] = ch;
                g_data_len += ch;

                if (g_data_len < 2 || g_data_len > (DEV_UART_RECV_BUFFER_SIZE - (PRO_LINK_PAKCET_SIZE - 2)))
                {
                    GW_LOG_ERR("uart data err: LEN err, len = %d", g_data_len);

                    if (ch == PRO_SOF_1)
                    {
                        state = SOP_STATE2;
                    }
                    else
                    {
                        state = SOP_STATE1;

                    }

                    break;
                }

                state = CONTROL_FIELD_STATE1;
                g_data_len -= 3;

                if (g_data_len == 0)
                {
                    state = CRC16_STATE1;
                }

                break;

            case CONTROL_FIELD_STATE1:
                g_uart_data.data[g_temp_data_len++] = ch;
                state = SEQ_STATE1;
                break;

            case SEQ_STATE1:
                g_uart_data.data[g_temp_data_len++] = ch;
                state = SEQ_STATE2;
                break;

            case SEQ_STATE2:
                g_uart_data.data[g_temp_data_len++] = ch;
                state = DATA_STATE;
                break;

            case DATA_STATE:
                if (g_data_len--)
                {
                    g_uart_data.data[g_temp_data_len++] = ch;
                    state = DATA_STATE;

                    if (g_data_len == 0)
                    {
                        state = CRC16_STATE1;
                    }

                    break;
                }

                break;

            case CRC16_STATE1:
                g_recv_crc16 = ((uint16_t)ch) << 8;
                g_uart_data.data[g_temp_data_len++] = ch;
                state = CRC16_STATE2;
                break;

            case CRC16_STATE2:
                state = SOP_STATE1;
                g_uart_data.data[g_temp_data_len++] = ch;
                g_uart_data.data_len = g_temp_data_len;
                g_recv_crc16 += ch;

                if (make_crc16(&g_uart_data.data[4], g_temp_data_len - 6) == g_recv_crc16)
                {
                    return true;
                }
                else
                {
                    GW_LOG_ERR("uart data err: CRC err:0x%04x\n",g_recv_crc16);
                    state = SOP_STATE1;
                }

                break;

            default:
                GW_LOG_ERR("uart data err: INNER err");

                if (ch == PRO_SOF_1)
                {
                    state = SOP_STATE2;
                }
                else
                {
                    state = SOP_STATE1;

                }

                break;
        }
    }

    return false;
}

int get_proto_frame(uint8_t *data, uint16_t data_len, pro_data_t *pro_data)
{
    if (pro_check_uart_frame(data, data_len))
    {
        pro_data->cf.ack = data[PRO_CF_INDEX] & 0x03;
        pro_data->cf.dir = (data[PRO_CF_INDEX] >> 5) & 0x01;
        pro_data->cf.sof_flag = (data[PRO_CF_INDEX] >> 4) & 0x01;
        pro_data->cf.mf_flag = (data[PRO_CF_INDEX] >> 3) & 0x01;

        pro_data->seq = (((uint16_t)(data[PRO_SEQ_INDEX])) << 8) + data[PRO_SEQ_INDEX + 1];

        pro_data->ch = data[PRO_DATA_INDEX+1];
        
        pro_data->opcode = (((uint16_t)(data[PRO_DATA_INDEX + 2])) << 8) + data[PRO_DATA_INDEX + 3];
        //pro_data->args_len = data_len - PRO_APP_PACKET_MIN_SIZE + 1;
        pro_data->args_len = data[PRO_DATA_INDEX] -3 ;
        memcpy(pro_data->arg, data + PRO_DATA_INDEX + 4, pro_data->args_len);

        return true;
    }

    return false;
}

uint8_t cf_to_uint8_t(control_field_t *cf)
{
    return ((((uint8_t)(cf->ack))) + ((cf->dir) << 5) + ((cf->sof_flag) << 4) + ((cf->mf_flag) << 3));
}

uint8_t proto_frame_to_uart(pro_data_t *pro_data, uint8_t *uart_data)
{
    uint8_t i = 0;
    uint16_t cf;
    uint8_t len;
    uint16_t crc;

    uart_data[i++] = PRO_SOF_1;
    uart_data[i++] = PRO_SOF_2;

    len = pro_data->args_len + 4 + 3;

    uart_data[i++] = len>>8;
    uart_data[i++] = len;

    cf = cf_to_uint8_t(&(pro_data->cf));
    //cf = 0x20;
    
    uart_data[i++] = cf;

    uart_data[i++] = pro_data->seq>>8;
    uart_data[i++] = pro_data->seq;

    uart_data[i++] = pro_data->args_len + 3;
    uart_data[i++] = pro_data->ch;
    uart_data[i++] = (pro_data->opcode) >> 8;
    uart_data[i++] = (pro_data->opcode);

    memcpy(uart_data + i, pro_data->arg, pro_data->args_len);
    i += pro_data->args_len;

    crc = make_crc16(&uart_data[4], i-4);
    uart_data[i++] = crc >> 8;
    uart_data[i++] = crc;

    return i;
}


void pro_send_link_ack(pro_data_t *pro_data)
{
    uint8_t buf[PRO_LINK_PAKCET_SIZE];
    uint16_t len = 2;
    uint16_t crc;
    uint8_t i = 0;

    buf[i++] = PRO_SOF_1;
    buf[i++] = PRO_SOF_2;

    buf[i++] = 0x00;
    buf[i++] = 0x30;

    len = 2;
    buf[i++] = len >> 8;
    buf[i++] = len;

    crc = make_crc16(buf, i);
    buf[i++] = crc >> 8;
    buf[i++] = crc;
    
    dev_send_uart(buf,i);
}

void dev_send_uart(uint8_t *data, uint16_t data_len)
{
    #if 1 // debug
    {
        static char data_print_buf[512] = {0};
        int i = 0;
        
        memset(data_print_buf, 0, sizeof(data_print_buf));

        for (i = 0; i < data_len; i ++)
        {
            snprintf(data_print_buf + strlen(data_print_buf), sizeof(data_print_buf), "%02X ", data[i]);
        }

        GW_LOG_DBG("uart send data %s\n", data_print_buf);
    }
    #endif

    uart_frame_send(data, data_len);
}

static void uart_protocol_print(pro_data_t *pro_data)
{
    
    GW_LOG_DBG("channel %02X\n", pro_data->ch);
    GW_LOG_DBG("opcode %04X\n", pro_data->opcode);
    GW_LOG_DBG("args_len: %d\n", pro_data->args_len);

    char print_buf[512] = {0};
    int i = 0;

    snprintf(print_buf, sizeof(print_buf), "args: ");

    for (i = 0; i < pro_data->args_len; i ++)
    {
        snprintf(print_buf + strlen(print_buf), sizeof(print_buf), "%02X ", pro_data->arg[i]);
    }

    GW_LOG_DBG("%s\n", print_buf);
}


/********proto app func************/

void connect_status_ack(pro_data_t pro_data)
{
    pro_data_t pro_data_tmp;
    memset((char*)&pro_data_tmp,0,sizeof(pro_data_t));
    memcpy(&pro_data_tmp,&pro_data,sizeof(pro_data_t));

    pro_data_tmp.cf.dir = 1;
    pro_data_tmp.cf.sof_flag = 0;

    pro_data_tmp.args_len = 0;
    pro_data_tmp.arg[pro_data_tmp.args_len++] = 0;  // err status

    uint8_t data_buf[255] = {0};
    uint8_t data_len = 0;

    data_len = proto_frame_to_uart(&pro_data_tmp,data_buf);
    dev_send_uart(data_buf, data_len);
}

void system_restart_ack(pro_data_t pro_data)
{
    pro_data_t pro_data_tmp;
    memset((char*)&pro_data_tmp,0,sizeof(pro_data_t));
    memcpy(&pro_data_tmp,&pro_data,sizeof(pro_data_t));

    pro_data_tmp.cf.dir = 1;
    pro_data_tmp.cf.sof_flag = 0;

    pro_data_tmp.args_len = 0;
    pro_data_tmp.arg[pro_data_tmp.args_len++] = 0;  // err status

    uint8_t data_buf[255] = {0};
    uint8_t data_len = 0;

    data_len = proto_frame_to_uart(&pro_data_tmp,data_buf);
    dev_send_uart(data_buf, data_len);

    sleep(2);
    my_system("reboot -f\n");
}

void read_mac_ack(pro_data_t pro_data)
{
    pro_data_t pro_data_tmp;
    char eth0_mac_str[32] = "";
    unsigned int  eth0_mac[6] = {0};


    memset((char*)&pro_data_tmp,0,sizeof(pro_data_t));
    memcpy(&pro_data_tmp,&pro_data,sizeof(pro_data_t));

    pro_data_tmp.cf.dir = 1;
    pro_data_tmp.cf.sof_flag = 0;

    //get mac
    if (get_mac(ETH0_MAC_NAME, eth0_mac_str, sizeof(eth0_mac_str)) == 0)
    {
        OLED_LOG_DBG("get eth0 mac error\n");
        return ;
    }

    sscanf(eth0_mac_str, "%x:%x:%x:%x:%x:%x", &eth0_mac[0], \
        &eth0_mac[1],&eth0_mac[2],&eth0_mac[3],&eth0_mac[4],&eth0_mac[5]);


    pro_data_tmp.args_len = 0;
    pro_data_tmp.arg[pro_data_tmp.args_len++] = 0;  // err status
    pro_data_tmp.arg[pro_data_tmp.args_len++] = 6; // mac len
    
    pro_data_tmp.arg[pro_data_tmp.args_len++] = eth0_mac[0]&0xff; // mac
    pro_data_tmp.arg[pro_data_tmp.args_len++] = eth0_mac[1]&0xff; // mac
    pro_data_tmp.arg[pro_data_tmp.args_len++] = eth0_mac[2]&0xff; // mac
    pro_data_tmp.arg[pro_data_tmp.args_len++] = eth0_mac[3]&0xff; // mac
    pro_data_tmp.arg[pro_data_tmp.args_len++] = eth0_mac[4]&0xff; // mac
    pro_data_tmp.arg[pro_data_tmp.args_len++] = eth0_mac[5]&0xff; // mac



    uint8_t data_buf[255] = {0};
    uint8_t data_len = 0;

    data_len = proto_frame_to_uart(&pro_data_tmp,data_buf);
    dev_send_uart(data_buf, data_len);

}

int my_system(const char * cmd)                             
{                                                          
	FILE * fp;                                                 
	int res; 
	char buf[1024];                                   
	if (cmd == NULL){                                                          
		GW_LOG_DBG("my_system cmd is NULL!\n");                        
		return -1;                                                
	}                                                         
	if ((fp = popen(cmd, "r") ) == NULL){                                                          
		perror("popen");                                           
	 	GW_LOG_DBG("popen error: %s/n", strerror(errno));
	 	return -1;  
	}                                                          
	else{                                                         
		while(fgets(buf, sizeof(buf), fp)){                                                          
			GW_LOG_DBG("%s", buf);                                         
		}                                                          
		if ( (res = pclose(fp)) == -1){                                                          
			GW_LOG_DBG("close popen file pointer fp error!\n"); 
			return res;
		}                                                         
		else if (res == 0){                                                          
		 	return res;                                               
		}                                                         
		else{                                                          
			GW_LOG_DBG("popen res is :%d\n", res); 
			return res;             
		}                                                          
	}                                                          
} 

int get_art_bin()
{
	my_system("dd if=/dev/mtd5 of=/tmp/art.bin");

	if(access("/tmp/art.bin",F_OK) == -1){
		GW_LOG_DBG(" file not exist: /tmp/art.bin\n");
		return 0;
	}

	return 1;
}

int write_art_bin()
{
	GW_LOG_DBG("write art and restart!!!\n");
	my_system("mtd write /tmp/art-modify.bin  art");
   // my_system("reboot -f");
	return 1;
}

long get_file_len(FILE * fp)
{
	long offset;
	
	fseek(fp,0,SEEK_END);  //移到文件结尾
	offset = ftell(fp);
	fseek(fp,0,SEEK_SET);  //移到文件开头

	return offset;
}

int mac_modify(unsigned char mac[6])
{
	FILE *fp;
	long offset = 0,fileLen = 0;
	char *file_content;

	if(!((mac[0]&0xff) == 0x28  && (mac[1]&0xff) == 0xd9  &&  (mac[2]&0xff) == 0x8a))
		return 0;

	if(get_art_bin() == 0){
		GW_LOG_DBG("get uboot bin error \n");
		return 0;
	}

	if(!(fp =  fopen("/tmp/art.bin","r"))){
		GW_LOG_DBG("can't open the file: /tmp/art.bin\n");
		return 0;		
	}

	offset = get_file_len(fp);
	GW_LOG_DBG("offset:%ld ",offset);

	file_content = (char *)malloc(offset);
	memset(file_content,0,offset);
	fileLen = fread(file_content,1,offset,fp);
	GW_LOG_DBG("fileLen:%ld \n",fileLen);
	fclose(fp);

	GW_LOG_DBG("mac:%02x-%02x-%02x-%02x-%02x-%02x\n",file_content[MAC_ADDR]&0xff,file_content[MAC_ADDR+1]&0xff,file_content[MAC_ADDR+2]&0xff,file_content[MAC_ADDR+3]&0xff,file_content[MAC_ADDR+4]&0xff,file_content[MAC_ADDR+5]&0xff);
	GW_LOG_DBG("mac-input:%02x-%02x-%02x-%02x-%02x-%02x\n",mac[0]&0xff,mac[1]&0xff,mac[2]&0xff,mac[3]&0xff,mac[4]&0xff,mac[5]&0xff);
	if((file_content[MAC_ADDR]&0xff) == 0x28  && (file_content[MAC_ADDR+1]&0xff) == 0xd9  &&  (file_content[MAC_ADDR+2]&0xff) == 0x8a) {
				GW_LOG_DBG("modifying\n");
				file_content[MAC_ADDR] = mac[0];
				file_content[MAC_ADDR+1] = mac[1];
				file_content[MAC_ADDR+2] = mac[2];
				file_content[MAC_ADDR+3] = mac[3];
				file_content[MAC_ADDR+4] = mac[4];
				file_content[MAC_ADDR+5] = mac[5];
	}
	GW_LOG_DBG("mac-modify:%02x-%02x-%02x-%02x-%02x-%02x\n",file_content[MAC_ADDR]&0xff,file_content[MAC_ADDR+1]&0xff,file_content[MAC_ADDR+2]&0xff,file_content[MAC_ADDR+3]&0xff,file_content[MAC_ADDR+4]&0xff,file_content[MAC_ADDR+5]&0xff);

	if(!(fp =  fopen("/tmp/art-modify.bin","w+"))){
		GW_LOG_DBG("can't open the file: /tmp/art-modify.bin\n");
		free(file_content);
		return 0;		
	}

	fwrite(file_content,1,offset,fp);
	fclose(fp);
	free(file_content);
	return 1;
}

int get_art_mac(unsigned char mac[6])
{
	FILE *fp;
	long offset = 0,fileLen = 0;
	char *file_content;

	if(get_art_bin() == 0){
		GW_LOG_DBG("get uboot bin error \n");
		return 0;
	}

	if(!(fp =  fopen("/tmp/art.bin","r"))){
		GW_LOG_DBG("can't open the file: /tmp/wifi_scan\n");
		return 0;		
	}

	offset = get_file_len(fp);
	GW_LOG_DBG("offset:%ld ",offset);

	file_content = (char *)malloc(offset);
	memset(file_content,0,offset);
	fileLen = fread(file_content,1,offset,fp);
	GW_LOG_DBG("fileLen:%ld \n",fileLen);
	fclose(fp);


	mac[0] = file_content[MAC_ADDR];
	mac[1] = file_content[MAC_ADDR+1];
	mac[2] = file_content[MAC_ADDR+2];
	mac[3] = file_content[MAC_ADDR+3];
	mac[4] = file_content[MAC_ADDR+4];
	mac[5] = file_content[MAC_ADDR+5];
	GW_LOG_DBG("mac-output:%02x-%02x-%02x-%02x-%02x-%02x\n",mac[0]&0xff,mac[1]&0xff,mac[2]&0xff,mac[3]&0xff,mac[4]&0xff,mac[5]&0xff);

	free(file_content);
	return 1;
}

void set_mac_ack(pro_data_t pro_data)
{
    unsigned char mac_iput[6] = {0};

    pro_data_t pro_data_tmp;
    //uint8_t arg_buf[256];
    
    memset((char*)&pro_data_tmp,0,sizeof(pro_data_t));
    memcpy(&pro_data_tmp,&pro_data,sizeof(pro_data_t));

    //pro_data_tmp.arg = arg_buf;
    memcpy(pro_data_tmp.arg,pro_data.arg,pro_data.args_len);

    pro_data_tmp.cf.dir = 1;
    pro_data_tmp.cf.sof_flag = 0;

    //pro_data_tmp.arg[pro_data_tmp.args_len++] = 0;  // err status
    uint8_t mac_len = pro_data_tmp.arg[0];

    int i = 0;
    for(i = 0; i < mac_len; i++)
    {
        mac_iput[i] = pro_data_tmp.arg[i+1];
    }

    printf("mac input:%02x-%02x-%02x-%02x-%02x-%02x\n",mac_iput[0],\
            mac_iput[1],mac_iput[2],mac_iput[3],mac_iput[4],mac_iput[5]);

    // ack handle
    if(mac_modify(mac_iput) == 0)
    {
         pro_data_tmp.arg[0] = E_Proto_ERROR; 
    }

    write_art_bin();

    pro_data_tmp.arg[0] = E_Proto_OK;  // err status

    memset(&pro_data_tmp.arg[1],0,pro_data_tmp.args_len);
    memcpy(&pro_data_tmp.arg[1],&pro_data.arg[0],pro_data.args_len);

    pro_data_tmp.args_len++;
    
    uint8_t data_buf[255] = {0};
    uint8_t data_len = 0;

    data_len = proto_frame_to_uart(&pro_data_tmp,data_buf);
    dev_send_uart(data_buf, data_len);
}

void read_flash_mac_ack(pro_data_t pro_data)
{
    pro_data_t pro_data_tmp;
    unsigned char  eth0_mac[6] = {0};

    memset((char*)&pro_data_tmp,0,sizeof(pro_data_t));
    memcpy(&pro_data_tmp,&pro_data,sizeof(pro_data_t));

    pro_data_tmp.cf.dir = 1;
    pro_data_tmp.cf.sof_flag = 0;

    //get mac
   
    get_art_mac(eth0_mac);

    pro_data_tmp.args_len = 0;
    pro_data_tmp.arg[pro_data_tmp.args_len++] = 0;  // err status
    pro_data_tmp.arg[pro_data_tmp.args_len++] = 6; // mac len
    
    pro_data_tmp.arg[pro_data_tmp.args_len++] = eth0_mac[0]&0xff; // mac
    pro_data_tmp.arg[pro_data_tmp.args_len++] = eth0_mac[1]&0xff; // mac
    pro_data_tmp.arg[pro_data_tmp.args_len++] = eth0_mac[2]&0xff; // mac
    pro_data_tmp.arg[pro_data_tmp.args_len++] = eth0_mac[3]&0xff; // mac
    pro_data_tmp.arg[pro_data_tmp.args_len++] = eth0_mac[4]&0xff; // mac
    pro_data_tmp.arg[pro_data_tmp.args_len++] = eth0_mac[5]&0xff; // mac



    uint8_t data_buf[255] = {0};
    uint8_t data_len = 0;

    data_len = proto_frame_to_uart(&pro_data_tmp,data_buf);
    dev_send_uart(data_buf, data_len);

}

void read_version_ack(pro_data_t pro_data)
{
    pro_data_t pro_data_tmp;
    memset((char*)&pro_data_tmp,0,sizeof(pro_data_t));
    memcpy(&pro_data_tmp,&pro_data,sizeof(pro_data_t));

    pro_data_tmp.cf.dir = 1;
    pro_data_tmp.cf.sof_flag = 0;

    int version_len = strlen(g_oled_config.version_str);

    pro_data_tmp.args_len = 0;
    pro_data_tmp.arg[pro_data_tmp.args_len++] = 0;  // err status
    pro_data_tmp.arg[pro_data_tmp.args_len++] = version_len; // version len

    memcpy(&pro_data_tmp.arg[pro_data_tmp.args_len],g_oled_config.version_str,version_len);

    pro_data_tmp.args_len += version_len;
    
    uint8_t data_buf[255] = {0};
    uint8_t data_len = 0;

    data_len = proto_frame_to_uart(&pro_data_tmp,data_buf);
    dev_send_uart(data_buf, data_len);
}

void exit_subboard_test_ack(pro_data_t pro_data)
{
    pro_data_t pro_data_tmp;
    memset((char*)&pro_data_tmp,0,sizeof(pro_data_t));
    memcpy(&pro_data_tmp,&pro_data,sizeof(pro_data_t));

    pro_data_tmp.cf.dir = 1;
    pro_data_tmp.cf.sof_flag = 0;

    //pro_data_tmp.arg[pro_data_tmp.args_len++] = 0;  // err status

    //标志位写入
    memset(run_flag,0,sizeof(run_flag));
    strcpy(run_flag ,RUN_FLAG_AGING);
    save_cfg_str_to_file(run_flag_file_name, run_flag);

    pro_data_tmp.args_len = 0;
    pro_data_tmp.arg[pro_data_tmp.args_len++] = 0;  // err status
    
    uint8_t data_buf[255] = {0};
    uint8_t data_len = 0;

    data_len = proto_frame_to_uart(&pro_data_tmp,data_buf);
    dev_send_uart(data_buf, data_len);
}

void set_sn_ack(pro_data_t pro_data)
{
    unsigned char sn_str[128] = {0};

    pro_data_t pro_data_tmp;
    //uint8_t arg_buf[256];
    
    memset((char*)&pro_data_tmp,0,sizeof(pro_data_t));
    memcpy(&pro_data_tmp,&pro_data,sizeof(pro_data_t));

    //pro_data_tmp.arg = arg_buf;
    memcpy(pro_data_tmp.arg,pro_data.arg,pro_data.args_len);

    pro_data_tmp.cf.dir = 1;
    pro_data_tmp.cf.sof_flag = 0;

    //pro_data_tmp.arg[pro_data_tmp.args_len++] = 0;  // err status
    uint8_t sn_len = pro_data_tmp.arg[0];
    int i = 0;
    for(i = 0; i < sn_len; i++)
    {
        sn_str[i] = pro_data_tmp.arg[i+1];
    }

    sn_str[i]='\0';
    printf("sn_str:%s\n",sn_str);

    pro_data_tmp.arg[0] = 0;  // err status

    memset(&pro_data_tmp.arg[1],0,pro_data_tmp.args_len);
    memcpy(&pro_data_tmp.arg[1],&pro_data.arg[0],pro_data.args_len);

    pro_data_tmp.args_len++;
    
    
    uint8_t data_buf[255] = {0};
    uint8_t data_len = 0;

    char buf[64] = {0};
    int ret_len = 0;
    char cmd[128] = {0};
    sprintf(cmd,"%s%s",SET_SN_CMD,sn_str);
    kk_execel_cmd(cmd,buf,64,&ret_len);
    //save_cfg_str_to_file(SN_CFG_FILE,(char *)sn_str);

    data_len = proto_frame_to_uart(&pro_data_tmp,data_buf);
    dev_send_uart(data_buf, data_len);
}

void get_sn_ack(pro_data_t pro_data)
{
    pro_data_t pro_data_tmp;
    memset((char*)&pro_data_tmp,0,sizeof(pro_data_t));
    memcpy(&pro_data_tmp,&pro_data,sizeof(pro_data_t));

    pro_data_tmp.cf.dir = 1;
    pro_data_tmp.cf.sof_flag = 0;

    //pro_data_tmp.arg[pro_data_tmp.args_len++] = 0;  // err status

    //标志位写入
    uint8_t sn[128] = {0};
    int sn_len = 0;

    kk_execel_cmd(GET_SN_CMD,(char *)sn,128,&sn_len);

    //int sn_len = strlen((char *)sn);

    pro_data_tmp.args_len = 0;
    if(sn_len == 0)
    {
         pro_data_tmp.arg[pro_data_tmp.args_len++] = 1;  // err status
    }
    else
    {
         pro_data_tmp.arg[pro_data_tmp.args_len++] = 0;  // err status
    }
    
   
    sn_len--;//去掉换行符

    pro_data_tmp.arg[pro_data_tmp.args_len++] = sn_len; // version len

    memcpy(&pro_data_tmp.arg[pro_data_tmp.args_len],(char *)sn,sn_len);
    pro_data_tmp.args_len += sn_len;
    
    uint8_t data_buf[255] = {0};
    uint8_t data_len = 0;

    data_len = proto_frame_to_uart(&pro_data_tmp,data_buf);
    dev_send_uart(data_buf, data_len);
}

/********************/


void uart_frame_handle()
{
    GW_LOG_DBG("uart_frame_handle\n");
    uint8_t *data = g_uart_data.data;
    uint8_t data_len = g_uart_data.data_len;
    pro_data_t pro_data;
    //uint8_t pro_data_buf[256];

    //pro_data.arg = pro_data_buf;

    if (get_proto_frame(data, data_len, &pro_data) == false)
    {
        return;
    }

    uart_protocol_print(&pro_data);

    // handle msg
    switch (pro_data.opcode)
    {
        case OPCODE_CONNECT_STATUS_QUERY:
        {
            connect_status_ack(pro_data);
            break;
        }

        case OPCODE_BURN_MAC:
        {
            //暂时不支持
            set_mac_ack(pro_data);
            break;
        }

        case OPCODE_READ_MAC:
        {
            read_mac_ack(pro_data);
            break;
        }

        case OPCODE_SET_SN:
        {
            set_sn_ack(pro_data);
            break;
        }

        case OPCODE_GET_SN:
        {
            get_sn_ack(pro_data);
            break;
        }

        case OPCODE_READ_VERSION:
        {
            read_version_ack(pro_data);
            break;
        }

         case OPCODE_EXIT_SUBBOARD_TEST:
        {
            exit_subboard_test_ack(pro_data);
            break;
        }
        case OPCODE_READ_MAC_FROM_FLASH:
        {
            read_flash_mac_ack(pro_data);
            break;
        }
        case OPCODE_SYSTEM_RESTART:
        {
            system_restart_ack(pro_data);
            break;
        }

        default:
        {
            GW_LOG_DBG("gw others opcode %04X ack\n", pro_data.opcode);
            break;
        }
    }

    return;
}

