/**@brief Function for handling the response on service discovery. * * @details This function will validate the response. * Invalid response - Handle discovery failure. * Valid response - Initiate Characteristic Discovery Procedure. */ static void event_discover_rsp(ble_ans_c_t * p_ans, const ble_evt_t * p_ble_evt) { if (p_ble_evt->evt.gattc_evt.gatt_status != BLE_GATT_STATUS_SUCCESS) { // We have received an unexpected result. // As we are in a connected state, but can not continue // our service discovery, we will go to running state. handle_discovery_failure(p_ans, p_ble_evt->evt.gattc_evt.gatt_status); } else { BLE_UUID_COPY_INST(m_service.service.uuid, p_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp.services[0].uuid); if (p_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp.count > 0) { const ble_gattc_service_t * p_service; p_service = &(p_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp.services[0]); m_service.service.handle_range.start_handle = p_service->handle_range.start_handle; m_service.service.handle_range.end_handle = p_service->handle_range.end_handle; characteristic_disc_req_send(p_ans, &(m_service.service.handle_range)); } else { // If we receive an answer, but it contains no service, we just go to state: Running. handle_discovery_failure(p_ans, p_ble_evt->evt.gattc_evt.gatt_status); } } }
/**@brief Function for handling of descriptor discovery responses. * * @details This function will validate and store the descriptor received. * If not all descriptors are discovered it will continue the descriptor discovery * procedure, otherwise it will continue to running state. * If we receive a GATT Client error, we will go to handling of discovery failure. */ static void event_descriptor_rsp(ble_ans_c_t * p_ans, const ble_evt_t * p_ble_evt) { if (p_ble_evt->evt.gattc_evt.gatt_status == BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND || p_ble_evt->evt.gattc_evt.gatt_status == BLE_GATT_STATUS_ATTERR_INVALID_HANDLE) { handle_discovery_failure(p_ans, NRF_ERROR_NOT_FOUND); } else if (p_ble_evt->evt.gattc_evt.gatt_status) { // We have received an unexpected result. // As we are in a connected state, but can not continue // our descriptor discovery, we will go to running state. handle_discovery_failure(p_ans, p_ble_evt->evt.gattc_evt.gatt_status); } else { if (p_ble_evt->evt.gattc_evt.params.desc_disc_rsp.count > 0) { descriptor_set(&m_service, &(p_ble_evt->evt.gattc_evt.params.desc_disc_rsp.descs[0])); } if (m_service.new_alert.handle_cccd == BLE_ANS_INVALID_HANDLE || m_service.unread_alert_status.handle_cccd == BLE_ANS_INVALID_HANDLE) { descriptor_disc_req_send(p_ans); } else { connection_established(p_ans); } } }
/**@brief Function for executing the Characteristic Descriptor Discovery Procedure. */ static void descriptor_disc_req_send(const ble_ans_c_t * p_ans) { ble_gattc_handle_range_t descriptor_handle; uint32_t err_code = NRF_SUCCESS; // If we have not discovered descriptors for all characteristics, // we will discover next descriptor. if (m_service.new_alert.handle_cccd == BLE_ANS_INVALID_HANDLE) { descriptor_handle.start_handle = m_service.new_alert.handle_value + 1; descriptor_handle.end_handle = m_service.new_alert.handle_value + 1; err_code = sd_ble_gattc_descriptors_discover(p_ans->conn_handle, &descriptor_handle); } else if (m_service.unread_alert_status.handle_cccd == BLE_ANS_INVALID_HANDLE) { descriptor_handle.start_handle = m_service.unread_alert_status.handle_value + 1; descriptor_handle.end_handle = m_service.unread_alert_status.handle_value + 1; err_code = sd_ble_gattc_descriptors_discover(p_ans->conn_handle, &descriptor_handle); } if (err_code == NRF_SUCCESS) { m_client_state = STATE_DISC_DESC; } else { handle_discovery_failure(p_ans, err_code); } }
/**@brief Function for executing the Characteristic Discovery Procedure. */ static void characteristic_disc_req_send(const ble_ans_c_t * p_ans, const ble_gattc_handle_range_t * p_handle) { uint32_t err_code; // With valid service, we should discover characteristics. err_code = sd_ble_gattc_characteristics_discover(p_ans->conn_handle, p_handle); if (err_code == NRF_SUCCESS) { m_client_state = STATE_DISC_CHAR; } else { handle_discovery_failure(p_ans, err_code); } }
/**@brief Function for executing the Service Discovery Procedure. */ static void service_disc_req_send(const ble_ans_c_t * p_ans) { uint16_t handle = START_HANDLE_DISCOVER; ble_uuid_t ans_uuid; uint32_t err_code; // Discover services on uuid Alert Notification. BLE_UUID_BLE_ASSIGN(ans_uuid, BLE_UUID_ALERT_NOTIFICATION_SERVICE); err_code = sd_ble_gattc_primary_services_discover(p_ans->conn_handle, handle, &ans_uuid); if (err_code != NRF_SUCCESS) { handle_discovery_failure(p_ans, err_code); } else { m_client_state = STATE_DISC_SERV; } }
/**@brief Function for executing the Service Discovery Procedure. */ static void service_disc_req_send(const ble_ancs_c_t * p_ancs) { uint16_t handle = START_HANDLE_DISCOVER; ble_uuid_t ancs_uuid; uint32_t err_code; // Discover services on uuid for ANCS. BLE_UUID_BLE_ASSIGN(ancs_uuid, BLE_UUID_APPLE_NOTIFICATION_CENTER_SERVICE); ancs_uuid.type = BLE_UUID_TYPE_VENDOR_BEGIN; err_code = sd_ble_gattc_primary_services_discover(p_ancs->conn_handle, handle, &ancs_uuid); if (err_code != NRF_SUCCESS) { handle_discovery_failure(p_ancs, err_code); } else { m_client_state = STATE_DISC_SERV; } }
/**@brief Function for handling a characteristic discovery response event. * * @details This function will validate and store the characteristics received. * If not all characteristics are discovered it will continue the characteristic discovery * procedure, otherwise it will continue with the descriptor discovery procedure. * If we receive a GATT Client error, we will go to handling of discovery failure. */ static void event_characteristic_rsp(ble_ans_c_t * p_ans, const ble_evt_t * p_ble_evt) { if (p_ble_evt->evt.gattc_evt.gatt_status == BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND || p_ble_evt->evt.gattc_evt.gatt_status == BLE_GATT_STATUS_ATTERR_INVALID_HANDLE) { if ((m_service.alert_notif_ctrl_point.handle_value == 0) || (m_service.suported_new_alert_cat.handle_value == 0) || (m_service.suported_unread_alert_cat.handle_value == 0) || (m_service.new_alert.handle_value == 0) || (m_service.unread_alert_status.handle_value == 0)) { // At least one required characteristic is missing on the server side. handle_discovery_failure(p_ans, NRF_ERROR_NOT_FOUND); } else { descriptor_disc_req_send(p_ans); } } else if (p_ble_evt->evt.gattc_evt.gatt_status) { // We have received an unexpected result. // As we are in a connected state, but can not continue // our service discovery, we must go to running state. handle_discovery_failure(p_ans, p_ble_evt->evt.gattc_evt.gatt_status); } else { uint32_t i; const ble_gattc_char_t * p_char_resp = NULL; // Iterate trough the characteristics and find the correct one. for (i = 0; i < p_ble_evt->evt.gattc_evt.params.char_disc_rsp.count; i++) { p_char_resp = &(p_ble_evt->evt.gattc_evt.params.char_disc_rsp.chars[i]); switch (p_char_resp->uuid.uuid) { case BLE_UUID_ALERT_NOTIFICATION_CONTROL_POINT_CHAR: characteristics_set(&m_service.alert_notif_ctrl_point, p_char_resp); break; case BLE_UUID_UNREAD_ALERT_CHAR: characteristics_set(&m_service.unread_alert_status, p_char_resp); break; case BLE_UUID_NEW_ALERT_CHAR: characteristics_set(&m_service.new_alert, p_char_resp); break; case BLE_UUID_SUPPORTED_UNREAD_ALERT_CATEGORY_CHAR: characteristics_set(&m_service.suported_unread_alert_cat, p_char_resp); break; case BLE_UUID_SUPPORTED_NEW_ALERT_CATEGORY_CHAR: characteristics_set(&m_service.suported_new_alert_cat, p_char_resp); break; default: // No implementation needed. break; } } if (p_char_resp != NULL) { // If not all characteristics are received, we do a 2nd/3rd/... round. ble_gattc_handle_range_t char_handle; char_handle.start_handle = p_char_resp->handle_value + 1; char_handle.end_handle = m_service.service.handle_range.end_handle; characteristic_disc_req_send(p_ans, &char_handle); } else { characteristic_disc_req_send(p_ans, &(m_service.service.handle_range)); } } }