doubao_chat/apps/demo/demo_edr/spp_trans_data.c

268 lines
7.3 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "app_config.h"
#include "spp_user.h"
#include "bt_common.h"
#include "btstack/avctp_user.h"
#include "system/timer.h"
#include "system/sys_time.h"
/// \cond DO_NOT_DOCUMENT
#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 (2)
#define TEST_SPP_SEND_SIZE 660
static u32 test_data_count;
static u8 spp_test_start;
#endif
/// \endcond
/**
* \name 流控配置
* \{
*/
#define SPP_DATA_RECIEVT_FLOW 0 /*!< 确定配置接口transport_spp_flow_cfg被调用后,在连接过程中通过接口transport_spp_flow_enable来控制流控开关 */
#define FLOW_SEND_CREDITS_NUM 1 /*!< 流控速度控制,控制命令中控制可接收的数据包个数,发送给对方的range(1~32) */
#define FLOW_SEND_CREDITS_TRIGGER_NUM 1 /*!< 触发更新控制命令的阈值,range(1 to <= FLOW_SEND_CREDITS_NUM) */
/* \} name */
/// \cond DO_NOT_DOCUMENT
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;
/// \endcond
/* ----------------------------------------------------------------------------*/
/**
* @brief spp传输发送数据
* @param[in] data: 准备发送的数据指针
* @param[in] len: 准备发送的数据长度
* @return 0: 发送成功
* @return other: 发送失败
*/
/* ----------------------------------------------------------------------------*/
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;
}
/* ----------------------------------------------------------------------------*/
/**
* @brief 检查spp是否允许发送数据
* @param[in] len: 准备发送的数据长度
* @return 1: 允许发送
* @return 0: 发送忙碌
*/
/* ----------------------------------------------------------------------------*/
int transport_spp_send_data_check(u16 len)
{
if (spp_api) {
if (spp_api->busy_state()) {
return 0;
}
}
return 1;
}
/* ----------------------------------------------------------------------------*/
/**
* @brief spp传输状态回调
* @param[in] state: 连接状态
*/
/* ----------------------------------------------------------------------------*/
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;
}
}
/* ----------------------------------------------------------------------------*/
/**
* @brief spp传输唤醒回调
*/
/* ----------------------------------------------------------------------------*/
static void transport_spp_send_wakeup(void)
{
/* putchar('W'); */
}
/* ----------------------------------------------------------------------------*/
/**
* @brief spp数据接收回调
* @param[in] priv: spp_channel
* @param[in] buf: 接收到的数据指针
* @param[in] len: 接收到的数据长度
*/
/* ----------------------------------------------------------------------------*/
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
}
//loop send data for test
if (transport_spp_send_data_check(len)) {
transport_spp_send_data(buf, len);
}
#endif
}
#if TEST_SPP_DATA_RATE
static void test_spp_send_data(void)
{
u16 send_len = TEST_SPP_SEND_SIZE;
if (transport_spp_send_data_check(send_len)) {
test_data_count += send_len;
transport_spp_send_data((u8 *)&test_data_count, send_len);
}
}
static void test_timer_handler(void *p)
{
static u32 t_sec = 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 (timer_get_sec() <= t_sec) {
return;
}
t_sec = timer_get_sec();
if (test_data_count) {
log_info("\n-spp_data_rate: %d bytes, %d kbytes-\n", test_data_count, test_data_count / 1024);
test_data_count = 0;
}
}
#endif
/* ----------------------------------------------------------------------------*/
/**
* @brief 初始化spp传输接口
* @note 需要在蓝牙协议栈初始化btstack_init()成功后收到BT_STATUS_INIT_OK消息后调用
*/
/* ----------------------------------------------------------------------------*/
void transport_spp_init(void)
{
#if (USER_SUPPORT_PROFILE_SPP==1)
log_info("transport_spp_init\n");
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
sys_timer_add(NULL, test_timer_handler, SPP_TIMER_MS);
#endif
}
/* ----------------------------------------------------------------------------*/
/**
* @brief 断开SPP传输连接
*/
/* ----------------------------------------------------------------------------*/
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);
}
}
/* ----------------------------------------------------------------------------*/
/**
* @brief 配置SPP传输接收流控控制参数
* @note 需要在蓝牙协议栈初始化btstack_init()前调用
*/
/* ----------------------------------------------------------------------------*/
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
}
/* ----------------------------------------------------------------------------*/
/**
* @brief SPP传输接收流控开关
* @param[in] en: 1-打开 0-关闭
* @return 0: 成功
* @return other: 失败
*/
/* ----------------------------------------------------------------------------*/
int transport_spp_flow_enable(u8 en)
{
int ret = -1;
#if SPP_DATA_RECIEVT_FLOW
if (spp_channel) {
ret = rfcomm_send_cretits_by_profile(spp_channel, en ? 0 : FLOW_SEND_CREDITS_NUM, !en);
log_info("transport_spp_flow_enable:%02x,%d,%d\n", spp_channel, en, ret);
}
#endif
return ret;
}