aboutsummaryrefslogtreecommitdiff
path: root/src/sample/ble_scatternet
diff options
context:
space:
mode:
Diffstat (limited to 'src/sample/ble_scatternet')
-rw-r--r--src/sample/ble_scatternet/app_flags.h40
-rw-r--r--src/sample/ble_scatternet/app_task.c111
-rw-r--r--src/sample/ble_scatternet/app_task.h27
-rw-r--r--src/sample/ble_scatternet/link_mgr.c137
-rw-r--r--src/sample/ble_scatternet/link_mgr.h87
-rw-r--r--src/sample/ble_scatternet/main.c297
-rw-r--r--src/sample/ble_scatternet/scatternet_app.c1205
-rw-r--r--src/sample/ble_scatternet/scatternet_app.h77
-rw-r--r--src/sample/ble_scatternet/user_cmd.c1968
-rw-r--r--src/sample/ble_scatternet/user_cmd.h31
10 files changed, 3980 insertions, 0 deletions
diff --git a/src/sample/ble_scatternet/app_flags.h b/src/sample/ble_scatternet/app_flags.h
new file mode 100644
index 0000000..efc5b06
--- /dev/null
+++ b/src/sample/ble_scatternet/app_flags.h
@@ -0,0 +1,40 @@
+/**
+*****************************************************************************************
+* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved.
+*****************************************************************************************
+ * @file app_flags.h
+ * @brief This file is used to config app functions.
+ * @author jane
+ * @date 2017-06-06
+ * @version v1.0
+ **************************************************************************************
+ * @attention
+ * <h2><center>&copy; COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2>
+ **************************************************************************************
+ */
+#ifndef _APP_FLAGS_H_
+#define _APP_FLAGS_H_
+
+#include "upperstack_config.h"
+
+/** @defgroup SCATTERNET_Config Scatternet App Configuration
+ * @brief This file is used to config app functions.
+ * @{
+ */
+/*============================================================================*
+ * Constants
+ *============================================================================*/
+
+/** @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
+
+/** @} */ /* End of group SCATTERNET_Config */
+#endif
diff --git a/src/sample/ble_scatternet/app_task.c b/src/sample/ble_scatternet/app_task.c
new file mode 100644
index 0000000..b4614be
--- /dev/null
+++ b/src/sample/ble_scatternet/app_task.c
@@ -0,0 +1,111 @@
+/**
+*****************************************************************************************
+* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved.
+*****************************************************************************************
+ * @file app_task.c
+ * @brief Routines to create App task and handle events & messages
+ * @author jane
+ * @date 2017-06-02
+ * @version v1.0
+ **************************************************************************************
+ * @attention
+ * <h2><center>&copy; COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2>
+ **************************************************************************************
+ */
+
+/*============================================================================*
+ * Header Files
+ *============================================================================*/
+#include <os_msg.h>
+#include <os_task.h>
+#include <gap.h>
+#include <gap_le.h>
+#include <trace.h>
+#include <app_task.h>
+#include <app_msg.h>
+#include <app_task.h>
+#include <scatternet_app.h>
+#include <data_uart.h>
+#include <user_cmd_parse.h>
+#include <user_cmd.h>
+
+
+/** @defgroup SCATTERNET_APP_TASK Scatternet App Task
+ * @brief This file handles the implementation of application task related functions.
+ *
+ * Create App task and handle events & messages
+ * @{
+ */
+/*============================================================================*
+ * Macros
+ *============================================================================*/
+
+#define APP_TASK_PRIORITY 1 //!< Task priorities
+#define APP_TASK_STACK_SIZE 256 * 6 //!< Task stack size
+#define MAX_NUMBER_OF_GAP_MESSAGE 0x20 //!< GAP message queue size
+#define MAX_NUMBER_OF_IO_MESSAGE 0x20 //!< IO message queue size
+#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE) //!< Event message queue size
+
+/*============================================================================*
+ * Variables
+ *============================================================================*/
+void *app_task_handle; //!< APP Task handle
+void *evt_queue_handle; //!< Event queue handle
+void *io_queue_handle; //!< IO queue handle
+
+/*============================================================================*
+ * Functions
+ *============================================================================*/
+void app_main_task(void *p_param);
+
+/**
+ * @brief Initialize App task
+ * @return void
+ */
+void app_task_init()
+{
+ os_task_create(&app_task_handle, "app", app_main_task, 0, APP_TASK_STACK_SIZE,
+ APP_TASK_PRIORITY);
+}
+
+/**
+ * @brief App task to handle events & messages
+ * @param[in] p_param Parameters sending to the task
+ * @return void
+ */
+void app_main_task(void *p_param)
+{
+ uint8_t event;
+
+ os_msg_queue_create(&io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG));
+ os_msg_queue_create(&evt_queue_handle, MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t));
+
+ gap_start_bt_stack(evt_queue_handle, io_queue_handle, MAX_NUMBER_OF_GAP_MESSAGE);
+
+ data_uart_init(evt_queue_handle, io_queue_handle);
+ user_cmd_init(&user_cmd_if, "scatternet");
+
+ driver_init();
+ while (true)
+ {
+ if (os_msg_recv(evt_queue_handle, &event, 0xFFFFFFFF) == true)
+ {
+ if (event == EVENT_IO_TO_APP)
+ {
+ T_IO_MSG io_msg;
+ if (os_msg_recv(io_queue_handle, &io_msg, 0) == true)
+ {
+ app_handle_io_msg(io_msg);
+ }
+ }
+ else
+ {
+ gap_handle_msg(event);
+ }
+ }
+ }
+}
+
+/** @} */ /* End of group SCATTERNET_APP_TASK */
+
+
diff --git a/src/sample/ble_scatternet/app_task.h b/src/sample/ble_scatternet/app_task.h
new file mode 100644
index 0000000..8dfcd2a
--- /dev/null
+++ b/src/sample/ble_scatternet/app_task.h
@@ -0,0 +1,27 @@
+/**
+*****************************************************************************************
+* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved.
+*****************************************************************************************
+ * @file app_task.h
+ * @brief Routines to create App task and handle events & messages
+ * @author jane
+ * @date 2017-06-02
+ * @version v1.0
+ **************************************************************************************
+ * @attention
+ * <h2><center>&copy; COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2>
+ **************************************************************************************
+ */
+#ifndef _APP_TASK_H_
+#define _APP_TASK_H_
+
+extern void driver_init(void);
+
+/**
+ * @brief Initialize App task
+ * @return void
+ */
+void app_task_init(void);
+
+#endif
+
diff --git a/src/sample/ble_scatternet/link_mgr.c b/src/sample/ble_scatternet/link_mgr.c
new file mode 100644
index 0000000..ee57041
--- /dev/null
+++ b/src/sample/ble_scatternet/link_mgr.c
@@ -0,0 +1,137 @@
+/**
+*****************************************************************************************
+* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved.
+*****************************************************************************************
+ * @file link_mgr.c
+ * @brief Multilink manager functions.
+ * @author jane
+ * @date 2017-06-06
+ * @version v1.0
+ **************************************************************************************
+ * @attention
+ * <h2><center>&copy; COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2>
+ **************************************************************************************
+ */
+/*============================================================================*
+ * Header Files
+ *============================================================================*/
+#include <link_mgr.h>
+#include <trace.h>
+#include <string.h>
+#include <ftl.h>
+
+/*============================================================================*
+ * Constants
+ *============================================================================*/
+#if F_BT_LE_USE_STATIC_RANDOM_ADDR
+/** @brief Define start offset of the flash to save static random address. */
+#define APP_STATIC_RANDOM_ADDR_OFFSET 0
+#endif
+
+/*============================================================================*
+ * Variables
+ *============================================================================*/
+/** @addtogroup SCATTERNET_GAP_MSG
+ * @{
+ */
+T_APP_LINK app_link_table[APP_MAX_LINKS];
+/** @} */
+/** @addtogroup SCATTERNET_SCAN_MGR
+ * @{
+ */
+T_DEV_INFO dev_list[APP_MAX_DEVICE_INFO];
+uint8_t dev_list_count = 0;
+/** @} */
+
+/*============================================================================*
+ * Functions
+ *============================================================================*/
+/** @addtogroup CENTRAL_SCAN_MGR
+ * @{
+ */
+/**
+ * @brief Add device information to device list.
+ *
+ * @param[in] bd_addr Peer device address.
+ * @param[in] bd_type Peer device address type.
+ * @retval true Success.
+ * @retval false Failed, device list is full.
+ */
+bool link_mgr_add_device(uint8_t *bd_addr, uint8_t bd_type)
+{
+ /* If result count not at max */
+ if (dev_list_count < APP_MAX_DEVICE_INFO)
+ {
+ uint8_t i;
+ /* Check if device is already in device list*/
+ for (i = 0; i < dev_list_count; i++)
+ {
+ if (memcmp(bd_addr, dev_list[i].bd_addr, GAP_BD_ADDR_LEN) == 0)
+ {
+ return true;
+ }
+ }
+
+ /*Add addr to device list list*/
+ memcpy(dev_list[dev_list_count].bd_addr, bd_addr, GAP_BD_ADDR_LEN);
+ dev_list[dev_list_count].bd_type = bd_type;
+
+ /*Increment device list count*/
+ dev_list_count++;
+ }
+ else
+ {
+ return false;
+ }
+ return true;
+}
+
+/**
+ * @brief Clear device list.
+ * @retval None.
+ */
+void link_mgr_clear_device_list(void)
+{
+ dev_list_count = 0;
+}
+/** @} */
+/** @addtogroup SCATTERNET_APP
+ * @{
+ */
+/** @defgroup SCATTERNET_RANDOM Static Random Address Storage
+ * @brief Use @ref F_BT_LE_USE_STATIC_RANDOM_ADDR to open
+ * @{
+ */
+#if F_BT_LE_USE_STATIC_RANDOM_ADDR
+/**
+ * @brief Save static random address information into flash.
+ * @param[in] p_addr Pointer to the buffer for saving data.
+ * @retval 0 Save success.
+ * @retval other Failed.
+ */
+uint32_t app_save_static_random_address(T_APP_STATIC_RANDOM_ADDR *p_addr)
+{
+ APP_PRINT_INFO0("app_save_static_random_address");
+ return ftl_save(p_addr, APP_STATIC_RANDOM_ADDR_OFFSET, sizeof(T_APP_STATIC_RANDOM_ADDR));
+}
+/**
+ * @brief Load static random address information from storage.
+ * @param[out] p_addr Pointer to the buffer for loading data.
+ * @retval 0 Load success.
+ * @retval other Failed.
+ */
+uint32_t app_load_static_random_address(T_APP_STATIC_RANDOM_ADDR *p_addr)
+{
+ uint32_t result;
+ result = ftl_load(p_addr, APP_STATIC_RANDOM_ADDR_OFFSET,
+ sizeof(T_APP_STATIC_RANDOM_ADDR));
+ APP_PRINT_INFO1("app_load_static_random_address: result 0x%x", result);
+ if (result)
+ {
+ memset(p_addr, 0, sizeof(T_APP_STATIC_RANDOM_ADDR));
+ }
+ return result;
+}
+#endif
+/** @} */
+/** @} */
diff --git a/src/sample/ble_scatternet/link_mgr.h b/src/sample/ble_scatternet/link_mgr.h
new file mode 100644
index 0000000..dd8ac7a
--- /dev/null
+++ b/src/sample/ble_scatternet/link_mgr.h
@@ -0,0 +1,87 @@
+/**
+*****************************************************************************************
+* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved.
+*****************************************************************************************
+ * @file link_mgr.h
+ * @brief Define multilink manager struct and functions.
+ * @author jane
+ * @date 2017-06-06
+ * @version v1.0
+ **************************************************************************************
+ * @attention
+ * <h2><center>&copy; COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2>
+ **************************************************************************************
+ */
+#ifndef _LINK_MANAGER_H_
+#define _LINK_MANAGER_H_
+/*============================================================================*
+ * Header Files
+ *============================================================================*/
+#include <app_msg.h>
+#include <gap_conn_le.h>
+#include <profile_client.h>
+
+/*============================================================================*
+ * Constants
+ *============================================================================*/
+/** @brief Define device list table size. */
+#define APP_MAX_DEVICE_INFO 6
+
+/** @addtogroup SCATTERNET_GAP_MSG
+ * @{
+ */
+/**
+ * @brief Application Link control block definition.
+ */
+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;
+/** @} */ /* End of group SCATTERNET_GAP_MSG */
+/** @addtogroup SCATTERNET_SCAN_MGR
+ * @{
+ */
+/**
+ * @brief Device list block definition.
+ */
+typedef struct
+{
+ uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */
+ uint8_t bd_type; /**< remote BD type*/
+} T_DEV_INFO;
+/** @} */
+/** @addtogroup SCATTERNET_RANDOM
+ * @{
+ */
+#if F_BT_LE_USE_STATIC_RANDOM_ADDR
+typedef struct
+{
+ uint8_t is_exist;
+ uint8_t reserved; /**< remote BD type*/
+ uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */
+} T_APP_STATIC_RANDOM_ADDR;
+#endif
+/** @} */
+/*============================================================================*
+ * Variables
+ *============================================================================*/
+/** @brief App link table */
+extern T_APP_LINK app_link_table[APP_MAX_LINKS];
+/** @brief Device list table, used to save discovered device informations. */
+extern T_DEV_INFO dev_list[APP_MAX_DEVICE_INFO];
+/** @brief The number of device informations saved in dev_list. */
+extern uint8_t dev_list_count;
+
+/*============================================================================*
+ * Functions
+ *============================================================================*/
+bool link_mgr_add_device(uint8_t *bd_addr, uint8_t bd_type);
+void link_mgr_clear_device_list(void);
+
+#if F_BT_LE_USE_STATIC_RANDOM_ADDR
+uint32_t app_save_static_random_address(T_APP_STATIC_RANDOM_ADDR *p_addr);
+uint32_t app_load_static_random_address(T_APP_STATIC_RANDOM_ADDR *p_addr);
+#endif
+#endif
diff --git a/src/sample/ble_scatternet/main.c b/src/sample/ble_scatternet/main.c
new file mode 100644
index 0000000..e121ae4
--- /dev/null
+++ b/src/sample/ble_scatternet/main.c
@@ -0,0 +1,297 @@
+/**
+*****************************************************************************************
+* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved.
+*****************************************************************************************
+ * @file main.c
+ * @brief Source file for BLE scatternet project, mainly used for initialize modules
+ * @author jane
+ * @date 2017-06-12
+ * @version v1.0
+ **************************************************************************************
+ * @attention
+ * <h2><center>&copy; COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2>
+ **************************************************************************************
+ */
+
+/*============================================================================*
+ * Header Files
+ *============================================================================*/
+#include <os_sched.h>
+#include <string.h>
+#include <app_task.h>
+#include <trace.h>
+#include <gap.h>
+#include <gap_bond_le.h>
+#include <gap_scan.h>
+#include <gap_msg.h>
+#include <profile_client.h>
+#include <simple_ble_client.h>
+#include <gaps_client.h>
+#include <bas_client.h>
+#include <link_mgr.h>
+#include <scatternet_app.h>
+#include <gap_adv.h>
+#include <profile_server.h>
+#include <simple_ble_service.h>
+#include <bas.h>
+#include <gatt_builtin_services.h>
+
+
+/** @defgroup SCATTERNET_DEMO_MAIN Scatternet Main
+ * @brief Main file to initialize hardware and BT stack and start task scheduling
+ * @{
+ */
+
+/*============================================================================*
+ * Constants
+ *============================================================================*/
+/** @brief Default scan interval (units of 0.625ms, 0x10=2.5ms) */
+#define DEFAULT_SCAN_INTERVAL 0x20
+/** @brief Default scan window (units of 0.625ms, 0x10=2.5ms) */
+#define DEFAULT_SCAN_WINDOW 0x10
+
+/** @brief Default minimum advertising interval when device is discoverable (units of 625us, 160=100ms) */
+#define DEFAULT_ADVERTISING_INTERVAL_MIN 320
+/** @brief Default Maximum advertising interval */
+#define DEFAULT_ADVERTISING_INTERVAL_MAX 320
+
+/** @brief GAP - scan response data (max size = 31 bytes) */
+static const uint8_t scan_rsp_data[] =
+{
+ 0x03,
+ GAP_ADTYPE_APPEARANCE,
+ LO_WORD(GAP_GATT_APPEARANCE_UNKNOWN),
+ HI_WORD(GAP_GATT_APPEARANCE_UNKNOWN),
+};
+
+/** @brief GAP - Advertisement data (max size = 31 bytes, best kept short to conserve power) */
+static const uint8_t adv_data[] =
+{
+ 0x02,
+ GAP_ADTYPE_FLAGS,
+ GAP_ADTYPE_FLAGS_LIMITED | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
+
+ 0x03,
+ GAP_ADTYPE_16BIT_COMPLETE,
+ LO_WORD(GATT_UUID_SIMPLE_PROFILE),
+ HI_WORD(GATT_UUID_SIMPLE_PROFILE),
+
+ 0x0F,
+ GAP_ADTYPE_LOCAL_NAME_COMPLETE,
+ 'B', 'L', 'E', '_', 'S', 'C', 'A', 'T', 'T', 'E', 'R', 'N', 'E', 'T',
+};
+
+/*============================================================================*
+ * Functions
+ *============================================================================*/
+/**
+ * @brief Initialize gap related parameters
+ * @return void
+ */
+void app_le_gap_init(void)
+{
+ /* Device name and device appearance */
+ uint8_t device_name[GAP_DEVICE_NAME_LEN] = "BLE_SCATTERNET";
+ uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN;
+
+ /* Scan parameters */
+ uint8_t scan_mode = GAP_SCAN_MODE_ACTIVE;
+ uint16_t scan_interval = DEFAULT_SCAN_INTERVAL;
+ uint16_t scan_window = DEFAULT_SCAN_WINDOW;
+ uint8_t scan_filter_policy = GAP_SCAN_FILTER_ANY;
+ uint8_t scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE;
+
+ /* advertising parameters */
+ uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND;
+ uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC;
+ uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0};
+ uint8_t adv_chann_map = GAP_ADVCHAN_ALL;
+ uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY;
+ uint16_t adv_int_min = DEFAULT_ADVERTISING_INTERVAL_MIN;
+ uint16_t adv_int_max = DEFAULT_ADVERTISING_INTERVAL_MIN;
+
+ /* GAP Bond Manager parameters */
+ uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE;
+ uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG;
+ uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT;
+ uint8_t auth_oob = false;
+ uint8_t auth_use_fix_passkey = false;
+ uint32_t auth_fix_passkey = 0;
+ uint8_t auth_sec_req_enable = false;
+ uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG;
+
+ /* 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_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable);
+ 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);
+#if F_BT_LE_USE_STATIC_RANDOM_ADDR
+ T_APP_STATIC_RANDOM_ADDR random_addr;
+ bool gen_addr = true;
+ uint8_t local_bd_type = GAP_LOCAL_ADDR_LE_RANDOM;
+ if (app_load_static_random_address(&random_addr) == 0)
+ {
+ if (random_addr.is_exist == true)
+ {
+ gen_addr = false;
+ }
+ }
+ if (gen_addr)
+ {
+ if (le_gen_rand_addr(GAP_RAND_ADDR_STATIC, random_addr.bd_addr) == GAP_CAUSE_SUCCESS)
+ {
+ random_addr.is_exist = true;
+ app_save_static_random_address(&random_addr);
+ }
+ }
+ le_cfg_local_identity_address(random_addr.bd_addr, GAP_IDENT_ADDR_RAND);
+ le_set_gap_param(GAP_PARAM_RANDOM_ADDR, 6, random_addr.bd_addr);
+ //only for peripheral,broadcaster
+ le_adv_set_param(GAP_PARAM_ADV_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type);
+ //only for central,observer
+ le_scan_set_param(GAP_PARAM_SCAN_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type);
+#endif
+#if F_BT_AIRPLANE_MODE_SUPPORT
+ gap_register_app_cb(app_gap_common_callback);
+#endif
+#if F_BT_GAPS_CHAR_WRITEABLE
+ uint8_t appearance_prop = GAPS_PROPERTY_WRITE_ENABLE;
+ uint8_t device_name_prop = GAPS_PROPERTY_WRITE_ENABLE;
+ T_LOCAL_APPEARANCE appearance_local;
+ T_LOCAL_NAME local_device_name;
+ if (flash_load_local_appearance(&appearance_local) == 0)
+ {
+ gaps_set_parameter(GAPS_PARAM_APPEARANCE, sizeof(uint16_t), &appearance_local.local_appearance);
+ }
+
+ if (flash_load_local_name(&local_device_name) == 0)
+ {
+ gaps_set_parameter(GAPS_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, local_device_name.local_name);
+ }
+ gaps_set_parameter(GAPS_PARAM_APPEARANCE_PROPERTY, sizeof(appearance_prop), &appearance_prop);
+ gaps_set_parameter(GAPS_PARAM_DEVICE_NAME_PROPERTY, sizeof(device_name_prop), &device_name_prop);
+ gatt_register_callback(gap_service_callback);
+#endif
+#if F_BT_LE_5_0_SET_PHY_SUPPORT
+ uint8_t phys_prefer = GAP_PHYS_PREFER_ALL;
+ uint8_t tx_phys_prefer = GAP_PHYS_PREFER_1M_BIT | GAP_PHYS_PREFER_2M_BIT |
+ GAP_PHYS_PREFER_CODED_BIT;
+ uint8_t rx_phys_prefer = GAP_PHYS_PREFER_1M_BIT | GAP_PHYS_PREFER_2M_BIT |
+ GAP_PHYS_PREFER_CODED_BIT;
+ le_set_gap_param(GAP_PARAM_DEFAULT_PHYS_PREFER, sizeof(phys_prefer), &phys_prefer);
+ le_set_gap_param(GAP_PARAM_DEFAULT_TX_PHYS_PREFER, sizeof(tx_phys_prefer), &tx_phys_prefer);
+ le_set_gap_param(GAP_PARAM_DEFAULT_RX_PHYS_PREFER, sizeof(rx_phys_prefer), &rx_phys_prefer);
+#endif
+}
+
+/**
+ * @brief Add GATT services, clients and register callbacks
+ * @return void
+ */
+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);
+
+ 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);
+}
+
+/**
+ * @brief Contains the initialization of pinmux settings and pad settings
+ * @note All the pinmux settings and pad settings shall be initiated in this function,
+ * but if legacy driver is used, the initialization of pinmux setting and pad setting
+ * should be performed with the IO initializing.
+ * @return void
+ */
+void board_init(void)
+{
+
+}
+
+/**
+ * @brief Contains the initialization of peripherals
+ * @note Both new architecture driver and legacy driver initialization method can be used
+ * @return void
+ */
+void driver_init(void)
+{
+
+}
+
+/**
+ * @brief Contains the power mode settings
+ * @return void
+ */
+void pwr_mgr_init(void)
+{
+}
+
+/**
+ * @brief Contains the initialization of all tasks
+ * @note There is only one task in BLE Scatternet APP, thus only one APP task is init here
+ * @return void
+ */
+void task_init(void)
+{
+ app_task_init();
+}
+
+/**
+ * @brief Entry of APP code
+ * @return int (To avoid compile warning)
+ */
+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;
+}
+/** @} */ /* End of group SCATTERNET_DEMO_MAIN */
+
diff --git a/src/sample/ble_scatternet/scatternet_app.c b/src/sample/ble_scatternet/scatternet_app.c
new file mode 100644
index 0000000..ce3c481
--- /dev/null
+++ b/src/sample/ble_scatternet/scatternet_app.c
@@ -0,0 +1,1205 @@
+/**
+*****************************************************************************************
+* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved.
+*****************************************************************************************
+ * @file scatternet_app.c
+ * @brief This file handles BLE scatternet application routines.
+ * @author jane
+ * @date 2017-06-06
+ * @version v1.0
+ **************************************************************************************
+ * @attention
+ * <h2><center>&copy; COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2>
+ **************************************************************************************
+ */
+
+/*============================================================================*
+ * Header Files
+ *============================================================================*/
+
+#include <string.h>
+#include <app_msg.h>
+#include <trace.h>
+#include <gap_scan.h>
+#include <gap.h>
+#include <gap_msg.h>
+#include <gap_bond_le.h>
+#include <scatternet_app.h>
+#include <link_mgr.h>
+#include <user_cmd.h>
+#include <user_cmd_parse.h>
+#include <simple_ble_client.h>
+#include <gaps_client.h>
+#include <bas_client.h>
+#include <profile_server.h>
+#include <simple_ble_service.h>
+#include <bas.h>
+#include <gatt_builtin_services.h>
+
+
+/** @defgroup SCATTERNET_APP Scatternet Application
+ * @brief This file handles BLE scatternet application routines.
+ * @{
+ */
+/*============================================================================*
+ * Variables
+ *============================================================================*/
+/** @addtogroup SCATTERNET_CLIIENT_CALLBACK
+ * @{
+ */
+T_CLIENT_ID simple_ble_client_id; /**< Simple ble service client id*/
+T_CLIENT_ID gaps_client_id; /**< gap service client id*/
+T_CLIENT_ID bas_client_id; /**< battery service client id*/
+/** @} */ /* End of group SCATTERNET_CLIIENT_CALLBACK */
+
+/** @addtogroup SCATTERNET_SEVER_CALLBACK
+ * @{
+ */
+T_SERVER_ID simp_srv_id; /**< Simple ble service id*/
+T_SERVER_ID bas_srv_id; /**< Battery service id */
+/** @} */ /* End of group SCATTERNET_SEVER_CALLBACK */
+
+/** @defgroup SCATTERNET_GAP_MSG GAP Message Handler
+ * @brief Handle GAP Message
+ * @{
+ */
+T_GAP_DEV_STATE gap_dev_state = {0, 0, 0, 0}; /**< GAP device state */
+/*============================================================================*
+ * Functions
+ *============================================================================*/
+void app_handle_gap_msg(T_IO_MSG *p_gap_msg);
+/**
+ * @brief All the application messages are pre-handled in this function
+ * @note All the IO MSGs are sent to this function, then the event handling
+ * function shall be called according to the MSG type.
+ * @param[in] io_msg IO message data
+ * @return void
+ */
+void app_handle_io_msg(T_IO_MSG io_msg)
+{
+ uint16_t msg_type = io_msg.type;
+ uint8_t rx_char;
+
+ switch (msg_type)
+ {
+ case IO_MSG_TYPE_BT_STATUS:
+ {
+ app_handle_gap_msg(&io_msg);
+ }
+ break;
+ case IO_MSG_TYPE_UART:
+ /* We handle user command informations from Data UART in this branch. */
+ rx_char = (uint8_t)io_msg.subtype;
+ user_cmd_collect(&user_cmd_if, &rx_char, sizeof(rx_char), user_cmd_table);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * @brief Handle msg GAP_MSG_LE_DEV_STATE_CHANGE
+ * @note All the gap device state events are pre-handled in this function.
+ * Then the event handling function shall be called according to the new_state
+ * @param[in] new_state New gap device state
+ * @param[in] cause GAP device state change cause
+ * @return void
+ */
+void app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause)
+{
+ APP_PRINT_INFO4("app_handle_dev_state_evt: init state %d, adv state %d, scan state %d, cause 0x%x",
+ new_state.gap_init_state, new_state.gap_adv_state,
+ new_state.gap_scan_state, cause);
+ if (gap_dev_state.gap_init_state != new_state.gap_init_state)
+ {
+ if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY)
+ {
+ uint8_t bt_addr[6];
+ APP_PRINT_INFO0("GAP stack ready");
+ /*stack ready*/
+ gap_get_param(GAP_PARAM_BD_ADDR, bt_addr);
+ data_uart_print("local bd addr: 0x%2x:%2x:%2x:%2x:%2x:%2x\r\n",
+ bt_addr[5], bt_addr[4], bt_addr[3],
+ bt_addr[2], bt_addr[1], bt_addr[0]);
+ }
+ }
+
+ if (gap_dev_state.gap_scan_state != new_state.gap_scan_state)
+ {
+ if (new_state.gap_scan_state == GAP_SCAN_STATE_IDLE)
+ {
+ APP_PRINT_INFO0("GAP scan stop");
+ data_uart_print("GAP scan stop\r\n");
+ }
+ else if (new_state.gap_scan_state == GAP_SCAN_STATE_SCANNING)
+ {
+ APP_PRINT_INFO0("GAP scan start");
+ data_uart_print("GAP scan start\r\n");
+ }
+ }
+
+ if (gap_dev_state.gap_adv_state != new_state.gap_adv_state)
+ {
+ if (new_state.gap_adv_state == GAP_ADV_STATE_IDLE)
+ {
+ if (new_state.gap_adv_sub_state == GAP_ADV_TO_IDLE_CAUSE_CONN)
+ {
+ APP_PRINT_INFO0("GAP adv stoped: because connection created");
+ }
+ else
+ {
+ APP_PRINT_INFO0("GAP adv stoped");
+ }
+ data_uart_print("GAP adv stoped\r\n");
+ }
+ else if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING)
+ {
+ APP_PRINT_INFO0("GAP adv start");
+ data_uart_print("GAP adv start\r\n");
+ }
+ }
+
+ gap_dev_state = new_state;
+}
+
+/**
+ * @brief Handle msg GAP_MSG_LE_CONN_STATE_CHANGE
+ * @note All the gap conn state events are pre-handled in this function.
+ * Then the event handling function shall be called according to the new_state
+ * @param[in] conn_id Connection ID
+ * @param[in] new_state New gap connection state
+ * @param[in] disc_cause Use this cause when new_state is GAP_CONN_STATE_DISCONNECTED
+ * @return void
+ */
+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:
+ {
+ uint16_t conn_interval;
+ uint16_t conn_latency;
+ uint16_t conn_supervision_timeout;
+
+ le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id);
+ le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id);
+ le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id);
+ le_get_conn_addr(conn_id, app_link_table[conn_id].bd_addr,
+ &app_link_table[conn_id].bd_type);
+ APP_PRINT_INFO5("GAP_CONN_STATE_CONNECTED:remote_bd %s, remote_addr_type %d, conn_interval 0x%x, conn_latency 0x%x, conn_supervision_timeout 0x%x",
+ TRACE_BDADDR(app_link_table[conn_id].bd_addr), app_link_table[conn_id].bd_type,
+ conn_interval, conn_latency, conn_supervision_timeout);
+ data_uart_print("Connected success conn_id %d\r\n", conn_id);
+#if F_BT_LE_5_0_SET_PHY_SUPPORT
+ {
+ uint8_t tx_phy;
+ uint8_t rx_phy;
+ le_get_conn_param(GAP_PARAM_CONN_RX_PHY_TYPE, &rx_phy, conn_id);
+ le_get_conn_param(GAP_PARAM_CONN_TX_PHY_TYPE, &tx_phy, conn_id);
+ APP_PRINT_INFO2("GAP_CONN_STATE_CONNECTED: tx_phy %d, rx_phy %d", tx_phy, rx_phy);
+ }
+#endif
+ }
+ break;
+
+ default:
+ break;
+
+ }
+}
+
+/**
+ * @brief Handle msg GAP_MSG_LE_AUTHEN_STATE_CHANGE
+ * @note All the gap authentication state events are pre-handled in this function.
+ * Then the event handling function shall be called according to the new_state
+ * @param[in] conn_id Connection ID
+ * @param[in] new_state New authentication state
+ * @param[in] cause Use this cause when new_state is GAP_AUTHEN_STATE_COMPLETE
+ * @return void
+ */
+void app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t cause)
+{
+ APP_PRINT_INFO2("app_handle_authen_state_evt:conn_id %d, cause 0x%x", conn_id, cause);
+
+ switch (new_state)
+ {
+ case GAP_AUTHEN_STATE_STARTED:
+ {
+ APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_STARTED");
+ }
+ break;
+
+ case GAP_AUTHEN_STATE_COMPLETE:
+ {
+ if (cause == GAP_SUCCESS)
+ {
+ data_uart_print("Pair success\r\n");
+ APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair success");
+
+ }
+ else
+ {
+ data_uart_print("Pair failed: cause 0x%x\r\n", cause);
+ APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair failed");
+ }
+ }
+ break;
+
+ default:
+ {
+ APP_PRINT_ERROR1("app_handle_authen_state_evt: unknown newstate %d", new_state);
+ }
+ break;
+ }
+}
+
+/**
+ * @brief Handle msg GAP_MSG_LE_CONN_MTU_INFO
+ * @note This msg is used to inform APP that exchange mtu procedure is completed.
+ * @param[in] conn_id Connection ID
+ * @param[in] mtu_size New mtu size
+ * @return void
+ */
+void app_handle_conn_mtu_info_evt(uint8_t conn_id, uint16_t mtu_size)
+{
+ APP_PRINT_INFO2("app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size);
+}
+
+/**
+ * @brief Handle msg GAP_MSG_LE_CONN_PARAM_UPDATE
+ * @note All the connection parameter update change events are pre-handled in this function.
+ * @param[in] conn_id Connection ID
+ * @param[in] status New update state
+ * @param[in] cause Use this cause when status is GAP_CONN_PARAM_UPDATE_STATUS_FAIL
+ * @return void
+ */
+void app_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status, uint16_t cause)
+{
+ switch (status)
+ {
+ case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS:
+ {
+ uint16_t conn_interval;
+ uint16_t conn_slave_latency;
+ uint16_t conn_supervision_timeout;
+
+ le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id);
+ le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id);
+ le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id);
+ APP_PRINT_INFO4("app_handle_conn_param_update_evt update success:conn_id %d, conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x",
+ conn_id, conn_interval, conn_slave_latency, conn_supervision_timeout);
+ }
+ break;
+
+ case GAP_CONN_PARAM_UPDATE_STATUS_FAIL:
+ {
+ APP_PRINT_ERROR2("app_handle_conn_param_update_evt update failed: conn_id %d, cause 0x%x",
+ conn_id, cause);
+ }
+ break;
+
+ case GAP_CONN_PARAM_UPDATE_STATUS_PENDING:
+ {
+ APP_PRINT_INFO1("app_handle_conn_param_update_evt update pending: conn_id %d", conn_id);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ * @brief All the BT GAP MSG are pre-handled in this function.
+ * @note Then the event handling function shall be called according to the
+ * subtype of T_IO_MSG
+ * @param[in] p_gap_msg Pointer to GAP msg
+ * @return void
+ */
+void app_handle_gap_msg(T_IO_MSG *p_gap_msg)
+{
+ T_LE_GAP_MSG gap_msg;
+ uint8_t conn_id;
+ memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param));
+
+ APP_PRINT_TRACE1("app_handle_gap_msg: subtype %d", p_gap_msg->subtype);
+ switch (p_gap_msg->subtype)
+ {
+ case GAP_MSG_LE_DEV_STATE_CHANGE:
+ {
+ app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state,
+ gap_msg.msg_data.gap_dev_state_change.cause);
+ }
+ break;
+
+ case GAP_MSG_LE_CONN_STATE_CHANGE:
+ {
+ app_handle_conn_state_evt(gap_msg.msg_data.gap_conn_state_change.conn_id,
+ (T_GAP_CONN_STATE)gap_msg.msg_data.gap_conn_state_change.new_state,
+ gap_msg.msg_data.gap_conn_state_change.disc_cause);
+ }
+ break;
+
+ case GAP_MSG_LE_CONN_MTU_INFO:
+ {
+ app_handle_conn_mtu_info_evt(gap_msg.msg_data.gap_conn_mtu_info.conn_id,
+ gap_msg.msg_data.gap_conn_mtu_info.mtu_size);
+ }
+ break;
+
+ case GAP_MSG_LE_CONN_PARAM_UPDATE:
+ {
+ app_handle_conn_param_update_evt(gap_msg.msg_data.gap_conn_param_update.conn_id,
+ gap_msg.msg_data.gap_conn_param_update.status,
+ gap_msg.msg_data.gap_conn_param_update.cause);
+ }
+ break;
+
+ case GAP_MSG_LE_AUTHEN_STATE_CHANGE:
+ {
+ app_handle_authen_state_evt(gap_msg.msg_data.gap_authen_state.conn_id,
+ gap_msg.msg_data.gap_authen_state.new_state,
+ gap_msg.msg_data.gap_authen_state.status);
+ }
+ break;
+
+ case GAP_MSG_LE_BOND_JUST_WORK:
+ {
+ conn_id = gap_msg.msg_data.gap_bond_just_work_conf.conn_id;
+ le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT);
+ APP_PRINT_INFO0("GAP_MSG_LE_BOND_JUST_WORK");
+ }
+ break;
+
+ case GAP_MSG_LE_BOND_PASSKEY_DISPLAY:
+ {
+ uint32_t display_value = 0;
+ conn_id = gap_msg.msg_data.gap_bond_passkey_display.conn_id;
+ le_bond_get_display_key(conn_id, &display_value);
+ APP_PRINT_INFO2("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, passkey %d",
+ conn_id, display_value);
+ le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT);
+ data_uart_print("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, passkey %d\r\n",
+ conn_id,
+ display_value);
+ }
+ break;
+
+ case GAP_MSG_LE_BOND_USER_CONFIRMATION:
+ {
+ uint32_t display_value = 0;
+ conn_id = gap_msg.msg_data.gap_bond_user_conf.conn_id;
+ le_bond_get_display_key(conn_id, &display_value);
+ APP_PRINT_INFO2("GAP_MSG_LE_BOND_USER_CONFIRMATION: conn_id %d, passkey %d",
+ conn_id, display_value);
+ data_uart_print("GAP_MSG_LE_BOND_USER_CONFIRMATION: conn_id %d, passkey %d\r\n",
+ conn_id,
+ display_value);
+ //le_bond_user_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT);
+ }
+ break;
+
+ case GAP_MSG_LE_BOND_PASSKEY_INPUT:
+ {
+ //uint32_t passkey = 888888;
+ conn_id = gap_msg.msg_data.gap_bond_passkey_input.conn_id;
+ APP_PRINT_INFO2("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d, key_press %d",
+ conn_id, gap_msg.msg_data.gap_bond_passkey_input.key_press);
+ data_uart_print("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d\r\n", conn_id);
+ //le_bond_passkey_input_confirm(conn_id, passkey, GAP_CFM_CAUSE_ACCEPT);
+ }
+ break;
+
+ case GAP_MSG_LE_BOND_OOB_INPUT:
+ {
+ uint8_t oob_data[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ conn_id = gap_msg.msg_data.gap_bond_oob_input.conn_id;
+ APP_PRINT_INFO1("GAP_MSG_LE_BOND_OOB_INPUT: conn_id %d", conn_id);
+ le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data);
+ le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT);
+ }
+ break;
+
+ default:
+ APP_PRINT_ERROR1("app_handle_gap_msg: unknown subtype %d", p_gap_msg->subtype);
+ break;
+ }
+}
+/** @} */ /* End of group SCATTERNET_GAP_MSG */
+
+/** @defgroup SCATTERNET_SCAN_MGR Scan Information manager
+ * @brief Scan Information manager
+ * @{
+ */
+/**
+ * @brief Use 16 bit uuid to filter scan information
+ * @param[in] uuid 16 bit UUID.
+ * @param[in] scan_info point to scan information data.
+ * @return filter result
+ * @retval true found success
+ * @retval false not found
+ */
+bool filter_scan_info_by_uuid(uint16_t uuid, T_LE_SCAN_INFO *scan_info)
+{
+ uint8_t buffer[32];
+ uint8_t pos = 0;
+
+ while (pos < scan_info->data_len)
+ {
+ /* Length of the AD structure. */
+ uint8_t length = scan_info->data[pos++];
+ uint8_t type;
+
+ if ((length < 1) || (length >= 31))
+ {
+ return false;
+ }
+
+ if ((length > 0x01) && ((pos + length) <= 31))
+ {
+ /* Copy the AD Data to buffer. */
+ memcpy(buffer, scan_info->data + pos + 1, length - 1);
+ /* AD Type, one octet. */
+ type = scan_info->data[pos];
+
+ switch (type)
+ {
+ case GAP_ADTYPE_16BIT_MORE:
+ case GAP_ADTYPE_16BIT_COMPLETE:
+ case GAP_ADTYPE_SERVICES_LIST_16BIT:
+ {
+ uint16_t *p_uuid = (uint16_t *)(buffer);
+ uint8_t i = length - 1;
+
+ while (i >= 2)
+ {
+ APP_PRINT_INFO2(" AD Data: UUID16 List Item %d = 0x%x", i / 2, *p_uuid);
+ if (*p_uuid == uuid)
+ {
+ return true;
+ }
+ p_uuid++;
+ i -= 2;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ pos += length;
+ }
+ return false;
+}
+/** @} */ /* End of group SCATTERNET_SCAN_MGR */
+
+/** @defgroup SCATTERNET_GAP_CALLBACK GAP Callback Event Handler
+ * @brief Handle GAP callback event
+ * @{
+ */
+/**
+ * @brief Callback for gap le to notify app
+ * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types.
+ * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA.
+ * @retval result @ref T_APP_RESULT
+ */
+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:
+ APP_PRINT_INFO3("GAP_MSG_LE_READ_RSSI:conn_id %d cause 0x%x rssi %d",
+ p_data->p_le_read_rssi_rsp->conn_id,
+ p_data->p_le_read_rssi_rsp->cause,
+ p_data->p_le_read_rssi_rsp->rssi);
+ break;
+
+ case GAP_MSG_LE_DATA_LEN_CHANGE_INFO:
+ APP_PRINT_INFO3("GAP_MSG_LE_DATA_LEN_CHANGE_INFO: conn_id %d, tx octets 0x%x, max_tx_time 0x%x",
+ p_data->p_le_data_len_change_info->conn_id,
+ p_data->p_le_data_len_change_info->max_tx_octets,
+ p_data->p_le_data_len_change_info->max_tx_time);
+ break;
+
+ case GAP_MSG_LE_BOND_MODIFY_INFO:
+ APP_PRINT_INFO1("GAP_MSG_LE_BOND_MODIFY_INFO: type 0x%x",
+ p_data->p_le_bond_modify_info->type);
+ break;
+
+ case GAP_MSG_LE_MODIFY_WHITE_LIST:
+ APP_PRINT_INFO2("GAP_MSG_LE_MODIFY_WHITE_LIST: operation %d, cause 0x%x",
+ p_data->p_le_modify_white_list_rsp->operation,
+ p_data->p_le_modify_white_list_rsp->cause);
+ break;
+ /* central reference msg*/
+ case GAP_MSG_LE_SCAN_INFO:
+ APP_PRINT_INFO5("GAP_MSG_LE_SCAN_INFO:adv_type 0x%x, bd_addr %s, remote_addr_type %d, rssi %d, data_len %d",
+ p_data->p_le_scan_info->adv_type,
+ TRACE_BDADDR(p_data->p_le_scan_info->bd_addr),
+ p_data->p_le_scan_info->remote_addr_type,
+ p_data->p_le_scan_info->rssi,
+ p_data->p_le_scan_info->data_len);
+
+ /* User can split interested information by using the function as follow. */
+ if (filter_scan_info_by_uuid(GATT_UUID_SIMPLE_PROFILE, p_data->p_le_scan_info))
+ {
+ APP_PRINT_INFO0("Found simple ble service");
+ link_mgr_add_device(p_data->p_le_scan_info->bd_addr, p_data->p_le_scan_info->remote_addr_type);
+ }
+ /* If you want to parse the scan info, please reference function app_parse_scan_info in observer app. */
+ break;
+
+ case GAP_MSG_LE_CONN_UPDATE_IND:
+ APP_PRINT_INFO5("GAP_MSG_LE_CONN_UPDATE_IND: conn_id %d, conn_interval_max 0x%x, conn_interval_min 0x%x, conn_latency 0x%x,supervision_timeout 0x%x",
+ p_data->p_le_conn_update_ind->conn_id,
+ p_data->p_le_conn_update_ind->conn_interval_max,
+ p_data->p_le_conn_update_ind->conn_interval_min,
+ p_data->p_le_conn_update_ind->conn_latency,
+ p_data->p_le_conn_update_ind->supervision_timeout);
+ /* if reject the proposed connection parameter from peer device, use APP_RESULT_REJECT. */
+ result = APP_RESULT_ACCEPT;
+ break;
+
+ case GAP_MSG_LE_SET_HOST_CHANN_CLASSIF:
+ APP_PRINT_INFO1("GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: cause 0x%x",
+ p_data->p_le_set_host_chann_classif_rsp->cause);
+ break;
+ /* peripheral reference msg*/
+ case GAP_MSG_LE_ADV_UPDATE_PARAM:
+ APP_PRINT_INFO1("GAP_MSG_LE_ADV_UPDATE_PARAM: cause 0x%x",
+ p_data->p_le_adv_update_param_rsp->cause);
+ break;
+
+ case GAP_MSG_LE_DISABLE_SLAVE_LATENCY:
+ APP_PRINT_INFO1("GAP_MSG_LE_DISABLE_SLAVE_LATENCY: cause 0x%x",
+ p_data->p_le_disable_slave_latency_rsp->cause);
+ break;
+
+ case GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP:
+ APP_PRINT_INFO1("GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP:cause 0x%x",
+ p_data->p_le_update_passed_chann_map_rsp->cause);
+ break;
+#if F_BT_LE_5_0_SET_PHY_SUPPORT
+ case GAP_MSG_LE_PHY_UPDATE_INFO:
+ APP_PRINT_INFO4("GAP_MSG_LE_PHY_UPDATE_INFO:conn_id %d, cause 0x%x, rx_phy %d, tx_phy %d",
+ p_data->p_le_phy_update_info->conn_id,
+ p_data->p_le_phy_update_info->cause,
+ p_data->p_le_phy_update_info->rx_phy,
+ p_data->p_le_phy_update_info->tx_phy);
+ break;
+
+ case GAP_MSG_LE_REMOTE_FEATS_INFO:
+ {
+ uint8_t remote_feats[8];
+ APP_PRINT_INFO3("GAP_MSG_LE_REMOTE_FEATS_INFO: conn id %d, cause 0x%x, remote_feats %b",
+ p_data->p_le_remote_feats_info->conn_id,
+ p_data->p_le_remote_feats_info->cause,
+ TRACE_BINARY(8, p_data->p_le_remote_feats_info->remote_feats));
+ if (p_data->p_le_remote_feats_info->cause == GAP_SUCCESS)
+ {
+ memcpy(remote_feats, p_data->p_le_remote_feats_info->remote_feats, 8);
+ if (remote_feats[LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX1] & LE_SUPPORT_FEATURES_LE_2M_MASK_BIT)
+ {
+ APP_PRINT_INFO0("GAP_MSG_LE_REMOTE_FEATS_INFO: support 2M");
+ }
+ if (remote_feats[LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX1] & LE_SUPPORT_FEATURES_LE_CODED_PHY_MASK_BIT)
+ {
+ APP_PRINT_INFO0("GAP_MSG_LE_REMOTE_FEATS_INFO: support CODED");
+ }
+ }
+ }
+ break;
+#endif
+ default:
+ APP_PRINT_ERROR1("app_gap_callback: unhandled cb_type 0x%x", cb_type);
+ break;
+ }
+ return result;
+}
+/** @} */ /* End of group SCATTERNET_GAP_CALLBACK */
+
+#if F_BT_AIRPLANE_MODE_SUPPORT
+/** @defgroup SCATTERNET_AIRPLANE Airplane Mode Handler
+ * @brief Use @ref F_BT_AIRPLANE_MODE_SUPPORT to open
+ * @{
+ */
+/**
+ * @brief Callback for gap common module to notify app
+ * @param[in] cb_type callback msy type @ref GAP_COMMON_MSG_TYPE.
+ * @param[in] p_cb_data point to callback data @ref T_GAP_CB_DATA.
+ * @retval void
+ */
+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;
+}
+/** @} */
+#endif
+
+#if F_BT_GAPS_CHAR_WRITEABLE
+/** @defgroup SCATTERNET_GAPS_WRITE GAP Service Callback Handler
+ * @brief Use @ref F_BT_GAPS_CHAR_WRITEABLE to open
+ * @{
+ */
+/**
+ * @brief All the BT GAP service callback events are handled in this function
+ * @param[in] service_id Profile service ID
+ * @param[in] p_para Pointer to callback data
+ * @return Indicates the function call is successful or not
+ * @retval result @ref T_APP_RESULT
+ */
+T_APP_RESULT gap_service_callback(T_SERVER_ID service_id, void *p_para)
+{
+ T_APP_RESULT result = APP_RESULT_SUCCESS;
+ T_GAPS_CALLBACK_DATA *p_gap_data = (T_GAPS_CALLBACK_DATA *)p_para;
+ APP_PRINT_INFO2("gap_service_callback conn_id = %d msg_type = %d\n", p_gap_data->conn_id,
+ p_gap_data->msg_type);
+ if (p_gap_data->msg_type == SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE)
+ {
+ switch (p_gap_data->msg_data.opcode)
+ {
+ case GAPS_WRITE_DEVICE_NAME:
+ {
+ T_LOCAL_NAME device_name;
+ memcpy(device_name.local_name, p_gap_data->msg_data.p_value, p_gap_data->msg_data.len);
+ device_name.local_name[p_gap_data->msg_data.len] = 0;
+ flash_save_local_name(&device_name);
+ }
+ break;
+
+ case GAPS_WRITE_APPEARANCE:
+ {
+ uint16_t appearance_val;
+ T_LOCAL_APPEARANCE appearance;
+
+ LE_ARRAY_TO_UINT16(appearance_val, p_gap_data->msg_data.p_value);
+ appearance.local_appearance = appearance_val;
+ flash_save_local_appearance(&appearance);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ return result;
+}
+/** @} */
+#endif
+
+/** @defgroup SCATTERNET_CLIIENT_CALLBACK Profile Client Callback Event Handler
+ * @brief Handle profile client callback event
+ * @{
+ */
+
+/**
+ * @brief Callback will be called when data sent from profile client layer.
+ * @param client_id the ID distinguish which module sent the data.
+ * @param conn_id connection ID.
+ * @param p_data pointer to data.
+ * @retval result @ref T_APP_RESULT
+ */
+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:
+ if (p_client_app_cb_data->cb_content.disc_state_data.disc_state == DISC_STATE_SRV_DONE)
+ {
+ APP_PRINT_INFO0("Discovery All Service Procedure Done.");
+ }
+ else
+ {
+ APP_PRINT_INFO0("Discovery state send to application directly.");
+ }
+ break;
+ case CLIENT_APP_CB_TYPE_DISC_RESULT:
+ if (p_client_app_cb_data->cb_content.disc_result_data.result_type == DISC_RESULT_ALL_SRV_UUID16)
+ {
+ APP_PRINT_INFO3("Discovery All Primary Service: UUID16 0x%x, start handle 0x%x, end handle 0x%x.",
+ p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->uuid16,
+ p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->att_handle,
+ p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->end_group_handle);
+ }
+ else
+ {
+ APP_PRINT_INFO0("Discovery result send to application directly.");
+ }
+ break;
+ default:
+ break;
+ }
+
+ }
+ 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:
+ switch (p_gaps_cb_data->cb_content.disc_state)
+ {
+ case DISC_GAPS_DONE:
+ /* Discovery Simple BLE service procedure successfully done. */
+ APP_PRINT_INFO0("app_client_callback: discover gaps procedure done.");
+ break;
+ case DISC_GAPS_FAILED:
+ /* Discovery Request failed. */
+ APP_PRINT_INFO0("app_client_callback: discover gaps request failed.");
+ break;
+ default:
+ break;
+ }
+ break;
+ case GAPS_CLIENT_CB_TYPE_READ_RESULT:
+ switch (p_gaps_cb_data->cb_content.read_result.type)
+ {
+ case GAPS_READ_DEVICE_NAME:
+ if (p_gaps_cb_data->cb_content.read_result.cause == GAP_SUCCESS)
+ {
+ APP_PRINT_INFO1("GAPS_READ_DEVICE_NAME: device name %s.",
+ TRACE_STRING(p_gaps_cb_data->cb_content.read_result.data.device_name.p_value));
+ }
+ else
+ {
+ APP_PRINT_INFO1("GAPS_READ_DEVICE_NAME: failded cause 0x%x",
+ p_gaps_cb_data->cb_content.read_result.cause);
+ }
+ break;
+ case GAPS_READ_APPEARANCE:
+ if (p_gaps_cb_data->cb_content.read_result.cause == GAP_SUCCESS)
+ {
+ APP_PRINT_INFO1("GAPS_READ_APPEARANCE: appearance %d",
+ p_gaps_cb_data->cb_content.read_result.data.appearance);
+ }
+ else
+ {
+ APP_PRINT_INFO1("GAPS_READ_APPEARANCE: failded cause 0x%x",
+ p_gaps_cb_data->cb_content.read_result.cause);
+ }
+ break;
+ case GAPS_READ_CENTRAL_ADDR_RESOLUTION:
+ if (p_gaps_cb_data->cb_content.read_result.cause == GAP_SUCCESS)
+ {
+ APP_PRINT_INFO1("GAPS_READ_CENTRAL_ADDR_RESOLUTION: central_addr_res %d",
+ p_gaps_cb_data->cb_content.read_result.data.central_addr_res);
+ }
+ else
+ {
+ APP_PRINT_INFO1("GAPS_READ_CENTRAL_ADDR_RESOLUTION: failded cause 0x%x",
+ p_gaps_cb_data->cb_content.read_result.cause);
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ else if (client_id == simple_ble_client_id)
+ {
+ T_SIMP_CLIENT_CB_DATA *p_simp_client_cb_data = (T_SIMP_CLIENT_CB_DATA *)p_data;
+ uint16_t value_size;
+ uint8_t *p_value;
+ switch (p_simp_client_cb_data->cb_type)
+ {
+ case SIMP_CLIENT_CB_TYPE_DISC_STATE:
+ switch (p_simp_client_cb_data->cb_content.disc_state)
+ {
+ case DISC_SIMP_DONE:
+ APP_PRINT_INFO0("app_client_callback: discover simp procedure done.");
+ break;
+ case DISC_SIMP_FAILED:
+ /* Discovery Request failed. */
+ APP_PRINT_INFO0("app_client_callback: discover simp request failed.");
+ break;
+ default:
+ break;
+ }
+ break;
+ case SIMP_CLIENT_CB_TYPE_READ_RESULT:
+ switch (p_simp_client_cb_data->cb_content.read_result.type)
+ {
+ case SIMP_READ_V1_READ:
+ if (p_simp_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS)
+ {
+ value_size = p_simp_client_cb_data->cb_content.read_result.data.v1_read.value_size;
+ p_value = p_simp_client_cb_data->cb_content.read_result.data.v1_read.p_value;
+ APP_PRINT_INFO2("SIMP_READ_V1_READ: value_size %d, value %b",
+ value_size, TRACE_BINARY(value_size, p_value));
+ }
+ else
+ {
+ APP_PRINT_ERROR1("SIMP_READ_V1_READ: failed cause 0x%x",
+ p_simp_client_cb_data->cb_content.read_result.cause);
+ }
+ break;
+ case SIMP_READ_V3_NOTIFY_CCCD:
+ if (p_simp_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS)
+ {
+ APP_PRINT_INFO1("SIMP_READ_V3_NOTIFY_CCCD: notify %d",
+ p_simp_client_cb_data->cb_content.read_result.data.v3_notify_cccd);
+ }
+ else
+ {
+ APP_PRINT_ERROR1("SIMP_READ_V3_NOTIFY_CCCD: failed cause 0x%x",
+ p_simp_client_cb_data->cb_content.read_result.cause);
+ };
+ break;
+ case SIMP_READ_V4_INDICATE_CCCD:
+ if (p_simp_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS)
+ {
+ APP_PRINT_INFO1("SIMP_READ_V4_INDICATE_CCCD: indicate %d",
+ p_simp_client_cb_data->cb_content.read_result.data.v4_indicate_cccd);
+ }
+ else
+ {
+ APP_PRINT_ERROR1("SIMP_READ_V4_INDICATE_CCCD: failed cause 0x%x",
+ p_simp_client_cb_data->cb_content.read_result.cause);
+ };
+ break;
+
+ default:
+ break;
+ }
+ break;
+ case SIMP_CLIENT_CB_TYPE_WRITE_RESULT:
+ switch (p_simp_client_cb_data->cb_content.write_result.type)
+ {
+ case SIMP_WRITE_V2_WRITE:
+ APP_PRINT_INFO1("SIMP_WRITE_V2_WRITE: write result 0x%x",
+ p_simp_client_cb_data->cb_content.write_result.cause);
+ break;
+ case SIMP_WRITE_V3_NOTIFY_CCCD:
+ APP_PRINT_INFO1("SIMP_WRITE_V3_NOTIFY_CCCD: write result 0x%x",
+ p_simp_client_cb_data->cb_content.write_result.cause);
+ break;
+ case SIMP_WRITE_V4_INDICATE_CCCD:
+ APP_PRINT_INFO1("SIMP_WRITE_V4_INDICATE_CCCD: write result 0x%x",
+ p_simp_client_cb_data->cb_content.write_result.cause);
+ break;
+ default:
+ break;
+ }
+ break;
+ case SIMP_CLIENT_CB_TYPE_NOTIF_IND_RESULT:
+ switch (p_simp_client_cb_data->cb_content.notif_ind_data.type)
+ {
+ case SIMP_V3_NOTIFY:
+ value_size = p_simp_client_cb_data->cb_content.notif_ind_data.data.value_size;
+ p_value = p_simp_client_cb_data->cb_content.notif_ind_data.data.p_value;
+ APP_PRINT_INFO2("SIMP_V3_NOTIFY: value_size %d, value %b",
+ value_size, TRACE_BINARY(value_size, p_value));
+ break;
+ case SIMP_V4_INDICATE:
+ value_size = p_simp_client_cb_data->cb_content.notif_ind_data.data.value_size;
+ p_value = p_simp_client_cb_data->cb_content.notif_ind_data.data.p_value;
+ APP_PRINT_INFO2("SIMP_V4_INDICATE: value_size %d, value %b",
+ value_size, TRACE_BINARY(value_size, p_value));
+ break;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ if (client_id == bas_client_id)
+ {
+ T_BAS_CLIENT_CB_DATA *p_bas_cb_data = (T_BAS_CLIENT_CB_DATA *)p_data;
+ switch (p_bas_cb_data->cb_type)
+ {
+ case BAS_CLIENT_CB_TYPE_DISC_STATE:
+ switch (p_bas_cb_data->cb_content.disc_state)
+ {
+ case DISC_BAS_DONE:
+ /* Discovery BAS procedure successfully done. */
+ APP_PRINT_INFO0("app_client_callback: discover bas procedure done");
+ break;
+ case DISC_BAS_FAILED:
+ /* Discovery Request failed. */
+ APP_PRINT_INFO0("app_client_callback: discover bas procedure failed");
+ break;
+ default:
+ break;
+ }
+ break;
+ case BAS_CLIENT_CB_TYPE_READ_RESULT:
+ switch (p_bas_cb_data->cb_content.read_result.type)
+ {
+ case BAS_READ_BATTERY_LEVEL:
+ if (p_bas_cb_data->cb_content.read_result.cause == GAP_SUCCESS)
+ {
+ APP_PRINT_INFO1("BAS_READ_BATTERY_LEVEL: battery level %d",
+ p_bas_cb_data->cb_content.read_result.data.battery_level);
+ }
+ else
+ {
+ APP_PRINT_ERROR1("BAS_READ_BATTERY_LEVEL: failed cause 0x%x",
+ p_bas_cb_data->cb_content.read_result.cause);
+ }
+ break;
+ case BAS_READ_NOTIFY:
+ if (p_bas_cb_data->cb_content.read_result.cause == GAP_SUCCESS)
+ {
+ APP_PRINT_INFO1("BAS_READ_NOTIFY: notify %d",
+ p_bas_cb_data->cb_content.read_result.data.notify);
+ }
+ else
+ {
+ APP_PRINT_ERROR1("BAS_READ_NOTIFY: failed cause 0x%x",
+ p_bas_cb_data->cb_content.read_result.cause);
+ };
+ break;
+
+ default:
+ break;
+ }
+ break;
+ case BAS_CLIENT_CB_TYPE_WRITE_RESULT:
+ switch (p_bas_cb_data->cb_content.write_result.type)
+ {
+ case BAS_WRITE_NOTIFY_ENABLE:
+ APP_PRINT_INFO1("BAS_WRITE_NOTIFY_ENABLE: write result 0x%x",
+ p_bas_cb_data->cb_content.write_result.cause);
+ break;
+ case BAS_WRITE_NOTIFY_DISABLE:
+ APP_PRINT_INFO1("BAS_WRITE_NOTIFY_DISABLE: write result 0x%x",
+ p_bas_cb_data->cb_content.write_result.cause);
+ break;
+ default:
+ break;
+ }
+ break;
+ case BAS_CLIENT_CB_TYPE_NOTIF_IND_RESULT:
+ APP_PRINT_INFO1("BAS_CLIENT_CB_TYPE_NOTIF_IND_RESULT: battery level %d",
+ p_bas_cb_data->cb_content.notify_data.battery_level);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return result;
+}
+/** @} */ /* End of group SCATTERNET_CLIENT_CALLBACK */
+/** @defgroup SCATTERNET_SEVER_CALLBACK Profile Server Callback Event Handler
+ * @brief Handle profile server callback event
+ * @{
+ */
+/**
+ * @brief All the BT Profile service callback events are handled in this function
+ * @note Then the event handling function shall be called according to the
+ * service_id
+ * @param service_id Profile service ID
+ * @param p_data Pointer to callback data
+ * @return T_APP_RESULT, which indicates the function call is successful or not
+ * @retval APP_RESULT_SUCCESS Function run successfully
+ * @retval others Function run failed, and return number indicates the reason
+ */
+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:
+ APP_PRINT_INFO5("PROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d",
+ p_param->event_data.send_data_result.conn_id,
+ p_param->event_data.send_data_result.cause,
+ p_param->event_data.send_data_result.service_id,
+ p_param->event_data.send_data_result.attrib_idx,
+ p_param->event_data.send_data_result.credits);
+ if (p_param->event_data.send_data_result.cause == GAP_SUCCESS)
+ {
+ APP_PRINT_INFO0("PROFILE_EVT_SEND_DATA_COMPLETE success");
+ }
+ else
+ {
+ APP_PRINT_ERROR0("PROFILE_EVT_SEND_DATA_COMPLETE failed");
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ 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:
+ {
+ switch (p_simp_cb_data->msg_data.notification_indification_index)
+ {
+ case SIMP_NOTIFY_INDICATE_V3_ENABLE:
+ {
+ APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_ENABLE");
+ }
+ break;
+
+ case SIMP_NOTIFY_INDICATE_V3_DISABLE:
+ {
+ APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_DISABLE");
+ }
+ break;
+ case SIMP_NOTIFY_INDICATE_V4_ENABLE:
+ {
+ APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_ENABLE");
+ }
+ break;
+ case SIMP_NOTIFY_INDICATE_V4_DISABLE:
+ {
+ APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_DISABLE");
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+
+ case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE:
+ {
+ if (p_simp_cb_data->msg_data.read_value_index == SIMP_READ_V1)
+ {
+ uint8_t value[2] = {0x01, 0x02};
+ APP_PRINT_INFO0("SIMP_READ_V1");
+ simp_ble_service_set_parameter(SIMPLE_BLE_SERVICE_PARAM_V1_READ_CHAR_VAL, 2, &value);
+ }
+ }
+ break;
+ case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE:
+ {
+ switch (p_simp_cb_data->msg_data.write.opcode)
+ {
+ case SIMP_WRITE_V2:
+ {
+ APP_PRINT_INFO2("SIMP_WRITE_V2: write type %d, len %d", p_simp_cb_data->msg_data.write.write_type,
+ p_simp_cb_data->msg_data.write.len);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ 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:
+ {
+ switch (p_bas_cb_data->msg_data.notification_indification_index)
+ {
+ case BAS_NOTIFY_BATTERY_LEVEL_ENABLE:
+ {
+ APP_PRINT_INFO0("BAS_NOTIFY_BATTERY_LEVEL_ENABLE");
+ }
+ break;
+
+ case BAS_NOTIFY_BATTERY_LEVEL_DISABLE:
+ {
+ APP_PRINT_INFO0("BAS_NOTIFY_BATTERY_LEVEL_DISABLE");
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+
+ case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE:
+ {
+ if (p_bas_cb_data->msg_data.read_value_index == BAS_READ_BATTERY_LEVEL)
+ {
+ uint8_t battery_level = 90;
+ APP_PRINT_INFO1("BAS_READ_BATTERY_LEVEL: battery_level %d", battery_level);
+ bas_set_parameter(BAS_PARAM_BATTERY_LEVEL, 1, &battery_level);
+ }
+ }
+ break;
+
+
+ default:
+ break;
+ }
+ }
+
+ return app_result;
+}
+/** @} */ /* End of group SCATTERNET_SEVER_CALLBACK */
+/** @} */ /* End of group SCATTERNET_APP */
+
diff --git a/src/sample/ble_scatternet/scatternet_app.h b/src/sample/ble_scatternet/scatternet_app.h
new file mode 100644
index 0000000..b40363d
--- /dev/null
+++ b/src/sample/ble_scatternet/scatternet_app.h
@@ -0,0 +1,77 @@
+/**
+*****************************************************************************************
+* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved.
+*****************************************************************************************
+ * @file scatternet_app.h
+ * @brief This file handles BLE scatternet application routines.
+ * @author jane
+ * @date 2017-06-06
+ * @version v1.0
+ **************************************************************************************
+ * @attention
+ * <h2><center>&copy; COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2>
+ **************************************************************************************
+ */
+
+#ifndef _SCATTERNET_APP_H_
+#define _SCATTERNET_APP_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*============================================================================*
+ * Header Files
+ *============================================================================*/
+#include <profile_client.h>
+#include <profile_server.h>
+
+/*============================================================================*
+ * Variables
+ *============================================================================*/
+extern T_CLIENT_ID gaps_client_id; /**< Simple ble service client id*/
+extern T_CLIENT_ID simple_ble_client_id; /**< gap service client id*/
+extern T_CLIENT_ID bas_client_id; /**< battery service client id*/
+extern T_SERVER_ID simp_srv_id; /**< Simple ble service id*/
+extern T_SERVER_ID bas_srv_id; /**< Battery service id */
+/*============================================================================*
+ * Functions
+ *============================================================================*/
+
+/**
+ * @brief All the application messages are pre-handled in this function
+ * @note All the IO MSGs are sent to this function, then the event handling
+ * function shall be called according to the MSG type.
+ * @param[in] io_msg IO message data
+ * @return void
+ */
+void app_handle_io_msg(T_IO_MSG io_msg);
+/**
+ * @brief Callback for gap le to notify app
+ * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types.
+ * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA.
+ * @retval result @ref T_APP_RESULT
+ */
+T_APP_RESULT app_gap_callback(uint8_t cb_type, void *p_cb_data);
+
+/**
+ * @brief Callback will be called when data sent from profile client layer.
+ * @param client_id the ID distinguish which module sent the data.
+ * @param conn_id connection ID.
+ * @param p_data pointer to data.
+ * @retval result @ref T_APP_RESULT
+ */
+T_APP_RESULT app_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data);
+T_APP_RESULT app_profile_callback(T_SERVER_ID service_id, void *p_data);
+#if F_BT_AIRPLANE_MODE_SUPPORT
+void app_gap_common_callback(uint8_t cb_type, void *p_cb_data);
+#endif
+#if F_BT_GAPS_CHAR_WRITEABLE
+T_APP_RESULT gap_service_callback(T_SERVER_ID service_id, void *p_para);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/sample/ble_scatternet/user_cmd.c b/src/sample/ble_scatternet/user_cmd.c
new file mode 100644
index 0000000..72fbb81
--- /dev/null
+++ b/src/sample/ble_scatternet/user_cmd.c
@@ -0,0 +1,1968 @@
+/**
+*****************************************************************************************
+* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved.
+*****************************************************************************************
+ * @file user_cmd.c
+ * @brief User defined test commands.
+ * @details User command interfaces.
+ * @author jane
+ * @date 2017-06-06
+ * @version v1.0
+ **************************************************************************************
+ * @attention
+ * <h2><center>&copy; COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2>
+ **************************************************************************************
+ */
+/*============================================================================*
+ * Header Files
+ *============================================================================*/
+#include <string.h>
+#include <trace.h>
+#include <profile_client.h>
+#include <gap_bond_le.h>
+#include <gap_scan.h>
+#include <user_cmd.h>
+#include <gap.h>
+#include <gap_conn_le.h>
+#include <link_mgr.h>
+#include <simple_ble_client.h>
+#include <gaps_client.h>
+#include <bas_client.h>
+#include <gap_adv.h>
+#include <scatternet_app.h>
+#include <simple_ble_service.h>
+#include <bas.h>
+#include <gatt_builtin_services.h>
+
+
+/** @defgroup SCATTERNET_CMD Scatternet User Command
+ * @brief This file handles Scatternet User Command.
+ * @{
+ */
+/*============================================================================*
+ * Variables
+ *============================================================================*/
+/** @brief User command interface data, used to parse the commands from Data UART. */
+T_USER_CMD_IF user_cmd_if;
+
+/*============================================================================*
+ * Functions
+ *============================================================================*/
+/**
+ * @brief Read the RSSI value
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "rssiread",
+ "rssiread [conn_id]\n\r",
+ "Read the RSSI value\n\r",
+ cmd_rssiread
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_rssiread(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t conn_id = p_parse_value->dw_param[0];
+ T_GAP_CAUSE cause;
+ cause = le_read_rssi(conn_id);
+
+ return (T_USER_CMD_PARSE_RESULT)cause;
+}
+
+/**
+ * @brief Show all devices connecting status
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "showcon",
+ "showcon\n\r",
+ "Show all devices connecting status\n\r",
+ cmd_showcon
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_showcon(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t conn_id;
+ T_GAP_CONN_INFO conn_info;
+ for (conn_id = 0; conn_id < APP_MAX_LINKS; conn_id++)
+ {
+ if (le_get_conn_info(conn_id, &conn_info))
+ {
+ data_uart_print("ShowCon conn_id %d state 0x%x role %d\r\n", conn_id,
+ conn_info.conn_state, conn_info.role);
+ data_uart_print("RemoteBd = [%02x:%02x:%02x:%02x:%02x:%02x] type = %d\r\n",
+ conn_info.remote_bd[5], conn_info.remote_bd[4],
+ conn_info.remote_bd[3], conn_info.remote_bd[2],
+ conn_info.remote_bd[1], conn_info.remote_bd[0],
+ conn_info.remote_bd_type);
+ }
+ }
+ data_uart_print("active link num %d, idle link num %d\r\n",
+ le_get_active_link_num(), le_get_idle_link_num());
+ return (RESULT_SUCCESS);
+}
+
+/**
+ * @brief LE connection param update request
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "conupdreq",
+ "conupdreq [conn_id] [interval_min] [interval_max] [latency] [supervision_timeout]\n\r",
+ "LE connection param update request\r\n\
+ sample: conupdreq 0 0x30 0x40 0 500\n\r",
+ cmd_conupdreq
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_conupdreq(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ T_GAP_CAUSE cause;
+ uint8_t conn_id = p_parse_value->dw_param[0];
+ uint16_t conn_interval_min = p_parse_value->dw_param[1];
+ uint16_t conn_interval_max = p_parse_value->dw_param[2];
+ uint16_t conn_latency = p_parse_value->dw_param[3];
+ uint16_t supervision_timeout = p_parse_value->dw_param[4];
+
+
+ cause = le_update_conn_param(conn_id,
+ conn_interval_min,
+ conn_interval_max,
+ conn_latency,
+ supervision_timeout,
+ 2 * (conn_interval_min - 1),
+ 2 * (conn_interval_max - 1)
+ );
+ return (T_USER_CMD_PARSE_RESULT)cause;
+}
+
+/**
+ * @brief Disconnect to remote device
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "disc",
+ "disc [conn_id]\n\r",
+ "Disconnect to remote device\n\r",
+ cmd_disc
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_disc(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t conn_id = p_parse_value->dw_param[0];
+ T_GAP_CAUSE cause;
+ cause = le_disconnect(conn_id);
+ return (T_USER_CMD_PARSE_RESULT)cause;
+}
+
+/**
+ * @brief Using connected device address to modify whitelist
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "wl",
+ "wl [op] [conn_id]\n\r",
+ "Using connected device address to modify whitelist \r\n\
+ [op]: 0-(clear), 1-(add), 2-(remove)\r\n\
+ sample: wl 0 1\n\r",
+ cmd_wl
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_wl(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ T_GAP_CAUSE cause;
+ T_GAP_WHITE_LIST_OP op = (T_GAP_WHITE_LIST_OP)p_parse_value->dw_param[0];
+ uint8_t conn_id = p_parse_value->dw_param[1];
+ T_GAP_CONN_INFO conn_info;
+
+ if (op == GAP_WHITE_LIST_OP_CLEAR)
+ {
+ cause = le_modify_white_list(GAP_WHITE_LIST_OP_CLEAR, NULL, GAP_REMOTE_ADDR_LE_PUBLIC);
+ return (T_USER_CMD_PARSE_RESULT)cause;
+ }
+
+ if (le_get_conn_info(conn_id, &conn_info))
+ {
+ cause = le_modify_white_list(op, conn_info.remote_bd,
+ (T_GAP_REMOTE_ADDR_TYPE)conn_info.remote_bd_type);
+ return (T_USER_CMD_PARSE_RESULT)cause;
+ }
+ else
+ {
+ return RESULT_CMD_ERR_PARAM;
+ }
+}
+/**
+ * @brief Config authentication mode
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "authmode",
+ "authmode [auth_flags] [io_cap] [sec_enable] [oob_enable]\n\r",
+ "Config authentication mode\r\n\
+ [auth_flags]:authentication req bit field: bit0-(bonding), bit2-(MITM), bit3-(SC)\r\n\
+ [io_cap]:set io Capabilities: 0-(display only), 1-(display yes/no), 2-(keyboard noly), 3-(no IO), 4-(keyboard display)\r\n\
+ [sec_enable]:Start smp pairing procedure when connected: 0-(disable), 1-(enable)\r\n\
+ [oob_enable]:Enable oob flag: 0-(disable), 1-(enable)\r\n\
+ sample: authmode 0x5 2 1 0\n\r",
+ cmd_authmode
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_authmode(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ T_GAP_CAUSE cause;
+ uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE;
+ uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG;
+ uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT;
+ uint8_t oob_enable = false;
+ uint8_t auth_sec_req_enable = false;
+ uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG;
+
+ if (p_parse_value->param_count > 0)
+ {
+ auth_flags = p_parse_value->dw_param[0];
+ auth_sec_req_flags = p_parse_value->dw_param[0];
+ }
+ if (p_parse_value->param_count > 1)
+ {
+ auth_io_cap = p_parse_value->dw_param[1];
+ }
+ if (p_parse_value->param_count > 2)
+ {
+ auth_sec_req_enable = p_parse_value->dw_param[2];
+ }
+ if (p_parse_value->param_count > 3)
+ {
+ oob_enable = p_parse_value->dw_param[3];
+ }
+ 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(uint8_t), &oob_enable);
+ le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable);
+ le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags),
+ &auth_sec_req_flags);
+ cause = gap_set_pairable_mode();
+ return (T_USER_CMD_PARSE_RESULT)cause;
+}
+
+/**
+ * @brief Send authentication request
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "sauth",
+ "sauth [conn_id]\n\r",
+ "Send authentication request\n\r",
+ cmd_sauth
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_sauth(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t conn_id = p_parse_value->dw_param[0];
+ T_GAP_CAUSE cause;
+ cause = le_bond_pair(conn_id);
+ return (T_USER_CMD_PARSE_RESULT)cause;
+}
+
+/**
+ * @brief Send user confirmation when show GAP_MSG_LE_BOND_USER_CONFIRMATION
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "userconf",
+ "userconf [conn_id] [conf]\n\r",
+ "Send user confirmation when show GAP_MSG_LE_BOND_USER_CONFIRMATION\r\n\
+ [conf]: 0-(Reject), 1-(Accept)\r\n\
+ sample: userconf 0 1\n\r",
+ cmd_userconf
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_userconf(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t conn_id = p_parse_value->dw_param[0];
+ T_GAP_CFM_CAUSE confirm = GAP_CFM_CAUSE_ACCEPT;
+ T_GAP_CAUSE cause;
+ if (p_parse_value->dw_param[1] == 0)
+ {
+ confirm = GAP_CFM_CAUSE_REJECT;
+ }
+ cause = le_bond_user_confirm(conn_id, confirm);
+ return (T_USER_CMD_PARSE_RESULT)cause;
+}
+
+/**
+ * @brief Input passkey when show GAP_MSG_LE_BOND_PASSKEY_INPUT
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "authkey",
+ "authkey [conn_id] [passkey]\n\r",
+ "Input passkey when show GAP_MSG_LE_BOND_PASSKEY_INPUT\r\n\
+ [passkey]: 0 - 999999\r\n\
+ sample: authkey 0 123456\n\r",
+ cmd_authkey
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_authkey(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t conn_id = p_parse_value->dw_param[0];
+ uint32_t passcode = p_parse_value->dw_param[1];
+ T_GAP_CAUSE cause;
+ T_GAP_CFM_CAUSE confirm = GAP_CFM_CAUSE_ACCEPT;
+ if (passcode > GAP_PASSCODE_MAX)
+ {
+ confirm = GAP_CFM_CAUSE_REJECT;
+ }
+ cause = le_bond_passkey_input_confirm(conn_id, passcode,
+ confirm);
+ return (T_USER_CMD_PARSE_RESULT)cause;
+}
+
+/**
+ * @brief Clear all bonded devices information
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "bondclear",
+ "bondclear\n\r",
+ "Clear all bonded devices information\n\r",
+ cmd_bondclear
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_bondclear(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ le_bond_clear_all_keys();
+ return (RESULT_SUCCESS);
+}
+
+/**
+ * @brief Get all Bonded devices information
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "bondinfo",
+ "bondinfo\n\r",
+ "Get all Bonded devices information\n\r",
+ cmd_bondinfo
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_bondinfo(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t i;
+ T_LE_KEY_ENTRY *p_entry;
+ uint8_t bond_storage_num = le_get_max_le_paired_device_num();
+ for (i = 0; i < bond_storage_num; i++)
+ {
+ p_entry = le_find_key_entry_by_idx(i);
+ if (p_entry != NULL)
+ {
+ data_uart_print("bond_dev[%d]: bd 0x%02x%02x%02x%02x%02x%02x, addr_type %d, flags 0x%x\r\n",
+ p_entry->idx,
+ p_entry->remote_bd.addr[5],
+ p_entry->remote_bd.addr[4],
+ p_entry->remote_bd.addr[3],
+ p_entry->remote_bd.addr[2],
+ p_entry->remote_bd.addr[1],
+ p_entry->remote_bd.addr[0],
+ p_entry->remote_bd.remote_bd_type,
+ p_entry->flags);
+ }
+ }
+
+ return (RESULT_SUCCESS);
+}
+
+#if F_BT_AIRPLANE_MODE_SUPPORT
+/**
+ * @brief Write airplane mode
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "wairplane",
+ "wairplane [mode]\n\r",
+ "Write airplane mode\r\n\
+ [mode]: 0-(normal), 1-(airplane)\n\r",
+ cmd_wairplane
+ },
+ * \endcode
+ */
+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;
+}
+
+/**
+ * @brief Read airplane mode
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "rairplane",
+ "rairplane\n\r",
+ "Read airplane mode\n\r",
+ cmd_rairplane
+ },
+ * \endcode
+ */
+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;
+}
+#endif
+/************************** Central only *************************************/
+/**
+ * @brief Start scan
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "scan",
+ "scan [filter_policy] [filter_duplicate]\n\r",
+ "Start scan\r\n\
+ [filter_policy]: 0-(any), 1-(whitelist), 2-(any RPA), 3-(whitelist RPA) \r\n\
+ [filter_duplicate]: 0-(disable), 1-(enable) \n\r",
+ cmd_scan
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_scan(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ T_GAP_CAUSE cause;
+ uint8_t scan_filter_policy = GAP_SCAN_FILTER_ANY;
+ uint8_t scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE;
+
+ if (p_parse_value->param_count > 0)
+ {
+ scan_filter_policy = p_parse_value->dw_param[0];
+ }
+ if (p_parse_value->param_count > 1)
+ {
+ scan_filter_duplicate = p_parse_value->dw_param[1];
+ }
+
+ link_mgr_clear_device_list();
+ 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);
+ cause = le_scan_start();
+ return (T_USER_CMD_PARSE_RESULT)cause;
+}
+
+/**
+ * @brief Stop scan
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "stopscan",
+ "stopscan\n\r",
+ "Stop scan\n\r",
+ cmd_stopscan
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_stopscan(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ T_GAP_CAUSE cause;
+ cause = le_scan_stop();
+ return (T_USER_CMD_PARSE_RESULT)cause;
+}
+
+/**
+ * @brief Show scan dev list: filter simple ble service
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "showdev",
+ "showdev\n\r",
+ "Show scan dev list: filter simple ble service\n\r",
+ cmd_showdev
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_showdev(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t i;
+ data_uart_print("Advertising and Scan response: filter uuid = 0xA00A dev list\r\n");
+ for (i = 0; i < dev_list_count; i++)
+ {
+ data_uart_print("RemoteBd[%d] = [%02x:%02x:%02x:%02x:%02x:%02x] type = %d\r\n",
+ i,
+ dev_list[i].bd_addr[5], dev_list[i].bd_addr[4],
+ dev_list[i].bd_addr[3], dev_list[i].bd_addr[2],
+ dev_list[i].bd_addr[1], dev_list[i].bd_addr[0],
+ dev_list[i].bd_type);
+ if (dev_list[i].bd_type == GAP_REMOTE_ADDR_LE_RANDOM)
+ {
+ uint8_t addr = dev_list[i].bd_addr[5] & RANDOM_ADDR_MASK;
+ if (addr == RANDOM_ADDR_MASK_STATIC)
+ {
+ data_uart_print("Static Random Addr\r\n");
+ }
+ else if (addr == RANDOM_ADDR_MASK_RESOLVABLE)
+ {
+ data_uart_print("Resolv Random Addr\r\n");
+ }
+ else if (addr == RANDOM_ADDR_MASK_NON_RESOLVABLE)
+ {
+ data_uart_print("Non-resolv Random Addr\r\n");
+ }
+ else
+ {
+ data_uart_print("Unknown Random Addr\r\n");
+ }
+ }
+ }
+
+ return (RESULT_SUCCESS);
+}
+
+/**
+ * @brief Connect to remote device: use address
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "con",
+ "con [BD0] [BD1] [BD2] [BD3] [BD4] [BD5] [addr_type]\n\r",
+ "Connect to remote device: use address\r\n\
+ [BD0] [BD1] [BD2] [BD3] [BD4] [BD5]: remote device address\r\n\
+ [addr_type]: 0-(public), 1-(random)\r\n\
+ sample: con x11 x22 x33 x44 x55 x66 0 \n\r",
+ cmd_con
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_con(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ T_GAP_CAUSE cause;
+ uint8_t addr[6] = {0};
+ uint8_t addr_len;
+ uint8_t addr_type = GAP_REMOTE_ADDR_LE_PUBLIC;
+ T_GAP_LE_CONN_REQ_PARAM conn_req_param;
+#if F_BT_LE_USE_STATIC_RANDOM_ADDR
+ T_GAP_LOCAL_ADDR_TYPE local_addr_type = GAP_LOCAL_ADDR_LE_RANDOM;
+#else
+ T_GAP_LOCAL_ADDR_TYPE local_addr_type = GAP_LOCAL_ADDR_LE_PUBLIC;
+#endif
+ conn_req_param.scan_interval = 0x10;
+ conn_req_param.scan_window = 0x10;
+ conn_req_param.conn_interval_min = 80;
+ conn_req_param.conn_interval_max = 80;
+ conn_req_param.conn_latency = 0;
+ conn_req_param.supv_tout = 1000;
+ conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1);
+ conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1);
+ le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param);
+
+ for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++)
+ {
+ addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1];
+ }
+ if (p_parse_value->param_count >= 7)
+ {
+ addr_type = p_parse_value->dw_param[6];
+ }
+
+ cause = le_connect(GAP_PHYS_CONN_INIT_1M_BIT, addr, (T_GAP_REMOTE_ADDR_TYPE)addr_type,
+ local_addr_type,
+ 1000);
+
+ return (T_USER_CMD_PARSE_RESULT)cause;
+}
+
+/**
+ * @brief Connect to remote device: use showdev to show idx
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "condev",
+ "condev [idx]\n\r",
+ "Connect to remote device: use showdev to show idx\r\n\
+ [idx]: use cmd showdev to show idx before use this cmd\r\n\
+ sample: condev 0\n\r",
+ cmd_condev
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_condev(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t dev_idx = p_parse_value->dw_param[0];
+ if (dev_idx < dev_list_count)
+ {
+ T_GAP_CAUSE cause;
+ T_GAP_LE_CONN_REQ_PARAM conn_req_param;
+#if F_BT_LE_USE_STATIC_RANDOM_ADDR
+ T_GAP_LOCAL_ADDR_TYPE local_addr_type = GAP_LOCAL_ADDR_LE_RANDOM;
+#else
+ T_GAP_LOCAL_ADDR_TYPE local_addr_type = GAP_LOCAL_ADDR_LE_PUBLIC;
+#endif
+
+ conn_req_param.scan_interval = 0x10;
+ conn_req_param.scan_window = 0x10;
+ conn_req_param.conn_interval_min = 80;
+ conn_req_param.conn_interval_max = 80;
+ conn_req_param.conn_latency = 0;
+ conn_req_param.supv_tout = 1000;
+ conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1);
+ conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1);
+ le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param);
+ cause = le_connect(GAP_PHYS_CONN_INIT_1M_BIT,
+ dev_list[dev_idx].bd_addr,
+ (T_GAP_REMOTE_ADDR_TYPE)dev_list[dev_idx].bd_type,
+ local_addr_type,
+ 1000);
+ return (T_USER_CMD_PARSE_RESULT)cause;
+ }
+ else
+ {
+ return RESULT_ERR;
+ }
+}
+
+/**
+ * @brief Set Host Channel Classification
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "chanclassset",
+ "chanclassset [idx0] [idx1] [idx2] [idx3] [idx4]\n\r",
+ "Set Host Channel Classification\r\n\
+ [idx0] [idx1] [idx2] [idx3] [idx4]: channel bit map\r\n\
+ sample: chanclassset xff xff x3f xff x00\n\r",
+ cmd_chanclassset
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_chanclassset(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ T_GAP_CAUSE cause;
+ uint8_t chan_map[5] = {0};
+ uint8_t i;
+ for (i = 0; i < 5; i++)
+ {
+ chan_map[i] = (uint8_t)p_parse_value->dw_param[i];
+ }
+
+ chan_map[4] = chan_map[4] & 0x1F;
+
+ cause = le_set_host_chann_classif(chan_map);
+
+ return (T_USER_CMD_PARSE_RESULT)cause;
+}
+/************************** GATT client *************************************/
+/**
+ * @brief Service discovery, discover all primary services
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "srvdis",
+ "srvdis [conn_id]\n\r",
+ "Service discovery, discover all primary services\n\r",
+ cmd_srvdis
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_srvdis(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t conn_id = p_parse_value->dw_param[0];
+ T_GAP_CAUSE cause;
+
+ cause = client_all_primary_srv_discovery(conn_id, CLIENT_PROFILE_GENERAL_ID);
+ return (T_USER_CMD_PARSE_RESULT)cause;
+}
+
+/**
+ * @brief Start discovery gap service
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "gapdis",
+ "gapdis [conn_id]\n\r",
+ "Start discovery gap service\n\r",
+ cmd_gapdis
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_gapdis(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t conn_id = p_parse_value->dw_param[0];
+ bool ret = gaps_start_discovery(conn_id);
+ if (ret)
+ {
+ return (RESULT_SUCCESS);
+ }
+ else
+ {
+ return (RESULT_ERR);
+ }
+}
+/**
+ * @brief Read GAP service characteristic value
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "gapread",
+ "gapread [conn_id] [type]\n\r",
+ "Read GAP service characteristic value\r\n\
+ [type]: 0-(read device name), 1-(read appearance)\r\n\
+ simple: gapread 0 0\n\r",
+ cmd_gapread
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_gapread(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t conn_id = p_parse_value->dw_param[0];
+ T_GAPS_READ_TYPE read_type = (T_GAPS_READ_TYPE)p_parse_value->dw_param[1];
+ bool ret = gaps_read(conn_id, read_type);
+ if (ret)
+ {
+ return (RESULT_SUCCESS);
+ }
+ else
+ {
+ return (RESULT_ERR);
+ }
+}
+
+/**
+ * @brief List GAP service handle cache
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "gaphdl",
+ "gaphdl [conn_id]\n\r",
+ "List GAP service handle cache\n\r",
+ cmd_gaphdl
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_gaphdl(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t conn_id = p_parse_value->dw_param[0];
+ uint16_t hdl_cache[HDL_GAPS_CACHE_LEN];
+ uint8_t hdl_idx;
+ bool ret = gaps_get_hdl_cache(conn_id, hdl_cache,
+ sizeof(uint16_t) * HDL_GAPS_CACHE_LEN);
+
+ if (ret)
+ {
+ for (hdl_idx = HDL_GAPS_SRV_START; hdl_idx < HDL_GAPS_CACHE_LEN; hdl_idx++)
+ {
+ data_uart_print("-->Index %d -- Handle 0x%x\r\n", hdl_idx, hdl_cache[hdl_idx]);
+ }
+ return (RESULT_SUCCESS);
+ }
+ else
+ {
+ return (RESULT_ERR);
+ }
+}
+
+/**
+ * @brief Start discovery simple ble service
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "simpdis",
+ "simpdis [conn_id]\n\r",
+ "Start discovery simple ble service\n\r",
+ cmd_simpdis
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_simpdis(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t conn_id = p_parse_value->dw_param[0];
+ bool ret = simp_ble_client_start_discovery(conn_id);
+ if (ret)
+ {
+ return (RESULT_SUCCESS);
+ }
+ else
+ {
+ return (RESULT_ERR);
+ }
+}
+/**
+ * @brief Read simple ble service characteristic and descriptor value
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "simpread",
+ "simpread [conn_id] [type] [pattern]\n\r",
+ "Read simple ble service characteristic and descriptor value\r\n\
+ [type]: 0-(read v1), 1-(v3 cccd), 2-(v4 cccd)\r\n\
+ [pattern]: 0-(read by handle), 1-(read by uuid)\r\n\
+ sample: simpread 0 1 0 \n\r",
+ cmd_simpread
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_simpread(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ /* Indicate which char to be read. */
+ uint8_t conn_id = p_parse_value->dw_param[0];
+ bool ret;
+ T_SIMP_READ_TYPE read_type = (T_SIMP_READ_TYPE)p_parse_value->dw_param[1];
+ /* Read by handle or UUID, 1--by UUID, 0--by handle. */
+ uint8_t read_pattern = (uint8_t)p_parse_value->dw_param[2];
+
+ if (read_pattern)
+ {
+ ret = simp_ble_client_read_by_uuid(conn_id, read_type);
+ }
+ else
+ {
+ ret = simp_ble_client_read_by_handle(conn_id, read_type);
+ }
+
+ if (ret)
+ {
+ return (RESULT_SUCCESS);
+ }
+ else
+ {
+ return (RESULT_ERR);
+ }
+}
+
+/**
+ * @brief Config simple ble service client characteristic configuration descriptor value
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "simpcccd",
+ "simpcccd [conn_id] [type] [enable]\n\r",
+ "Config simple ble service client characteristic configuration descriptor value\r\n\
+ [type]: 0-(v3 notify), 1-(v4 indication)\r\n\
+ [enable]: 0-(disable), 1-(enable) \r\n\
+ sample: simpcccd 0 1 1\n\r",
+ cmd_simpcccd
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_simpcccd(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ /* Indicate which char CCCD command. */
+ bool ret = false;
+ uint8_t conn_id = p_parse_value->dw_param[0];
+ uint8_t type = p_parse_value->dw_param[1];
+ /* Enable or disable, 1--enable, 0--disable. */
+ bool cccd_data = (bool)p_parse_value->dw_param[2];
+
+ switch (type)
+ {
+ case 0:/* V3 Notify char notif enable/disable. */
+ ret = simp_ble_client_set_v3_notify(conn_id, cccd_data);
+ break;
+ case 1:/* V4 Indicate char indicate enable/disable. */
+ ret = simp_ble_client_set_v4_ind(conn_id, cccd_data);
+ break;
+ default:
+ break;
+ }
+
+ if (ret)
+ {
+ return (RESULT_SUCCESS);
+ }
+ else
+ {
+ return (RESULT_ERR);
+ }
+}
+
+/**
+ * @brief Write simple ble service V2 characteristic value
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "simpwritev2",
+ "simpwritev2 [conn_id] [type] [len]\n\r",
+ "Write simple ble service V2 characteristic value\r\n\
+ [type]: 1-(write request), 2-(write command) \r\n\
+ [len]: type=1 len range:0-270, type=2 len range: 0-(mtu-3)\r\n\
+ sample: simpwritev2 0 1 10\n\r",
+ cmd_simpwritev2
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_simpwritev2(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t conn_id = p_parse_value->dw_param[0];
+ T_GATT_WRITE_TYPE write_type = (T_GATT_WRITE_TYPE)p_parse_value->dw_param[1];
+ uint8_t data[270];
+ uint16_t length = 270;
+ uint16_t i;
+ for (i = 0; i < 270; i++)
+ {
+ data[i] = i;
+ }
+ if (write_type > GATT_WRITE_TYPE_CMD)
+ {
+ return (RESULT_ERR);
+ }
+ if (p_parse_value->param_count > 2)
+ {
+ length = p_parse_value->dw_param[2];
+ if (length > 270)
+ {
+ length = 270;
+ }
+ }
+ if (simp_ble_client_write_v2_char(conn_id, length, data, write_type))
+ {
+ return (RESULT_SUCCESS);
+ }
+ else
+ {
+ return (RESULT_ERR);
+ }
+}
+
+/**
+ * @brief List simple ble service handle cache
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "simphdl",
+ "simphdl [conn_id]\n\r",
+ "List simple ble service handle cache\n\r",
+ cmd_simphdl
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_simphdl(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t conn_id = p_parse_value->dw_param[0];
+ uint16_t hdl_cache[HDL_SIMBLE_CACHE_LEN];
+ uint8_t hdl_idx;
+ bool ret = simp_ble_client_get_hdl_cache(conn_id, hdl_cache,
+ sizeof(uint16_t) * HDL_SIMBLE_CACHE_LEN);
+
+ if (ret)
+ {
+ for (hdl_idx = HDL_SIMBLE_SRV_START; hdl_idx < HDL_SIMBLE_CACHE_LEN; hdl_idx++)
+ {
+ data_uart_print("-->Index %d -- Handle 0x%x\r\n", hdl_idx, hdl_cache[hdl_idx]);
+ }
+ return (RESULT_SUCCESS);
+ }
+ else
+ {
+ return (RESULT_ERR);
+ }
+}
+/**
+ * @brief Start discovery battery service
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "basdis",
+ "basdis [conn_id]\n\r",
+ "Start discovery battery service\n\r",
+ cmd_basdis
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_basdis(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t conn_id = p_parse_value->dw_param[0];
+ bool ret = bas_start_discovery(conn_id);
+ if (ret)
+ {
+ return (RESULT_SUCCESS);
+ }
+ else
+ {
+ return (RESULT_ERR);
+ }
+}
+/**
+ * @brief Read battery service characteristic and descriptor value
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "basread",
+ "basread [conn_id] [type]\n\r",
+ "Read battery service characteristic and descriptor value\r\n\
+ [type]: 0-(battery level value), 1-(battery cccd)\r\n\
+ sample: basread 0 1 \n\r",
+ cmd_basread
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_basread(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t conn_id = p_parse_value->dw_param[0];
+ bool ret = false;
+ if (p_parse_value->dw_param[1] == 0)
+ {
+ ret = bas_read_battery_level(conn_id);
+ }
+ else if (p_parse_value->dw_param[1] == 1)
+ {
+ ret = bas_read_notify(conn_id);
+ }
+
+ if (ret)
+ {
+ return (RESULT_SUCCESS);
+ }
+ else
+ {
+ return (RESULT_ERR);
+ }
+}
+
+/**
+ * @brief Config battery service client characteristic configuration descriptor value
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "bascccd",
+ "bascccd [conn_id] [notify]\n\r",
+ "Config battery service client characteristic configuration descriptor value\r\n\
+ [notify]: 0-(disable), 1-(enable)\n\r",
+ cmd_bascccd
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_bascccd(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t conn_id = p_parse_value->dw_param[0];
+ bool notify = p_parse_value->dw_param[1];
+ bool ret;
+ ret = bas_set_notify(conn_id, notify);
+
+ if (ret)
+ {
+ return (RESULT_SUCCESS);
+ }
+ else
+ {
+ return (RESULT_ERR);
+ }
+}
+
+/**
+ * @brief List battery service handle cache
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "bashdl",
+ "bashdl [conn_id]\n\r",
+ "List battery service handle cache\n\r",
+ cmd_bashdl
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_bashdl(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t conn_id = p_parse_value->dw_param[0];
+ uint16_t hdl_cache[HDL_BAS_CACHE_LEN];
+ uint8_t hdl_idx;
+ bool ret = bas_get_hdl_cache(conn_id, hdl_cache,
+ sizeof(uint16_t) * HDL_BAS_CACHE_LEN);
+
+ if (ret)
+ {
+ for (hdl_idx = HDL_BAS_SRV_START; hdl_idx < HDL_BAS_CACHE_LEN; hdl_idx++)
+ {
+ data_uart_print("-->Index %d -- Handle 0x%x\r\n", hdl_idx, hdl_cache[hdl_idx]);
+ }
+ return (RESULT_SUCCESS);
+ }
+ else
+ {
+ return (RESULT_ERR);
+ }
+}
+
+/************************** Peripheral Only *************************************/
+/**
+ * @brief Start advertising without setting advertising parameters
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "startadv",
+ "startadv\n\r",
+ "start advertising without setting advertising parameters\n\r",
+ cmd_startadv
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_startadv(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ //advertising parameters
+ T_GAP_CAUSE cause;
+ cause = le_adv_start();
+ return (T_USER_CMD_PARSE_RESULT)cause;
+}
+/**
+ * @brief Stop advertising
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "stopadv",
+ "stopadv\n\r",
+ "Stop advertising\n\r",
+ cmd_stopadv
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_stopadv(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ T_GAP_CAUSE cause;
+ cause = le_adv_stop();
+ return (T_USER_CMD_PARSE_RESULT)cause;
+}
+/**
+ * @brief Start Undirected advertising
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "adv",
+ "adv [adv_interval] [filter_policy]\n\r",
+ "Start Undirected advertising\r\n\
+ [adv_interval]: 0x0020 - 0x4000 (20ms - 10240ms, 0.625ms/step)\r\n\
+ [filter_policy]: 0-(all), 1-(whitelist scan), 2-(whitelist conn), 3-(whitelist all)\r\n\
+ sample: adv x40 0 \n\r",
+ cmd_adv
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_adv(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ T_GAP_CAUSE cause;
+ uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND;
+ uint8_t adv_chann_map = GAP_ADVCHAN_ALL;
+ uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY;
+ uint16_t adv_int_min = 80;
+ uint16_t adv_int_max = 80;
+
+ if (p_parse_value->param_count > 0)
+ {
+ adv_int_min = p_parse_value->dw_param[0];
+ adv_int_max = p_parse_value->dw_param[0];
+ }
+ if (p_parse_value->param_count > 1)
+ {
+ adv_filter_policy = p_parse_value->dw_param[1];
+ }
+
+ le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type);
+ 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);
+
+ cause = le_adv_start();
+ return (T_USER_CMD_PARSE_RESULT)cause;
+}
+/**
+ * @brief Start lower duty directed advertising
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "advld",
+ "advld [BD0] [BD1] [BD2] [BD3] [BD4] [BD5]\n\r",
+ "Start lower duty directed advertising\r\n\
+ [BD0] [BD1] [BD2] [BD3] [BD4] [BD5]: peer address\r\n\
+ sample: advld x11 x22 x33 x44 x55 x66\n\r",
+ cmd_advld
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_advld(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ T_GAP_CAUSE cause;
+ uint8_t adv_evt_type = GAP_ADTYPE_ADV_LDC_DIRECT_IND;
+ uint8_t adv_chann_map = GAP_ADVCHAN_ALL;
+ uint16_t adv_int_min = 300;
+ uint16_t adv_int_max = 320;
+ uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC;
+ uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0};
+ uint8_t addr_len;
+
+ for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++)
+ {
+ adv_direct_addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1];
+ }
+
+ 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_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type);
+ le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map);
+ 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);
+
+ cause = le_adv_start();
+
+ return (T_USER_CMD_PARSE_RESULT)cause;
+}
+/**
+ * @brief Start high duty directed advertising
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "advhd",
+ "advhd [BD0] [BD1] [BD2] [BD3] [BD4] [BD5]\n\r",
+ "Start high duty directed advertising\r\n\
+ [BD0] [BD1] [BD2] [BD3] [BD4] [BD5]: peer address\r\n\
+ sample: advhd x11 x22 x33 x44 x55 x66\n\r",
+ cmd_advhd
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_advhd(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ T_GAP_CAUSE cause;
+ uint8_t adv_evt_type = GAP_ADTYPE_ADV_HDC_DIRECT_IND;
+ uint8_t adv_chann_map = GAP_ADVCHAN_ALL;
+ uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC;
+ uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0};
+ uint8_t addr_len;
+
+ for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++)
+ {
+ adv_direct_addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1];
+ }
+
+ 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_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type);
+ le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map);
+
+ cause = le_adv_start();
+
+ return (T_USER_CMD_PARSE_RESULT)cause;
+}
+/**
+ * @brief Start scannable undirected advertising
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "advscan",
+ "advscan\n\r",
+ "Start scannable undirected advertising\n\r",
+ cmd_advscan
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_advscan(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ T_GAP_CAUSE cause;
+ uint8_t adv_evt_type = GAP_ADTYPE_ADV_SCAN_IND;
+ uint8_t adv_chann_map = GAP_ADVCHAN_ALL;
+ uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY;
+ uint16_t adv_int_min = 300;
+ uint16_t adv_int_max = 320;
+
+ le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type);
+ 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);
+
+ cause = le_adv_start();
+
+ return (T_USER_CMD_PARSE_RESULT)cause;
+}
+/**
+ * @brief Start non_connectable undirected advertising
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "advnonconn",
+ "advnonconn\n\r",
+ "Start non_connectable undirected advertising\n\r",
+ cmd_advnonconn
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_advnonconn(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ T_GAP_CAUSE cause;
+ uint8_t adv_evt_type = GAP_ADTYPE_ADV_NONCONN_IND;
+ uint8_t adv_chann_map = GAP_ADVCHAN_ALL;
+ uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY;
+ uint16_t adv_int_min = 300;
+ uint16_t adv_int_max = 320;
+
+ le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type);
+ 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);
+
+ cause = le_adv_start();
+ return (T_USER_CMD_PARSE_RESULT)cause;
+}
+
+/**
+ * @brief On off slave latency
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "latency",
+ "latency [conn_id] [on_off]\n\r",
+ "On off slave latency\r\n\
+ [on_off]: 0-(turn on the latency), 1-(turn off the latency)\r\n\
+ sample: latency 0 1\n\r",
+ cmd_latency
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_latency(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t conn_id = p_parse_value->dw_param[0];
+ bool disable = p_parse_value->dw_param[1];
+ T_GAP_CAUSE cause;
+
+ cause = le_disable_slave_latency(conn_id, disable);
+ return (T_USER_CMD_PARSE_RESULT)cause;
+}
+/**
+ * @brief Update instant passed channel map
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "epassed",
+ "epassed [enable]\n\r",
+ "Update instant passed channel map\r\n\
+ [enable]: 0 - (disable), 1-(enable)\r\n\
+ sample: epassed 1\n\r",
+ cmd_epassed
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_epassed(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ /* Indicate which char to be written. */
+ bool enable = p_parse_value->dw_param[0];
+ T_GAP_CAUSE cause;
+
+ cause = le_update_passed_chann_map(enable);
+ return (T_USER_CMD_PARSE_RESULT)cause;
+}
+
+/************************** GATT services *************************************/
+/**
+ * @brief Set GAP service Peripheral Preferred Connection Parameters Char value
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "gapprefconn",
+ "gapprefconn [conn_interval_min] [conn_interval_max] [latency] [supervision_timeout]\n\r",
+ "Set GAP service Peripheral Preferred Connection Parameters Char value\r\n\
+ [conn_interval_min]: 0x0006 to 0x0C80(1.25ms/step)\r\n\
+ [conn_interval_max]: 0x0006 to 0x0C80(1.25ms/step)\r\n\
+ [latency]: 0x0000 to 0x01F3\r\n\
+ [supervision_timeout]: 0x000A to 0x0C80(10ms/step)\r\n\
+ sample: gapprefconn x80 x90 0 500 \n\r",
+ cmd_gapprefconn
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_gapprefconn(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint16_t conn_interval_min = p_parse_value->dw_param[0];
+ uint16_t conn_interval_max = p_parse_value->dw_param[1];
+ uint16_t slave_latency = p_parse_value->dw_param[2];
+ uint16_t supervision_timeout = p_parse_value->dw_param[3];
+ gaps_set_peripheral_preferred_conn_param(conn_interval_min, conn_interval_max,
+ slave_latency, supervision_timeout);
+ return (RESULT_SUCCESS);
+}
+/**
+ * @brief Send V3 notification
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "simpv3notify",
+ "simpv3notify [conn_id] [len] \n\r",
+ "Send V3 notification\r\n\
+ [len]: 0 - (mtu-3)\n\r",
+ cmd_simpv3notify
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_simpv3notify(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t conn_id = p_parse_value->dw_param[0];
+ uint8_t notif_val[244];
+ uint16_t length = p_parse_value->dw_param[1];
+ uint16_t i;
+
+ if (length > 244)
+ {
+ return RESULT_ERR;
+ }
+ for (i = 0; i < length; i++)
+ {
+ notif_val[i] = i;
+ }
+
+ if (simp_ble_service_send_v3_notify(conn_id, simp_srv_id,
+ &notif_val,
+ length))
+ {
+ return (RESULT_SUCCESS);
+ }
+ else
+ {
+ return (RESULT_ERR);
+ }
+}
+/**
+ * @brief Send V4 indication
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "simpv4ind",
+ "simpv4ind [conn_id] [len]\n\r",
+ "Send V4 indication\r\n\
+ [len]: 0 - (mtu-3)\n\r",
+ cmd_simpv4ind
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_simpv4ind(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t conn_id = p_parse_value->dw_param[0];
+ uint8_t ind_val[244];
+ uint16_t length = p_parse_value->dw_param[1];
+ uint16_t i;
+
+ if (length > 244)
+ {
+ return RESULT_ERR;
+ }
+ for (i = 0; i < length; i++)
+ {
+ ind_val[i] = i;
+ }
+
+ if (simp_ble_service_send_v4_indicate(conn_id, simp_srv_id,
+ &ind_val,
+ length))
+ {
+ return (RESULT_SUCCESS);
+ }
+ else
+ {
+ return (RESULT_ERR);
+ }
+}
+
+/**
+ * @brief Send battery level notification
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "basnotify",
+ "basnotify [conn_id] [battery_level] \n\r",
+ "Send battery level notification\r\n\
+ [battery_level]: 0 - 100\r\n\
+ sample: basnotify 0 80\n\r",
+ cmd_basnotify
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_basnotify(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t conn_id = p_parse_value->dw_param[0];
+ uint8_t battery_level = p_parse_value->dw_param[1];
+
+ if (bas_battery_level_value_notify(conn_id, bas_srv_id, battery_level))
+ {
+ return (RESULT_SUCCESS);
+ }
+ else
+ {
+ return (RESULT_ERR);
+ }
+}
+#if F_BT_LE_5_0_SET_PHY_SUPPORT
+/**
+ * @brief Set the PHY preferences for the connection
+ *
+ * <b>Command table define</b>
+ * \code{.c}
+ {
+ "setphy",
+ "setphy [conn_id] [type]\n\r",
+ "Set the PHY preferences for the connection\r\n\
+ [type]: 0-(1M), 1-(2M), 2-(CODED-S8), 3-(CODED-S2), 4-(tx 2M, rx 1M) \n\r",
+ cmd_setphy
+ },
+ * \endcode
+ */
+static T_USER_CMD_PARSE_RESULT cmd_setphy(T_USER_CMD_PARSED_VALUE *p_parse_value)
+{
+ uint8_t conn_id = p_parse_value->dw_param[0];
+ uint8_t all_phys;
+ uint8_t tx_phys;
+ uint8_t rx_phys;
+ T_GAP_PHYS_OPTIONS phy_options = GAP_PHYS_OPTIONS_CODED_PREFER_S8;
+ T_GAP_CAUSE cause;
+
+ if (p_parse_value->dw_param[1] == 0)
+ {
+ all_phys = GAP_PHYS_PREFER_ALL;
+ tx_phys = GAP_PHYS_PREFER_1M_BIT;
+ rx_phys = GAP_PHYS_PREFER_1M_BIT;
+ }
+ else if (p_parse_value->dw_param[1] == 1)
+ {
+ all_phys = GAP_PHYS_PREFER_ALL;
+ tx_phys = GAP_PHYS_PREFER_2M_BIT;
+ rx_phys = GAP_PHYS_PREFER_2M_BIT;
+ }
+ else if (p_parse_value->dw_param[1] == 2)
+ {
+ all_phys = GAP_PHYS_PREFER_ALL;
+ tx_phys = GAP_PHYS_PREFER_CODED_BIT;
+ rx_phys = GAP_PHYS_PREFER_CODED_BIT;
+ phy_options = GAP_PHYS_OPTIONS_CODED_PREFER_S8;
+ }
+ else if (p_parse_value->dw_param[1] == 3)
+ {
+ all_phys = GAP_PHYS_PREFER_ALL;
+ tx_phys = GAP_PHYS_PREFER_CODED_BIT;
+ rx_phys = GAP_PHYS_PREFER_CODED_BIT;
+ phy_options = GAP_PHYS_OPTIONS_CODED_PREFER_S2;
+ }
+ else
+ {
+ all_phys = GAP_PHYS_NO_PREFER_TX_BIT;
+ tx_phys = GAP_PHYS_PREFER_2M_BIT;
+ rx_phys = GAP_PHYS_PREFER_1M_BIT;
+ }
+ cause = le_set_phy(conn_id, all_phys, tx_phys, rx_phys, phy_options);
+
+ return (T_USER_CMD_PARSE_RESULT)cause;
+}
+#endif
+
+/*----------------------------------------------------
+ * command table
+ * --------------------------------------------------*/
+const T_USER_CMD_TABLE_ENTRY user_cmd_table[] =
+{
+ /************************** Common cmd *************************************/
+ {
+ "rssiread",
+ "rssiread [conn_id]\n\r",
+ "Read the RSSI value\n\r",
+ cmd_rssiread
+ },
+ {
+ "conupdreq",
+ "conupdreq [conn_id] [interval_min] [interval_max] [latency] [supervision_timeout]\n\r",
+ "LE connection param update request\r\n\
+ sample: conupdreq 0 0x30 0x40 0 500\n\r",
+ cmd_conupdreq
+ },
+ {
+ "showcon",
+ "showcon\n\r",
+ "Show all devices connecting status\n\r",
+ cmd_showcon
+ },
+ {
+ "disc",
+ "disc [conn_id]\n\r",
+ "Disconnect to remote device\n\r",
+ cmd_disc
+ },
+ {
+ "wl",
+ "wl [op] [conn_id]\n\r",
+ "Using connected device address to modify whitelist \r\n\
+ [op]: 0-(clear), 1-(add), 2-(remove)\r\n\
+ sample: wl 0 1\n\r",
+ cmd_wl
+ },
+ {
+ "authmode",
+ "authmode [auth_flags] [io_cap] [sec_enable] [oob_enable]\n\r",
+ "Config authentication mode\r\n\
+ [auth_flags]:authentication req bit field: bit0-(bonding), bit2-(MITM), bit3-(SC)\r\n\
+ [io_cap]:set io Capabilities: 0-(display only), 1-(display yes/no), 2-(keyboard noly), 3-(no IO), 4-(keyboard display)\r\n\
+ [sec_enable]:Start smp pairing procedure when connected: 0-(disable), 1-(enable)\r\n\
+ [oob_enable]:Enable oob flag: 0-(disable), 1-(enable)\r\n\
+ sample: authmode 0x5 2 1 0\n\r",
+ cmd_authmode
+ },
+ {
+ "sauth",
+ "sauth [conn_id]\n\r",
+ "Send authentication request\n\r",
+ cmd_sauth
+ },
+ {
+ "userconf",
+ "userconf [conn_id] [conf]\n\r",
+ "Send user confirmation when show GAP_MSG_LE_BOND_USER_CONFIRMATION\r\n\
+ [conf]: 0-(Reject), 1-(Accept)\r\n\
+ sample: userconf 0 1\n\r",
+ cmd_userconf
+ },
+ {
+ "authkey",
+ "authkey [conn_id] [passkey]\n\r",
+ "Input passkey when show GAP_MSG_LE_BOND_PASSKEY_INPUT\r\n\
+ [passkey]: 0 - 999999\r\n\
+ sample: authkey 0 123456\n\r",
+ cmd_authkey
+ },
+ {
+ "bondinfo",
+ "bondinfo\n\r",
+ "Get all Bonded devices information\n\r",
+ cmd_bondinfo
+ },
+ {
+ "bondclear",
+ "bondclear\n\r",
+ "Clear all bonded devices information\n\r",
+ cmd_bondclear
+ },
+#if F_BT_AIRPLANE_MODE_SUPPORT
+ {
+ "wairplane",
+ "wairplane [mode]\n\r",
+ "Write airplane mode\r\n\
+ [mode]: 0-(normal), 1-(airplane)\n\r",
+ cmd_wairplane
+ },
+ {
+ "rairplane",
+ "rairplane\n\r",
+ "Read airplane mode\n\r",
+ cmd_rairplane
+ },
+#endif
+ /************************** Central only *************************************/
+ {
+ "scan",
+ "scan [filter_policy] [filter_duplicate]\n\r",
+ "Start scan\r\n\
+ [filter_policy]: 0-(any), 1-(whitelist), 2-(any RPA), 3-(whitelist RPA) \r\n\
+ [filter_duplicate]: 0-(disable), 1-(enable) \n\r",
+ cmd_scan
+ },
+ {
+ "stopscan",
+ "stopscan\n\r",
+ "Stop scan\n\r",
+ cmd_stopscan
+ },
+ {
+ "showdev",
+ "showdev\n\r",
+ "Show scan dev list: filter simple ble service\n\r",
+ cmd_showdev
+ },
+ {
+ "con",
+ "con [BD0] [BD1] [BD2] [BD3] [BD4] [BD5] [addr_type]\n\r",
+ "Connect to remote device: use address\r\n\
+ [BD0] [BD1] [BD2] [BD3] [BD4] [BD5]: remote device address\r\n\
+ [addr_type]: 0-(public), 1-(random)\r\n\
+ sample: con x11 x22 x33 x44 x55 x66 0 \n\r",
+ cmd_con
+ },
+ {
+ "condev",
+ "condev [idx]\n\r",
+ "Connect to remote device: use showdev to show idx\r\n\
+ [idx]: use cmd showdev to show idx before use this cmd\r\n\
+ sample: condev 0\n\r",
+ cmd_condev
+ },
+ {
+ "chanclassset",
+ "chanclassset [idx0] [idx1] [idx2] [idx3] [idx4]\n\r",
+ "Set Host Channel Classification\r\n\
+ [idx0] [idx1] [idx2] [idx3] [idx4]: channel bit map\r\n\
+ sample: chanclassset xff xff x3f xff x00\n\r",
+ cmd_chanclassset
+ },
+ /************************** GATT client *************************************/
+ {
+ "srvdis",
+ "srvdis [conn_id]\n\r",
+ "Service discovery, discover all primary services\n\r",
+ cmd_srvdis
+ },
+ /*GAPS client*/
+ {
+ "gapdis",
+ "gapdis [conn_id]\n\r",
+ "Start discovery gap service\n\r",
+ cmd_gapdis
+ },
+ {
+ "gapread",
+ "gapread [conn_id] [type]\n\r",
+ "Read GAP service characteristic value\r\n\
+ [type]: 0-(read device name), 1-(read appearance)\r\n\
+ simple: gapread 0 0\n\r",
+ cmd_gapread
+ },
+ {
+ "gaphdl",
+ "gaphdl [conn_id]\n\r",
+ "List GAP service handle cache\n\r",
+ cmd_gaphdl
+ },
+ /*Simple ble client*/
+ {
+ "simpdis",
+ "simpdis [conn_id]\n\r",
+ "Start discovery simple ble service\n\r",
+ cmd_simpdis
+ },
+ {
+ "simpread",
+ "simpread [conn_id] [type] [pattern]\n\r",
+ "Read simple ble service characteristic and descriptor value\r\n\
+ [type]: 0-(read v1), 1-(v3 cccd), 2-(v4 cccd)\r\n\
+ [pattern]: 0-(read by handle), 1-(read by uuid)\r\n\
+ sample: simpread 0 1 0 \n\r",
+ cmd_simpread
+ },
+ {
+ "simpcccd",
+ "simpcccd [conn_id] [type] [enable]\n\r",
+ "Config simple ble service client characteristic configuration descriptor value\r\n\
+ [type]: 0-(v3 notify), 1-(v4 indication)\r\n\
+ [enable]: 0-(disable), 1-(enable) \r\n\
+ sample: simpcccd 0 1 1\n\r",
+ cmd_simpcccd
+ },
+ {
+ "simpwritev2",
+ "simpwritev2 [conn_id] [type] [len]\n\r",
+ "Write simple ble service V2 characteristic value\r\n\
+ [type]: 1-(write request), 2-(write command) \r\n\
+ [len]: type=1 len range:0-270, type=2 len range: 0-(mtu-3)\r\n\
+ sample: simpwritev2 0 1 10\n\r",
+ cmd_simpwritev2
+ },
+ {
+ "simphdl",
+ "simphdl [conn_id]\n\r",
+ "List simple ble service handle cache\n\r",
+ cmd_simphdl
+ },
+ /*BAS client*/
+ {
+ "basdis",
+ "basdis [conn_id]\n\r",
+ "Start discovery battery service\n\r",
+ cmd_basdis
+ },
+ {
+ "basread",
+ "basread [conn_id] [type]\n\r",
+ "Read battery service characteristic and descriptor value\r\n\
+ [type]: 0-(battery level value), 1-(battery cccd)\r\n\
+ sample: basread 0 1 \n\r",
+ cmd_basread
+ },
+ {
+ "bascccd",
+ "bascccd [conn_id] [notify]\n\r",
+ "Config battery service client characteristic configuration descriptor value\r\n\
+ [notify]: 0-(disable), 1-(enable)\n\r",
+ cmd_bascccd
+ },
+ {
+ "bashdl",
+ "bashdl [conn_id]\n\r",
+ "List battery service handle cache\n\r",
+ cmd_bashdl
+ },
+ /************************** Peripheral Only *************************************/
+ {
+ "startadv",
+ "startadv\n\r",
+ "start advertising without setting advertising parameters\n\r",
+ cmd_startadv
+ },
+ {
+ "stopadv",
+ "stopadv\n\r",
+ "Stop advertising\n\r",
+ cmd_stopadv
+ },
+ {
+ "adv",
+ "adv [adv_interval] [filter_policy]\n\r",
+ "Start Undirected advertising\r\n\
+ [adv_interval]: 0x0020 - 0x4000 (20ms - 10240ms, 0.625ms/step)\r\n\
+ [filter_policy]: 0-(all), 1-(whitelist scan), 2-(whitelist conn), 3-(whitelist all)\r\n\
+ sample: adv x40 0 \n\r",
+ cmd_adv
+ },
+ {
+ "advld",
+ "advld [BD0] [BD1] [BD2] [BD3] [BD4] [BD5]\n\r",
+ "Start lower duty directed advertising\r\n\
+ [BD0] [BD1] [BD2] [BD3] [BD4] [BD5]: peer address\r\n\
+ sample: advld x11 x22 x33 x44 x55 x66\n\r",
+ cmd_advld
+ },
+ {
+ "advhd",
+ "advhd [BD0] [BD1] [BD2] [BD3] [BD4] [BD5]\n\r",
+ "Start high duty directed advertising\r\n\
+ [BD0] [BD1] [BD2] [BD3] [BD4] [BD5]: peer address\r\n\
+ sample: advhd x11 x22 x33 x44 x55 x66\n\r",
+ cmd_advhd
+ },
+ {
+ "advscan",
+ "advscan\n\r",
+ "Start scannable undirected advertising\n\r",
+ cmd_advscan
+ },
+ {
+ "advnonconn",
+ "advnonconn\n\r",
+ "Start non_connectable undirected advertising\n\r",
+ cmd_advnonconn
+ },
+ {
+ "latency",
+ "latency [conn_id] [on_off]\n\r",
+ "On off slave latency\r\n\
+ [on_off]: 0-(turn on the latency), 1-(turn off the latency)\r\n\
+ sample: latency 0 1\n\r",
+ cmd_latency
+ },
+ {
+ "epassed",
+ "epassed [enable]\n\r",
+ "Update instant passed channel map\r\n\
+ [enable]: 0 - (disable), 1-(enable)\r\n\
+ sample: epassed 1\n\r",
+ cmd_epassed
+ },
+ /************************** GATT services *************************************/
+ {
+ "gapprefconn",
+ "gapprefconn [conn_interval_min] [conn_interval_max] [latency] [supervision_timeout]\n\r",
+ "Set GAP service Peripheral Preferred Connection Parameters Char value\r\n\
+ [conn_interval_min]: 0x0006 to 0x0C80(1.25ms/step)\r\n\
+ [conn_interval_max]: 0x0006 to 0x0C80(1.25ms/step)\r\n\
+ [latency]: 0x0000 to 0x01F3\r\n\
+ [supervision_timeout]: 0x000A to 0x0C80(10ms/step)\r\n\
+ sample: gapprefconn x80 x90 0 500 \n\r",
+ cmd_gapprefconn
+ },
+ {
+ "simpv3notify",
+ "simpv3notify [conn_id] [len] \n\r",
+ "Send V3 notification\r\n\
+ [len]: 0 - (mtu-3)\n\r",
+ cmd_simpv3notify
+ },
+ {
+ "simpv4ind",
+ "simpv4ind [conn_id] [len]\n\r",
+ "Send V4 indication\r\n\
+ [len]: 0 - (mtu-3)\n\r",
+ cmd_simpv4ind
+ },
+ {
+ "basnotify",
+ "basnotify [conn_id] [battery_level] \n\r",
+ "Send battery level notification\r\n\
+ [battery_level]: 0 - 100\r\n\
+ sample: basnotify 0 80\n\r",
+ cmd_basnotify
+ },
+#if F_BT_LE_5_0_SET_PHY_SUPPORT
+ {
+ "setphy",
+ "setphy [conn_id] [type]\n\r",
+ "Set the PHY preferences for the connection\r\n\
+ [type]: 0-(1M), 1-(2M), 2-(CODED-S8), 3-(CODED-S2), 4-(tx 2M, rx 1M) \n\r",
+ cmd_setphy
+ },
+#endif
+ /* MUST be at the end: */
+ {
+ 0,
+ 0,
+ 0,
+ 0
+ }
+};
+/** @} */ /* End of group SCATTERNET_CMD */
+
+
diff --git a/src/sample/ble_scatternet/user_cmd.h b/src/sample/ble_scatternet/user_cmd.h
new file mode 100644
index 0000000..c1615aa
--- /dev/null
+++ b/src/sample/ble_scatternet/user_cmd.h
@@ -0,0 +1,31 @@
+/**
+*********************************************************************************************************
+* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved.
+**********************************************************************************************************
+* @file user_cmd.h
+* @brief Define user command.
+* @details
+* @author jane
+* @date 2016-02-18
+* @version v0.1
+*********************************************************************************************************
+*/
+#ifndef _USER_CMD_H_
+#define _USER_CMD_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <data_uart.h>
+#include <user_cmd_parse.h>
+
+extern const T_USER_CMD_TABLE_ENTRY user_cmd_table[];
+extern T_USER_CMD_IF user_cmd_if;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
+