LE Scatternet
ble_scatternet 示例工程可以作为开发同时支持 Peripheral Role 和 Central Role 的应用程序的框架。
Scatternet 特征:
在同一时间,作为 Peripheral 角色与多个 Central 建立连线。
在同一时间,作为 Peripheral 角色和 Central 角色。
不支持角色转换。
环境需求
该示例支持以下开发套件:
Hardware Platforms |
Board Name |
---|---|
RTL8752H HDK |
RTL8752H EVB |
为快速搭建起开发环境,可参考 快速入门 中提供的详细指导。
硬件连线
请参考 快速入门 中的 RTL8752H EVB 接口和模块。
该示例工程需要支持用户命令接口。 具体连线介绍请参考 用户命令接口 中的 Data UART 连接。
配置
配置选项
该示例工程全部配置选项在
src\sample\ble_scatternet\app_flags.h
中,
开发者可以根据实际需求配置。
/** @brief Config APP LE link number */
#define APP_MAX_LINKS 2
/** @brief Config airplane mode support: 0-Not built in, 1-built in, use user command to set*/
#define F_BT_AIRPLANE_MODE_SUPPORT 0
/** @brief Config device name characteristic and appearance characteristic property: 0-Not writeable, 1-writeable, save to flash*/
#define F_BT_GAPS_CHAR_WRITEABLE 0
/** @brief Config set physical: 0-Not built in, 1-built in, use user command to set*/
#define F_BT_LE_5_0_SET_PHY_SUPPORT 1
/** @brief Config local address type: 0-public address, 1-static random address */
#define F_BT_LE_USE_STATIC_RANDOM_ADDR 0
飞行模式的设置:
配置
F_BT_AIRPLANE_MODE_SUPPORT
以打开飞行模式(默认关闭)。打开飞行模式后,系统会关闭蓝牙功能。更多信息请参考 代码介绍 中的 Airplane Mode 设置。GAP service characteristic 的可写属性:
配置
F_BT_GAPS_CHAR_WRITEABLE
以打开该功能(默认关闭)。更多信息请参考 LE Host 中的 GAP Service Characteristic 的可写属性。静态随机地址的使用:
配置
F_BT_LE_USE_STATIC_RANDOM_ADDR
以打开该功能(默认关闭)。更多信息请参考 LE Host 中的 本地设备使用 Static Random Address。PHY 设置:
配置
F_BT_LE_5_0_SET_PHY_SUPPORT
以打开该功能(默认关闭)。更多信息请参考 LE Host 中的 Physical (PHY) 设置。
生成系统配置文件
开发者可以通过 MP Tool 配置以下项目:
Configurable Item |
Value |
---|---|
LE Master Link Num |
≥1 |
LE Slave Link Num |
≥1 |
备注
开发者配置的
LE Master Link Num
值与LE Slave Link Num
值之和应大于等于app_flags.h
中配置的APP_MAX_LINKS
值。更多有关于 MP Tool 配置的信息请参考 快速入门 中的 生成 System Config File。
编译和下载
该示例可以在 SDK 文件夹中找到:
Project file: board\evb\ble_scatternet\mdk
Project file: board\evb\ble_scatternet\gcc
编译和运行该示例请遵循以下步骤:
打开项目文件。
要编译目标文件, 请参考 快速入门 的 编译 APP Image 中列出的步骤。
编译成功后,目录
board\evb\ble_scatternet\mdk\bin
下会生成 app bin 文件app_MP_sdk_xxx.bin
。在 EVB 上按下 reset 键,程序将开始运行。
测试验证
将示例工程烧录到 EVB 后,开发者可以使用两个开发板分别运行 LE Peripheral 示例工程和 LE Central 示例工程。
与另一块开发板对测
准备三块开发板分别命名为 DUT, Tester 1 和 Tester 2 ,开发者可以使用 Debug Analyzer
做 Log 验证 。
准备步骤
使用 MP Tool 将 DUT 地址设为 [00:11:22:33:44:80],然后编译 ble_scatternet 示例工程并下载 images 到 DUT 上。 开发者可以在电脑的串口辅助工具端输入用户命令,请参考 用户命令接口 中的 如何使用命令。
使用 MP Tool 将 Tester 1 地址设为 [00:11:22:33:44:81],然后编译 ble_peripheral 示例工程,并下载 images 到 Tester 1 上。更多信息请参考 LE Peripheral 中的 编译和下载。
使用 MP Tool 将 Tester 2 地址设为 [00:11:22:33:44:85],然后编译 ble_central 示例工程,并下载 images 到 Tester 2 上。更多信息请参考 LE Central 中的 编译和下载。
更多关于如何修改 蓝牙地址 的细节请查阅 快速入门 中的 生成 System Config File。
测试步骤
因为同时支持 Peripheral Role 和 Central Role, 所以测试流程是 LE Peripheral 的测试流程和 LE Central 的测试流程的结合。
与 Tester 1 连接
按 Tester 1 上的 reset 键, Tester 1 将开始发送可连接广播。
如果成功启动广播,会打印下面的 Debug Analyzer 日志。
如果没有看到下列日志,说明广播启动失败。请检查软件和硬件环境。
[APP] !**GAP adv start
按 DUT 上的 reset 键,开发者可以在电脑的串口辅助工具端输入用户命令。
如果 DUT 成功启动且串口辅助工具配置成功,开发者会看到如下日志。串口辅助工具端会显示本地地址。
如果没有看到下列日志,请检查软件和硬件环境。
local bd addr: xx:xx:xx:xx:xx:xx
DUT 和 Tester 1 间的测试流程如下:
Step
DUT User Command
Description
DUT Log
1
bondclear
删除 DUT 端的绑定信息。
Debug Analyzer 显示:
[GAP] !**le_clear_all_keys
2
scan
DUT 开始扫描附近的 LE 设备。
Debug Analyzer 显示:
[APP] !**GAP scan start [APP] GAP_MSG_LE_SCAN_INFO: bd_addr 00::11::22::33::44::80, bdtype 0, adv_type 0x0, rssi -17, data_len 23
3
stopscan
停止扫描。
Debug Analyzer 显示:
[APP] !**GAP scan stop
4
showdev
显示扫描到的设备列表,该设备列表通过 simple LE service 的 UUID 筛选。
Serial port assistant tool 显示:
Advertising and Scan response: filter uuid = 0xA00A dev list RemoteBd[0] = [00:11:22:33:44:81] type = 0
5
condev 0
作为 Central role 发起连线。
Serial port assistant tool 显示:
Connected success conn_id 0
与 Tester 2 连接
按 Tester 2 上的 reset 键,开发者可以在电脑的串口辅助工具端输入用户命令。
如果 Tester 2 成功启动且串口辅助工具配置成功, 开发者会看到如下日志。串口辅助工具端会显示本地地址。 如果没有看到下列日志,请检查软件和硬件环境。
local bd addr: xx:xx:xx:xx:xx:xx
此部分 DUT 和 Tester 2 的测试流程如下:
Step
DUT User Command
Tester 2 User Command
Description
Tester 2 Log
DUT Log
6
bond clear
清除 Tester 2 端的绑定信息。
Debug Analyzer 显示:
[GAP] !**le_clear_all_keys
7
startadv
DUT 发送可连接可扫描的非定向广播。
Debug Analyzer 显示:
[APP] !**GAP adv start
8
scan
Tester 2 开始扫描附近的 LE 设备。
Debug Analyzer 显示:
[APP] !**GAP scan start
[APP] GAP_MSG_LE_SCAN_INFO: bd_addr 00::11::22::33::44::80, bdtype 0, adv_type 0x0, rssi -17, data_len 23
9
stopscan
Tester 2 停止扫描。
Debug Analyzer 显示:
[APP] !**GAP scan stop
10
showdev
显示扫描到的设备列表。该设备列表通过 simple LE service 的 UUID 筛选。
Serial port assistant tool 显示:
Advertising and Scan response: filter uuid = 0xA00A dev list
RemoteBd[0] = [00:11:22:33:44:80] type = 0
11
condev 0
Tester 2 发起向 DUT 建立连线,
0
表示 DUT 在设备列表中的序列号Serial port assistant tool 显示:
Connected success conn_id 0
12
showcon
显示 DUT 端已经建立的连线。
Serial port assistant tool 显示:
ShowCon conn_id 0 state 0x00000002 role 1
RemoteBd = [00:11:22:33:44:81] type = 0
ShowCon conn_id 1 state 0x00000002 role 2
RemoteBd = [00:11:22:33:44:85] type = 0
active link num 2, idle link num 0
与 Tester 1 和 Tester 2 交互
此时, DUT 已经分别作为 Central Role 和 Peripheral Role 与 Tester 1 和 Tester 2 建立了连线。接着将进行以下测试:
Step
DUT User Command
Tester 2 User Command
Description
Tester 2 Log
DUT Log
13
sauth 0
DUT 向 Tester 1 发送配对请求。
Serial port assistant tool 显示:
Pair success
14
disc 0
断开与 Tester 1 的连线。
Serial port assistant tool 显示:
Disconnect conn_id 0
15
disc 1
断开与 Tester 2 的连线。
Serial port assistant tool 显示:
Disconnect conn_id 1
16
condev 0
DUT 与 Tester 1 回连。
Serial port assistant tool 显示:
Connected success conn_id 0
17
startadv
DUT 发送可连接可扫描非定向广播。
Serial port assistant tool 显示:
GAP adv start
18
condev 0
Tester 2 与 DUT 回连。
Serial port assistant tool 显示:
Connected success conn_id 0
Pair success
19
sauth 0
DUT 向 Tester 1 发送配对请求。
Serial port assistant tool 显示:
Pair success
20
conupdreq 1 x30 x40 0 1000
DUT 向 Tester 2 发送连接参数更新请求。
Debug Analyzer 显示:
[APP] !**app_handle_conn_param_update_evt update success:conn_id 0, conn_interval 0x3c, conn_slave_latency 0x0, conn_supervision_timeout 0x3e8
Debug Analyzer 显示:
[APP] !**app_handle_conn_param_update_evt update success:conn_id 1, conn_interval 0x3c, conn_slave_latency 0x0, conn_supervision_timeout 0x3e8
21
conupdreq 0 x30 x40 0 1000
DUT 向 Tester 1 发送连接参数更新请求。
Debug Analyzer 显示:
[APP] !**app_handle_conn_param_update_evt update success:conn_id 0, conn_interval 0x3c, conn_slave_latency 0x0, conn_supervision_timeout 0x3e8
22
setphy 1 1
DUT 将与 Tester 2 的 PHY 设为 2M。
Debug Analyzer 显示:
[BTIFMSG] ↗BTIF_MSG_LE_PHY_UPDATE_INFO (CMD:0x01AB) cause:0x0000 link_id:0x000A tx_phy:0x02(BTIF_LE_PHY_2M) rx_phy:0x02(BTIF_LE_PHY_2M)
Debug Analyzer 显示:
[BTIFMSG] ↗BTIF_MSG_LE_PHY_UPDATE_INFO (CMD:0x01AB) cause:0x0000 link_id:0x0012 tx_phy:0x02(BTIF_LE_PHY_2M) rx_phy:0x02(BTIF_LE_PHY_2M)
[APP] !**GAP_MSG_LE_PHY_UPDATE_INFO:conn_id 1, cause 0x0, rx_phy 2, tx_phy 2
23
setphy 0 1
DUT 将与 Tester 1 的 PHY 设为 2M。
Debug Analyzer 显示:
[BTIFMSG] ↗BTIF_MSG_LE_PHY_UPDATE_INFO (CMD:0x01AB) cause:0x0000 link_id:0x000A tx_phy:0x02(BTIF_LE_PHY_2M) rx_phy:0x02(BTIF_LE_PHY_2M)
[APP] !**GAP_MSG_LE_PHY_UPDATE_INFO:conn_id 0, cause 0x0, rx_phy 2, tx_phy 2
24
simpdis 0
DUT 发起 discovery 流程,获取 Simple LE Service 信息。
Debug Analyzer 显示:
[APP] !**app_client_callback: discover simp procedure done
25
gapdis 0
DUT 发起 discovery 流程,获取 GAP Service 信息。
Debug Analyzer 显示:
[APP] !**GAPS_READ_DEVICE_NAME: device name BLE_PERIPHERAL
代码介绍
本章将按照以下几个部分进行介绍:
源码路径 中介绍项目目录和源代码文件。
Bluetooth Host 介绍 中介绍了 Bluetooth Host 相关信息。
初始化 中介绍 Scatternet 相关参数和 Bluetooth Host 初始化。
多链路管理 中介绍了链路管理模块。
GAP 消息处理 中介绍 Scatternet 相关的 GAP 消息处理。
GAP 回调函数处理 中介绍 Scatternet 相关的 GAP 回调函数处理。
Profile Client 消息回调函数 中介绍了 Scatternet 相关的 Profile Client 回调函数处理。
Profile Service 消息回调函数 中介绍了 Scatternet 相关的 Profile Service 回调函数处理。
Airplane Mode 设置 中介绍了设置飞行模式的流程。
源码路径
工程目录:
board\evb\ble_scatternet
。源码目录:
src\sample\ble_scatternet
。
ble_scatternet 示例工程中的源文件当前被分为几个组,如下所示:
└── Project: scatternet
└── scatternet
└── include Includes startup code.
├── lib Includes all binary symbol files that user application is built on.
├── ROM.lib
├── gap_utils.lib
├── lowerstack.lib
└── rtl8752h_sdk.lib
├── cmsis Includes startup code.
├── peripheral Includes all peripheral drivers and module code used by the application.
└── app Includes the ble_scatternet user application implementation.
├── data_uart.c
├── user_cmd_parse.c
├── overlay_mgr.c
├── app_task.c
├── link_mgr.c
├── main.c
├── scatternet_app.c
└── user_cmd.c
示例工程使用与 upperstack_0_0
匹配的默认 GAP LIB,请参阅文档 Host Image 中的 GAP LIB 的使用方法 以获取更多信息。
Bluetooth Host 介绍
示例工程默认使用 Bluetooth Host image 版本 upperstack_0_0
,更多信息可参阅
Host Image。
关于 Bluetooth Host 所支持的蓝牙功能的详细信息,请参阅文件 bin\upperstack_img\upperstack_0_0\upperstack_config.h
。
初始化
当 EVB 启动并且芯片复位时, main()
函数将被调用,它执行以下初始化函数:
int main(void)
{
board_init();
le_gap_init(APP_MAX_LINKS);
gap_lib_init();
app_le_gap_init();
app_le_profile_init();
pwr_mgr_init();
task_init();
os_sched_start();
return 0;
}
le_gap_init()
用于初始化 GAP 并配置链接个数。app_le_profile_init()
用于初始化 profile。app_le_gap_init()
用于初始化 GAP 参数,开发者可以自行配置以下参数:Device name 和 device appearance,Advertising 参数,Scan 参数,GAP Bond Manager 参数(请参考 LE Host 中的 Device Name 和 Device Appearance 的配置, Advertising 参数的配置, Scan 参数的配置, Pairing 参数的配置)。
void app_le_gap_init(void)
{
/* Device name and device appearance */
......
/* Scan parameters */
......
/* GAP Bond Manager parameters */
......
/* Set device name and device appearance */
le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name);
le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance);
/* Set scan parameters */
le_scan_set_param(GAP_PARAM_SCAN_MODE, sizeof(scan_mode), &scan_mode);
le_scan_set_param(GAP_PARAM_SCAN_INTERVAL, sizeof(scan_interval), &scan_interval);
le_scan_set_param(GAP_PARAM_SCAN_WINDOW, sizeof(scan_window), &scan_window);
le_scan_set_param(GAP_PARAM_SCAN_FILTER_POLICY, sizeof(scan_filter_policy),
&scan_filter_policy);
le_scan_set_param(GAP_PARAM_SCAN_FILTER_DUPLICATES, sizeof(scan_filter_duplicate),
&scan_filter_duplicate);
/* Set advertising parameters */
le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type);
le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type);
le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr);
le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map);
le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy);
le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min);
le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max);
le_adv_set_param(GAP_PARAM_ADV_DATA, sizeof(adv_data), (void *)adv_data);
le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data);
/* Setup the GAP Bond Manager */
gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode);
gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags);
gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap);
gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob);
le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey);
le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey),
&auth_use_fix_passkey);
le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags),
&auth_sec_req_flags);
/* register gap message callback */
le_register_app_cb(app_gap_callback);
......
}
更多关于 LE GAP 初始化和启动流程的信息可以查阅 LE Host 中的 GAP 参数的初始化。
多链路管理
应用的链路控制模块在 link_mgr.h
中定义。
typedef struct
{
T_GAP_CONN_STATE conn_state; /**< Connection state. */
T_GAP_REMOTE_ADDR_TYPE bd_type; /**< remote BD type*/
uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */
} T_APP_LINK;
extern T_APP_LINK app_link_table[APP_MAX_LINKS];
app_link_table
用于保存链路相关信息。
GAP 消息处理
当 APP 从 Bluetooth Host 接收到 GAP 消息时,函数 app_handle_gap_msg()
会被调用。
当收到 GAP_MSG_LE_CONN_STATE_CHANGE
消息后, app_handle_conn_state_evt()
会更新 app_link_table
中的信息。
void app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause)
{
if (conn_id >= APP_MAX_LINKS)
{
return;
}
APP_PRINT_INFO4("app_handle_conn_state_evt: conn_id %d, conn_state(%d -> %d), disc_cause 0x%x",
conn_id, app_link_table[conn_id].conn_state, new_state, disc_cause);
app_link_table[conn_id].conn_state = new_state;
switch (new_state)
{
case GAP_CONN_STATE_DISCONNECTED:
{
if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE))
&& (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE)))
{
APP_PRINT_ERROR2("app_handle_conn_state_evt: connection lost, conn_id %d, cause 0x%x", conn_id,
disc_cause);
}
data_uart_print("Disconnect conn_id %d\r\n", conn_id);
memset(&app_link_table[conn_id], 0, sizeof(T_APP_LINK));
}
break;
case GAP_CONN_STATE_CONNECTED:
{
le_get_conn_addr(conn_id, app_link_table[conn_id].bd_addr,
&app_link_table[conn_id].bd_type);
data_uart_print("Connected success conn_id %d\r\n", conn_id);
}
break;
default:
break;
}
}
GAP 回调函数处理
app_gap_callback()
用于处理 GAP 回调函数消息,
更多信息参见 LE Host 中的 Bluetooth LE GAP 回调函数。
T_APP_RESULT app_gap_callback(uint8_t cb_type, void *p_cb_data)
{
T_APP_RESULT result = APP_RESULT_SUCCESS;
T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data;
switch (cb_type)
{
/* common msg*/
case GAP_MSG_LE_READ_RSSI:
.......
}
Profile Client 消息回调函数
当 APP 使用 xxx_add_client 注册 specific client 时,APP 需注册回调函数以处理 specific client 的消息。 APP 可以针对不同的 clients 注册不同的回调函数,也可以注册通用回调函数以处理 specific clients 的消息。
app_client_callback()
是通用回调函数,根据 client ID 区分不同的 clients。
void app_le_profile_init(void)
{
client_init(3);
gaps_client_id = gaps_add_client(app_client_callback, APP_MAX_LINKS);
simple_ble_client_id = simp_ble_add_client(app_client_callback, APP_MAX_LINKS);
bas_client_id = bas_add_client(app_client_callback, APP_MAX_LINKS);
client_register_general_client_cb(app_client_callback);
}
T_APP_RESULT app_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data)
{
T_APP_RESULT result = APP_RESULT_SUCCESS;
APP_PRINT_INFO2("app_client_callback: client_id %d, conn_id %d",
client_id, conn_id);
if (client_id == CLIENT_PROFILE_GENERAL_ID)
{
T_CLIENT_APP_CB_DATA *p_client_app_cb_data = (T_CLIENT_APP_CB_DATA *)p_data;
switch (p_client_app_cb_data->cb_type)
{
case CLIENT_APP_CB_TYPE_DISC_STATE:
......
}
else if (client_id == gaps_client_id)
{
T_GAPS_CLIENT_CB_DATA *p_gaps_cb_data = (T_GAPS_CLIENT_CB_DATA *)p_data;
switch (p_gaps_cb_data->cb_type)
{
case GAPS_CLIENT_CB_TYPE_DISC_STATE:
......
}
}
ble_scatternet 示例工程支持的 GATT profile clients 包括 GAP Service Client,Simple LE Service Client 和 Battery Service Client 。
Profile Service 消息回调函数
当 APP 使用 xxx_add_service 注册 specific service 时,APP 需要注册回调函数以处理 specific service 的消息。
APP 需要调用 server_register_app_cb()
注册回调函数以处理 profile server layer 的信息。
APP 可以针对不同的 services 注册不同的回调函数,也可以注册通用回调函数以处理 specific services 和 profile server layer 的消息。
app_profile_callback()
通用回调函数,根据 service ID 区分不同的 services。
void app_le_profile_init(void)
{
server_init(2);
simp_srv_id = simp_ble_service_add_service(app_profile_callback);
bas_srv_id = bas_add_service(app_profile_callback);
server_register_app_cb(app_profile_callback);
}
更多信息参见 LE Host 中的 GATT Profile Server。
通用 profile server 回调函数
SERVICE_PROFILE_GENERAL_ID
是 profile server layer 使用的 service ID。Profile server layer 包含两种消息类型:-
该消息用于通知 GAP 启动流程中的服务注册流程已经结束。
PROFILE_EVT_SEND_DATA_COMPLETE
Profile server layer 使用该消息向 APP 通知发送 notification 或者 indication 的结果。
T_APP_RESULT app_profile_callback(T_SERVER_ID service_id, void *p_data) { T_APP_RESULT app_result = APP_RESULT_SUCCESS; if (service_id == SERVICE_PROFILE_GENERAL_ID) { T_SERVER_APP_CB_DATA *p_param = (T_SERVER_APP_CB_DATA *)p_data; switch (p_param->eventId) { case PROFILE_EVT_SRV_REG_COMPLETE:// srv register result event. APP_PRINT_INFO1("PROFILE_EVT_SRV_REG_COMPLETE: result %d", p_param->event_data.service_reg_result); break; case PROFILE_EVT_SEND_DATA_COMPLETE: ...... break; ...... }
-
Battery Service
bas_srv_id
是 battery service 的 service ID。T_APP_RESULT app_profile_callback(T_SERVER_ID service_id, void *p_data) { T_APP_RESULT app_result = APP_RESULT_SUCCESS; ...... else if (service_id == bas_srv_id) { T_BAS_CALLBACK_DATA *p_bas_cb_data = (T_BAS_CALLBACK_DATA *)p_data; switch (p_bas_cb_data->msg_type) { case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: ...... }
Simple LE Service
simp_srv_id
是 simple LE service 的 service ID。T_APP_RESULT app_profile_callback(T_SERVER_ID service_id, void *p_data) { T_APP_RESULT app_result = APP_RESULT_SUCCESS; ...... else if (service_id == simp_srv_id) { TSIMP_CALLBACK_DATA *p_simp_cb_data = (TSIMP_CALLBACK_DATA *)p_data; switch (p_simp_cb_data->msg_type) { case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: ...... }
Airplane Mode 设置
注册 GAP Common 回调函数
APP 需要调用
gap_register_app_cb()
以注册回调函数。void app_le_gap_init(void) { ...... gap_register_app_cb(app_gap_common_callback); }
GAP Common 回调函数消息处理
void app_gap_common_callback(uint8_t cb_type, void *p_cb_data) { T_GAP_CB_DATA cb_data; memcpy(&cb_data, p_cb_data, sizeof(T_GAP_CB_DATA)); APP_PRINT_INFO1("app_gap_common_callback: cb_type = %d", cb_type); switch (cb_type) { case GAP_MSG_WRITE_AIRPLAN_MODE: APP_PRINT_INFO1("GAP_MSG_WRITE_AIRPLAN_MODE: cause 0x%x", cb_data.p_gap_write_airplan_mode_rsp->cause); break; case GAP_MSG_READ_AIRPLAN_MODE: APP_PRINT_INFO2("GAP_MSG_READ_AIRPLAN_MODE: cause 0x%x, mode %d", cb_data.p_gap_read_airplan_mode_rsp->cause, cb_data.p_gap_read_airplan_mode_rsp->mode); break; default: break; } return; }
该回调函数可处理
GAP_MSG_WRITE_AIRPLAN_MODE
和GAP_MSG_READ_AIRPLAN_MODE
消息。相关 APIs
gap_write_airplan_mode()
用于写 airplane mode。gap_read_airplan_mode()
用于读 airplane mode。
static T_USER_CMD_PARSE_RESULT cmd_wairplane(T_USER_CMD_PARSED_VALUE *p_parse_value) { T_GAP_CAUSE cause; uint8_t mode = p_parse_value->dw_param[0]; cause = gap_write_airplan_mode(mode); return (T_USER_CMD_PARSE_RESULT)cause; } static T_USER_CMD_PARSE_RESULT cmd_rairplane(T_USER_CMD_PARSED_VALUE *p_parse_value) { T_GAP_CAUSE cause; cause = gap_read_airplan_mode(); return (T_USER_CMD_PARSE_RESULT)cause; }