624 lines
16 KiB
C
Raw Normal View History

2025-05-14 11:26:23 +08:00
#include <components/system.h>
#include <os/os.h>
#include <os/mem.h>
#include <os/str.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include "pan_service.h"
#include "bt_comm_list.h"
#include "components/bluetooth/bk_dm_bluetooth_types.h"
#include "components/bluetooth/bk_dm_bt_types.h"
#include "components/bluetooth/bk_dm_bt.h"
#include "components/bluetooth/bk_dm_pan.h"
#include "storage/bluetooth_storage.h"
#include "pan_user_config.h"
#include "bt_manager.h"
#include "net.h"
#include "panif.h"
#include "netif/etharp.h"
#include "app_event.h"
#define TAG "pan"
#define LOGI(...) BK_LOGI(TAG, ##__VA_ARGS__)
#define LOGW(...) BK_LOGW(TAG, ##__VA_ARGS__)
#define LOGE(...) BK_LOGE(TAG, ##__VA_ARGS__)
#define LOGD(...) BK_LOGD(TAG, ##__VA_ARGS__)
//#define PAN_GPIO_DEBUG //GPIO debug
#ifdef PAN_GPIO_DEBUG
#define PAN_NET_OUTPUT() do { GPIO_UP(32); GPIO_DOWN(32);} while (0)
#define PAN_TX() do { GPIO_UP(33); GPIO_DOWN(33);} while (0)
#define PAN_NET_INPUT_START() do { GPIO_DOWN(34); GPIO_UP(34);} while (0)
#define PAN_NET_INPUT_END() do { GPIO_DOWN(34); } while (0)
#define PAN_TX_DONE() do { GPIO_UP(35); GPIO_DOWN(35);} while (0)
#else
#define PAN_NET_OUTPUT()
#define PAN_TX()
#define PAN_NET_INPUT_START()
#define PAN_NET_INPUT_END()
#define PAN_TX_DONE()
#endif
enum
{
BT_PAN_MSG_NULL = 0,
BT_PAN_DATA_IND_MSG = 1,
BT_PAN_TX_DONE_IND_MSG = 2,
BT_PAN_TX_MSG = 3,
BT_PAN_EXIT_MSG = 4,
};
typedef struct
{
uint8_t type;
uint16_t len;
char *data;
} bt_pan_service_msg_t;
static beken_queue_t bt_pan_service_msg_que = NULL;
static beken_thread_t bt_pan_service_thread_handle = NULL;
uint8_t paired_bt_mac[6] = { 0 };
uint8_t s_pan_state = BK_BTPAN_STATE_DISCONNECTED;
uint8_t s_acl_buf_count = CONFIG_NB_ACL_BUFF;
static bt_comm_list_t *s_pan_tx_list = NULL;
static void *s_pan_tx_lock = NULL;
static uint8_t s_pan_service_already_init = 0;
void pan_show_tx_data_cache_count(void)
{
LOGI("%s, %d\r\n",__func__, s_pan_tx_list->length);
}
static int pan_push_tx_data_to_list(void *data, uint16_t len)
{
int ret = 0;
if (s_pan_tx_list->length > CONFIG_MAX_TX_CACHE_COUNT)
{
LOGE("the tx cache count exceeds the limit(%d), discard the tx data!!!\r\n",CONFIG_MAX_TX_CACHE_COUNT);
return -1;
}
uint8_t *p_data = (uint8_t *)psram_malloc(len);
if (p_data)
{
os_memcpy(p_data, data, len);
bt_comm_list_append(s_pan_tx_list, p_data);
}
else
{
LOGE("%s, psram_malloc failed!!!\r\n",__func__);
ret = -1;
}
return ret;
}
void bt_pan_reconnect_failure_handler(void)
{
bt_clear_reconnect_info();
bt_manager_set_mode(BT_MNG_MODE_IDLE);
extern uint8_t network_disc_evt_posted;
if (network_disc_evt_posted == 0) {
app_event_send_msg(APP_EVT_RECONNECT_NETWORK_FAIL, 0);
network_disc_evt_posted = 1;
}
#if CONFIG_STA_AUTO_RECONNECT
extern int demo_network_auto_reconnect(bool val);
extern bool smart_config_running;
if (!smart_config_running) {
demo_network_auto_reconnect(true);
}
#endif
}
void bt_start_pan_reconnect(void)
{
uint8_t recon_addr[6] = {0};
LOGI("%s\n", __func__);
if ((bluetooth_storage_get_newest_linkkey_info(recon_addr, NULL)) < 0)
{
LOGI("%s can't find linkkey info\n", __func__);
//bt_manager_set_mode(BT_MNG_MODE_PAIRING);
bt_pan_reconnect_failure_handler();
}
else
{
LOGI("%s find addr\n", __func__);
bt_manager_start_reconnect(recon_addr, 1);
}
}
void bt_pan_service_main(void *arg)
{
#if 0
uint8_t recon_addr[6] = {0};
if ((bluetooth_storage_get_newest_linkkey_info(recon_addr, NULL)) < 0)
{
LOGI("%s can't find linkkey info\n", __func__);
bt_manager_set_mode(BT_MNG_MODE_PAIRING);
}
else
{
LOGI("%s find addr\n", __func__);
//bt_manager_start_reconnect(recon_addr, 1);
}
#endif
while (1)
{
bk_err_t err;
bt_pan_service_msg_t msg;
err = rtos_pop_from_queue(&bt_pan_service_msg_que, &msg, BEKEN_WAIT_FOREVER);
if (kNoErr == err)
{
switch (msg.type)
{
case BT_PAN_DATA_IND_MSG:
{
eth_data_t *p_data = (eth_data_t *)msg.data;
#if CONFIG_NET_PAN
struct netif *netif;
struct eth_hdr *ethhdr;
#endif
uint8_t *dest = p_data->dest;
uint8_t *src = p_data->src;
LOGD("PAN_DATA_IND, pro:0x%04x, dest[%02x:%02x:%02x:%02x:%02x:%02x],src[%02x:%02x:%02x:%02x:%02x:%02x], len : %d\r\n",
p_data->protocol, dest[0], dest[1], dest[2], dest[3], dest[4], dest[5],
src[0], src[1], src[2], src[3], src[4], src[5], p_data->payload_len);
LOGD(" data : %x %x- %x %x\r\n", p_data->payload[0], p_data->payload[1], p_data->payload[p_data->payload_len - 2], p_data->payload[p_data->payload_len - 1]);
#if CONFIG_NET_PAN
/* PAN Wi-Fi Part */
struct pbuf *p = pbuf_alloc(PBUF_RAW, p_data->payload_len + sizeof(struct eth_hdr), PBUF_POOL);
if (p == NULL)
{
LOGI("Failed to allocate pbuf\r\n");
os_free(msg.data);
break;
}
if (p_data->payload_len < 0 || p_data->payload_len > p->len - sizeof(struct eth_hdr))
{
LOGI("Payload too large or invalid for pbuf\r\n");
pbuf_free(p);
os_free(msg.data);
break;
}
ethhdr = (struct eth_hdr *)p->payload;
os_memcpy(ethhdr->dest.addr, p_data->dest, PAN_HWADDR_LEN);
os_memcpy(ethhdr->src.addr, p_data->src, PAN_HWADDR_LEN);
ethhdr->type = htons(p_data->protocol);
netif = net_get_pan_handle();
if (netif == NULL || !netif_is_up(netif))
{
LOGI("Network interface is not ready\r\n");
pbuf_free(p);
os_free(msg.data);
break;
}
os_memcpy(p->payload + sizeof(struct eth_hdr), p_data->payload, p_data->payload_len);
PAN_NET_INPUT_START();
panif_input(netif, p);
PAN_NET_INPUT_END();
#endif
os_free(msg.data);
}
break;
case BT_PAN_TX_DONE_IND_MSG:
{
s_acl_buf_count++;
}
case BT_PAN_TX_MSG:
{
if (s_acl_buf_count && (!bt_comm_list_is_empty(s_pan_tx_list)))
{
PAN_TX();
rtos_lock_mutex(&s_pan_tx_lock);
eth_data_t *eth_data = bt_comm_list_front(s_pan_tx_list);
s_acl_buf_count--;
bk_bt_pan_write(paired_bt_mac, eth_data);
bt_comm_list_remove(s_pan_tx_list, eth_data);
rtos_unlock_mutex(&s_pan_tx_lock);
}
}
break;
case BT_PAN_EXIT_MSG:
goto exit;
break;
default:
LOGD("Unknown message type: %d\r\n", msg.type);
break;
}
}
}
exit:
rtos_deinit_queue(&bt_pan_service_msg_que);
bt_pan_service_msg_que = NULL;
bt_pan_service_thread_handle = NULL;
rtos_delete_thread(NULL);
}
int bt_pan_service_task_init(void)
{
bk_err_t ret = BK_OK;
if ((!bt_pan_service_thread_handle) && (!bt_pan_service_msg_que))
{
ret = rtos_init_queue(&bt_pan_service_msg_que,
"bt_pan_service_msg_que",
sizeof(bt_pan_service_msg_t),
BT_PAN_SERVICE_MSG_COUNT);
if (ret != kNoErr)
{
LOGE("bt pan service msg queue failed \r\n");
return BK_FAIL;
}
ret = rtos_create_thread(&bt_pan_service_thread_handle,
BT_PAN_SERVICE_TASK_PRIORITY,
"bt_pan_service",
(beken_thread_function_t)bt_pan_service_main,
4096,
(beken_thread_arg_t)0);
if (ret != kNoErr)
{
LOGE("bt pan service task fail \r\n");
rtos_deinit_queue(&bt_pan_service_msg_que);
bt_pan_service_msg_que = NULL;
bt_pan_service_thread_handle = NULL;
}
return kNoErr;
}
else
{
return kInProgressErr;
}
}
void bt_pan_media_data_ind(eth_data_t *data)
{
bt_pan_service_msg_t service_msg;
int rc = -1;
os_memset(&service_msg, 0x0, sizeof(bt_pan_service_msg_t));
if (bt_pan_service_msg_que == NULL)
{
return;
}
uint16_t data_len = sizeof(eth_data_t) + data->payload_len;
service_msg.data = (char *)os_malloc(data_len);
if (service_msg.data == NULL)
{
LOGE("%s, malloc failed\r\n", __func__);
return;
}
os_memcpy(service_msg.data, data, data_len);
service_msg.type = BT_PAN_DATA_IND_MSG;
service_msg.len = data_len;
rc = rtos_push_to_queue(&bt_pan_service_msg_que, &service_msg, BEKEN_NO_WAIT);
if (kNoErr != rc)
{
LOGE("%s, send queue failed\r\n", __func__);
if (service_msg.data)
{
os_free(service_msg.data);
}
}
}
void bt_pan_tx_done_ind(void)
{
bt_pan_service_msg_t service_msg;
int rc = -1;
os_memset(&service_msg, 0x0, sizeof(bt_pan_service_msg_t));
if (bt_pan_service_msg_que == NULL)
{
return;
}
service_msg.type = BT_PAN_TX_DONE_IND_MSG;
service_msg.len = 0;
rc = rtos_push_to_queue(&bt_pan_service_msg_que, &service_msg, BEKEN_NO_WAIT);
if (kNoErr != rc)
{
LOGE("%s, send queue failed\r\n", __func__);
}
}
void bt_pan_trigger_tx(void)
{
bt_pan_service_msg_t service_msg;
int rc = -1;
os_memset(&service_msg, 0x0, sizeof(bt_pan_service_msg_t));
if (bt_pan_service_msg_que == NULL)
{
return;
}
service_msg.type = BT_PAN_TX_MSG;
service_msg.len = 0;
rc = rtos_push_to_queue(&bt_pan_service_msg_que, &service_msg, BEKEN_NO_WAIT);
if (kNoErr != rc)
{
LOGE("%s, send queue failed\r\n", __func__);
}
}
static void bk_bt_app_pan_cb(bk_pan_cb_event_t event, bk_pan_cb_param_t *param)
{
LOGD("%s event: %d\r\n", __func__, event);
switch (event)
{
case BK_PAN_CONNECTION_STATE_EVT:
{
uint8_t *bda = param->conn_state.remote_bda;
LOGI("PAN connection state: %d, [%02x:%02x:%02x:%02x:%02x:%02x]\r\n",
param->conn_state.con_state, bda[5], bda[4], bda[3], bda[2], bda[1], bda[0]);
s_pan_state = param->conn_state.con_state;
if (BK_BTPAN_STATE_CONNECTED == param->conn_state.con_state)
{
os_memcpy(paired_bt_mac, bda, 6);
bt_manager_set_connect_state(BT_STATE_PROFILE_CONNECTED);
#if 0
np_type_filter_t np_type;
np_type.num_filters = 2;
np_type.start[0] = 0x800;
np_type.end[0] = 0x800;
np_type.start[1] = 0x806;
np_type.end[1] = 0x806;
bk_bt_pan_set_protocol_filters(bda, &np_type);
#endif
#if CONFIG_NET_PAN
pan_ip_start();
#endif
}
else
{
#if CONFIG_NET_PAN
LOGD("PAN not connected!\r\n");
pan_ip_down();
#endif
if (s_pan_tx_list)
{
rtos_lock_mutex(&s_pan_tx_lock);
bt_comm_list_clear(s_pan_tx_list);
rtos_unlock_mutex(&s_pan_tx_lock);
s_acl_buf_count = CONFIG_NB_ACL_BUFF;
}
}
}
break;
case BK_PAN_DATA_READY_EVT:
{
bt_pan_media_data_ind(param->pan_data.eth_data);
}
break;
case BK_PAN_WRITE_DATA_CNF_EVT:
{
LOGD("PAN WRITE DATA CNF\r\n");
PAN_TX_DONE();
bt_pan_tx_done_ind();
}
break;
default:
LOGW("Invalid PAN event: %d\r\n", event);
break;
}
}
static void bk_pan_connect(uint8_t *remote_addr)
{
bk_bt_pan_connect(remote_addr, BK_PAN_ROLE_PANU, BK_PAN_ROLE_NAP);
}
static void bk_pan_disconnect(uint8_t *remote_addr)
{
bk_bt_pan_disconnect(remote_addr);
}
#if CONFIG_NET_PAN
static void pan_output(struct netif *netif, struct pbuf *p)
{
struct eth_hdr *ethhdr;
ethhdr = (struct eth_hdr *)p->payload;
PAN_NET_OUTPUT();
eth_data_t *p_eth_data = os_malloc(sizeof(eth_data_t) + p->tot_len);
if (p_eth_data == NULL)
{
return;
}
os_memcpy(p_eth_data->dest, ethhdr->dest.addr, PAN_HWADDR_LEN);
os_memcpy(p_eth_data->src, ethhdr->src.addr, PAN_HWADDR_LEN);
LOGD("src_mac %2x:%2x:%2x:%2x:%2x:%2x\r\n", p_eth_data->src[0], p_eth_data->src[1], p_eth_data->src[2],
p_eth_data->src[3], p_eth_data->src[4], p_eth_data->src[5]);
LOGD("dest_mac %2x:%2x:%2x:%2x:%2x:%2x\r\n", p_eth_data->dest[0], p_eth_data->dest[1], p_eth_data->dest[2],
p_eth_data->dest[3], p_eth_data->dest[4], p_eth_data->dest[5]);
#ifdef CONFIG_IPV6
p_eth_data->protocol = 0x86dd;
#endif
p_eth_data->protocol = htons(ethhdr->type);
p_eth_data->payload_len = p->tot_len;
os_memcpy(p_eth_data->payload, (uint8_t *)p->payload + sizeof(struct eth_hdr), p_eth_data->payload_len);
//LOGI("data %d\r\n",p->tot_len);
if (BK_BTPAN_STATE_CONNECTED == s_pan_state)
{
rtos_lock_mutex(&s_pan_tx_lock);
pan_push_tx_data_to_list(p_eth_data, sizeof(eth_data_t) + p->tot_len);
rtos_unlock_mutex(&s_pan_tx_lock);
bt_pan_trigger_tx();
}
else
{
LOGE("%s, pan is not connected!\r\n", __func__);
}
os_free(p_eth_data);
}
#endif
int pan_service_init(void)
{
LOGI("%s\r\n", __func__);
if (s_pan_service_already_init)
{
LOGI("pan service already initialised\r\n");
return 0;
}
bt_manager_init(0);
btm_callback_s btm_cb =
{
.gap_cb = NULL,
.start_connect_cb = bk_pan_connect,
.start_disconnect_cb = bk_pan_disconnect,
.stop_connect_cb = NULL,
};
bt_manager_register_callback(&btm_cb);
bt_pan_service_task_init();
bk_bt_pan_init(BK_PAN_ROLE_PANU);
bk_bt_pan_register_callback(bk_bt_app_pan_cb);
#if CONFIG_NET_PAN
net_pan_init();
bk_panif_register_callback(pan_output);
#endif
cli_pan_demo_init();
s_pan_tx_list = bt_comm_list_new();
if (!s_pan_tx_list)
{
LOGE("%s, s_pan_tx_list failed to new!\r\n", __func__);
}
rtos_init_mutex(&s_pan_tx_lock);
s_acl_buf_count = CONFIG_NB_ACL_BUFF;
s_pan_service_already_init = 1;
return 0;
}
void bt_pan_service_task_deinit(void)
{
bt_pan_service_msg_t service_msg;
int rc = -1;
os_memset(&service_msg, 0x0, sizeof(bt_pan_service_msg_t));
if (bt_pan_service_msg_que == NULL)
{
return;
}
service_msg.type = BT_PAN_EXIT_MSG;
service_msg.len = 0;
rc = rtos_push_to_queue(&bt_pan_service_msg_que, &service_msg, BEKEN_NO_WAIT);
if (kNoErr != rc)
{
LOGE("%s, send queue failed\r\n", __func__);
}
}
int pan_service_deinit(void)
{
LOGI("%s\r\n", __func__);
if (!s_pan_service_already_init)
{
LOGI("pan service already de-initialised\r\n");
return 0;
}
bt_manager_deinit();
bt_pan_service_task_deinit();
pan_ip_down();
net_pan_remove_netif();
cli_pan_demo_deinit();
if (s_pan_tx_list)
{
rtos_lock_mutex(&s_pan_tx_lock);
bt_comm_list_free(s_pan_tx_list);
rtos_unlock_mutex(&s_pan_tx_lock);
s_pan_tx_list = NULL;
}
if (s_pan_tx_lock)
{
rtos_deinit_mutex(&s_pan_tx_lock);
s_pan_tx_lock = NULL;
}
s_pan_service_already_init = 0;
return 0;
}