743 lines
20 KiB
C
743 lines
20 KiB
C
/****************************************************************************
|
|
*
|
|
* Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
|
|
*
|
|
* This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
|
|
* be copied by any method or incorporated into another program without
|
|
* the express written consent of Aerospace C.Power. This Information or any portion
|
|
* thereof remains the property of Aerospace C.Power. The Information contained herein
|
|
* is believed to be accurate and Aerospace C.Power assumes no responsibility or
|
|
* liability for its use in any way and conveys no license or title under
|
|
* any patent or copyright and makes no representation or warranty that this
|
|
* Information is free from patent or copyright infringement.
|
|
*
|
|
* ****************************************************************************/
|
|
|
|
#include "os_types.h"
|
|
#include "os_utils_api.h"
|
|
#include "os_mem_api.h"
|
|
#include "iot_config.h"
|
|
#include "iot_errno_api.h"
|
|
#include "iot_io_api.h"
|
|
#include "iot_config_api.h"
|
|
#include "iot_utils_api.h"
|
|
#include "iot_board_api.h"
|
|
#include "iot_task_api.h"
|
|
#include "iot_crc_api.h"
|
|
#include "iot_uart_h.h"
|
|
#include "iot_bt_ext_msg.h"
|
|
#include "iot_bt_ext.h"
|
|
#include "iot_bt_ext_upgrade.h"
|
|
#include "iot_bt_ext_dev_mgmt.h"
|
|
|
|
#if IOT_BT_EXT_ENABLE
|
|
|
|
/* for debug mode. default 0 */
|
|
#define IOT_BT_EXT_DEBUG 0
|
|
|
|
/* task priority */
|
|
#define IOT_BT_EXT_TASK_PRIO 7
|
|
/* task stack size */
|
|
#define IOT_BT_EXT_TASK_STACK_SIZE 512
|
|
/* task message count */
|
|
#define IOT_BT_EXT_TASK_MSG_COUNT 64
|
|
|
|
/* alarm timer period */
|
|
#define IOT_BT_EXT_ALARM_PERIOD_MS 1000
|
|
|
|
#define iot_bt_ext_ctxt_get() (g_bt_ext_ctxt)
|
|
|
|
static iot_bt_ext_ctxt_t *g_bt_ext_ctxt = NULL;
|
|
|
|
#if IOT_BT_EXT_DEBUG
|
|
#define iot_bt_ext_dbg(fmt, ...) iot_printf(fmt, ##__VA_ARGS__)
|
|
#else
|
|
#define iot_bt_ext_dbg(fmt, ...)
|
|
#endif
|
|
|
|
/* sub system config table */
|
|
static const iot_bt_ext_sub_cfg_t gc_bt_ext_sub_cfg_tbl[] = {
|
|
/* bt upgrade port config */
|
|
{
|
|
/* sub port id */
|
|
IOT_BT_EXT_PORT_UPGRADE,
|
|
/* sub port open function */
|
|
iot_bt_ext_upgrade_init,
|
|
/* sub port close function */
|
|
iot_bt_ext_upgrade_deinit,
|
|
/* sub port rx report callback function */
|
|
iot_bt_ext_upgrade_rx,
|
|
/* sub port alarm task callback function, implement by post messages */
|
|
iot_bt_ext_upgrade_timeover_cb,
|
|
},
|
|
/* bt device management port config */
|
|
{
|
|
/* sub port id */
|
|
IOT_BT_EXT_PORT_DEV_MGMT,
|
|
/* sub port open function */
|
|
iot_bt_ext_dm_open,
|
|
/* sub port close function */
|
|
iot_bt_ext_dm_close,
|
|
/* sub port rx report callback function */
|
|
iot_bt_ext_dm_rx,
|
|
/* sub port alarm task callback function, implement by post messages */
|
|
iot_bt_ext_dm_alarm_cb,
|
|
},
|
|
};
|
|
|
|
static void iot_bt_ext_data_print(uint8_t is_tx, uint16_t len, uint8_t *buf)
|
|
{
|
|
uint16_t i;
|
|
|
|
iot_printf("bt:is_tx=%d,len=%d. ", is_tx, len);
|
|
len = min(len, 32);
|
|
for (i = 0; i < len; i++) {
|
|
iot_printf("0x%02x ", *(buf + i));
|
|
}
|
|
iot_printf("\n");
|
|
}
|
|
|
|
void iot_bt_ext_clean_msg(uint16_t msg_type, uint16_t msg_id)
|
|
{
|
|
iot_bt_ext_ctxt_t *bt_ctxt = iot_bt_ext_ctxt_get();
|
|
if (bt_ctxt) {
|
|
iot_task_clean_msg(bt_ctxt->task_hdl, msg_type, msg_id);
|
|
}
|
|
}
|
|
|
|
/* post message to task */
|
|
uint32_t iot_bt_ext_post_msg(uint16_t msg_type, uint16_t msg_id, void *data)
|
|
{
|
|
iot_task_msg_t *msg;
|
|
iot_bt_ext_msg_type_t *task_msg;
|
|
iot_bt_ext_ctxt_t *bt_ctxt = iot_bt_ext_ctxt_get();
|
|
|
|
msg = iot_task_alloc_msg_with_reserved(bt_ctxt->task_hdl, 0);
|
|
|
|
if (NULL == msg) {
|
|
//IOT_ASSERT(0);
|
|
return ERR_NOMEM;
|
|
}
|
|
|
|
task_msg = (iot_bt_ext_msg_type_t *)msg;
|
|
|
|
task_msg->msg.type = msg_type;
|
|
task_msg->msg.id = msg_id;
|
|
task_msg->data = data;
|
|
|
|
iot_task_queue_msg(bt_ctxt->task_hdl, &task_msg->msg, 0);
|
|
return ERR_OK;
|
|
}
|
|
|
|
static iot_bt_ext_rpt_func_t iot_bt_ext_rpt_hdl_get(uint8_t port)
|
|
{
|
|
uint8_t i, offset;
|
|
iot_bt_ext_ctxt_t *bt_ctxt = iot_bt_ext_ctxt_get();
|
|
|
|
/* sub port */
|
|
if (port < IOT_BT_EXT_PORT_USER_BASE) {
|
|
for (i = 0; i < bt_ctxt->sub_info.sub_num; i++) {
|
|
if (bt_ctxt->sub_info.cfg[i].port_id == port) {
|
|
return bt_ctxt->sub_info.cfg[i].rx_rpt_func;
|
|
}
|
|
}
|
|
} else { /* user port */
|
|
for (i = IOT_BT_EXT_PORT_USER_BASE; i < IOT_BT_EXT_PORT_USER_END; i++) {
|
|
offset = i - IOT_BT_EXT_PORT_USER_BASE;
|
|
if (bt_ctxt && (bt_ctxt->user_info[offset].port_id == port)) {
|
|
return bt_ctxt->user_info[offset].rx_rpt_func;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void iot_bt_ext_rpt_handle(uint8_t port, iot_pkt_t *pkt)
|
|
{
|
|
iot_bt_ext_ctxt_t *bt_ctxt = iot_bt_ext_ctxt_get();
|
|
|
|
if (!bt_ctxt) {
|
|
if (pkt) {
|
|
iot_pkt_free(pkt);
|
|
pkt = NULL;
|
|
}
|
|
return;
|
|
}
|
|
|
|
iot_bt_ext_dbg("bt:%s. port=%d\n", __FUNCTION__, port);
|
|
|
|
iot_bt_ext_rpt_func_t func = iot_bt_ext_rpt_hdl_get(port);
|
|
|
|
if (func) {
|
|
func(pkt);
|
|
} else {
|
|
iot_printf("bt:port[%d] rpt not support\n", port);
|
|
iot_pkt_free(pkt);
|
|
}
|
|
}
|
|
|
|
static void iot_bt_ext_proto_parse(iot_pkt_t *pkt)
|
|
{
|
|
uint16_t crc_cal, len;
|
|
uint32_t err_no = 0;
|
|
uint8_t *buf;
|
|
iot_bt_ext_proto_start_t *proto_start;
|
|
iot_bt_ext_proto_hdr_t *proto_hdr;
|
|
iot_bt_ext_proto_end_t *proto_end;
|
|
|
|
if (!pkt) {
|
|
return;
|
|
}
|
|
|
|
buf = (uint8_t *)iot_pkt_data(pkt);
|
|
len = (uint16_t)iot_pkt_data_len(pkt);
|
|
|
|
iot_bt_ext_data_print(0, len, buf);
|
|
do {
|
|
/* check total len */
|
|
if (len < IOT_BT_EXT_PROTO_PACKET_MIN_LEN) {
|
|
err_no = (uint32_t)__LINE__;
|
|
break;
|
|
}
|
|
|
|
/* check start field */
|
|
proto_start = (iot_bt_ext_proto_start_t *)buf;
|
|
iot_bt_ext_dbg("bt:proto-start.0x%x-0x%x\n",
|
|
proto_start->start[0], proto_start->start[1]);
|
|
if ((IOT_BT_EXT_PROTO_START_CODE != proto_start->start[0])
|
|
|| (IOT_BT_EXT_PROTO_START_CODE != proto_start->start[1])) {
|
|
err_no = (uint32_t)__LINE__;
|
|
break;
|
|
}
|
|
|
|
/* check header field */
|
|
proto_hdr = (iot_bt_ext_proto_hdr_t *)(proto_start + 1);
|
|
iot_bt_ext_dbg("bt:proto-hdr.version:%d,port:%d,"
|
|
"crc=0x%x,len:%d\n",
|
|
proto_hdr->version, proto_hdr->port, proto_hdr->crc,
|
|
proto_hdr->length);
|
|
|
|
/* check version */ //TODO:
|
|
|
|
/* check port valid */
|
|
if (proto_hdr->port >= IOT_BT_EXT_PORT_USER_END) {
|
|
err_no = (uint32_t)__LINE__;
|
|
break;
|
|
}
|
|
/* check payload len */
|
|
if (proto_hdr->length > (len - IOT_BT_EXT_PROTO_PACKET_MIN_LEN)) {
|
|
err_no = (uint32_t)__LINE__;
|
|
break;
|
|
}
|
|
|
|
/* check payload crc */
|
|
crc_cal = iot_getcrc16((uint8_t *)(proto_hdr + 1), proto_hdr->length,
|
|
IOT_CRC16_TYPE_BT);
|
|
iot_bt_ext_dbg("bt:proto-src_crc=0x%x, cal_crc=0x%x\n",
|
|
proto_hdr->crc, crc_cal);
|
|
if (proto_hdr->crc != crc_cal) {
|
|
//err_no = (uint32_t)__LINE__;
|
|
//break;
|
|
}
|
|
|
|
/* check tail */
|
|
proto_end = (iot_bt_ext_proto_end_t *)((uint8_t *)(proto_hdr + 1) +
|
|
proto_hdr->length);
|
|
iot_bt_ext_dbg("bt:proto-end.0x%x-0x%x\n",
|
|
proto_end->end[0], proto_end->end[1]);
|
|
if ((IOT_BT_EXT_PROTO_END_CODE != proto_end->end[0])
|
|
|| (IOT_BT_EXT_PROTO_END_CODE != proto_end->end[1])) {
|
|
err_no = (uint32_t)__LINE__;
|
|
break;
|
|
}
|
|
|
|
/* set pkt data ptr for payload start */
|
|
iot_pkt_pull(pkt, sizeof(*proto_start) + sizeof(*proto_hdr));
|
|
/* set pkt tail ptr for payload end */
|
|
iot_pkt_shrink(pkt, sizeof(*proto_end));
|
|
iot_bt_ext_dbg("bt:proto_rpt_sub pkt_len=%d\n", iot_pkt_data_len(pkt));
|
|
/* report pkt */
|
|
iot_bt_ext_rpt_handle(proto_hdr->port, pkt);
|
|
} while(0);
|
|
|
|
if (err_no) {
|
|
iot_printf("bt:proto_parse.err=%d.\n", err_no);
|
|
iot_pkt_free(pkt);
|
|
}
|
|
}
|
|
|
|
/* protocol uart tx */
|
|
static void iot_bt_ext_send_handle(uint8_t port, iot_pkt_t *pkt)
|
|
{
|
|
uint16_t crc, len;
|
|
uint32_t err_no = 0;
|
|
iot_bt_ext_proto_start_t *proto_start;
|
|
iot_bt_ext_proto_hdr_t *proto_hdr;
|
|
iot_bt_ext_proto_end_t *proto_end;
|
|
iot_bt_ext_ctxt_t *bt_ctxt = iot_bt_ext_ctxt_get();
|
|
|
|
do {
|
|
if ((NULL == bt_ctxt) || (NULL == pkt)) {
|
|
err_no = __LINE__;
|
|
break;
|
|
}
|
|
|
|
/* get input data len and crc */
|
|
len = (uint16_t)iot_pkt_data_len(pkt);
|
|
crc = iot_getcrc16(iot_pkt_data(pkt), len, IOT_CRC16_TYPE_BT);
|
|
|
|
/* set pkt data ptr */
|
|
proto_start = (iot_bt_ext_proto_start_t *)iot_pkt_push(pkt,
|
|
sizeof(iot_bt_ext_proto_start_t) + sizeof(iot_bt_ext_proto_hdr_t));
|
|
if (NULL == proto_start) {
|
|
err_no = __LINE__;
|
|
break;
|
|
}
|
|
|
|
/* set tail ptr */
|
|
if (NULL == iot_pkt_put(pkt, sizeof(iot_bt_ext_proto_end_t))) {
|
|
err_no = __LINE__;
|
|
break;
|
|
}
|
|
|
|
/* fill start code */
|
|
os_mem_set(proto_start, IOT_BT_EXT_PROTO_START_CODE,
|
|
sizeof(*proto_start));
|
|
|
|
/* fill proto header */
|
|
proto_hdr = (iot_bt_ext_proto_hdr_t *)(proto_start + 1);
|
|
proto_hdr->version = IOT_BT_EXT_PROTO_VERSION;
|
|
proto_hdr->port = port;
|
|
proto_hdr->length = len;
|
|
proto_hdr->crc = crc;
|
|
|
|
/* fill tail */
|
|
proto_end = (iot_bt_ext_proto_end_t *)((uint8_t *)(proto_hdr + 1)
|
|
+ len);
|
|
os_mem_set(proto_end, IOT_BT_EXT_PROTO_END_CODE, sizeof(*proto_end));
|
|
|
|
/* print output data */
|
|
iot_bt_ext_data_print(1, (uint16_t)iot_pkt_data_len(pkt),
|
|
(uint8_t *)iot_pkt_data(pkt));
|
|
|
|
/* send data */
|
|
iot_uart_send(bt_ctxt->peri_info.peri_hdl, pkt, NULL);
|
|
} while(0);
|
|
|
|
if (err_no) {
|
|
iot_bt_ext_dbg("bt:%s, err = %d\n", __FUNCTION__, err_no);
|
|
if (pkt) {
|
|
iot_pkt_free(pkt);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void iot_bt_ext_msg_handle(iot_task_h task_h, iot_task_msg_t *msg)
|
|
{
|
|
iot_bt_ext_msg_type_t *msg_entry = (iot_bt_ext_msg_type_t *)msg;
|
|
|
|
switch (msg_entry->msg.type) {
|
|
case IOT_BT_EXT_MSG_TYPE_DATA_RX:
|
|
iot_bt_ext_proto_parse((iot_pkt_t *)msg_entry->data);
|
|
break;
|
|
|
|
case IOT_BT_EXT_MSG_TYPE_DATA_TX:
|
|
iot_bt_ext_send_handle((uint8_t)msg_entry->msg.id,
|
|
(iot_pkt_t *)msg_entry->data);
|
|
break;
|
|
|
|
case IOT_BT_EXT_MSG_TYPE_UPGRADE:
|
|
iot_bt_ext_upgrade_msg_handle((uint8_t)msg_entry->msg.id,
|
|
msg_entry->data);
|
|
break;
|
|
|
|
case IOT_BT_EXT_MSG_TYPE_DEV_MGMT:
|
|
iot_bt_ext_dm_msg_handle(msg_entry->msg.id, msg_entry->data);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
iot_task_free_msg(task_h, &(msg_entry->msg));
|
|
}
|
|
|
|
static void iot_bt_ext_msg_cancel(iot_task_h task_h, iot_task_msg_t *msg)
|
|
{
|
|
iot_bt_ext_msg_type_t *msg_entry = (iot_bt_ext_msg_type_t *)msg;
|
|
|
|
switch (msg_entry->msg.type) {
|
|
case IOT_BT_EXT_MSG_TYPE_DATA_RX:
|
|
case IOT_BT_EXT_MSG_TYPE_DATA_TX:
|
|
if (msg_entry->data) {
|
|
iot_pkt_free((iot_pkt_t *)msg_entry->data);
|
|
}
|
|
break;
|
|
|
|
case IOT_BT_EXT_MSG_TYPE_UPGRADE:
|
|
case IOT_BT_EXT_MSG_TYPE_DEV_MGMT:
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
iot_task_free_msg(task_h, &(msg_entry->msg));
|
|
}
|
|
|
|
static iot_task_h iot_bt_ext_task_init(void)
|
|
{
|
|
iot_task_config_t task_cfg = {0};
|
|
|
|
/* task config */
|
|
task_cfg.stack_size = IOT_BT_EXT_TASK_STACK_SIZE;
|
|
task_cfg.task_prio = IOT_BT_EXT_TASK_PRIO;
|
|
task_cfg.msg_size = sizeof(iot_bt_ext_msg_type_t);
|
|
task_cfg.msg_cnt = IOT_BT_EXT_TASK_MSG_COUNT;
|
|
task_cfg.queue_cnt = 1;
|
|
task_cfg.queue_cfg[0].quota = 0;
|
|
task_cfg.task_event_func = NULL;
|
|
task_cfg.msg_exe_func = iot_bt_ext_msg_handle;
|
|
task_cfg.msg_cancel_func = iot_bt_ext_msg_cancel;
|
|
|
|
return iot_task_create(IOT_DRIVER_MID, &task_cfg);
|
|
}
|
|
|
|
static void iot_bt_ext_peri_recv(uint8_t* buffer, uint32_t buffer_len,
|
|
bool_t is_full_frame, uint32_t invalid_data_len)
|
|
{
|
|
iot_pkt_t *pkt;
|
|
(void)invalid_data_len;
|
|
(void)is_full_frame;
|
|
|
|
iot_bt_ext_dbg("bt:%s-rx len %d\n", __FUNCTION__, buffer_len);
|
|
|
|
pkt = iot_pkt_alloc(buffer_len, IOT_DRIVER_MID);
|
|
if (pkt) {
|
|
os_mem_cpy(iot_pkt_put(pkt, buffer_len), buffer, buffer_len);
|
|
iot_bt_ext_post_msg(IOT_BT_EXT_MSG_TYPE_DATA_RX, 0, pkt);
|
|
}
|
|
}
|
|
|
|
static iot_uart_h iot_bt_ext_uart_init(iot_bt_ext_uart_cfg_t *cfg)
|
|
{
|
|
uint8_t uart_type;
|
|
iot_uart_h uart_hdl = NULL;
|
|
iot_frame_fmt fmt = { 0 };
|
|
|
|
fmt.preamble_code[0] = IOT_BT_EXT_PROTO_START_CODE;
|
|
fmt.preamble_code[1] = IOT_BT_EXT_PROTO_START_CODE;
|
|
fmt.preamble_codelen = IOT_BT_EXT_PROTO_START_LEN;
|
|
fmt.datalen_offset = sizeof(iot_bt_ext_proto_hdr_t)
|
|
- IOT_BT_EXT_PROTO_PL_LEN_FIELD_LEN;
|
|
fmt.datalen_size = IOT_BT_EXT_PROTO_PL_LEN_FIELD_LEN;
|
|
fmt.datalen_fix = 0;
|
|
fmt.backcode[0] = IOT_BT_EXT_PROTO_END_CODE;
|
|
fmt.backcode[1] = IOT_BT_EXT_PROTO_END_CODE;
|
|
fmt.backcode_offset = 0;
|
|
fmt.backcode_len = IOT_BT_EXT_PROTO_END_LEN;
|
|
fmt.frame_timeout = 20;
|
|
fmt.timeout_mode = TIMEOUT_PERDATA;
|
|
//TODO: will fix uart port
|
|
#if (HW_PLATFORM >= HW_PLATFORM_FPGA)
|
|
uart_type = UART_EXT_BT_PORT;
|
|
#else
|
|
uart_type = UART_IR_PORT; //TODO:
|
|
#endif
|
|
if (iot_board_get_uart(uart_type) >= IOT_UART_PORT_SUPP_MAX) {
|
|
return uart_hdl;
|
|
}
|
|
uart_hdl = iot_uart_open(iot_board_get_uart(uart_type),
|
|
iot_bt_ext_peri_recv, IOT_EXT_BT_PERI_BUF_LEN, &fmt);
|
|
if (uart_hdl && cfg) {
|
|
if (!iot_uart_set_config(uart_hdl, cfg->baud, (uint8_t)cfg->parity,
|
|
(uint8_t)cfg->data, (uint8_t)cfg->stop)) {
|
|
uart_hdl = (iot_uart_h)NULL;
|
|
}
|
|
}
|
|
|
|
return uart_hdl;
|
|
}
|
|
|
|
static void iot_bt_ext_alarm_inform(timer_id_t timer_id, void *arg)
|
|
{
|
|
uint8_t i;
|
|
iot_bt_ext_alarm_func_t alarm_func;
|
|
iot_bt_ext_ctxt_t *bt_ctxt;
|
|
|
|
(void)timer_id;
|
|
bt_ctxt = (iot_bt_ext_ctxt_t *)arg;
|
|
|
|
if (!bt_ctxt) {
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < bt_ctxt->sub_info.sub_num; i++) {
|
|
alarm_func = bt_ctxt->sub_info.cfg[i].alarm_func;
|
|
if (alarm_func) {
|
|
alarm_func((uint32_t)bt_ctxt->alarm_period);
|
|
}
|
|
}
|
|
}
|
|
|
|
static uint32_t iot_bt_ext_alarm_init(iot_bt_ext_ctxt_t *bt_ctxt)
|
|
{
|
|
if (!bt_ctxt) {
|
|
return ERR_INVAL;
|
|
}
|
|
|
|
|
|
bt_ctxt->alarm_timer = os_create_timer(IOT_DRIVER_MID, true,
|
|
(os_timer_func_t)iot_bt_ext_alarm_inform, bt_ctxt);
|
|
if (!bt_ctxt->alarm_timer) {
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
bt_ctxt->alarm_period = IOT_BT_EXT_ALARM_PERIOD_MS;
|
|
return ERR_OK;
|
|
}
|
|
|
|
static void iot_bt_ext_alarm_start(iot_bt_ext_ctxt_t *bt_ctxt)
|
|
{
|
|
if (bt_ctxt && bt_ctxt->alarm_timer) {
|
|
if (0 == bt_ctxt->alarm_period) {
|
|
bt_ctxt->alarm_period = IOT_BT_EXT_ALARM_PERIOD_MS;
|
|
}
|
|
os_start_timer(bt_ctxt->alarm_timer, bt_ctxt->alarm_period);
|
|
}
|
|
}
|
|
|
|
static uint32_t iot_bt_ext_sub_open(iot_bt_ext_ctxt_t *bt_ctxt)
|
|
{
|
|
uint8_t i;
|
|
iot_bt_ext_sub_open_func_t func;
|
|
|
|
if (!bt_ctxt) {
|
|
return ERR_INVAL;
|
|
}
|
|
|
|
bt_ctxt->sub_info.sub_num = sizeof(gc_bt_ext_sub_cfg_tbl)
|
|
/ sizeof(gc_bt_ext_sub_cfg_tbl[0]);
|
|
bt_ctxt->sub_info.cfg = (iot_bt_ext_sub_cfg_t *)gc_bt_ext_sub_cfg_tbl;
|
|
|
|
for (i = 0; i < bt_ctxt->sub_info.sub_num; i++) {
|
|
func = bt_ctxt->sub_info.cfg[i].open_func;
|
|
if (func) {
|
|
if (ERR_OK != func()) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (i < bt_ctxt->sub_info.sub_num) {
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
static void iot_bt_ext_sub_close(iot_bt_ext_ctxt_t *bt_ctxt)
|
|
{
|
|
uint8_t i;
|
|
iot_bt_ext_sub_close_func_t func;
|
|
|
|
if (bt_ctxt) {
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < bt_ctxt->sub_info.sub_num; i++) {
|
|
func = bt_ctxt->sub_info.cfg[i].close_func;
|
|
if (func) {
|
|
func();
|
|
}
|
|
}
|
|
|
|
bt_ctxt->sub_info.sub_num = 0;
|
|
bt_ctxt->sub_info.cfg = NULL;
|
|
}
|
|
|
|
iot_pkt_t *iot_bt_ext_send_pkt_get(uint32_t len)
|
|
{
|
|
iot_pkt_t *pkt;
|
|
|
|
if (NULL == iot_bt_ext_ctxt_get()) {
|
|
return NULL;
|
|
}
|
|
|
|
IOT_PKT_GET(pkt, IOT_BT_EXT_PROTO_PACKET_MIN_LEN + len,
|
|
sizeof(iot_bt_ext_proto_start_t) + sizeof(iot_bt_ext_proto_hdr_t),
|
|
IOT_DRIVER_MID);
|
|
|
|
return pkt;
|
|
}
|
|
|
|
uint32_t iot_bt_ext_rpt_register(uint8_t port, iot_bt_ext_rpt_func_t cb)
|
|
{
|
|
uint8_t offset;
|
|
iot_bt_ext_ctxt_t *bt_ctxt = iot_bt_ext_ctxt_get();
|
|
|
|
/* check port valid */
|
|
if ((port < IOT_BT_EXT_PORT_USER_BASE)
|
|
|| (port >= IOT_BT_EXT_PORT_USER_END)) {
|
|
return ERR_INVAL;
|
|
}
|
|
|
|
if (bt_ctxt) {
|
|
offset = port - IOT_BT_EXT_PORT_USER_BASE;
|
|
bt_ctxt->user_info[offset].port_id = port;
|
|
bt_ctxt->user_info[offset].rx_rpt_func = cb;
|
|
iot_bt_ext_dbg("bt:%s. port=%d, func=0x%x\n",
|
|
__FUNCTION__, port, (uint32_t)cb);
|
|
return ERR_OK;
|
|
}
|
|
|
|
return ERR_NOT_READY;
|
|
}
|
|
|
|
void iot_bt_ext_send(uint8_t port, iot_pkt_t *pkt)
|
|
{
|
|
if (NULL == iot_bt_ext_ctxt_get()) {
|
|
return;
|
|
}
|
|
|
|
iot_bt_ext_post_msg(IOT_BT_EXT_MSG_TYPE_DATA_TX, port, pkt);
|
|
}
|
|
|
|
uint32_t iot_bt_ext_open(void)
|
|
{
|
|
uint32_t reason = 0;
|
|
|
|
if (g_bt_ext_ctxt) {
|
|
iot_printf("bt:exist\n");
|
|
return ERR_EXIST;
|
|
}
|
|
|
|
do {
|
|
/* check port id valid */
|
|
BUILD_BUG_ON((uint32_t)IOT_BT_EXT_PORT_SUB_NUM <=
|
|
(uint32_t)IOT_BT_EXT_PORT_USER_BASE);
|
|
|
|
/* alloc ctxt */
|
|
if (NULL == (g_bt_ext_ctxt = os_mem_malloc(IOT_DRIVER_MID,
|
|
sizeof(*g_bt_ext_ctxt)))) {
|
|
reason = (uint32_t)__LINE__;
|
|
break;
|
|
}
|
|
|
|
os_mem_set(g_bt_ext_ctxt, 0, sizeof(*g_bt_ext_ctxt));
|
|
|
|
/* init task ctxt */
|
|
g_bt_ext_ctxt->task_hdl = iot_bt_ext_task_init();
|
|
if (NULL == g_bt_ext_ctxt->task_hdl) {
|
|
reason = (uint32_t)__LINE__;
|
|
break;
|
|
}
|
|
|
|
/* init uart ctxt */
|
|
g_bt_ext_ctxt->peri_info.uart_cfg.parity = IOT_UART_PARITY_EVEN;
|
|
g_bt_ext_ctxt->peri_info.uart_cfg.data = 8;
|
|
g_bt_ext_ctxt->peri_info.uart_cfg.stop = 1;
|
|
g_bt_ext_ctxt->peri_info.uart_cfg.baud = 115200;
|
|
g_bt_ext_ctxt->peri_info.peri_hdl
|
|
= iot_bt_ext_uart_init(&g_bt_ext_ctxt->peri_info.uart_cfg);
|
|
if (NULL == g_bt_ext_ctxt->peri_info.peri_hdl) {
|
|
reason = (uint32_t)__LINE__;
|
|
break;
|
|
}
|
|
|
|
/* open sub module */
|
|
if (ERR_OK != iot_bt_ext_sub_open(g_bt_ext_ctxt)) {
|
|
reason = (uint32_t)__LINE__;
|
|
break;
|
|
}
|
|
|
|
if (ERR_OK != iot_bt_ext_alarm_init(g_bt_ext_ctxt)) {
|
|
reason = (uint32_t)__LINE__;
|
|
break;
|
|
}
|
|
} while(0);
|
|
|
|
iot_printf("bt:open-%d\n", reason);
|
|
if (reason) {
|
|
iot_bt_ext_close();
|
|
return ERR_FAIL;
|
|
} else {
|
|
iot_bt_ext_reset(IOT_BT_EXT_DM_BT_HW_RST);
|
|
/* start alarm timer */
|
|
iot_bt_ext_alarm_start(g_bt_ext_ctxt);
|
|
|
|
return ERR_OK;
|
|
}
|
|
}
|
|
|
|
uint32_t iot_bt_ext_close(void)
|
|
{
|
|
iot_bt_ext_ctxt_t *bt_ctxt = iot_bt_ext_ctxt_get();
|
|
|
|
if (NULL == bt_ctxt) {
|
|
return ERR_NOT_EXIST;
|
|
}
|
|
|
|
iot_bt_ext_sub_close(bt_ctxt);
|
|
|
|
/* release resources */
|
|
if (bt_ctxt->alarm_timer) {
|
|
os_delete_timer(bt_ctxt->alarm_timer);
|
|
bt_ctxt->alarm_timer = (timer_id_t)0;
|
|
}
|
|
|
|
if (bt_ctxt->peri_info.peri_hdl) {
|
|
iot_uart_close(bt_ctxt->peri_info.peri_hdl);
|
|
bt_ctxt->peri_info.peri_hdl = NULL;
|
|
}
|
|
|
|
if (bt_ctxt->task_hdl) {
|
|
iot_task_delete(bt_ctxt->task_hdl);
|
|
bt_ctxt->task_hdl = NULL;
|
|
}
|
|
|
|
os_mem_free(bt_ctxt);
|
|
g_bt_ext_ctxt = NULL;
|
|
|
|
iot_printf("bt:closed\n");
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
#else /* IOT_BT_EXT_ENABLE */
|
|
|
|
iot_pkt_t *iot_bt_ext_send_pkt_get(uint32_t len)
|
|
{
|
|
(void)len;
|
|
return NULL;
|
|
}
|
|
|
|
void iot_bt_ext_send(uint8_t port, iot_pkt_t *pkt)
|
|
{
|
|
(void)port;
|
|
if (pkt) {
|
|
iot_pkt_free(pkt);
|
|
}
|
|
return;
|
|
}
|
|
|
|
uint32_t iot_bt_ext_rpt_register(uint8_t port, iot_bt_ext_rpt_func_t cb)
|
|
{
|
|
(void)port;
|
|
(void)cb;
|
|
return ERR_NOSUPP;
|
|
}
|
|
|
|
uint32_t iot_bt_ext_open(void)
|
|
{
|
|
return ERR_NOSUPP;
|
|
}
|
|
|
|
uint32_t iot_bt_ext_close(void)
|
|
{
|
|
return ERR_OK;
|
|
}
|
|
|
|
#endif /* IOT_BT_EXT_ENABLE */
|