|
|
#include "zble_module.h"
#include <stdint.h>
#include <string.h>
#include "ble_bas.h"
#include "znordic.h"
#include "basic/version.h"
#if BLE_DFU_ENABLED
#include "nrf_bootloader_info.h"
#endif
/*******************************************************************************
* �㲥����?? * *******************************************************************************/ #define MIN_CONN_INTERVAL MSEC_TO_UNITS(20, UNIT_1_25_MS) /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */
#define MAX_CONN_INTERVAL MSEC_TO_UNITS(75, UNIT_1_25_MS) /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */
#define SLAVE_LATENCY 0 /**< Slave latency. */
#define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) /**< Connection supervisory timeout (4 seconds), Supervision Timeout uses 10 ms units. */
#define NUS_SERVICE_UUID_TYPE BLE_UUID_TYPE_VENDOR_BEGIN /**< UUID type for the Nordic UART Service (vendor specific). */
#define APP_ADV_INTERVAL 64 /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */
#define APP_ADV_DURATION 18000 /**< The advertising duration (180 seconds) in units of 10 milliseconds. */
BLE_ADVERTISING_DEF(m_advertising); /**< Advertising module instance. */
/*******************************************************************************
* GATT���� * *******************************************************************************/ NRF_BLE_GATT_DEF(m_gatt); /**< GATT module instance. */
/*******************************************************************************
* ���Ӳ������� * *******************************************************************************/ #define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */
#define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000) /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
#define MAX_CONN_PARAMS_UPDATE_COUNT 3 /**< Number of attempts before giving up the connection parameter negotiation. */
/*******************************************************************************
* CODE * *******************************************************************************/
static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< ��ǰ���Ӿ��� */ static uint16_t m_mtu_size = BLE_GATT_ATT_MTU_DEFAULT - 3; static zble_event_listener_t m_event_listener;
static void ble_evt_handler(ble_evt_t const *p_ble_evt, void *p_context) { uint32_t err_code; static zble_event_t zevent; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; zevent.eventType = kzble_event_connected; if (m_event_listener) m_event_listener(&zevent); break;
case BLE_GAP_EVT_DISCONNECTED: m_conn_handle = BLE_CONN_HANDLE_INVALID; zevent.eventType = kzble_event_disconnected; if (m_event_listener) m_event_listener(&zevent); break;
case BLE_GAP_EVT_PHY_UPDATE_REQUEST: { NRF_LOG_DEBUG("PHY update request."); ble_gap_phys_t const phys = { .rx_phys = BLE_GAP_PHY_AUTO, .tx_phys = BLE_GAP_PHY_AUTO, }; err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys); ZERROR_CHECK(err_code); } break;
case BLE_GAP_EVT_SEC_PARAMS_REQUEST: // Pairing not supported
err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); ZERROR_CHECK(err_code); break;
case BLE_GATTS_EVT_SYS_ATTR_MISSING: // No system attributes have been stored.
err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0); ZERROR_CHECK(err_code); break;
case BLE_GATTC_EVT_TIMEOUT: // Disconnect on GATT Client timeout event.
err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); ZERROR_CHECK(err_code); break;
case BLE_GATTS_EVT_TIMEOUT: // Disconnect on GATT Server timeout event.
err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); ZERROR_CHECK(err_code); break;
default: // No implementation needed.
break; } } static void gatt_evt_handler(nrf_ble_gatt_t *p_gatt, nrf_ble_gatt_evt_t const *p_evt) { /*******************************************************************************
* MTU SIZE ���� * *******************************************************************************/ if ((m_conn_handle == p_evt->conn_handle) && (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED)) { m_mtu_size = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH; NRF_LOG_DEBUG("ATT MTU exchange completed. central %d peripheral %d", p_gatt->att_mtu_desired_central, p_gatt->att_mtu_desired_periph); } } static void on_conn_params_evt(ble_conn_params_evt_t *p_evt) { uint32_t err_code; if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED) { err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE); ZERROR_CHECK(err_code); } } static void conn_params_error_handler(uint32_t nrf_error) { APP_ERROR_HANDLER(nrf_error); } static void on_adv_evt(ble_adv_evt_t ble_adv_evt) { switch (ble_adv_evt) { case BLE_ADV_EVT_FAST: // err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
// ZERROR_CHECK(err_code);
break; case BLE_ADV_EVT_IDLE: // sleep_mode_enter();
break; default: break; } }
void zble_module_start_adv() { uint32_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST); ZERROR_CHECK(err_code); } void zble_module_stop_adv() { sd_ble_gap_adv_stop(m_advertising.adv_handle); // ZERROR_CHECK(err_code);
} bool zble_module_is_connected() { return m_conn_handle != BLE_CONN_HANDLE_INVALID; }
/*******************************************************************************
* INIT * *******************************************************************************/ void zble_module_reglistener(zble_event_listener_t event_listener) { m_event_listener = event_listener; }
#if BLE_DFU_ENABLED
/**@brief Handler for shutdown preparation.
* * @details During shutdown procedures, this function will be called at a 1 second interval * untill the function returns true. When the function returns true, it means that the * app is ready to reset to DFU mode. * * @param[in] event Power manager event. * * @retval True if shutdown is allowed by this power manager handler, otherwise false. */ static bool app_shutdown_handler(nrf_pwr_mgmt_evt_t event) { switch (event) { case NRF_PWR_MGMT_EVT_PREPARE_DFU: NRF_LOG_INFO("Power management wants to reset to DFU mode."); // YOUR_JOB: Get ready to reset into DFU mode
//
// If you aren't finished with any ongoing tasks, return "false" to
// signal to the system that reset is impossible at this stage.
//
// Here is an example using a variable to delay resetting the device.
//
// if (!m_ready_for_reset)
// {
// return false;
// }
// else
//{
//
// // Device ready to enter
// uint32_t err_code;
// err_code = sd_softdevice_disable();
// APP_ERROR_CHECK(err_code);
// err_code = app_timer_stop_all();
// APP_ERROR_CHECK(err_code);
//}
break;
default: // YOUR_JOB: Implement any of the other events available from the power management module:
// -NRF_PWR_MGMT_EVT_PREPARE_SYSOFF
// -NRF_PWR_MGMT_EVT_PREPARE_WAKEUP
// -NRF_PWR_MGMT_EVT_PREPARE_RESET
return true; }
NRF_LOG_INFO("Power management allowed to reset to DFU mode."); return true; }
// lint -esym(528, m_app_shutdown_handler)
/**@brief Register application shutdown handler with priority 0.
*/ NRF_PWR_MGMT_HANDLER_REGISTER(app_shutdown_handler, 0);
static void buttonless_dfu_sdh_state_observer(nrf_sdh_state_evt_t state, void *p_context) { if (state == NRF_SDH_EVT_STATE_DISABLED) { // Softdevice was disabled before going into reset. Inform bootloader to skip CRC on next boot.
nrf_power_gpregret2_set(BOOTLOADER_DFU_SKIP_CRC);
// Go to system off.
nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF); } }
/* nrf_sdh state observer. */ NRF_SDH_STATE_OBSERVER(m_buttonless_dfu_state_obs, 0) = { .handler = buttonless_dfu_sdh_state_observer, };
static void advertising_config_get(ble_adv_modes_config_t *p_config) { memset(p_config, 0, sizeof(ble_adv_modes_config_t));
p_config->ble_adv_fast_enabled = true; p_config->ble_adv_fast_interval = APP_ADV_INTERVAL; p_config->ble_adv_fast_timeout = APP_ADV_DURATION; }
static void disconnect(uint16_t conn_handle, void *p_context) { UNUSED_PARAMETER(p_context);
ret_code_t err_code = sd_ble_gap_disconnect(conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); if (err_code != NRF_SUCCESS) { NRF_LOG_WARNING("Failed to disconnect connection. Connection handle: %d Error: %d", conn_handle, err_code); } else { NRF_LOG_DEBUG("Disconnected connection handle %d", conn_handle); } }
// YOUR_JOB: Update this code if you want to do anything given a DFU event (optional).
/**@brief Function for handling dfu events from the Buttonless Secure DFU service
* * @param[in] event Event from the Buttonless Secure DFU service. */ static void ble_dfu_evt_handler(ble_dfu_buttonless_evt_type_t event) { switch (event) { case BLE_DFU_EVT_BOOTLOADER_ENTER_PREPARE: { NRF_LOG_INFO("Device is preparing to enter bootloader mode.");
// Prevent device from advertising on disconnect.
ble_adv_modes_config_t config; advertising_config_get(&config); config.ble_adv_on_disconnect_disabled = true; ble_advertising_modes_config_set(&m_advertising, &config);
// Disconnect all other bonded devices that currently are connected.
// This is required to receive a service changed indication
// on bootup after a successful (or aborted) Device Firmware Update.
uint32_t conn_count = ble_conn_state_for_each_connected(disconnect, NULL); NRF_LOG_INFO("Disconnected %d links.", conn_count); break; }
case BLE_DFU_EVT_BOOTLOADER_ENTER: // YOUR_JOB: Write app-specific unwritten data to FLASH, control finalization of this
// by delaying reset by reporting false in app_shutdown_handler
NRF_LOG_INFO("Device will enter bootloader mode."); break;
case BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED: NRF_LOG_ERROR("Request to enter bootloader mode failed asynchroneously."); // YOUR_JOB: Take corrective measures to resolve the issue
// like calling APP_ERROR_CHECK to reset the device.
break;
case BLE_DFU_EVT_RESPONSE_SEND_ERROR: NRF_LOG_ERROR("Request to send a response to client failed."); // YOUR_JOB: Take corrective measures to resolve the issue
// like calling APP_ERROR_CHECK to reset the device.
APP_ERROR_CHECK(false); break;
default: NRF_LOG_ERROR("Unknown event from ble_dfu_buttonless."); break; } } #endif
// static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifier. */
// {{0x0002, BLE_UUID_TYPE_VENDOR_BEGIN}};
// static ble_uuid_t m_adv_uuids[] = {{BLE_UUID_DEVICE_INFORMATION_SERVICE, BLE_UUID_TYPE_BLE}};
#define COMPANY_IDENTIFIER_DATA_LEGTH 2 /**< Total length of information advertised by the Beacon. */
static uint8_t p_company_identifier_data[COMPANY_IDENTIFIER_DATA_LEGTH] = { (FIRMWARE_VERSION >> 8) & 0xFF, FIRMWARE_VERSION & 0xFF,
};
void zble_module_init(zble_module_cfg_t *cfg) { /**
* @brief * ��ʼ������Э��ջ����ע�������¼������������̶����룬����?? */ { NRF_SDH_BLE_OBSERVER(m_ble_observer, 3, ble_evt_handler, NULL); } /*******************************************************************************
* GAP��ʼ?? * *******************************************************************************/ { uint32_t err_code; ble_gap_conn_params_t gap_conn_params; ble_gap_conn_sec_mode_t sec_mode;
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
err_code = sd_ble_gap_device_name_set(&sec_mode, (const uint8_t *)cfg->deviceName, strlen(cfg->deviceName)); ZERROR_CHECK(err_code);
memset(&gap_conn_params, 0, sizeof(gap_conn_params));
gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL; gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL; gap_conn_params.slave_latency = SLAVE_LATENCY; gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT;
err_code = sd_ble_gap_ppcp_set(&gap_conn_params); ZERROR_CHECK(err_code); }
/*******************************************************************************
* GATT ��ʼ?? * *******************************************************************************/ { ret_code_t err_code;
err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler); ZERROR_CHECK(err_code);
err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE); ZERROR_CHECK(err_code); }
/*******************************************************************************
* �㲥��ʼ?? * *******************************************************************************/ { uint32_t err_code; ble_advertising_init_t init;
memset(&init, 0, sizeof(init)); static ble_advdata_manuf_data_t manuf_specific_data; manuf_specific_data.company_identifier = APP_COMPANY_IDENTIFIER; manuf_specific_data.data.p_data = (uint8_t *)p_company_identifier_data; manuf_specific_data.data.size = COMPANY_IDENTIFIER_DATA_LEGTH;
init.advdata.name_type = BLE_ADVDATA_FULL_NAME; init.advdata.include_appearance = true; init.advdata.p_manuf_specific_data = &manuf_specific_data; // init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;
init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
// init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
// init.srdata.uuids_complete.p_uuids = m_adv_uuids;
err_code = sd_ble_gap_appearance_set(BLE_APPEARANCE_GENERIC_HEART_RATE_SENSOR); APP_ERROR_CHECK(err_code);
init.srdata.uuids_complete.uuid_cnt = 0; init.srdata.uuids_complete.p_uuids = NULL;
init.config.ble_adv_fast_enabled = true; init.config.ble_adv_fast_interval = APP_ADV_INTERVAL; init.config.ble_adv_fast_timeout = 0; init.evt_handler = on_adv_evt;
err_code = ble_advertising_init(&m_advertising, &init); ZERROR_CHECK(err_code);
ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG); }
/*******************************************************************************
* ����������ʼ?? * *******************************************************************************/ #if BLE_DFU_ENABLED
{ ble_dfu_buttonless_init_t dfus_init = {0}; dfus_init.evt_handler = ble_dfu_evt_handler; ret_code_t err_code = ble_dfu_buttonless_init(&dfus_init); ZERROR_CHECK(err_code); if (cfg->on_service_init) cfg->on_service_init(); } #endif
/*******************************************************************************
* ���Ӳ�����ʼ?? * *******************************************************************************/ { uint32_t err_code; ble_conn_params_init_t cp_init;
memset(&cp_init, 0, sizeof(cp_init));
cp_init.p_conn_params = NULL; cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY; cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY; cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT; cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID; cp_init.disconnect_on_fail = false; cp_init.evt_handler = on_conn_params_evt; cp_init.error_handler = conn_params_error_handler;
err_code = ble_conn_params_init(&cp_init); ZERROR_CHECK(err_code); }
// zble_module_start_adv();
}
int32_t zble_module_get_mtu_size() { return m_mtu_size; }
bool zble_module_disconnect(){ ble_conn_state_for_each_connected(disconnect, NULL); return true; }
|