LE Scatternet

LE scatternet示例工程可以作为开发同时支持Peripheral Role和Central Role的应用程序的框架。

Scatternet特征:

  • 在同一时间,作为Peripheral角色与多个Central建立连线。

  • 在同一时间,作为Peripheral角色和Central角色。

  • 不支持角色转换。

环境需求

该示例支持以下开发工具包:

环境需求

Hardware Platforms

Board Name

RTL87x2G HDK

RTL87x2G EVB

为快速搭建起开发环境,可参考 快速入门 中提供的详细指导。

硬件连线

请参考 快速入门 中的 EVB接口和模块

该示例工程需要支持用户命令接口。 具体连线介绍请参考 User Command Interface 中的 Data UART连接

配置

配置选项

该示例工程全部配置选项在 samples\bluetooth\ble_scatternet\src\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         0
/** @brief  Config local address type: 0-pulic address, 1-static random address */
#define F_BT_LE_USE_STATIC_RANDOM_ADDR      0

生成系统配置文件

开发者可以通过MP Tool配置以下项目:

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: samples\bluetooth\ble_scatternet\proj\rtl87x2g\mdk

Project file: samples\bluetooth\ble_scatternet\proj\rtl87x2g\gcc

编译和运行该示例请遵循以下步骤:

  1. 打开项目文件。

  2. 要编译目标文件, 请参考 快速入门编译APP Image 中列出的步骤。

  3. 编译成功后,目录 samples\bluetooth\ble_scatternet\proj\rtl87x2g\mdk\bin 下会生成app bin文件 app_MP_sdk_xxx.bin

  4. 要下载app bin到 EVB,请参考 快速入门MP Tool 下载 中列出的步骤。

  5. 在EVB上按下 reset 键,程序将开始运行。

测试验证

将示例工程烧录到EVB后,开发者可以使用两个开发板分别运行 LE Peripheral 示例工程和 LE Central 示例工程。

与另一块开发板对测

准备三块开发板分别命名为 DUTTester 1Tester 2 ,开发者可以使用 Debug AnalyzerLog验证

准备步骤

  1. 使用MP Tool将 DUT 地址设为[00:11:22:33:44:80],然后编译 LE Scatternet示例工程并下载images到 DUT 上。 开发者可以在电脑的串口辅助工具端输入用户命令,请参考 User Command Interface 中的 如何使用命令

  2. 使用MP Tool将 Tester 1 地址设为[00:11:22:33:44:81],然后编译 LE Peripheral示例工程,并下载images到 Tester 1 上。更多信息请参考 LE Peripheral 中的 编译和下载

  3. 使用MP Tool将 Tester 2 地址设为[00:11:22:33:44:85],然后编译 LE Central示例工程,并下载images到 Tester 2 上。更多信息请参考 LE Central 中的 编译和下载

更多关于如何修改 蓝牙地址 的细节请查阅 快速入门 中的 生成System Config File

测试步骤

因为同时支持Peripheral Role和Central Role, 所以测试流程是 LE Peripheral 的测试流程和 LE Central 的测试流程的结合。

与Tester 1连接
  1. Tester 1 上的 reset 键, Tester 1 将开始发送可连接广播。

如果成功启动广播,会打印下面的 Debug Analyzer 日志。 如果没有看到下列日志,说明广播启动失败。请检查软件和硬件环境。

[APP] !**GAP adv start
  1. DUT 上的 reset 键,开发者可以在电脑的串口辅助工具端输入用户命令。

如果 DUT 成功启动且串口辅助工具配置成功, 开发者会看到如下日志。串口辅助工具端会显示本地地址。 如果没有看到下列日志,请检查软件和硬件环境。

local bd addr: xx:xx:xx:xx:xx:xx

DUTTester 1 间的测试流程如下:

Step

DUT User Command

Description

DUT Log

1

bondclear

删除 DUT 端的绑定信息。

Debug Analyzer shows:

[GAP] !**le_clear_all_keys

2

scan

DUT 开始扫描附近的LE设备。

Debug Analyzer shows:

