268 lines
7.3 KiB
C
268 lines
7.3 KiB
C
#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;
|
||
}
|
||
|