diff options
Diffstat (limited to 'src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/app.c')
-rw-r--r-- | src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/app.c | 608 |
1 files changed, 608 insertions, 0 deletions
diff --git a/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/app.c b/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/app.c new file mode 100644 index 0000000..cbc9143 --- /dev/null +++ b/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/app.c @@ -0,0 +1,608 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file peripheral_app.c + * @brief This file handles BLE peripheral application routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + * <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> + ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include <string.h> + +#include <gap.h> +#include <gap_adv.h> +#include <gap_bond_le.h> +#include <gap_conn_le.h> +#include <gap_msg.h> +#if F_BT_ANCS_CLIENT_SUPPORT +#include <ancs_client.h> +#include "ancs.h" +#endif +#include <bas.h> +#include <simple_ble_service.h> + +#include "trace.h" + +#include "app.h" +#include "io_adc.h" + +/** @defgroup PERIPH_APP Peripheral Application + * @brief This file handles BLE peripheral application routines. + * @{ + */ + +/*============================================================================* + * Variables + *============================================================================*/ +/** @addtogroup PERIPH_SEVER_CALLBACK Profile Server Callback Event Handler + * @brief Handle profile server callback event + * @{ + */ +T_SERVER_ID simp_srv_id; /**< Simple ble service id*/ +T_SERVER_ID bas_srv_id; /**< Battery service id */ +/** @} */ /* End of group PERIPH_SEVER_CALLBACK */ + +/** @defgroup PERIPH_GAP_MSG GAP Message Handler + * @brief Handle GAP Message + * @{ + */ +T_GAP_DEV_STATE gap_dev_state = {0, 0, 0, 0}; /**< GAP device state */ +T_GAP_CONN_STATE gap_conn_state = GAP_CONN_STATE_DISCONNECTED; /**< GAP connection 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; + + switch (msg_type) + { + case IO_MSG_TYPE_BT_STATUS: + { + app_handle_gap_msg(&io_msg); + } + break; +#if F_BT_ANCS_CLIENT_SUPPORT + case IO_MSG_TYPE_ANCS: + { + ancs_handle_msg(&io_msg); + } + break; +#endif + case IO_MSG_TYPE_ADC: + { +// APP_PRINT_INFO0("[app] app_handle_io_msg: adc msg."); + io_handle_adc_msg(&io_msg); + //Add user code here! + } + 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_INFO3("app_handle_dev_state_evt: init state %d, adv state %d, cause 0x%x", + new_state.gap_init_state, new_state.gap_adv_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) + { + APP_PRINT_INFO0("GAP stack ready"); + /*stack ready*/ +// le_adv_start(); + } + } + + 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"); + } + } + else if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) + { + APP_PRINT_INFO0("GAP adv start"); + } + } + + 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) +{ + APP_PRINT_INFO4("app_handle_conn_state_evt: conn_id %d old_state %d new_state %d, disc_cause 0x%x", + conn_id, gap_conn_state, new_state, disc_cause); + 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_ERROR1("app_handle_conn_state_evt: connection lost cause 0x%x", disc_cause); + } + + le_adv_start(); + } + break; + + case GAP_CONN_STATE_CONNECTED: + { + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint8_t remote_bd[6]; + T_GAP_REMOTE_ADDR_TYPE remote_bd_type; + + 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, remote_bd, &remote_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(remote_bd), remote_bd_type, + conn_interval, conn_latency, conn_supervision_timeout); + } + break; + + default: + break; + } + gap_conn_state = new_state; +} + +/** + * @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) + { +#if F_BT_ANCS_CLIENT_SUPPORT + ancs_start_discovery(conn_id); +#endif + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair success"); + + } + else + { + 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_INFO3("app_handle_conn_param_update_evt update success:conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x", + conn_interval, conn_slave_latency, conn_supervision_timeout); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_FAIL: + { + APP_PRINT_ERROR1("app_handle_conn_param_update_evt update failed: cause 0x%x", cause); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_PENDING: + { + APP_PRINT_INFO0("app_handle_conn_param_update_evt update pending."); + } + 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_INFO1("GAP_MSG_LE_BOND_PASSKEY_DISPLAY:passkey %d", display_value); + le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + 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_INFO1("GAP_MSG_LE_BOND_USER_CONFIRMATION: passkey %d", 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_INFO1("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d", 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_INFO0("GAP_MSG_LE_BOND_OOB_INPUT"); + 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 PERIPH_GAP_MSG */ + +/** @defgroup PERIPH_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) + { + 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_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; + + default: + APP_PRINT_ERROR1("app_gap_callback: unhandled cb_type 0x%x", cb_type); + break; + } + return result; +} +/** @} */ /* End of group PERIPH_GAP_CALLBACK */ + +/** @defgroup PERIPH_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 PERIPH_SEVER_CALLBACK */ + +/** @} */ /* End of group PERIPH_APP */ |