[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 shows:

[APP] !**GAP scan stop

4

showdev

显示扫描到的设备列表,该设备列表通过simple LE service的UUID筛选。

Serial port assistant tool shows:

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 shows:

Connected success conn_id 0

与Tester 2连接
  • Tester 2 上的 reset 键,开发者可以在电脑的串口辅助工具端输入用户命令。

    如果 Tester 2 成功启动且串口辅助工具配置成功, 开发者会看到如下日志。串口辅助工具端会显示本地地址。 如果没有看到下列日志,请检查软件和硬件环境。

    local bd addr: xx:xx:xx:xx:xx:xx
    

    此部分 DUTTester 2 的测试流程如下:

    Step

    DUT User Command

    Tester 2 User Command

    Description

    Tester 2 Log

    DUT Log

    6

    bond clear

    清除 Tester 2 端的绑定信息。

    Debug Analyzer shows:

    [GAP] !**le_clear_all_keys

    7

    startadv

    DUT 发送可连接可扫描的非定向广播。

    Debug Analyzer shows:

    [APP] !**GAP adv start

    8

    scan

    Tester 2 开始扫描附近的LE设备。

    Debug Analyzer shows:

    [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 shows:

    [APP] !**GAP scan stop

    10

    showdev

    显示扫描到的设备列表。该设备列表通过simple LE service的UUID筛选。

    Serial port assistant tool shows:

    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 shows:

    Connected success conn_id 0

    12

    showcon

    显示 DUT 端已经建立的连线。

    Serial port assistant tool shows:

    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 1Tester 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 shows:

Pair succes

14

disc 0

断开与 Tester 1 的连线。

Serial port assistant tool shows:

Disconnect conn_id 0

15

disc 1

断开与 Tester 2 的连线。

Serial port assistant tool shows:

Disconnect conn_id 1

16

condev 0

DutTester 1 回连。

Serial port assistant tool shows:

Connected success conn_id 0

17

startadv

Dut 发送可连接可扫描非定向广播。

Serial port assistant tool shows:

GAP adv start

18

condev 0

Tester 2DUT 回连。

Serial port assistant tool shows:

Connected success conn_id 0

Pair success

19

sauth 0

DUTTester 1 发送配对请求。

Serial port assistant tool shows:

Pair success

20

conupdreq 1 x30 x40 0 1000

DUTTester 2 发送连接参数更新请求。

Debug Analyzer shows:

[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 shows:

[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

DUTTester 1 发送连接参数更新请求。

Debug Analyzer shows:

[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 shows:

[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 shows:

[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 shows:

[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 shows:

[APP] !**app_client_callback: discover simp procedure done

25

gapdis 0

DUT 发起discovery流程,获取GAP Service信息。

Debug Analyzer shows:

[APP] !**GAPS_READ_DEVICE_NAME: device name BLE_PERIPHERAL

代码介绍

本章将按照以下几个部分进行介绍:

源码路径

  • 工程目录: samples\bluetooth\ble_scatternet\proj

  • 源码目录: samples\bluetooth\ble_scatternet\src

LE scatternet示例工程中的源文件当前被分为几个组,如下所示:

└── Project: scatternet
    └── secure_only_app
        └── Device                   includes startup code
        ├── CMSE Library             Non-secure callable library
        ├── Lib                      includes all binary symbol files that user application is built on
            ├── ROM_NS.lib
            └── lowerstack.lib
            └── rtl87x2g_sdk.lib
            └── gap_utils.lib
        ├── peripheral               includes all peripheral drivers and module code used by the application
        ├── Profile                  includes LE profiles or services used by the sample application
        └── APP                      includes the ble_scatternet user application implementation
            ├── app_task.c
            ├── main.c
            ├── link_mgr.c
            ├── scatternet_app.c
            ├── user_cmd.c
            ├── user_cmd_parse.c
            └── data_uart.c

示例工程使用与 bt_host_0_0 匹配的默认GAP LIB,请参阅文档 Bluetooth Host Image 中的 GAP LIB的使用方法 以获取更多信息。

Bluetooth Host介绍

示例工程默认使用Bluetooth Host image版本 bt_host_0_0,更多信息可参阅 Bluetooth Host Image

关于Bluetooth Host所支持的蓝牙功能的详细信息,请参阅文件 bin\rtl87x2g\bt_host_image\bt_host_0_0\bt_host_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;
}
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消息的信息可以查阅 LE Host 中的 蓝牙状态消息

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:
       ......
   }
}

Scatternet示例工程支持的GATT profile clients包括 GAP Service ClientSimple LE Service ClientBattery 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包含两种消息类型:

    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设置

  1. 注册GAP Common回调函数
    APP需要调用 gap_register_app_cb() 以注册回调函数。
void app_le_gap_init(void)
{
    ......
    gap_register_app_cb(app_gap_common_callback);
}
  1. 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_MODEGAP_MSG_READ_AIRPLAN_MODE 消息。

  1. 相关APIs

    1. gap_write_airplan_mode() 用于写airplane mode。

    2. 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;
    }