esp8266-std/driver/ne_general.c

589 lines
15 KiB
C

/*
* 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;loop<input_len;loop++){
check_sum += input[loop];
}
check_sum = ~check_sum;
check_sum += 1;
return check_sum;
}
int32 ne_general_split(void *arg, uint32 *offset, uint8 *input, uint32 len, uint8 *output, uint32 *out_len)
{
uint16 check_sum_c;
uint16 check_sum_d;
uint16 msg_len;
int pos;
/* cycle check protocol */
for(pos=*offset; pos<len; pos++){
ne_general_protocol_header_t *frame = (ne_general_protocol_header_t *)(input + pos);
/* header check */
if (frame == NULL || frame->header != 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:
{
uint8 mcu_version[5];
memset(mcu_version, 0, sizeof(mcu_version));
memcpy(mcu_version, input, 4);
GENERAL_LOG_EX(LOG_Info, "mcu version=%s\r\n", mcu_version);
}
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;
}