|
|
@ -5,8 +5,11 @@ |
|
|
|
#include <stdint.h> |
|
|
|
#include <string.h> |
|
|
|
|
|
|
|
|
|
|
|
#include "znordic.h" |
|
|
|
|
|
|
|
#ifdef DFU_SUPPORT |
|
|
|
#include "nrf_bootloader_info.h" |
|
|
|
#endif |
|
|
|
/******************************************************************************* |
|
|
|
* ¹ã²¥°üÅä?? * |
|
|
|
*******************************************************************************/ |
|
|
@ -142,6 +145,146 @@ bool zble_module_is_connected() { return m_conn_handle != BLE_CONN_HANDLE_INVALI |
|
|
|
*******************************************************************************/ |
|
|
|
void zble_module_reglistener(zble_event_listener_t event_listener) { m_event_listener = event_listener; } |
|
|
|
|
|
|
|
#ifdef DFU_SUPPORT |
|
|
|
|
|
|
|
/**@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 |
|
|
|
|
|
|
|
void zble_module_init(zble_module_cfg_t* cfg) { |
|
|
|
/** |
|
|
|
* @brief |
|
|
@ -185,12 +328,19 @@ void zble_module_init(zble_module_cfg_t* cfg) { |
|
|
|
ZERROR_CHECK(err_code); |
|
|
|
} |
|
|
|
|
|
|
|
/******************************************************************************* |
|
|
|
* À¶ÑÀ·þÎñ³õʼ?? * |
|
|
|
*******************************************************************************/ |
|
|
|
/******************************************************************************* |
|
|
|
* À¶ÑÀ·þÎñ³õʼ?? * |
|
|
|
*******************************************************************************/ |
|
|
|
#ifdef DFU_SUPPORT |
|
|
|
{ |
|
|
|
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 |
|
|
|
|
|
|
|
/******************************************************************************* |
|
|
|
* ¹ã²¥³õʼ?? * |
|
|
|