/* * ne_device.c -- provide iot-system device layer operation interface. * * * ORIGINAL AUTHOR: * * Copyright (c) 2018 Netease Corporation */ #include "c_types.h" #include "user_main.h" #include "esp_common.h" #include "cfg.h" #include "uart.h" #include "ne_general.h" #include "ne_device.h" #include "log.h" #include "esp_MSG_ctrl.h" #include "ota.h" #include "freertos/semphr.h" static void *ne_general_sema; static uint8 ne_general_net_status; int32 ne_general_init(void *arg) { #if 0 UART_WaitTxFifoEmpty(UART0); UART_WaitTxFifoEmpty(UART1); UART_IntrConfTypeDef uart_intr; uart_intr.UART_IntrEnMask = UART_RXFIFO_TOUT_INT_ENA | UART_FRM_ERR_INT_ENA | UART_RXFIFO_FULL_INT_ENA; uart_intr.UART_RX_FifoFullIntrThresh = 120; uart_intr.UART_RX_TimeOutIntrThresh = 2; uart_intr.UART_TX_FifoEmptyIntrThresh = 10; UART_IntrConfig(UART0, &uart_intr); UART_ConfigTypeDef uart_config; uart_config.baud_rate = BIT_RATE_9600; uart_config.data_bits = UART_WordLength_8b; uart_config.parity = USART_Parity_None; uart_config.stop_bits = USART_StopBits_1; uart_config.flow_ctrl = USART_HardwareFlowControl_None; uart_config.UART_RxFlowThresh = 120; uart_config.UART_InverseMask = UART_None_Inverse; UART_ParamConfig(UART0, &uart_config); uart_config.flow_ctrl = USART_HardwareFlowControl_None; UART_ParamConfig(UART1, &uart_config); UART_SetPrintPort(UART1); // uart1 for log. ETS_UART_INTR_ENABLE(); #endif UART_WaitTxFifoEmpty(UART0); UART_WaitTxFifoEmpty(UART1); UART_IntrConfTypeDef uart_intr; uart_intr.UART_IntrEnMask = UART_RXFIFO_TOUT_INT_ENA | UART_FRM_ERR_INT_ENA | UART_RXFIFO_FULL_INT_ENA; uart_intr.UART_RX_FifoFullIntrThresh = 120; uart_intr.UART_RX_TimeOutIntrThresh = 2; uart_intr.UART_TX_FifoEmptyIntrThresh = 10; UART_IntrConfig(UART0, &uart_intr); UART_ConfigTypeDef uart_config; uart_config.UART_RxFlowThresh = 120; uart_config.UART_InverseMask = UART_None_Inverse; uart_config.baud_rate = USR_CFG_UART(0, Baud); uart_config.data_bits = USR_CFG_UART(0, DataBits); uart_config.parity = USR_CFG_UART(0, Parity); uart_config.stop_bits = USR_CFG_UART(0, StopBits); uart_config.flow_ctrl = USR_CFG_UART(0, FlowCtrl); UART_ParamConfig(UART0, &uart_config); uart_config.baud_rate = USR_CFG_UART(1, Baud); uart_config.data_bits = USR_CFG_UART(1, DataBits); uart_config.parity = USR_CFG_UART(1, Parity); uart_config.stop_bits = USR_CFG_UART(1, StopBits); uart_config.flow_ctrl = USR_CFG_UART(1, FlowCtrl); UART_ParamConfig(UART1, &uart_config); UART_SetPrintPort(UART1); // uart1 for log. ETS_UART_INTR_ENABLE(); ne_general_sema = xSemaphoreCreateMutex(); if (ne_general_sema == NULL) { GENERAL_LOG_EX(LOG_Info, "init fail!\r\n"); return -ERR_FAIL; } /* set network status */ ne_general_set_network_status(NE_GENERAL_NETWORK_DISCONNECT); /* notic net status to mcu */ ne_general_notic_net_status(ne_general_get_network_status()); return ERR_OK; } void ne_general_set_network_status(uint8 net_status) { if(ne_general_net_status != net_status){ ne_general_net_status = net_status; //notic mcu } } uint8 ne_general_get_network_status(void) { return ne_general_net_status; } int32 ne_general_deinit(void * arg) { return ERR_OK; } int32 ne_general_write(void *arg, uint8 *input, uint32 len) { xSemaphoreTake(ne_general_sema, portMAX_DELAY); uart_tx_buf(0, input, len); xSemaphoreGive(ne_general_sema); return ERR_OK; } int32 ne_general_read(void *arg, uint8 **output, uint32 *len) { static int32 recv_temp_len=0; ne_uart_recv_t * recv = ne_get_uart_recv_info(); if(recv->recv_len > recv_temp_len){ recv_temp_len = recv->recv_len; } else if(recv->recv_len == recv_temp_len && recv_temp_len != 0){ *len = recv_temp_len; *output = recv->uart_buf; recv_temp_len = 0; return ERR_OK; } else{ recv_temp_len = 0; } return -ERR_FAIL; } /* * yanxuan sweeper 16bit check. */ uint16 ne_general_check_16bit(uint8_t *input, uint16 input_len) { uint16 check_sum=0; uint16 loop; for(loop=0;loopheader != NE_DEVICE_GENERAL_HEAD || (len - pos < sizeof(ne_general_protocol_header_t))) continue; /* protocol len check */ msg_len = (frame->len[0]<<0); msg_len |= (frame->len[1]<<8); if(msg_len > NE_DEVICE_BUF_SIZE || (msg_len > len - pos - 3)){ GENERAL_LOG_EX(LOG_Debug," len overflow!\r\n"); continue; } /* compare checksum */ check_sum_d = (frame->checksum[0]<<0); check_sum_d |= (frame->checksum[1]<<8); check_sum_c = ne_general_check_16bit(frame->len, msg_len); if(check_sum_d != check_sum_c){ GENERAL_LOG_EX(LOG_Debug,"check_sum_d=0x%x, check_sum_c=0x%x\r\n",check_sum_d, check_sum_c); continue; } /*get payload*/ *out_len = msg_len + 3; memcpy(output, input + pos, *out_len); *offset = pos + *out_len; return ERR_OK; } GENERAL_LOG_EX(LOG_Debug," analysis fail!\r\n"); *offset = pos; return -ERR_FAIL; } void ne_general_apconfig_rsp(uint8 result) { ne_general_rsp_data_t rsp_data; uint8 sbuf[NE_GENERAL_MAX_SBUF_LEN]; int32 slen; rsp_data.result = result; slen = ne_general_create_frame(NE_DEVICE_GENERAL_WIFI_PROCESS, (uint8_t *)&rsp_data, sizeof(rsp_data), sbuf, NE_GENERAL_MAX_SBUF_LEN); if(slen < 0){ GENERAL_LOG_EX(LOG_Error, "create frame fail!\r\n"); } ne_general_write(NULL, sbuf, slen); } void ne_general_notic_net_status(uint8 net_status) { ne_general_rsp_data_t rsp_data; uint32 slen; uint8 sbuf[NE_GENERAL_MAX_SBUF_LEN]; GENERAL_LOG_EX(LOG_Info, "notic net status=%d\r\n", net_status); rsp_data.msgtype = NE_DEVICE_GENERAL_CMD_STATUS_NOTIC; rsp_data.result = net_status; slen = ne_general_create_frame(NE_DEVICE_GENERAL_WIFI_PROCESS, (uint8_t *)&rsp_data, sizeof(rsp_data), sbuf, NE_GENERAL_MAX_SBUF_LEN); if(slen < 0){ GENERAL_LOG_EX(LOG_Error, "create frame fail!\r\n"); } ne_general_write(NULL, sbuf, slen); } void ne_general_get_mcu_version(void) { uint8 msgtype; uint32 slen; uint8 sbuf[NE_GENERAL_MAX_SBUF_LEN]; GENERAL_LOG_EX(LOG_Info, "get mcu version\r\n"); msgtype = NE_DEVICE_GENERAL_CMD_GET_VERSION; slen = ne_general_create_frame(NE_DEVICE_GENERAL_WIFI_PROCESS, &msgtype, sizeof(msgtype), sbuf, NE_GENERAL_MAX_SBUF_LEN); if(slen < 0){ GENERAL_LOG_EX(LOG_Error, "create frame fail!\r\n"); } ne_general_write(NULL, sbuf, slen); } static int32 ne_general_local_process(uint8 *input, uint32 ilen) { uint8 msgtype = input[0]; GENERAL_LOG_EX(LOG_Info, "[msgtype]=%d \r\n", msgtype); switch(msgtype){ case NE_DEVICE_GENERAL_CMD_START_CONNET: { ne_general_rsp_data_t rsp_data; uint32 slen; uint8 sbuf[NE_GENERAL_MAX_SBUF_LEN]; GENERAL_LOG_EX(LOG_Info, "start apconfig\r\n"); /* get mcu product id - save to flash - set init flag */ set_platform_product_id(input + 1, 4); ne_cfg_set_init_type(NE_DEVICE_APCONFIG); wifi_station_disconnect(); /* respond result to mcu */ rsp_data.msgtype = NE_DEVICE_GENERAL_CMD_START_CONNET; rsp_data.result = NE_GENERAL_SUCCESS; slen = ne_general_create_frame(NE_DEVICE_GENERAL_WIFI_PROCESS, (uint8_t *)&rsp_data, sizeof(rsp_data), sbuf, NE_GENERAL_MAX_SBUF_LEN); if(slen < 0){ GENERAL_LOG_EX(LOG_Error, "create frame fail!\r\n"); } ne_general_write(NULL, sbuf, slen); /* reset */ vTaskDelay(500 / portTICK_RATE_MS); system_restart(); break; } case NE_DEVICE_GENERAL_CMD_CANNEL_CONNET: { ne_general_rsp_data_t rsp_data; uint32 slen; uint8 sbuf[NE_GENERAL_MAX_SBUF_LEN]; GENERAL_LOG_EX(LOG_Info, "exit apconfig\r\n"); SoftAPExitCfgMode(0); /* respond result to mcu */ rsp_data.msgtype = NE_DEVICE_GENERAL_CMD_CANNEL_CONNET; rsp_data.result = NE_GENERAL_SUCCESS; slen = ne_general_create_frame(NE_DEVICE_GENERAL_WIFI_PROCESS, (uint8_t *)&rsp_data, sizeof(rsp_data), sbuf, NE_GENERAL_MAX_SBUF_LEN); if(slen < 0){ GENERAL_LOG_EX(LOG_Error, "create frame fail!\r\n"); } ne_general_write(NULL, sbuf, slen); /* reset */ vTaskDelay(500 / portTICK_RATE_MS); system_restart(); break; } case NE_DEVICE_GENERAL_CMD_GET_STATUS: { ne_general_rsp_data_t rsp_data; uint32 slen; uint8 sbuf[NE_GENERAL_MAX_SBUF_LEN]; GENERAL_LOG_EX(LOG_Info, "notic net status=%d\r\n", ne_general_get_network_status()); rsp_data.msgtype = NE_DEVICE_GENERAL_CMD_GET_STATUS; rsp_data.result = ne_general_get_network_status(); slen = ne_general_create_frame(NE_DEVICE_GENERAL_WIFI_PROCESS, (uint8_t *)&rsp_data, sizeof(rsp_data), sbuf, NE_GENERAL_MAX_SBUF_LEN); if(slen < 0){ GENERAL_LOG_EX(LOG_Error, "create frame fail!\r\n"); } ne_general_write(NULL, sbuf, slen); } break; case NE_DEVICE_GENERAL_CMD_CLEAR_SSID: { ne_general_rsp_data_t rsp_data; uint32 slen; uint8 sbuf[NE_GENERAL_MAX_SBUF_LEN]; GENERAL_LOG_EX(LOG_Info, "clear ssid psk\r\n"); ne_clear_ssid_psk(); /* respond result to mcu */ rsp_data.msgtype = NE_DEVICE_GENERAL_CMD_CLEAR_SSID; rsp_data.result = NE_GENERAL_SUCCESS; slen = ne_general_create_frame(NE_DEVICE_GENERAL_WIFI_PROCESS, (uint8_t *)&rsp_data, sizeof(rsp_data), sbuf, NE_GENERAL_MAX_SBUF_LEN); if(slen < 0){ GENERAL_LOG_EX(LOG_Error, "create frame fail!\r\n"); } ne_general_write(NULL, sbuf, slen); } break; case NE_DEVICE_GENERAL_CMD_RESET_WIFI: { ne_general_rsp_data_t rsp_data; uint32 slen; uint8 sbuf[NE_GENERAL_MAX_SBUF_LEN]; GENERAL_LOG_EX(LOG_Info, "reset wifi\r\n"); /* respond result to mcu */ rsp_data.msgtype = NE_DEVICE_GENERAL_CMD_RESET_WIFI; rsp_data.result = NE_GENERAL_SUCCESS; slen = ne_general_create_frame(NE_DEVICE_GENERAL_WIFI_PROCESS, (uint8_t *)&rsp_data, sizeof(rsp_data), sbuf, NE_GENERAL_MAX_SBUF_LEN); if(slen < 0){ GENERAL_LOG_EX(LOG_Error, "create frame fail!\r\n"); } ne_general_write(NULL, sbuf, slen); /* reset */ vTaskDelay(500 / portTICK_RATE_MS); system_restart(); } break; case NE_DEVICE_GENERAL_CMD_GET_VERSION: { uint32 slen; uint8 sbuf[NE_GENERAL_MAX_SBUF_LEN]; uint32 wifiVer = atoi(FIRMWARE_VERSION); slen = ne_general_create_frame(NE_DEVICE_GENERAL_CMD_GET_VERSION, (uint8_t *)&wifiVer, 4, sbuf, NE_GENERAL_MAX_SBUF_LEN); if(slen < 0){ GENERAL_LOG_EX(LOG_Error, "create frame fail!\r\n"); } ne_general_write(NULL, sbuf, slen); } break; case NE_DEVICE_GENERAL_CMD_GET_CHIPID: { uint32 slen; ne_general_rsp_data_t rsp_data; const char* pId = GetPlatformDevId(); unsigned char* pBuf = (unsigned char*)HAL_Malloc(strlen(pId) + NE_GENERAL_MAX_SBUF_LEN); if(pBuf) { slen = ne_general_create_frame(NE_DEVICE_GENERAL_CMD_GET_CHIPID, (uint8_t *)pId, strlen(pId), pBuf, strlen(pId) + NE_GENERAL_MAX_SBUF_LEN); } else { rsp_data.msgtype = NE_DEVICE_GENERAL_CMD_GET_CHIPID; rsp_data.result = NE_GENERAL_FAIL; slen = ne_general_create_frame(NE_DEVICE_GENERAL_CMD_GET_CHIPID, (uint8_t *)&rsp_data, sizeof(rsp_data), pBuf, strlen(pId) + NE_GENERAL_MAX_SBUF_LEN); } if(slen < 0){ GENERAL_LOG_EX(LOG_Error, "create frame fail!\r\n"); } ne_general_write(NULL, pBuf, slen); HAL_Free(pBuf); } break; default: break; } return ERR_OK; } static uint8 *ne_general_ota_print(uint8 msg) { switch(msg){ case NE_GENERAL_OTA_INFO: return "NE_GENERAL_OTA_INFO"; case NE_GENERAL_OTA_START: return "NE_GENERAL_OTA_START"; case NE_GENERAL_OTA_DOWNLOAD: return "NE_GENERAL_OTA_DOWNLOAD"; case NE_GENERAL_OTA_READ: return "NE_GENERAL_OTA_READ"; case NE_GENERAL_OTA_STOP: return "NE_GENERAL_OTA_STOP"; default: return "NE_GENERAL_OTA_UNKNOWN"; } } static void _ne_general_ota_process(uint8_t *input, uint8_t len) { uint8_t msg_type; ne_general_protocol_header_t* header = (ne_general_protocol_header_t*)input; if(len > 255){ GENERAL_LOG_EX(LOG_Error, "len error!\r\n"); } input += sizeof(ne_general_protocol_header_t); msg_type = input[0]; GENERAL_LOG_EX(LOG_Info, "[OTA Process] %s\r\n", ne_general_ota_print(msg_type)); switch(msg_type){ case NE_GENERAL_OTA_START: { struct OTA_Start_Cmd cmd; cmd.type = OTA_DEVICE_MCU; MSG_ctrl_cmd_put(MSG_CONTROL_CMD_OTA_START, &cmd); } break; case NE_GENERAL_OTA_DOWNLOAD: { struct OTA_SegDownload_Cmd cmd; cmd.seg_num = input[1]; cmd.seg_size = 256*1000; MSG_ctrl_cmd_put(MSG_CONTROL_CMD_OTA_SEGDOWNLOAD, &cmd); } break; case NE_GENERAL_OTA_READ: { struct OTA_SegRead_Cmd cmd; cmd.length = (input[1]<<0); cmd.length |= (input[2]<<8); cmd.offset = (input[3]<<0); cmd.offset |= (input[4]<<8); cmd.offset |= (input[5]<<16); cmd.offset |= (input[6]<<24); MSG_ctrl_cmd_put(MSG_CONTROL_CMD_OTA_SEGREAD, &cmd); } break; case NE_GENERAL_OTA_STOP: { struct OTA_Quit_Cmd cmd; MSG_ctrl_cmd_put(MSG_CONTROL_CMD_OTA_QUIT, &cmd); } break; } } int ne_general_create_frame(uint8_t frame_type, uint8_t *payload, int in_len, uint8 *output, int max_len) { uint16 temp_len,temp_check; int count = 0; int msg_len; ne_general_protocol_header_t *pframe; /* params check */ if(payload == NULL || output == NULL || in_len <= 0 || in_len + sizeof(ne_general_protocol_header_t) > max_len){ return -ERR_FAIL; } pframe = (ne_general_protocol_header_t *)output; memset(pframe, 0 , sizeof(ne_general_protocol_header_t)); /* set msg header */ pframe->header = 0x3c; temp_len = in_len + sizeof(ne_general_protocol_header_t) - 3; pframe->len[0] = temp_len & 0x00ff; pframe->len[1] = temp_len >> 8; pframe->type = frame_type; pframe->version[0] = 0x01; pframe->version[1] = 0x00; /* get payload */ memcpy(output + sizeof(ne_general_protocol_header_t), payload, in_len); /* calculate sum */ temp_check = ne_general_check_16bit(pframe->len, temp_len); pframe->checksum[0] = temp_check & 0x00ff; pframe->checksum[1] = temp_check >> 8; /* message len */ msg_len = temp_len + 3; return msg_len; } static uint8 *ne_general_dir_print(uint8 dir) { switch(dir){ case MSG_DIRECTION_UART_UP: return "MSG_DIRECTION_UART_UP"; case MSG_DIRECTION_UART_DOWN: return "MSG_DIRECTION_UART_DOWN"; case MSG_DIRECTION_CLOUD_UP: return "MSG_DIRECTION_CLOUD_UP"; case MSG_DIRECTION_CLOUD_DOWN: return "MSG_DIRECTION_CLOUD_DOWN"; case MSG_DIRECTION_OTA_UP: return "MSG_DIRECTION_OTA_UP"; case MSG_DIRECTION_OTA_DOWN: return "MSG_DIRECTION_OTA_DOWN"; case MSG_DIRECTION_BDATA_UP: return "MSG_DIRECTION_BDATA_UP"; case MSG_DIRECTION_BDATA_DOWN: return "MSG_DIRECTION_BDATA_DOWN"; default: return "MSG_DIRECTION_UNKNOWN"; } } int32 ne_general_process(void *arg, uint8 msgdir, uint8 *input, uint32 ilen, uint8 * output, uint32 maxlen) { int32 ret = -ERR_FAIL; if(input == NULL || ilen <= 0) return -ERR_FAIL; GENERAL_LOG_EX(LOG_Info, "[direction]: %s \r\n", ne_general_dir_print(msgdir)); if(msgdir == MSG_DIRECTION_CLOUD_DOWN || msgdir == MSG_DIRECTION_OTA_DOWN){ uint8 frame_type; if(ilen > maxlen) return -ERR_FAIL; if(msgdir == MSG_DIRECTION_CLOUD_DOWN) frame_type = NE_DEVICE_GENERAL_PASS_THROUGH; else if(msgdir == MSG_DIRECTION_OTA_DOWN) frame_type == NE_DEVICE_GENERAL_MCU_OTA; return ne_general_create_frame(frame_type, input, ilen, output, maxlen); } else{ ne_general_protocol_header_t *frame = (ne_general_protocol_header_t *)input; GENERAL_LOG_EX(LOG_Info, "[frame_type]=%d \r\n", frame->type); switch(frame->type){ case NE_DEVICE_GENERAL_PASS_THROUGH: ProCacheMCUMsg(input, ilen, MSG_TYPE_BYPASS); break; case NE_DEVICE_GENERAL_ALL_UPLOAD: ProCacheMCUMsg(input, ilen, MSG_TYPE_SHADOW); break; case NE_DEVICE_GENERAL_MCU_OTA: _ne_general_ota_process(input, ilen); break; case NE_DEVICE_GENERAL_WIFI_PROCESS: ret = ne_general_local_process(input + sizeof(ne_general_protocol_header_t), ilen - sizeof(ne_general_protocol_header_t)); break; case NE_DEVICE_GENERAL_ABNORMAL: break; default: break; } } return ERR_OK; }