Files
banban/ql-kernel/threadx/quec/quec_wifi_msg.c
T

513 lines
18 KiB
C

/**
@file
quec_wifi_msg.c
@brief
Quectel wifi msg api.
*/
/*============================================================================
Copyright (c) 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential.
=============================================================================*/
/*===========================================================================
EDIT HISTORY FOR MODULE
This section contains comments describing changes made to the module.
Notice that changes are listed in reverse chronological order.
WHEN WHO WHAT, WHERE, WHY
---------- ------------ ----------------------------------------------------
=============================================================================*/
/*===========================================================================
* include files
===========================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "quec_cust_feature.h"
#include "quec_debug.h"
#include "quec_rtos.h"
#include "quec_common.h"
#include "quec_wifi_app.h"
#include "quec_wifi_msg.h"
#include "quec_wifi_uart.h"
#include "quec_wifi_spi.h"
#ifndef MIN_SYS
#ifdef QUEC_FGM842D_WIFI_SUPPORT
/*========================================================================
* Macro Definition
*========================================================================*/
#define QUEC_WIFI_MSG_LOG(msg, ...) custom_log("WIFI_MSG", msg, ##__VA_ARGS__)
#define QUEC_FREE_PTR(p) {if(p != NULL) {free(p);p = NULL;}}
#define QUEC_WIFI_MSG_TASK_EVENT_CNT 5
#define QUEC_WIFI_MSG_MSG_QUEUE_CNT 200
#ifdef LTEONLY_THIN_SINGLE_SIM_2MFLASH
#define QUEC_WIFI_MSG_THREAD_PRIORITY 83
#else
#define QUEC_WIFI_MSG_THREAD_PRIORITY 33
#endif
/*========================================================================
* Enumeration Definition
*========================================================================*/
/*========================================================================
* Type Definition
*=========================================================================*/
typedef struct
{
quec_task_t task;
quec_wifi_msg_app_notify_cb msg_notify_cb;
char *malloc_data_field;
quec_queue_t msg_queue;
} quec_wifi_msg_manager_s;
/*========================================================================
* Global Variable
*========================================================================*/
quec_wifi_msg_manager_s quec_wifi_msg_manager = {0};
quec_mutex_t quec_wifi_msg_mutex = NULL;
/*========================================================================
* function Definition
*========================================================================*/
extern void wifi_dump_buffer(const char *name, unsigned char *buf, int len);
quec_wifi_msg_errcode_e quec_wifi_msg_app_notify_cb_register(quec_wifi_msg_app_notify_cb cb)
{
// APP engine notification cb for handling app command
quec_wifi_msg_manager_s *manager = &quec_wifi_msg_manager;
quec_rtos_mutex_lock(quec_wifi_msg_mutex, 0xFFFFFFFF);
manager->msg_notify_cb = cb;
quec_rtos_mutex_unlock(quec_wifi_msg_mutex);
return QUEC_WIFI_MSG_SUCCESS;
}
int quec_wifi_msg_npto_parse(char *src, int src_len, quec_wifi_msg_protocol_head_info_s *cmdPkt, int *dst_len, int *result)
{
int i = 0;
int cmdlen = 0;
char *ptr = src;
unsigned char checksum;
//wifi_dump_buffer("msg", src, src_len);
// Check source input length
if (src_len < QUEC_PROTOCOL_HEAD_MAX_SIZE)
{
QUEC_WIFI_MSG_LOG("less than protocol header size!!\r\n");
*dst_len = 0; // free no magic buff
*result = QUEC_WIFI_NPTO_PARSE_RESULT_TOOSMALL;
return -1;
}
// Find header identification "QUEC_WIFI_UART_MAGIC0 QUEC_WIFI_UART_MAGIC1"
for (i = 0; i < (src_len - 1); i++)
{
if (ptr[i] == QUEC_WIFI_UART_MAGIC0 && ptr[i + 1] == QUEC_WIFI_UART_MAGIC1)
{
break;
}
}
QUEC_WIFI_MSG_LOG("i=%d", i);
// Return error when no header
if (i >= (src_len - 1))
{
QUEC_WIFI_MSG_LOG("no search magic!!");
/*
Parse error:
No valid magic header,returns i as parsing length.
e.g. "0x12 0x34 0x56..."=>*dst_len = i
*/
*dst_len = i;
*result = QUEC_WIFI_NPTO_PARSE_RESULT_NOMAGIC;
return -1;
}
// Check command length
cmdlen = src_len - i;
if (cmdlen < QUEC_PROTOCOL_HEAD_MAX_SIZE)
{
QUEC_WIFI_MSG_LOG("to small!! cmdlen = %d", cmdlen);
/*
Parse error:
No valid parsing buffer length,returns i as parsing length.
e.g. "uint8_t uint8_t"=>*dst_len = i
*/
*dst_len = i;
*result = QUEC_WIFI_NPTO_PARSE_RESULT_TOOSMALL;
return 0;
}
// Get command header
memcpy(cmdPkt, &ptr[i], QUEC_PROTOCOL_HEAD_MAX_SIZE);
if (cmdPkt->cmdlen > QUEC_PROTOCOL_MSG_MAX_LEN)
{
/*
Parse error:
Command length from header is too large,but is valid.Return i + 2 as parsing length.
e.g. "uint8_t uint8_t uint16_t"=>*dst_len = i + 2
*/
*dst_len = i + 2;
*result = QUEC_WIFI_NPTO_PARSE_RESULT_UNKNOWN;
return -1;
}
// Check if command length is valid
if (cmdPkt->cmdlen > cmdlen)
{
QUEC_WIFI_MSG_LOG("to small!!cmdPkt->cmdlen = %d cmdlen=%d", cmdPkt->cmdlen, cmdlen);
/*
Parse error:
Command length from header is larger than parsing buffer length.Drop command length.Return i as parsing length.
e.g. "uint8_t uint8_t"=>*dst_len = i
*/
*dst_len = i;
*result = QUEC_WIFI_NPTO_PARSE_RESULT_TOOSMALL;
return 0;
}
// Get data field
if ((cmdPkt->cmdlen - QUEC_PROTOCOL_HEAD_MAX_SIZE) > 0)
{
cmdPkt->data = malloc(cmdPkt->cmdlen - QUEC_PROTOCOL_HEAD_MAX_SIZE+1);//add \0 to end
QUEC_WIFI_MSG_LOG("cmdPkt->data = %p", cmdPkt->data);
if (cmdPkt->data == NULL)
{
QUEC_WIFI_MSG_LOG("malloc failed cmdPkt->cmdlen=%d", cmdPkt->cmdlen);
/*
Malloc error:
No enough memory.Return i + 2 as parsing length.
e.g. "uint8_t uint8_t uint16_t"=>*dst_len = i + 2
*/
*dst_len = i + 2;
*result = QUEC_WIFI_NPTO_PARSE_RESULT_UNKNOWN;
return -1;
}
// Copy data field
memset(cmdPkt->data,0,cmdPkt->cmdlen - QUEC_PROTOCOL_HEAD_MAX_SIZE+1);
memcpy(cmdPkt->data, &ptr[i + QUEC_PROTOCOL_HEAD_MAX_SIZE], cmdPkt->cmdlen - QUEC_PROTOCOL_HEAD_MAX_SIZE);
}
if (cmdPkt->checksum != 0) // WIFI UART UL FRAME
{
// Set checksum 0 for re-calculation
ptr[i + 5] = 0;
checksum = npto_CRC(&ptr[i], cmdPkt->cmdlen);
// Compare checksum from header to calculated checksum
if (checksum != cmdPkt->checksum)
{
QUEC_WIFI_MSG_LOG("crc check error checksum=%x cmdPkt->checksum=%x", checksum, cmdPkt->checksum);
/*
Checksum error:
Checksum mismatched.Return i + 2 as parsing length.
e.g. "uint8_t uint8_t uint16_t"=>*dst_len = i + 2
*/
if (cmdPkt->data != NULL)
{
free(cmdPkt->data);
cmdPkt->data = NULL;
}
*dst_len = i + 2;
*result = QUEC_WIFI_NPTO_PARSE_RESULT_ERRCRC;
return -1;
}
}
/*
Parse successfully.Return i + command length as parsing length.
e.g. "uint8_t uint8_t ......"=>*dst_len = i + cmdPkt->cmdlen
*/
*dst_len = i + cmdPkt->cmdlen;
*result = QUEC_WIFI_NPTO_PARSE_RESULT_SUCC;
return QUEC_WIFI_NPTO_PARSE_RESULT_SUCC;
}
int quec_wifi_msg_recv(void *ctx)
{
quec_wifi_msg_info_s *info = (quec_wifi_msg_info_s *)ctx;
quec_wifi_msg_manager_s *manager = &quec_wifi_msg_manager;
// Data streams from UART/SPI and so on.It needs to be registered as physical device callback.
// Once we get data,it will be passed to MSG engine.
QuecOSStatus err;
quec_wifi_msg_info_s msg_info = {0};
msg_info.data = info->data;
msg_info.data_len = info->data_len;
QUEC_WIFI_MSG_LOG("msg_info.data=%p", msg_info.data);
err = quec_rtos_queue_release(manager->msg_queue, sizeof(quec_wifi_msg_info_s), (uint8 *)&msg_info, QUEC_NO_WAIT);
if (err != kNoErr)
{
free(info->data);
info->data = NULL;
QUEC_WIFI_MSG_LOG("release msg_queue failed");
}
return err;
}
/*使能sta�, 接�到的cmd大致�:
->41(QUEC_WIFI_APP_RESET_DONE)
->7 (QUEC_WIFI_NPTO_WLAN_DESTROY_CMD)
->6 (QUEC_WIFI_NPTO_WLAN_CREATE_CMD)
->1 (QUEC_WIFI_NPTO_STA_IP_START_CMD)
*/
quec_wifi_msg_protocol_info_s protocol_info = {0};
static void quec_wifi_msg_thread(void *argv)
{
QuecOSStatus err;
quec_wifi_msg_info_s msg_info = {0};
int max_cache_len = QUEC_MSG_CACHE_MAX_LEN; // max cache 4 data
quec_wifi_msg_protocol_head_info_s protocol_head_info = {0};
int dst_buff_len = 0;
int result = 0;
quec_wifi_msg_manager_s *manager = &quec_wifi_msg_manager;
// Create message queue
err = quec_rtos_queue_create(&manager->msg_queue, sizeof(quec_wifi_msg_info_s), QUEC_WIFI_MSG_MSG_QUEUE_CNT);
if (err)
{
goto exit;
}
// Malloc command data streams receive cache
protocol_info.data = malloc(max_cache_len);
if (protocol_info.data == NULL)
{
err = -1;
goto exit;
}
// Pointer is used for deinit.
manager->malloc_data_field = protocol_info.data;
memset(&protocol_head_info, 0, sizeof(quec_wifi_msg_protocol_head_info_s));
while (1)
{
memset(&msg_info, 0, sizeof(quec_wifi_msg_info_s));
protocol_head_info.data = NULL;
dst_buff_len = 0;
result = 0;
err = quec_rtos_queue_wait(manager->msg_queue, (uint8 *)&msg_info, sizeof(quec_wifi_msg_info_s), QUEC_WAIT_FOREVER);
if (err != kNoErr)
{
QUEC_WIFI_MSG_LOG("wait error err= %d", err);
goto exit;
}
// Protocol processing
if (msg_info.data_len + protocol_info.data_len > max_cache_len)
{
QUEC_WIFI_MSG_LOG("msg data too long!!!!!");
goto exit;
}
//将数�追加到未处�的数�尾部
memcpy(protocol_info.data + protocol_info.data_len, msg_info.data, msg_info.data_len);
//�新计算�处�的数�长度.
protocol_info.data_len = protocol_info.data_len + msg_info.data_len;
while (protocol_info.data_len > 0)
{
check_parse:
quec_wifi_msg_npto_parse(protocol_info.data, protocol_info.data_len, &protocol_head_info, &dst_buff_len, &result);
QUEC_WIFI_MSG_LOG("data_len=%d dst_buff_len=%d result=%d", protocol_info.data_len, dst_buff_len, result);
if (dst_buff_len > 0 && protocol_info.data_len >= dst_buff_len)
{
memmove(protocol_info.data, protocol_info.data + dst_buff_len, protocol_info.data_len - dst_buff_len);
protocol_info.data_len -= dst_buff_len;
if(QUEC_WIFI_NPTO_PARSE_RESULT_ERRCRC==result && protocol_info.data_len >= QUEC_PROTOCOL_HEAD_MAX_SIZE)
{
goto check_parse;
}
}
// protocol success
if (result == QUEC_WIFI_NPTO_PARSE_RESULT_SUCC)
{
QUEC_WIFI_MSG_LOG("rx wifi cmd=%d", protocol_head_info.command);
switch (protocol_head_info.command)
{
case QUEC_WIFI_NPTO_802_3_STREAM:
{
// Pass data streams to NET engine
extern int quec_wifi_uart_ul(uint8_t *data,uint16_t len);
if(quec_wifi_uart_ul(protocol_head_info.data,(protocol_head_info.cmdlen - QUEC_PROTOCOL_HEAD_MAX_SIZE)))
{
QUEC_WIFI_MSG_LOG("UART UL ERROR");
}
QUEC_FREE_PTR(protocol_head_info.data);
break;
}
case QUEC_WIFI_NPTO_STA_IP_START_CMD:
{
quec_wifi_sta_ip_start(protocol_head_info.data);
QUEC_FREE_PTR(protocol_head_info.data);
break;
}
case QUEC_WIFI_NPTO_STA_IP_DOWN_CMD:
{
quec_wifi_sta_ip_down(NULL);
//protocol_head_info.data is 0, no need to free.
break;
}
case QUEC_WIFI_NPTO_UAP_IP_START_CMD:
case QUEC_WIFI_NPTO_UAP_STA_CONNECT_CMD:
{
if(quec_wifi_wlan_create(protocol_head_info.data) == QUEC_WIFI_SUCCESS)
{
quec_wifi_uap_ip_start(protocol_head_info.data);
}
QUEC_FREE_PTR(protocol_head_info.data);
break;
}
case QUEC_WIFI_NPTO_UAP_IP_DOWN_CMD:
{
quec_wifi_wlan_lan_destroy(protocol_head_info.data);
QUEC_FREE_PTR(protocol_head_info.data);
break;
}
case QUEC_WIFI_NPTO_WLAN_CREATE_CMD:
{
quec_wifi_wlan_create(protocol_head_info.data);
QUEC_FREE_PTR(protocol_head_info.data);
break;
}
case QUEC_WIFI_NPTO_WLAN_DESTROY_CMD:
{
quec_wifi_wlan_destroy(protocol_head_info.data);
QUEC_FREE_PTR(protocol_head_info.data);
break;
}
case QUEC_WIFI_NPTO_UAP_STA_DISCONNECT_CMD:
{
quec_wifi_wlan_destory_lan_by_id(protocol_head_info.data);
QUEC_FREE_PTR(protocol_head_info.data);
break;
}
case QUEC_WIFI_APP_STA_STATUS_CMD:
{
quec_rtos_mutex_lock(quec_wifi_msg_mutex, 0xFFFFFFFF);
if (manager->msg_notify_cb != NULL)
{
quec_wifi_msg_cmd_info_s info = {
.msg_id = QUEC_WIFI_APP_STA_LINK_STATUS_CMD,
.msg_info = protocol_head_info.data};
manager->msg_notify_cb(&info);
}
else
{
QUEC_FREE_PTR(protocol_head_info.data);
}
quec_rtos_mutex_unlock(quec_wifi_msg_mutex);
break;
}
case QUEC_WIFI_APP_SCAN_START_CMD:
case QUEC_WIFI_APP_EVENT_NOTIFY:
case QUEC_WIFI_APP_OTA_CMD:
case QUEC_WIFI_BOOT_UPGRADE_CMD:
case QUEC_WIFI_APP_GET_VERSION:
case QUEC_WIFI_APP_RESET_DONE:
case QUEC_WIFI_APP_SET_BLACK_MAC:
case QUEC_WIFI_APP_WIFI_STATE_REPORT:
case QUEC_BLE_APP_INFO_RPT:
case QUEC_BLE_APP_GET_BLE_MAC_ADDR_CMD:
case QUEC_WIFI_APP_AP_SET_CHANNEL:
{
quec_rtos_mutex_lock(quec_wifi_msg_mutex, 0xFFFFFFFF);
if (manager->msg_notify_cb != NULL)
{
quec_wifi_msg_cmd_info_s info = {
.msg_id = protocol_head_info.command,
.msg_info = protocol_head_info.data};
manager->msg_notify_cb(&info);
//will free protocol_head_info.data in function quec_wifi_app_thread
}
else
{
QUEC_FREE_PTR(protocol_head_info.data);
}
quec_rtos_mutex_unlock(quec_wifi_msg_mutex);
break;
}
default:
{
QUEC_FREE_PTR(protocol_head_info.data);
QUEC_WIFI_MSG_LOG("command=%d error", protocol_head_info.command);
break;
}
}
}
else
{
break;
}
}
QUEC_WIFI_MSG_LOG("msg_info.data=%p", msg_info.data);
if (msg_info.data != NULL)
{
free(msg_info.data);
msg_info.data = NULL;
}
}
exit:
quec_rtos_mutex_lock(quec_wifi_msg_mutex, 0xFFFFFFFF);
QUEC_WIFI_MSG_LOG("quec_wifi_msg_init set 0");
memset(manager, 0, sizeof(quec_wifi_msg_manager_s));
quec_rtos_mutex_unlock(quec_wifi_msg_mutex);
quec_rtos_task_delete(NULL);
return;
}
quec_wifi_msg_errcode_e quec_wifi_msg_init(void *argv)
{
quec_wifi_msg_errcode_e ret = QUEC_WIFI_MSG_SUCCESS;
quec_wifi_msg_manager_s *manager = &quec_wifi_msg_manager;
QUEC_WIFI_MSG_LOG("quec_wifi_msg_init");
// Create mutex.Never delete.
if (NULL == quec_wifi_msg_mutex)
{
if (0 != quec_rtos_mutex_create(&(quec_wifi_msg_mutex)))
{
ret = QUEC_WIFI_MSG_MUTEX_CREATE_ERR;
return ret;
}
}
if(manager->task==NULL)
{
memset(manager, 0, sizeof(quec_wifi_msg_manager_s));
QUEC_WIFI_MSG_LOG("quec_wifi_msg_init set 0");
if (0 != quec_rtos_task_create(&manager->task, 2048, QUEC_WIFI_MSG_THREAD_PRIORITY, "wifi_msg", quec_wifi_msg_thread, NULL, QUEC_WIFI_MSG_TASK_EVENT_CNT))
{
QUEC_WIFI_MSG_LOG("quec_wifi_msg_init err");
ret = QUEC_WIFI_MSG_TASK_CREATE_ERR;
}
}
return ret;
}
quec_wifi_msg_errcode_e quec_wifi_msg_deinit(void *argv)
{
return QUEC_WIFI_MSG_SUCCESS;
}
#endif /* QUEC_FGM842D_WIFI_SUPPORT */
#endif /* MIN_SYS */