doubao_chat/apps/demo/demo_DevKitBoard/spp_trans_data.c

212 lines
4.9 KiB
C

#include "app_config.h"
#include "spp_user.h"
#include "bt_common.h"
#include "btstack/avctp_user.h"
#if SPP_TRANS_DATA_EN
#if 1
extern void printf_buf(u8 *buf, u32 len);
#define log_info printf
#define log_info_hexdump printf_buf
#else
#define log_info(...)
#define log_info_hexdump(...)
#endif
#define TEST_SPP_DATA_RATE 0
#if TEST_SPP_DATA_RATE
#define SPP_TIMER_MS (100)
static u32 test_data_count;
static u32 spp_timer_handle = 0;
static u32 spp_test_start;
#endif
/*
打开流控使能后,确定配置接口 transport_spp_flow_cfg 被调用初始化配置
然后使用过程 通过接口 transport_spp_flow_enable 来控制流控开关
*/
#define SPP_DATA_RECIEVT_FLOW 0//流控功能使能
//流控速度控制,可以不用更改
#define FLOW_SEND_CREDITS_NUM 1 //控制命令中 控制可接收的数据包个数,发送给对方的,range(1~32)
#define FLOW_SEND_CREDITS_TRIGGER_NUM 1 //触发更新控制命令的阈值,range(1 to <= FLOW_SEND_CREDITS_NUM)
int transport_spp_flow_enable(u8 en);
void rfcomm_change_credits_setting(u16 init_credits, u8 base);
int rfcomm_send_cretits_by_profile(u16 rfcomm_cid, u16 credit, u8 auto_flag);
static struct spp_operation_t *spp_api = NULL;
static u8 spp_state;
static u16 spp_channel;
int transport_spp_send_data(u8 *data, u16 len)
{
if (spp_api) {
log_info("spp_api_tx(%d) \n", len);
/* log_info_hexdump(data, len); */
clear_sniff_cnt();
return spp_api->send_data(NULL, data, len);
}
return SPP_USER_ERR_SEND_FAIL;
}
int transport_spp_send_data_check(u16 len)
{
if (spp_api) {
if (spp_api->busy_state()) {
return 0;
}
}
return 1;
}
static void transport_spp_state_cbk(u8 state)
{
spp_state = state;
switch (state) {
case SPP_USER_ST_CONNECT:
log_info("SPP_USER_ST_CONNECT ~~~\n");
break;
case SPP_USER_ST_DISCONN:
log_info("SPP_USER_ST_DISCONN ~~~\n");
spp_channel = 0;
break;
default:
break;
}
}
static void transport_spp_send_wakeup(void)
{
putchar('W');
}
static void transport_spp_recieve_cbk(void *priv, u8 *buf, u16 len)
{
spp_channel = (u16)priv;
log_info("spp_api_rx(%d) \n", len);
log_info_hexdump(buf, len);
clear_sniff_cnt();
#if TEST_SPP_DATA_RATE
if ((buf[0] == 'A') && (buf[1] == 'F')) {
spp_test_start = 1;//start
} else if ((buf[0] == 'A') && (buf[1] == 'A')) {
spp_test_start = 0;//stop
}
#endif
//loop send data for test
if (transport_spp_send_data_check(len)) {
transport_spp_send_data(buf, len);
}
}
#if TEST_SPP_DATA_RATE
static void test_spp_send_data(void)
{
u16 send_len = 250;
if (transport_spp_send_data_check(send_len)) {
test_data_count += send_len;
transport_spp_send_data(&test_data_count, send_len);
}
}
static void test_timer_handler(void)
{
static u32 t_count = 0;
if (SPP_USER_ST_CONNECT != spp_state) {
test_data_count = 0;
spp_test_start = 0;
return;
}
if (spp_test_start) {
test_spp_send_data();
}
if (++t_count < (1000 / SPP_TIMER_MS)) {
return;
}
t_count = 0;
if (test_data_count) {
log_info("\n-spp_data_rate: %d bps-\n", test_data_count * 8);
test_data_count = 0;
}
}
#endif
void transport_spp_init(void)
{
log_info("transport_spp_init\n");
#if (USER_SUPPORT_PROFILE_SPP==1)
spp_state = 0;
spp_get_operation_table(&spp_api);
spp_api->regist_recieve_cbk(0, transport_spp_recieve_cbk);
spp_api->regist_state_cbk(0, transport_spp_state_cbk);
spp_api->regist_wakeup_send(NULL, transport_spp_send_wakeup);
#endif
#if TEST_SPP_DATA_RATE
spp_timer_handle = sys_timer_add(NULL, test_timer_handler, SPP_TIMER_MS);
#endif
}
void transport_spp_disconnect(void)
{
if (SPP_USER_ST_CONNECT == spp_state) {
log_info("transport_spp_disconnect\n");
user_send_cmd_prepare(USER_CTRL_SPP_DISCONNECT, 0, NULL);
}
}
static void timer_spp_flow_test(void)
{
static u8 sw = 0;
if (spp_channel) {
sw = !sw;
transport_spp_flow_enable(sw);
}
}
//配置流控制的参数,蓝牙协议栈初始化前调用配置
void transport_spp_flow_cfg(void)
{
#if SPP_DATA_RECIEVT_FLOW
rfcomm_change_credits_setting(FLOW_SEND_CREDITS_NUM, FLOW_SEND_CREDITS_TRIGGER_NUM);
//for test
/* sys_timer_add(0,timer_spp_flow_test,2000); */
#endif
}
//流控使能 EN: 1-停止收数 or 0-继续收数
int transport_spp_flow_enable(u8 en)
{
int ret = -1;
u16 credits = FLOW_SEND_CREDITS_NUM;
#if SPP_DATA_RECIEVT_FLOW
if (spp_channel) {
if (en) {
credits = 0;
}
ret = rfcomm_send_cretits_by_profile(spp_channel, credits, !en);
}
#endif
log_info("transport_spp_flow_enable:%02x,%d,%d\n", spp_channel, en, ret);
return ret;
}
#endif