/**@brief Function for handling the Device Manager events. * * @param[in] p_evt Data associated to the Device Manager event. */ static uint32_t device_manager_evt_handler(dm_handle_t const * p_handle, dm_event_t const * p_evt, ret_code_t event_result) { uint32_t err_code; APP_ERROR_CHECK(event_result); ble_ancs_c_on_device_manager_evt(&m_ancs_c, p_handle, p_evt); switch (p_evt->event_id) { case DM_EVT_CONNECTION: m_peer_handle = (*p_handle); err_code = app_timer_start(m_sec_req_timer_id, SECURITY_REQUEST_DELAY, NULL); APP_ERROR_CHECK(err_code); break; case DM_EVT_LINK_SECURED: err_code = ble_db_discovery_start(&m_ble_db_discovery, p_evt->event_param.p_gap_param->conn_handle); APP_ERROR_CHECK(err_code); break; default: break; } return NRF_SUCCESS; }
/**@brief Function for handling BLE_GAP_EVT_CONNECTED events. * Save the connection handle and GAP role, then discover the peer DB. */ void on_ble_gap_evt_connected(ble_gap_evt_t const * p_gap_evt) { m_conn_handle = p_gap_evt->conn_handle; m_gap_role = p_gap_evt->params.connected.role; if (m_gap_role == BLE_GAP_ROLE_PERIPH) { NRF_LOG_INFO("Connected as a peripheral.\r\n"); } else if (m_gap_role == BLE_GAP_ROLE_CENTRAL) { NRF_LOG_INFO("Connected as a central.\r\n"); } // Stop scanning and advertising. (void) sd_ble_gap_scan_stop(); (void) sd_ble_gap_adv_stop(); NRF_LOG_INFO("Discovering GATT database...\r\n"); // Zero the database before starting discovery. memset(&m_ble_db_discovery, 0x00, sizeof(m_ble_db_discovery)); ret_code_t err_code; err_code = ble_db_discovery_start(&m_ble_db_discovery, p_gap_evt->conn_handle); APP_ERROR_CHECK(err_code); bsp_board_leds_off(); }
/**@brief Function for handling the Device Manager events. * * @param[in] p_evt Data associated to the Device Manager event. */ static uint32_t device_manager_evt_handler(dm_handle_t const * p_handle, dm_event_t const * p_evt, ret_code_t event_result) { QS_BEGIN(TRACE_DM_EVT, &l_SD) QS_U8(0, p_evt->event_id); QS_END() QS_START_TX(); uint32_t err_code; switch (p_evt->event_id) { case DM_EVT_CONNECTION: m_peer_handle = (*p_handle); err_code = app_timer_start(m_sec_req_timer_id, SECURITY_REQUEST_DELAY, NULL); APP_ERROR_CHECK(err_code); break; case DM_EVT_LINK_SECURED: err_code = ble_db_discovery_start(&m_ble_db_discovery, p_evt->event_param.p_gap_param->conn_handle); APP_ERROR_CHECK(err_code); break; default: break; } return NRF_SUCCESS; }
/**@brief Function for service discovery. * * @param[in] p_client Client context information. */ static void service_discover(client_t * p_client) { uint32_t err_code; p_client->state = STATE_SERVICE_DISC; err_code = ble_db_discovery_start(&(p_client->srv_db), p_client->srv_db.conn_handle); APP_ERROR_CHECK(err_code); }
/**@brief Function for handling the Application's BLE Stack events. * * @param[in] p_ble_evt Bluetooth stack event. */ static void on_ble_evt(ble_evt_t * p_ble_evt) { uint32_t err_code = NRF_SUCCESS; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_DISCONNECTED: NRF_LOG_INFO("Disconnected\r\n"); err_code = bsp_indication_set(BSP_INDICATE_IDLE); APP_ERROR_CHECK(err_code); break; // BLE_GAP_EVT_DISCONNECTED case BLE_GAP_EVT_CONNECTED: NRF_LOG_INFO("Connected\r\n"); err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); APP_ERROR_CHECK(err_code); m_cur_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; err_code = ble_db_discovery_start(&m_ble_db_discovery, m_cur_conn_handle); APP_ERROR_CHECK(err_code); err_code = app_timer_start(m_sec_req_timer_id, SECURITY_REQUEST_DELAY, NULL); APP_ERROR_CHECK(err_code); break; // BLE_GAP_EVT_CONNECTED case BLE_GATTC_EVT_TIMEOUT: // Disconnect on GATT Client timeout event. NRF_LOG_DEBUG("GATT Client Timeout.\r\n"); m_cur_conn_handle = BLE_CONN_HANDLE_INVALID; err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(err_code); break; // BLE_GATTC_EVT_TIMEOUT case BLE_GATTS_EVT_TIMEOUT: // Disconnect on GATT Server timeout event. NRF_LOG_DEBUG("GATT Server Timeout.\r\n"); err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(err_code); break; // BLE_GATTS_EVT_TIMEOUT #if (NRF_SD_BLE_API_VERSION == 3) case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: err_code = sd_ble_gatts_exchange_mtu_reply(p_ble_evt->evt.gatts_evt.conn_handle, NRF_BLE_MAX_MTU_SIZE); APP_ERROR_CHECK(err_code); break; // BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST #endif default: // No implementation needed. break; } }
/**@brief Callback handling device manager events. * * @details This function is called to notify the application of device manager events. * * @param[in] p_handle Device Manager Handle. For link related events, this parameter * identifies the peer. * @param[in] p_event Pointer to the device manager event. * @param[in] event_status Status of the event. */ static ret_code_t device_manager_event_handler(const dm_handle_t * p_handle, const dm_event_t * p_event, const ret_code_t event_result) { uint32_t err_code; switch (p_event->event_id) { case DM_EVT_CONNECTION: { APPL_LOG("[APPL]: >> DM_EVT_CONNECTION\r\n"); #ifdef ENABLE_DEBUG_LOG_SUPPORT ble_gap_addr_t * peer_addr; peer_addr = &p_event->event_param.p_gap_param->params.connected.peer_addr; #endif // ENABLE_DEBUG_LOG_SUPPORT APPL_LOG("[APPL]:[%02X %02X %02X %02X %02X %02X]: Connection Established\r\n", peer_addr->addr[0], peer_addr->addr[1], peer_addr->addr[2], peer_addr->addr[3], peer_addr->addr[4], peer_addr->addr[5]); err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); APP_ERROR_CHECK(err_code); m_conn_handle = p_event->event_param.p_gap_param->conn_handle; m_dm_device_handle = (*p_handle); // Discover peer's services. err_code = ble_db_discovery_start(&m_ble_db_discovery, p_event->event_param.p_gap_param->conn_handle); APP_ERROR_CHECK(err_code); m_peer_count++; if (m_peer_count < MAX_PEER_COUNT) { scan_start(); } APPL_LOG("[APPL]: << DM_EVT_CONNECTION\r\n"); break; } case DM_EVT_DISCONNECTION: { APPL_LOG("[APPL]: >> DM_EVT_DISCONNECTION\r\n"); memset(&m_ble_db_discovery, 0 , sizeof (m_ble_db_discovery)); err_code = bsp_indication_set(BSP_INDICATE_IDLE); APP_ERROR_CHECK(err_code); if (m_peer_count == MAX_PEER_COUNT) { scan_start(); } m_peer_count--; APPL_LOG("[APPL]: << DM_EVT_DISCONNECTION\r\n"); break; } case DM_EVT_SECURITY_SETUP: { APPL_LOG("[APPL]:[0x%02X] >> DM_EVT_SECURITY_SETUP\r\n", p_handle->connection_id); // Slave securtiy request received from peer, if from a non bonded device, // initiate security setup, else, wait for encryption to complete. err_code = dm_security_setup_req(&m_dm_device_handle); APP_ERROR_CHECK(err_code); APPL_LOG("[APPL]:[0x%02X] << DM_EVT_SECURITY_SETUP\r\n", p_handle->connection_id); break; } case DM_EVT_SECURITY_SETUP_COMPLETE: { APPL_LOG("[APPL]: >> DM_EVT_SECURITY_SETUP_COMPLETE\r\n"); // Heart rate service discovered. Enable notification of Heart Rate Measurement. err_code = ble_hrs_c_hrm_notif_enable(&m_ble_hrs_c); APP_ERROR_CHECK(err_code); APPL_LOG("[APPL]: << DM_EVT_SECURITY_SETUP_COMPLETE\r\n"); break; } case DM_EVT_LINK_SECURED: APPL_LOG("[APPL]: >> DM_LINK_SECURED_IND\r\n"); APPL_LOG("[APPL]: << DM_LINK_SECURED_IND\r\n"); break; case DM_EVT_DEVICE_CONTEXT_LOADED: APPL_LOG("[APPL]: >> DM_EVT_LINK_SECURED\r\n"); APP_ERROR_CHECK(event_result); APPL_LOG("[APPL]: << DM_EVT_DEVICE_CONTEXT_LOADED\r\n"); break; case DM_EVT_DEVICE_CONTEXT_STORED: APPL_LOG("[APPL]: >> DM_EVT_DEVICE_CONTEXT_STORED\r\n"); APP_ERROR_CHECK(event_result); APPL_LOG("[APPL]: << DM_EVT_DEVICE_CONTEXT_STORED\r\n"); break; case DM_EVT_DEVICE_CONTEXT_DELETED: APPL_LOG("[APPL]: >> DM_EVT_DEVICE_CONTEXT_DELETED\r\n"); APP_ERROR_CHECK(event_result); APPL_LOG("[APPL]: << DM_EVT_DEVICE_CONTEXT_DELETED\r\n"); break; default: break; } return NRF_SUCCESS; }
/**@brief Function for handling BLE Stack events concerning central applications. * * @details This function keeps the connection handles of central applications up-to-date. It * parses scanning reports, initiating a connection attempt to peripherals when a * target UUID is found, and manages connection parameter update requests. Additionally, * it updates the status of LEDs used to report central applications activity. * * @note Since this function updates connection handles, @ref BLE_GAP_EVT_DISCONNECTED events * should be dispatched to the target application before invoking this function. * * @param[in] p_ble_evt Bluetooth stack event. */ static void on_ble_evt(const ble_evt_t * const p_ble_evt) { // For readability. const ble_gap_evt_t * const p_gap_evt = &p_ble_evt->evt.gap_evt; switch (p_ble_evt->header.evt_id) { // Upon connection, check which peripheral has connected, initiate DB // discovery, update LEDs status and resume scanning if necessary. case BLE_GAP_EVT_CONNECTED: { uint32_t err_code; NRF_LOG_PRINTF("[APP]: link 0x%x established, start discovery on it\r\n", p_gap_evt->conn_handle); APP_ERROR_CHECK_BOOL(p_gap_evt->conn_handle < TOTAL_LINK_COUNT); err_code = ble_lbs_c_handles_assign(&m_ble_lbs_c[p_gap_evt->conn_handle], p_gap_evt->conn_handle, NULL); APP_ERROR_CHECK(err_code); err_code = ble_db_discovery_start(&m_ble_db_discovery[p_gap_evt->conn_handle], p_gap_evt->conn_handle); if (err_code != NRF_ERROR_BUSY) { APP_ERROR_CHECK(err_code); } // Update LEDs status, and check if we should be looking for more // peripherals to connect to. LEDS_ON(CENTRAL_CONNECTED_LED); if (ble_conn_state_n_centrals() == CENTRAL_LINK_COUNT) { LEDS_OFF(CENTRAL_SCANNING_LED); } else { // Resume scanning. LEDS_ON(CENTRAL_SCANNING_LED); scan_start(); } } break; // BLE_GAP_EVT_CONNECTED // Upon disconnection, reset the connection handle of the peer which disconnected, update // the LEDs status and start scanning again. case BLE_GAP_EVT_DISCONNECTED: { uint32_t central_link_cnt; // Number of central links. NRF_LOG_PRINTF("LBS central link 0x%x disconnected (reason: %d)\r\n", p_gap_evt->conn_handle, p_gap_evt->params.disconnected.reason); uint32_t err_code = app_button_disable(); APP_ERROR_CHECK(err_code); // Start scanning scan_start(); // Update LEDs status. LEDS_ON(CENTRAL_SCANNING_LED); central_link_cnt = ble_conn_state_n_centrals(); if (central_link_cnt == 0) { LEDS_OFF(CENTRAL_CONNECTED_LED); } } break; // BLE_GAP_EVT_DISCONNECTED case BLE_GAP_EVT_ADV_REPORT: on_adv_report(p_ble_evt); break; // BLE_GAP_ADV_REPORT case BLE_GAP_EVT_TIMEOUT: { // We have not specified a timeout for scanning, so only connection attemps can timeout. if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN) { APPL_LOG("[APPL]: Connection Request timed out.\r\n"); } } break; // BLE_GAP_EVT_TIMEOUT case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: { // Accept parameters requested by peer. ret_code_t err_code; err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle, &p_gap_evt->params.conn_param_update_request.conn_params); APP_ERROR_CHECK(err_code); } break; // BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST default: // No implementation needed. break; } }
/**@brief Function for handling BLE Stack events concerning central applications. * * @details This function keeps the connection handles of central applications up-to-date. It * parses scanning reports, initiating a connection attempt to peripherals when a target UUID * is found, and manages connection parameter update requests. Additionally, it updates the status * of LEDs used to report central applications activity. * * @note Since this function updates connection handles, @ref BLE_GAP_EVT_DISCONNECTED events * should be dispatched to the target application before invoking this function. * * @param[in] p_ble_evt Bluetooth stack event. */ static void on_ble_central_evt(const ble_evt_t * const p_ble_evt) { const ble_gap_evt_t * const p_gap_evt = &p_ble_evt->evt.gap_evt; switch (p_ble_evt->header.evt_id) { /** Upon connection, check which peripheral has connected (HR or RSC), initiate DB * discovery, update LEDs status and resume scanning if necessary. */ case BLE_GAP_EVT_CONNECTED: { uint32_t err_code; /** If no Heart Rate sensor or RSC sensor is currently connected, try to find them on this peripheral*/ if (m_conn_handle_hrs_c == BLE_CONN_HANDLE_INVALID) { NRF_LOG_PRINTF("try to find HRS or RSC on conn_handle 0x%x\r\n", p_gap_evt->conn_handle); APP_ERROR_CHECK_BOOL(p_gap_evt->conn_handle < CENTRAL_LINK_COUNT + PERIPHERAL_LINK_COUNT); err_code = ble_db_discovery_start(&m_ble_db_discovery[p_gap_evt->conn_handle], p_gap_evt->conn_handle); APP_ERROR_CHECK(err_code); } /** Update LEDs status, and check if we should be looking for more * peripherals to connect to. */ LEDS_ON(CENTRAL_CONNECTED_LED); if (ble_conn_state_n_centrals() == CENTRAL_LINK_COUNT) { LEDS_OFF(CENTRAL_SCANNING_LED); } else { // Resume scanning. LEDS_ON(CENTRAL_SCANNING_LED); scan_start(); } } break; // BLE_GAP_EVT_CONNECTED /** Upon disconnection, reset the connection handle of the peer which disconnected, update * the LEDs status and start scanning again. */ case BLE_GAP_EVT_DISCONNECTED: { uint8_t n_centrals; if (p_gap_evt->conn_handle == m_conn_handle_hrs_c) { NRF_LOG_PRINTF("HRS central disconnected (reason: %d)\r\n", p_gap_evt->params.disconnected.reason); m_conn_handle_hrs_c = BLE_CONN_HANDLE_INVALID; } if (m_conn_handle_hrs_c == BLE_CONN_HANDLE_INVALID) { // Start scanning scan_start(); // Update LEDs status. LEDS_ON(CENTRAL_SCANNING_LED); } n_centrals = ble_conn_state_n_centrals(); if (n_centrals == 0) { LEDS_OFF(CENTRAL_CONNECTED_LED); } } break; // BLE_GAP_EVT_DISCONNECTED case BLE_GAP_EVT_ADV_REPORT: { uint32_t err_code; if (strlen(m_target_periph_name) != 0) { if (find_adv_name(&p_gap_evt->params.adv_report, m_target_periph_name)) { // Initiate connection. err_code = sd_ble_gap_connect(&p_gap_evt->params.adv_report.peer_addr, &m_scan_param, &m_connection_param); if (err_code != NRF_SUCCESS) { APPL_LOG("[APPL]: Connection Request Failed, reason %d\r\n", err_code); } } } else { /** We do not want to connect to two peripherals offering the same service, so when * a UUID is matched, we check that we are not already connected to a peer which * offers the same service. */ if (find_adv_uuid(&p_gap_evt->params.adv_report, BLE_UUID_HEART_RATE_SERVICE)&& (m_conn_handle_hrs_c == BLE_CONN_HANDLE_INVALID)) { // Initiate connection. err_code = sd_ble_gap_connect(&p_gap_evt->params.adv_report.peer_addr, &m_scan_param, &m_connection_param); if (err_code != NRF_SUCCESS) { APPL_LOG("[APPL]: Connection Request Failed, reason %d\r\n", err_code); } } } } break; // BLE_GAP_ADV_REPORT case BLE_GAP_EVT_TIMEOUT: { // We have not specified a timeout for scanning, so only connection attemps can timeout. if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN) { APPL_LOG("[APPL]: Connection Request timed out.\r\n"); } } break; // BLE_GAP_EVT_TIMEOUT case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: { // Accept parameters requested by peer. ret_code_t err_code; err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle, &p_gap_evt->params.conn_param_update_request.conn_params); APP_ERROR_CHECK(err_code); } break; // BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST default: // No implementation needed. break; } }
/* Function for handling the Application's BLE Stack events. Parameters: p_ble_evt Bluetooth stack event. */ static void on_ble_evt(ble_evt_t * p_ble_evt) { uint32_t err_code; uint8_t index = 0; const ble_gap_evt_t * p_gap_evt = &p_ble_evt->evt.gap_evt; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_ADV_REPORT: { const ble_gap_evt_adv_report_t *p_adv_report = &p_gap_evt->params.adv_report; index = get_devices_list_id(p_adv_report->peer_addr); /* id device has been already found or list is full */ if( index != 0xFF) { /* device already found */ /* new adv update */ target_name_if_present(p_adv_report, found_devices[index].name, &found_devices[index].name_length); } else { /* if UUID is present */ if (is_uuid_present(&m_nus_uuid, p_adv_report)) { /* get last free index */ index = devices_list_index; /* increment last free index */ devices_list_index++; /* insert the new device into the list: copy address */ strncpy((char *)(found_devices[index].gap_addr.addr), (char *)(p_adv_report->peer_addr.addr), (size_t)6); /* copy address type */ found_devices[index].gap_addr.addr_type = p_adv_report->peer_addr.addr_type; } } break; } case BLE_GAP_EVT_CONNECTED: { /* if pending connection index of central role is valid */ if(pending_nus_conn_index < NUM_OF_CONNECTIONS) { /* store related connection handle */ active_conn_handles[pending_nus_conn_index] = p_ble_evt->evt.gap_evt.conn_handle; /* set current handle as this one */ m_ble_nus_c.conn_handle = p_ble_evt->evt.gap_evt.conn_handle; /* reset pending NUS connection index */ pending_nus_conn_index = 0xFF; /* reset uart */ uart_reset(); /* set "connection" pin as connected */ nrf_gpio_pin_write(CONN_PIN_NUMBER, CONNECTED_PIN_STATE); /* send confirmation string */ uart_send_string((uint8_t *)"OK.", 3); /* start discovery of services. The NUS Client waits for a discovery result */ err_code = ble_db_discovery_start(&m_ble_db_discovery, p_ble_evt->evt.gap_evt.conn_handle); APP_ERROR_CHECK(err_code); } else { /* internal error: do nothing */ } break; } case BLE_GAP_EVT_DISCONNECTED: { /* it should not pass here */ break; } case BLE_GAP_EVT_TIMEOUT: { if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_SCAN) { /* scan timed out */ uart_send_string((uint8_t *)"TIMEOUT.", 8); } else if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN) { /* connection request timed out: do nothing */ } else { /* do nothing */ } break; } case BLE_GAP_EVT_SEC_PARAMS_REQUEST: { /* ATTENTION: Pairing not supported at the moment */ err_code = sd_ble_gap_sec_params_reply(p_ble_evt->evt.gap_evt.conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); APP_ERROR_CHECK(err_code); break; } case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: { /* Accepting parameters requested by peer. */ err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle, &p_gap_evt->params.conn_param_update_request.conn_params); APP_ERROR_CHECK(err_code); break; } default: break; } }
/**@brief Function for handling BLE Stack events concerning central applications. * * @details This function keeps the connection handles of central applications up-to-date. It * parses scanning reports, initiating a connection attempt to peripherals when a target UUID * is found, and manages connection parameter update requests. Additionally, it updates the status * of LEDs used to report central applications activity. * * @note Since this function updates connection handles, @ref BLE_GAP_EVT_DISCONNECTED events * should be dispatched to the target application before invoking this function. * * @param[in] p_ble_evt Bluetooth stack event. */ static void on_ble_central_evt(const ble_evt_t * const p_ble_evt) { // The addresses of peers we attempted to connect to. static ble_gap_addr_t periph_addr_hrs; static ble_gap_addr_t periph_addr_rsc; // For readability. const ble_gap_evt_t * const p_gap_evt = &p_ble_evt->evt.gap_evt; switch (p_ble_evt->header.evt_id) { /** Upon connection, check which peripheral has connected (HR or RSC), initiate DB * discovery, update LEDs status and resume scanning if necessary. */ case BLE_GAP_EVT_CONNECTED: { uint32_t err_code; // For readability. const ble_gap_addr_t * const peer_addr = &p_gap_evt->params.connected.peer_addr; /** Check which peer has connected, save the connection handle and initiate DB discovery. * DB discovery will invoke a callback (hrs_c_evt_handler and rscs_c_evt_handler) * upon completion, which is used to enable notifications from the peer. */ if(memcmp(&periph_addr_hrs, peer_addr, sizeof(ble_gap_addr_t)) == 0) { NRF_LOG_PRINTF("HRS central connected\r\n"); // Reset the peer address we had saved. memset(&periph_addr_hrs, 0, sizeof(ble_gap_addr_t)); m_conn_handle_hrs_c = p_gap_evt->conn_handle; NRF_LOG_PRINTF("Starting DB discovery for HRS\r\n"); err_code = ble_db_discovery_start(&m_ble_db_discovery_hrs, p_gap_evt->conn_handle); APP_ERROR_CHECK(err_code); } else if(memcmp(&periph_addr_rsc, peer_addr, sizeof(ble_gap_addr_t)) == 0) { NRF_LOG_PRINTF("RSC central connected\r\n"); // Reset the peer address we had saved. memset(&periph_addr_rsc, 0, sizeof(ble_gap_addr_t)); m_conn_handle_rscs_c = p_gap_evt->conn_handle; NRF_LOG_PRINTF("Starting DB discovery for RSCS\r\n"); err_code = ble_db_discovery_start(&m_ble_db_discovery_rsc, p_gap_evt->conn_handle); APP_ERROR_CHECK(err_code); } /** Update LEDs status, and check if we should be looking for more * peripherals to connect to. */ LEDS_ON(CENTRAL_CONNECTED_LED); if (ble_conn_state_n_centrals() == MAX_CONNECTED_CENTRALS) { LEDS_OFF(CENTRAL_SCANNING_LED); } else { // Resume scanning. LEDS_ON(CENTRAL_SCANNING_LED); scan_start(); } } break; // BLE_GAP_EVT_CONNECTED /** Upon disconnection, reset the connection handle of the peer which disconnected, update * the LEDs status and start scanning again. */ case BLE_GAP_EVT_DISCONNECTED: { uint8_t n_centrals; if (p_gap_evt->conn_handle == m_conn_handle_hrs_c) { NRF_LOG_PRINTF("HRS central disconnected (reason: %d)\r\n", p_gap_evt->params.disconnected.reason); m_conn_handle_hrs_c = BLE_CONN_HANDLE_INVALID; } else if(p_gap_evt->conn_handle == m_conn_handle_rscs_c) { NRF_LOG_PRINTF("RSC central disconnected (reason: %d)\r\n", p_gap_evt->params.disconnected.reason); m_conn_handle_rscs_c = BLE_CONN_HANDLE_INVALID; } // Start scanning // scan_start(); // Update LEDs status. LEDS_ON(CENTRAL_SCANNING_LED); n_centrals = ble_conn_state_n_centrals(); if (n_centrals == 0) { LEDS_OFF(CENTRAL_CONNECTED_LED); } } break; // BLE_GAP_EVT_DISCONNECTED case BLE_GAP_EVT_ADV_REPORT: { uint32_t err_code; data_t adv_data; data_t type_data; // For readibility. const ble_gap_addr_t * const peer_addr = &p_gap_evt->params.adv_report.peer_addr; // Initialize advertisement report for parsing. adv_data.p_data = (uint8_t *)p_gap_evt->params.adv_report.data; adv_data.data_len = p_gap_evt->params.adv_report.dlen; err_code = adv_report_parse(BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE, &adv_data, &type_data); if (err_code != NRF_SUCCESS) { // Look for the services in 'complete' if it was not found in 'more available'. err_code = adv_report_parse(BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE, &adv_data, &type_data); if (err_code != NRF_SUCCESS) { // If we can't parse the data, then exit. break; } } // Verify if any UUID match the Heart rate or Running speed and cadence services. for (uint32_t u_index = 0; u_index < (type_data.data_len / UUID16_SIZE); u_index++) { bool do_connect = false; uint16_t extracted_uuid; UUID16_EXTRACT(&extracted_uuid, &type_data.p_data[u_index * UUID16_SIZE]); /** We do not want to connect to two peripherals offering the same service, so when * a UUID is matched, we check that we are not already connected to a peer which * offers the same service. We then save the peer address, so that upon connection * we can tell which peer has connected and update its respective connection * handle. */ if ((extracted_uuid == BLE_UUID_HEART_RATE_SERVICE) && (m_conn_handle_hrs_c == BLE_CONN_HANDLE_INVALID)) { do_connect = true; memcpy(&periph_addr_hrs, peer_addr, sizeof(ble_gap_addr_t)); } else if ((extracted_uuid == BLE_UUID_RUNNING_SPEED_AND_CADENCE) && (m_conn_handle_rscs_c == BLE_CONN_HANDLE_INVALID)) { do_connect = true; memcpy(&periph_addr_rsc, peer_addr, sizeof(ble_gap_addr_t)); } if (do_connect) { // Initiate connection. err_code = sd_ble_gap_connect(peer_addr, &m_scan_param, &m_connection_param); if (err_code != NRF_SUCCESS) { APPL_LOG("[APPL]: Connection Request Failed, reason %d\r\n", err_code); } } } } break; // BLE_GAP_ADV_REPORT case BLE_GAP_EVT_TIMEOUT: { // We have not specified a timeout for scanning, so only connection attemps can timeout. if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN) { APPL_LOG("[APPL]: Connection Request timed out.\r\n"); } } break; // BLE_GAP_EVT_TIMEOUT case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: { // Accept parameters requested by peer. ret_code_t err_code; err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle, &p_gap_evt->params.conn_param_update_request.conn_params); APP_ERROR_CHECK(err_code); } break; // BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST default: // No implementation needed. break; } }
/**@brief Callback handling device manager events. * * @details This function is called to notify the application of device manager events. * * @param[in] p_handle Device Manager Handle. For link related events, this parameter * identifies the peer. * @param[in] p_event Pointer to the device manager event. * @param[in] event_status Status of the event. */ static ret_code_t device_manager_event_handler(const dm_handle_t * p_handle, const dm_event_t * p_event, const ret_code_t event_result) { uint32_t err_code; switch(p_event->event_id) { case DM_EVT_CONNECTION: { nrf_gpio_pin_set(CONNECTED_LED_PIN_NO); printf("Connected \r\n"); m_dm_device_handle = (*p_handle); // Discover peer's services. err_code = ble_db_discovery_start(&m_ble_db_discovery, p_event->event_param.p_gap_param->conn_handle); APP_ERROR_CHECK(err_code); m_peer_count++; if (m_peer_count < MAX_PEER_COUNT) { scan_start(); } break; } case DM_EVT_DISCONNECTION: { memset(&m_ble_db_discovery, 0 , sizeof (m_ble_db_discovery)); nrf_gpio_pin_clear(CONNECTED_LED_PIN_NO); if (m_peer_count == MAX_PEER_COUNT) { scan_start(); } m_peer_count--; break; } case DM_EVT_SECURITY_SETUP: { // Slave securtiy request received from peer, if from a non bonded device, // initiate security setup, else, wait for encryption to complete. err_code = dm_security_setup_req(&m_dm_device_handle); APP_ERROR_CHECK(err_code); break; } case DM_EVT_SECURITY_SETUP_COMPLETE: { // Nordic UART service discovered. Enable notification of RX channel. err_code = ble_uart_c_rx_notif_enable(&m_ble_uart_c); APP_ERROR_CHECK(err_code); break; } case DM_EVT_LINK_SECURED: break; case DM_EVT_DEVICE_CONTEXT_LOADED: APP_ERROR_CHECK(event_result); break; case DM_EVT_DEVICE_CONTEXT_STORED: APP_ERROR_CHECK(event_result); break; case DM_EVT_DEVICE_CONTEXT_DELETED: APP_ERROR_CHECK(event_result); break; default: break; } return NRF_SUCCESS; }
/**@brief Function for handling the Application's BLE Stack events. * * @param[in] p_ble_evt Bluetooth stack event. */ static void on_ble_evt(ble_evt_t * p_ble_evt) { uint32_t err_code = NRF_SUCCESS; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_DISCONNECTED: err_code = bsp_indication_set(BSP_INDICATE_IDLE); APP_ERROR_CHECK(err_code); break;//BLE_GAP_EVT_DISCONNECTED case BLE_GAP_EVT_CONNECTED: err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); APP_ERROR_CHECK(err_code); err_code = ble_db_discovery_start(&m_ble_db_discovery, p_ble_evt->evt.gap_evt.conn_handle); APP_ERROR_CHECK(err_code); break;//BLE_GAP_EVT_CONNECTED case BLE_GATTC_EVT_TIMEOUT: /* fall through */ case BLE_GATTS_EVT_TIMEOUT: // Disconnect on GATT Server and Client timeout events. err_code = sd_ble_gap_disconnect(m_ans_c.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(err_code); break;//BLE_GATTC_EVT_TIMEOUT and BLE_GATTS_EVT_TIMEOUT case BLE_EVT_USER_MEM_REQUEST: err_code = sd_ble_user_mem_reply(m_ans_c.conn_handle, NULL); APP_ERROR_CHECK(err_code); break;//BLE_EVT_USER_MEM_REQUEST case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: { ble_gatts_rw_authorize_reply_params_t auth_reply; if(p_ble_evt->evt.gatts_evt.params.authorize_request.type != BLE_GATTS_AUTHORIZE_TYPE_INVALID) { if ((p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op == BLE_GATTS_OP_PREP_WRITE_REQ) || (p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_NOW) || (p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)) { if (p_ble_evt->evt.gatts_evt.params.authorize_request.type == BLE_GATTS_AUTHORIZE_TYPE_WRITE) { auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; } else { auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_READ; } auth_reply.params.write.gatt_status = APP_FEATURE_NOT_SUPPORTED; err_code = sd_ble_gatts_rw_authorize_reply(m_ans_c.conn_handle,&auth_reply); APP_ERROR_CHECK(err_code); } } }break;//BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST default: // No implementation needed. break; } }