LE Scatternet

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

Scatternet特征:

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

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

  • 不支持角色转换。

环境需求

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

环境需求

Hardware Platforms

Board Name

RTL87x2G HDK

RTL87x2G EVB

该示例工程需要通过使用电脑的Data Uart输入指令来执行交互。还需要两个设备分别运行LE Central角色和LE Peripheral角色。

更多要求,请参考 快速入门

硬件连线

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

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

配置选项

APP配置选项

APP所有需要配置的内容在 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

生成系统配置文件

开发者可以通过MPTool配置链接个数:

MPTool配置

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 值。

更多有关于MPTool配置的信息请参考 快速入门 中的 生成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 ,请参考 快速入门MPTool 中列出的步骤。

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

测试验证

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

与另一块开发板对测

准备三块开发板分别命名为 DUTTester 1Tester 2 ,开发者可以使用 DebugAnalyzer 抓取Soc端Log

准备步骤

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

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

  3. 使用MPTool将 Tester 2 地址设为[00:11:22:33:44:85],然后编译 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 将开始发送可连接广播。

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

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

如果 DUT 成功启动且 serial port assistant tool 配置成功, 开发者会看到如下日志。serial port assistant tool端会显示本地地址。 如果没有看到下列日志,说明广播启动失败。请检查软件和硬件环境。

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

DUTTester 1 间的测试流程如下:

Step

DUT user command

Description

DUT Log

1

bondclear

删除 DUT 端的绑定信息

DebugAnalyser shows:

[GAP] !**le_clear_all_keys

2

scan

DUT 开始扫描附近的LE设备

DebugAnalyser 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

停止扫描

DebugAnalyser shows:

[APP] !**GAP scan stop

4

showdev

显示扫描到的设备列表

该设备列表通过simple BLE 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 成功启动且 serial port assistant tool 配置成功, 开发者会看到如下日志。serial port assistant tool端会显示本地地址。 如果没有看到下列日志,说明广播启动失败。请检查软件和硬件环境。

    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 端的绑定信息

    DebugAnalyser shows:

    [GAP] !**le_clear_all_keys

    7

    startadv

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

    DebugAnalyser shows:

    [APP] !**GAP adv start

    8

    scan

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

    DebugAnalyser 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 停止扫描

    DebugAnalyser shows:

    [APP] !**GAP scan stop

    10

    showdev

    显示扫描到的设备列表。该设备列表通过simple BLE 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 发送连接参数更新请求

DebugAnalyser shows:

[APP] !**app_handle_conn_param_update_evt update success:conn_id 0, conn_interval 0x3c, conn_slave_latency 0x0, conn_supervision_timeout 0x3e8

DebugAnalyser 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 发送连接参数更新请求

DebugAnalyser 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

DebugAnalyser 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)

DebugAnalyser 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

DebugAnalyser 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 BLE Service信息

DebugAnalyser shows:

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

25

gapdis 0

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

DebugAnalyser shows:

[APP] !**GAPS_READ_DEVICE_NAME: device name BLE_PERIPHERAL

代码介绍

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

源码路径

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

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

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

└── Project: scatternet
    └── secure_only_app
        └── Device                   includes startup code
        ├── CMSE Library             Non-secure callable lib
        ├── 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,请参阅文档 BT Host Image 中的 GAP Lib的使用方法 以获取更多信息。

BT Host介绍

示例工程使用 bt_host_0_0 中的默认BT Host image,更多信息可参阅 BT Host Image

关于BT 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从GAP层接收到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 BLE 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使用的消息包含以下两种消息类型:
    • PROFILE_EVT_SRV_REG_COMPLETE
      该消息用于通知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 BLE Service
    simp_srv_id 是simple BLE 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

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