static ret_code_t on_rw_authorize_req(nrf_ble_escs_t * p_escs, ble_evt_t * p_ble_evt) { ret_code_t err_code; VERIFY_PARAM_NOT_NULL(p_escs); VERIFY_PARAM_NOT_NULL(p_ble_evt); ble_gatts_evt_rw_authorize_request_t *ar = &p_ble_evt->evt.gatts_evt.params.authorize_request; if (ar->type == BLE_GATTS_AUTHORIZE_TYPE_READ) { err_code = on_read(p_escs, p_ble_evt); RETURN_IF_ERROR(err_code); } else if (ar->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE) { if (ar->request.write.op == BLE_GATTS_OP_WRITE_REQ || ar->request.write.op == BLE_GATTS_OP_WRITE_CMD) { err_code = on_write(p_escs, p_ble_evt); RETURN_IF_ERROR(err_code); } else if(ar->request.write.op == BLE_GATTS_OP_PREP_WRITE_REQ || ar->request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_NOW) { on_long_write(p_escs, p_ble_evt); } else { } } else { return NRF_ERROR_INVALID_STATE; } return NRF_SUCCESS; }
ret_code_t im_whitelist_custom(ble_gap_whitelist_t const * p_whitelist) { ret_code_t err_code; pm_peer_id_t new_irk_whitelist_peer_ids[BLE_GAP_WHITELIST_IRK_MAX_COUNT]; uint32_t n_new_irk_whitelist_peer_ids = 0; VERIFY_PARAM_NOT_NULL(p_whitelist); for (uint32_t i = 0; i < BLE_GAP_WHITELIST_IRK_MAX_COUNT; i++) { new_irk_whitelist_peer_ids[i] = PM_PEER_ID_INVALID; } pm_peer_id_t compared_peer_id = pdb_next_peer_id_get(PM_PEER_ID_INVALID); while (compared_peer_id != PM_PEER_ID_INVALID) { pm_peer_data_flash_t compared_data; err_code = pdb_read_buf_get(compared_peer_id, PM_PEER_DATA_ID_BONDING, &compared_data, NULL); if (err_code == NRF_SUCCESS) { for (uint32_t i = 0; i < p_whitelist->irk_count; i++) { bool valid_irk = is_valid_irk(&compared_data.p_bonding_data->peer_id.id_info); bool duplicate_irk = valid_irk && (memcmp(p_whitelist->pp_irks[i]->irk, compared_data.p_bonding_data->peer_id.id_info.irk, BLE_GAP_SEC_KEY_LEN) == 0 ); if (duplicate_irk) { new_irk_whitelist_peer_ids[i] = compared_peer_id; n_new_irk_whitelist_peer_ids++; } } } compared_peer_id = pdb_next_peer_id_get(compared_peer_id); } if (n_new_irk_whitelist_peer_ids != p_whitelist->irk_count) { return NRF_ERROR_NOT_FOUND; } else { for (uint32_t i = 0; i < n_new_irk_whitelist_peer_ids; i++) { m_im.irk_whitelist_peer_ids[i] = new_irk_whitelist_peer_ids[i]; } m_im.n_irk_whitelist_peer_ids = n_new_irk_whitelist_peer_ids; return NRF_SUCCESS; } }
ret_code_t pm_link_status_get(uint16_t conn_handle, pm_link_status_t * p_link_status) { VERIFY_PARAM_NOT_NULL(p_link_status); if (conn_handle == BLE_CONN_HANDLE_INVALID) { return NRF_ERROR_INVALID_PARAM; } // Read the bonded status from the user flag that is maintained by events. p_link_status->bonded = ble_conn_state_user_flag_get(conn_handle, m_pm.bonding_flag_id); // Read the connected, encrypted and mitm status from the connection state module. p_link_status->connected = ble_conn_state_valid(conn_handle); p_link_status->encrypted = ble_conn_state_encrypted(conn_handle); p_link_status->mitm_protected = ble_conn_state_mitm_protected(conn_handle); return NRF_SUCCESS; }
static uint32_t get_evt_type_for_handle(uint16_t handle, uint16_t * p_uuid) { VERIFY_PARAM_NOT_NULL(p_uuid); for(uint8_t i = 0; i < BLE_ESCS_NUMBER_OF_CHARACTERISTICS; ++i) { if(m_handle_to_uuid_map[i].val_handle == handle) { *p_uuid = m_handle_to_uuid_map[i].uuid; return NRF_SUCCESS; } } return NRF_ERROR_NOT_FOUND; }
ret_code_t nrf_ble_bms_auth_response(nrf_ble_bms_t * p_bms, bool authorize) { VERIFY_PARAM_NOT_NULL(p_bms); VERIFY_TRUE(p_bms->auth_status == NRF_BLE_BMS_AUTH_STATUS_PENDING, NRF_ERROR_INVALID_STATE); if (authorize) { p_bms->auth_status = NRF_BLE_BMS_AUTH_STATUS_ALLOWED; } else { p_bms->auth_status = NRF_BLE_BMS_AUTH_STATUS_DENIED; } return NRF_SUCCESS; }
uint32_t ble_ancs_c_attr_add(ble_ancs_c_t * p_ancs, const ble_ancs_c_notif_attr_id_values_t id, uint8_t * p_data, const uint16_t len) { VERIFY_PARAM_NOT_NULL(p_data); if ((len == 0) || (len > BLE_ANCS_ATTR_DATA_MAX)) { return NRF_ERROR_INVALID_LENGTH; } p_ancs->ancs_attr_list[id].get = true; p_ancs->ancs_attr_list[id].attr_len = len; p_ancs->ancs_attr_list[id].p_attr_data = p_data; return NRF_SUCCESS; }
ret_code_t pm_conn_sec_status_get(uint16_t conn_handle, pm_conn_sec_status_t * p_conn_sec_status) { VERIFY_MODULE_INITIALIZED(); VERIFY_PARAM_NOT_NULL(p_conn_sec_status); ble_conn_state_status_t status = ble_conn_state_status(conn_handle); if (status == BLE_CONN_STATUS_INVALID) { return BLE_ERROR_INVALID_CONN_HANDLE; } p_conn_sec_status->connected = (status == BLE_CONN_STATUS_CONNECTED); p_conn_sec_status->bonded = ble_conn_state_user_flag_get(conn_handle, m_bonding_flag_id); p_conn_sec_status->encrypted = ble_conn_state_encrypted(conn_handle); p_conn_sec_status->mitm_protected = ble_conn_state_mitm_protected(conn_handle); return NRF_SUCCESS; }
uint32_t ble_ancs_c_handles_assign(ble_ancs_c_t * p_ancs, const uint16_t conn_handle, const ble_ancs_c_service_t * p_peer_handles) { VERIFY_PARAM_NOT_NULL(p_ancs); p_ancs->conn_handle = conn_handle; if (p_peer_handles != NULL) { p_ancs->service.control_point_char.handle_value = p_peer_handles->control_point_char.handle_value; p_ancs->service.data_source_cccd.handle = p_peer_handles->data_source_cccd.handle; p_ancs->service.data_source_char.handle_value = p_peer_handles->data_source_char.handle_value; p_ancs->service.notif_source_cccd.handle = p_peer_handles->notif_source_cccd.handle; p_ancs->service.notif_source_char.handle_value = p_peer_handles->notif_source_char.handle_value; } return NRF_SUCCESS; }
uint32_t ble_db_discovery_start(ble_db_discovery_t * const p_db_discovery, uint16_t conn_handle) { VERIFY_PARAM_NOT_NULL(p_db_discovery); VERIFY_MODULE_INITIALIZED(); if (m_num_of_handlers_reg == 0) { // No user modules were registered. There are no services to discover. return NRF_ERROR_INVALID_STATE; } if (p_db_discovery->discovery_in_progress) { return NRF_ERROR_BUSY; } p_db_discovery->conn_handle = conn_handle; ble_gatt_db_srv_t * p_srv_being_discovered; m_pending_usr_evt_index = 0; p_db_discovery->discoveries_count = 0; p_db_discovery->curr_srv_ind = 0; p_db_discovery->curr_char_ind = 0; p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); p_srv_being_discovered->srv_uuid = m_registered_handlers[p_db_discovery->curr_srv_ind]; NRF_LOG_INFO("Starting discovery of service with UUID 0x%x for Connection handle %d\r\n", p_srv_being_discovered->srv_uuid.uuid, conn_handle); uint32_t err_code; err_code = sd_ble_gattc_primary_services_discover(conn_handle, SRV_DISC_START_HANDLE, &(p_srv_being_discovered->srv_uuid)); VERIFY_SUCCESS(err_code); p_db_discovery->discovery_in_progress = true; return NRF_SUCCESS; }
ret_code_t es_gatts_send_op_not_permitted(nrf_ble_escs_t * p_escs, bool read) { ble_gatts_rw_authorize_reply_params_t reply = {0}; VERIFY_PARAM_NOT_NULL(p_escs); if (read) { reply.type = BLE_GATTS_AUTHORIZE_TYPE_READ; reply.params.read.gatt_status = BLE_GATT_STATUS_ATTERR_READ_NOT_PERMITTED; } else { reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; reply.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_WRITE_NOT_PERMITTED; } return es_gatts_send_reply(p_escs, &reply); }
uint32_t ble_rgb_btn_set(ble_rgb_btn_t * p_rgb_btn, uint8_t btn_state) { ble_gatts_hvx_params_t params; uint16_t length = 1; VERIFY_PARAM_NOT_NULL(p_rgb_btn); if ((p_rgb_btn->conn_handle == BLE_CONN_HANDLE_INVALID) || (!p_rgb_btn->is_notification_enabled)) { return NRF_ERROR_INVALID_STATE; } memset(¶ms, 0, sizeof(params)); params.type = BLE_GATT_HVX_NOTIFICATION; params.handle = p_rgb_btn->btn_char_handles.value_handle; params.p_data = &btn_state; params.p_len = &length; return sd_ble_gatts_hvx(p_rgb_btn->conn_handle, ¶ms); }
uint32_t ble_bas_c_bl_read(ble_bas_c_t * p_ble_bas_c) { VERIFY_PARAM_NOT_NULL(p_ble_bas_c); if (p_ble_bas_c->conn_handle == BLE_CONN_HANDLE_INVALID) { return NRF_ERROR_INVALID_STATE; } tx_message_t * msg; msg = &m_tx_buffer[m_tx_insert_index++]; m_tx_insert_index &= TX_BUFFER_MASK; msg->req.read_handle = p_ble_bas_c->peer_bas_db.bl_handle; msg->conn_handle = p_ble_bas_c->conn_handle; msg->type = READ_REQ; tx_buffer_process(); return NRF_SUCCESS; }
uint32_t ble_dfu_buttonless_init(const ble_dfu_buttonless_init_t * p_dfu_init) { uint32_t err_code; ble_uuid_t service_uuid; ble_uuid128_t nordic_base_uuid = BLE_NORDIC_VENDOR_BASE_UUID; VERIFY_PARAM_NOT_NULL(p_dfu_init); // Initialize the service structure. m_dfu.conn_handle = BLE_CONN_HANDLE_INVALID; m_dfu.evt_handler = p_dfu_init->evt_handler; m_dfu.is_waiting_for_reset = false; m_dfu.is_ctrlpt_indication_enabled = false; if (m_dfu.evt_handler == NULL) { m_dfu.evt_handler = dummy_evt_handler; } err_code = ble_dfu_buttonless_backend_init(&m_dfu); VERIFY_SUCCESS(err_code); BLE_UUID_BLE_ASSIGN(service_uuid, BLE_DFU_SERVICE_UUID); // Add the DFU service declaration. err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &service_uuid, &(m_dfu.service_handle)); VERIFY_SUCCESS(err_code); // Add vendor specific base UUID to use with the Buttonless DFU characteristic. err_code = sd_ble_uuid_vs_add(&nordic_base_uuid, &m_dfu.uuid_type); VERIFY_SUCCESS(err_code); // Add the Buttonless DFU Characteristic (with bonds/without bonds). err_code = ble_dfu_buttonless_char_add(&m_dfu); VERIFY_SUCCESS(err_code); return NRF_SUCCESS; }
ret_code_t pds_peer_data_read_ptr_get(pm_peer_id_t peer_id, pm_peer_data_id_t data_id, pm_peer_data_flash_t * p_data, pm_store_token_t * p_token) { ret_code_t retval; fds_flash_record_t record; fds_record_desc_t record_desc; VERIFY_MODULE_INITIALIZED(); VERIFY_PEER_ID_IN_RANGE(peer_id); VERIFY_PEER_DATA_ID_IN_RANGE(data_id); VERIFY_PARAM_NOT_NULL(p_data); retval = find_fds_item(peer_id, data_id, &record_desc); if (retval != FDS_SUCCESS) { return NRF_ERROR_NOT_FOUND; } // Shouldn't fail, unless the record was deleted. (void)fds_record_open(&record_desc, &record); if (p_data != NULL) { p_data->data_id = data_id; p_data->length_words = record.p_header->tl.length_words; p_data->p_all_data = record.p_data; } if (p_token != NULL) { *p_token = (uint32_t)record.p_header->record_id; } // Shouldn't fail, unless the record was already closed. (void)fds_record_close(&record_desc); return NRF_SUCCESS; }
ret_code_t pm_peer_data_store(pm_peer_id_t peer_id, pm_peer_data_id_t data_id, void const * p_data, uint16_t length, pm_store_token_t * p_token) { VERIFY_MODULE_INITIALIZED(); VERIFY_PARAM_NOT_NULL(p_data); if (ALIGN_NUM(4, length) != length) { return NRF_ERROR_INVALID_PARAM; } pm_peer_data_flash_t peer_data; memset(&peer_data, 0, sizeof(peer_data)); peer_data.length_words = BYTES_TO_WORDS(length); peer_data.data_id = data_id; peer_data.p_all_data = p_data; return pdb_raw_store(peer_id, &peer_data, p_token); }
ret_code_t gcm_init(gcm_evt_handler_t evt_handler) { VERIFY_PARAM_NOT_NULL(evt_handler); ret_code_t err_code; err_code = gscm_init(gscm_evt_handler); VERIFY_SUCCESS(err_code); err_code = gccm_init(gccm_evt_handler); VERIFY_SUCCESS(err_code); internal_state_reset(&m_gcm); m_gcm.evt_handler = evt_handler; err_code = im_register(im_evt_handler); VERIFY_SUCCESS(err_code); err_code = smd_register(smd_evt_handler); VERIFY_SUCCESS(err_code); m_gcm.flag_id_local_db_update_pending = ble_conn_state_user_flag_acquire(); m_gcm.flag_id_local_db_apply_pending = ble_conn_state_user_flag_acquire(); m_gcm.flag_id_service_changed_pending = ble_conn_state_user_flag_acquire(); m_gcm.flag_id_service_changed_sent = ble_conn_state_user_flag_acquire(); if ((m_gcm.flag_id_local_db_update_pending == BLE_CONN_STATE_USER_FLAG_INVALID) || (m_gcm.flag_id_local_db_apply_pending == BLE_CONN_STATE_USER_FLAG_INVALID) || (m_gcm.flag_id_service_changed_pending == BLE_CONN_STATE_USER_FLAG_INVALID) || (m_gcm.flag_id_service_changed_sent == BLE_CONN_STATE_USER_FLAG_INVALID)) { err_code = NRF_ERROR_INTERNAL; } return err_code; }
uint32_t ble_nus_c_string_send(ble_nus_c_t * p_ble_nus_c, uint8_t * p_string, uint16_t length) { VERIFY_PARAM_NOT_NULL(p_ble_nus_c); if (length > BLE_NUS_MAX_DATA_LEN) { return NRF_ERROR_INVALID_PARAM; } if ( p_ble_nus_c->conn_handle == BLE_CONN_HANDLE_INVALID) { return NRF_ERROR_INVALID_STATE; } const ble_gattc_write_params_t write_params = { .write_op = BLE_GATT_OP_WRITE_CMD, .flags = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE, .handle = p_ble_nus_c->nus_tx_handle, .offset = 0, .len = length, .p_value = p_string }; return sd_ble_gattc_write(p_ble_nus_c->conn_handle, &write_params); }
uint32_t dfu_data_pkt_handle(dfu_update_packet_t * p_packet) { uint32_t data_length; uint32_t err_code; uint32_t * p_data; VERIFY_PARAM_NOT_NULL(p_packet); // Check pointer alignment. if (!is_word_aligned(p_packet->params.data_packet.p_data_packet)) { // The p_data_packet is not word aligned address. return NRF_ERROR_INVALID_ADDR; } switch (m_dfu_state) { case DFU_STATE_RDY: case DFU_STATE_RX_INIT_PKT: return NRF_ERROR_INVALID_STATE; case DFU_STATE_RX_DATA_PKT: data_length = p_packet->params.data_packet.packet_length * sizeof(uint32_t); if ((m_data_received + data_length) > m_image_size) { // The caller is trying to write more bytes into the flash than the size provided to // the dfu_image_size_set function. This is treated as a serious error condition and // an unrecoverable one. Hence point the variable mp_app_write_address to the top of // the flash area. This will ensure that all future application data packet writes // will be blocked because of the above check. m_data_received = 0xFFFFFFFF; return NRF_ERROR_DATA_SIZE; } // Valid peer activity detected. Hence restart the DFU timer. err_code = dfu_timer_restart(); VERIFY_SUCCESS(err_code); p_data = (uint32_t *)p_packet->params.data_packet.p_data_packet; // Do AES Decrption. dfu_aes_128_ofb_decrypt(p_data, data_length/sizeof(uint32_t), m_data_received); // Check the protected data before copying it and make sure its retain or update the data. uint32_t bootloader_position = m_data_received - m_start_packet.sd_image_size; for (int w = 0; w < data_length/sizeof(uint32_t); w++) { bootloader_position = bootloader_position + 4; if(m_start_packet.bl_image_size > 0 && (m_data_received > m_start_packet.sd_image_size) && (bootloader_position >= ((uint32_t)(&__start_protected_data) - m_uicr_bootloader_start_address))) { if(p_data[w] == 0x00000000) { p_data[w] = 0xFFFFFFFF; } else if(p_data[w] == 0xFFFFFFFF) p_data[w] = (uint32_t)(*((uint32_t *)(bootloader_position - 4 + m_uicr_bootloader_start_address))); } } err_code = pstorage_store(mp_storage_handle_active, (uint8_t *)p_data, data_length, m_data_received); VERIFY_SUCCESS(err_code); m_data_received += data_length; if (m_data_received != m_image_size) { // The entire image is not received yet. More data is expected. err_code = NRF_ERROR_INVALID_LENGTH; } else { // The entire image has been received. Return NRF_SUCCESS. err_code = NRF_SUCCESS; } break; default: err_code = NRF_ERROR_INVALID_STATE; break; } return err_code; }
ret_code_t nrf_ble_escs_init(nrf_ble_escs_t * p_escs, const nrf_ble_escs_init_t * p_escs_init) { uint32_t err_code; ble_uuid_t ble_uuid; ble_uuid128_t ecs_base_uuid = ESCS_BASE_UUID; uint8_t zero_val = 0; VERIFY_PARAM_NOT_NULL(p_escs); VERIFY_PARAM_NOT_NULL(p_escs_init); // Initialize the service structure. p_escs->conn_handle = BLE_CONN_HANDLE_INVALID; p_escs->write_evt_handler = p_escs_init->write_evt_handler; p_escs->read_evt_handler = p_escs_init->read_evt_handler; // Add a custom base UUID. err_code = sd_ble_uuid_vs_add(&ecs_base_uuid, &p_escs->uuid_type); VERIFY_SUCCESS(err_code); ble_uuid.type = p_escs->uuid_type; ble_uuid.uuid = BLE_UUID_ESCS_SERVICE; // Add the service. err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_escs->service_handle); VERIFY_SUCCESS(err_code); m_handle_to_uuid_map_idx = 0; // Set up initial values for characteristics // Eddystone spec requires big endian nrf_ble_escs_broadcast_cap_t temp = p_escs_init->p_init_vals->broadcast_cap; temp.supp_frame_types = BYTES_SWAP_16BIT(temp.supp_frame_types); nrf_ble_escs_adv_interval_t temp_interval = p_escs_init->p_init_vals->adv_interval; temp_interval = BYTES_SWAP_16BIT(temp_interval); // Adding chracteristics err_code = char_add(&BROADCAST_CAP_CHAR_INIT, p_escs, &temp, &p_escs->broadcast_cap_handles); VERIFY_SUCCESS(err_code); err_code = char_add(&ACTIVE_SLOT_CHAR_INIT, p_escs, p_escs->p_active_slot, &p_escs->active_slot_handles); VERIFY_SUCCESS(err_code); err_code = char_add(&ADV_INTERVAL_CHAR_INIT, p_escs, &temp_interval, &p_escs->adv_interval_handles); VERIFY_SUCCESS(err_code); err_code = char_add(&RADIO_TX_PWR_CHAR_INIT, p_escs, &(p_escs_init->p_init_vals->radio_tx_pwr), &p_escs->radio_tx_pwr_handles); VERIFY_SUCCESS(err_code); err_code = char_add(&ADV_TX_PWR_CHAR_INIT, p_escs, &(p_escs_init->p_init_vals->adv_tx_pwr), &p_escs->adv_tx_pwr_handles); VERIFY_SUCCESS(err_code); err_code = char_add(&LOCK_STATE_CHAR_INIT, p_escs, p_escs->p_lock_state, &p_escs->lock_state_handles); VERIFY_SUCCESS(err_code); err_code = char_add(&UNLOCK_CHAR_INIT, p_escs, &zero_val, &p_escs->unlock_handles); VERIFY_SUCCESS(err_code); err_code = char_add(&PUBLIC_ECDH_KEY_CHAR_INIT, p_escs, &zero_val, &p_escs->pub_ecdh_key_handles); VERIFY_SUCCESS(err_code); err_code = char_add(&EID_ID_KEY_CHAR_INIT, p_escs, &zero_val, &p_escs->eid_id_key_handles); VERIFY_SUCCESS(err_code); err_code = char_add(&RW_ADV_SLOT_CHAR_INIT, p_escs, &zero_val, &p_escs->rw_adv_slot_handles); VERIFY_SUCCESS(err_code); err_code = char_add(&FACTORY_RESET_CHAR_INIT, p_escs, &(p_escs_init->p_init_vals->factory_reset), &p_escs->factory_reset_handles); VERIFY_SUCCESS(err_code); err_code = char_add(&REMAIN_CONNECTABLE_CHAR_INIT, p_escs, &(p_escs_init->p_init_vals->remain_connectable.r_is_non_connectable_supported), &p_escs->remain_connectable_handles); VERIFY_SUCCESS(err_code); return NRF_SUCCESS; }
ret_code_t peer_data_deserialize(pm_peer_data_flash_t const * p_in_data, pm_peer_data_t * p_out_data) { VERIFY_PARAM_NOT_NULL(p_in_data); VERIFY_PARAM_NOT_NULL(p_out_data); if (p_out_data->length_words < p_in_data->length_words) { p_out_data->length_words = p_in_data->length_words; return NRF_ERROR_NO_MEM; } p_out_data->length_words = p_in_data->length_words; p_out_data->data_type = p_in_data->data_type; switch (p_in_data->data_type) { case PM_PEER_DATA_ID_BONDING: *p_out_data->data.p_bonding_data = *p_in_data->data.p_bonding_data; break; case PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING: *p_out_data->data.p_service_changed_pending = *p_in_data->data.p_service_changed_pending; break; case PM_PEER_DATA_ID_GATT_LOCAL: VERIFY_PARAM_NOT_NULL(p_out_data->data.p_local_gatt_db->p_data); if (p_out_data->data.p_local_gatt_db->len < p_in_data->data.p_local_gatt_db->len) { p_out_data->data.p_local_gatt_db->len = p_in_data->data.p_local_gatt_db->len; return NRF_ERROR_NO_MEM; } else { p_out_data->data.p_local_gatt_db->flags = p_in_data->data.p_local_gatt_db->flags; p_out_data->data.p_local_gatt_db->len = p_in_data->data.p_local_gatt_db->len; memcpy(p_out_data->data.p_local_gatt_db->p_data, p_in_data->data.p_local_gatt_db->p_data, p_in_data->data.p_local_gatt_db->len); } break; case PM_PEER_DATA_ID_GATT_REMOTE: VERIFY_PARAM_NOT_NULL(p_out_data->data.p_remote_gatt_db->p_data); if (p_out_data->data.p_remote_gatt_db->service_count < p_in_data->data.p_remote_gatt_db->service_count) { p_out_data->data.p_remote_gatt_db->service_count = p_in_data->data.p_remote_gatt_db->service_count; return NRF_ERROR_NO_MEM; } else { p_out_data->data.p_remote_gatt_db->service_count = p_in_data->data.p_remote_gatt_db->service_count; memcpy(p_out_data->data.p_remote_gatt_db->p_data, p_in_data->data.p_remote_gatt_db->p_data, p_in_data->data.p_remote_gatt_db->service_count * sizeof(ble_gatt_db_srv_t)); } break; case PM_PEER_DATA_ID_APPLICATION: memcpy(p_out_data->data.p_application_data, p_in_data->data.p_application_data, p_in_data->length_words * 4); break; default: break; } return NRF_SUCCESS; }
/**@brief Function for handling events from the Peer Data Storage module. * * @param[in] p_event The event to handle. */ static void pds_evt_handler(pds_evt_t const * p_event) { ret_code_t err_code; pdb_buffer_record_t * p_write_buffer_record; bool retry_flash_full = false; pdb_evt_t event = { .peer_id = p_event->peer_id, .data_id = p_event->data_id, }; p_write_buffer_record = write_buffer_record_find(p_event->peer_id, p_event->data_id); switch (p_event->evt_id) { case PDS_EVT_STORED: if ( (p_write_buffer_record != NULL) //&& (p_write_buffer_record->store_token == p_event->store_token) && (p_write_buffer_record->store_requested)) { write_buffer_record_release(p_write_buffer_record); event.evt_id = PDB_EVT_WRITE_BUF_STORED; pdb_evt_send(&event); } else { event.evt_id = PDB_EVT_RAW_STORED; pdb_evt_send(&event); } break; case PDS_EVT_ERROR_STORE: if ( (p_write_buffer_record != NULL) && (p_write_buffer_record->store_token == p_event->store_token) && (p_write_buffer_record->store_requested)) { // Retry if internal buffer. m_pdb.n_writes++; p_write_buffer_record->store_requested = false; p_write_buffer_record->store_busy = true; } else { event.evt_id = PDB_EVT_RAW_STORE_FAILED; pdb_evt_send(&event); } break; case PDS_EVT_CLEARED: event.evt_id = PDB_EVT_CLEARED; pdb_evt_send(&event); break; case PDS_EVT_ERROR_CLEAR: event.evt_id = PDB_EVT_CLEAR_FAILED; pdb_evt_send(&event); break; case PDS_EVT_COMPRESSED: retry_flash_full = true; event.evt_id = PDB_EVT_COMPRESSED; pdb_evt_send(&event); break; default: break; } if (m_pdb.n_writes > 0) { for (int i = 0; i < N_WRITE_BUFFER_RECORDS; i++) { if ((m_pdb.write_buffer_records[i].store_busy) || (m_pdb.write_buffer_records[i].store_flash_full && retry_flash_full)) { err_code = pdb_write_buf_store(m_pdb.write_buffer_records[i].peer_id, m_pdb.write_buffer_records[i].data_id); if (err_code != NRF_SUCCESS) { event.peer_id = m_pdb.write_buffer_records[i].peer_id; event.data_id = m_pdb.write_buffer_records[i].data_id; if (err_code == NRF_ERROR_NO_MEM) { event.evt_id = PDB_EVT_ERROR_NO_MEM; } else { event.evt_id = PDB_EVT_ERROR_UNEXPECTED; } pdb_evt_send(&event); break; } } } } } ret_code_t pdb_register(pdb_evt_handler_t evt_handler) { if (m_pdb.n_registrants >= MAX_REGISTRANTS) { return NRF_ERROR_NO_MEM; } VERIFY_PARAM_NOT_NULL(evt_handler); if (!MODULE_INITIALIZED) { ret_code_t err_code; internal_state_reset(&m_pdb); err_code = pds_register(pds_evt_handler); if (err_code != NRF_SUCCESS) { return err_code; } PM_BUFFER_INIT(&m_pdb.write_buffer, N_WRITE_BUFFERS, PDB_WRITE_BUF_SIZE, err_code); if (err_code != NRF_SUCCESS) { return err_code; } } m_pdb.evt_handlers[m_pdb.n_registrants] = evt_handler; m_pdb.n_registrants += 1; return NRF_SUCCESS; } pm_peer_id_t pdb_peer_allocate(void) { if (!MODULE_INITIALIZED) { return PM_PEER_ID_INVALID; } return pds_peer_id_allocate(); } ret_code_t pdb_peer_free(pm_peer_id_t peer_id) { VERIFY_MODULE_INITIALIZED(); return pds_peer_id_free(peer_id); }
ret_code_t nrf_ble_cgms_init(nrf_ble_cgms_t * p_cgms, const nrf_ble_cgms_init_t * p_cgms_init) { VERIFY_PARAM_NOT_NULL(p_cgms); VERIFY_PARAM_NOT_NULL(p_cgms_init); VERIFY_PARAM_NOT_NULL(p_cgms_init->evt_handler); uint32_t err_code; ble_uuid_t ble_uuid; // Initialize data base err_code = cgms_db_init(); if (err_code != NRF_SUCCESS) { return err_code; } err_code = next_sequence_number_set(); if (err_code != NRF_SUCCESS) { return err_code; } // Initialize service structure p_cgms->evt_handler = p_cgms_init->evt_handler; p_cgms->error_handler = p_cgms_init->error_handler; p_cgms->feature = p_cgms_init->feature; p_cgms->sensor_status = p_cgms_init->initial_sensor_status; p_cgms->session_run_time = p_cgms_init->initial_run_time; p_cgms->is_session_started = false; p_cgms->nb_run_session = 0; p_cgms->conn_handle = BLE_CONN_HANDLE_INVALID; p_cgms->feature.feature = 0; p_cgms->feature.feature |= NRF_BLE_CGMS_FEAT_MULTIPLE_BOND_SUPPORTED; p_cgms->feature.feature |= NRF_BLE_CGMS_FEAT_MULTIPLE_SESSIONS_SUPPORTED; p_cgms->feature.type = NRF_BLE_CGMS_MEAS_TYPE_VEN_BLOOD; p_cgms->feature.sample_location = NRF_BLE_CGMS_MEAS_LOC_AST; p_cgms->feature.feature |= NRF_BLE_CGMS_FEAT_MULTIPLE_BOND_SUPPORTED; memcpy(p_cgms->calibration_val[0].value, init_calib_val, NRF_BLE_CGMS_MAX_CALIB_LEN); // Initialize global variables p_cgms->cgms_com_state = STATE_NO_COMM; p_cgms->racp_data.racp_proc_records_reported_since_txcomplete = 0; // Add service BLE_UUID_BLE_ASSIGN(ble_uuid, BLE_UUID_CGM_SERVICE); err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_cgms->service_handle); if (err_code != NRF_SUCCESS) { return err_code; } // Add glucose measurement characteristic err_code = cgms_meas_char_add(p_cgms); if (err_code != NRF_SUCCESS) { return err_code; } // Add glucose measurement feature characteristic err_code = glucose_feature_char_add(p_cgms); if (err_code != NRF_SUCCESS) { return err_code; } // Add glucose measurement status characteristic err_code = status_char_add(p_cgms); if (err_code != NRF_SUCCESS) { return err_code; } // Add record control access point characteristic err_code = cgms_racp_char_add(p_cgms); if (err_code != NRF_SUCCESS) { return err_code; } // Add Start Session Time characteristic err_code = cgms_sst_char_add(p_cgms); if (err_code != NRF_SUCCESS) { return err_code; } // Add Session Run Time characteristic err_code = srt_char_add(p_cgms); if (err_code != NRF_SUCCESS) { return err_code; } // Add Specific Operations Control Point characteristic err_code = cgms_socp_char_add(p_cgms); if (err_code != NRF_SUCCESS) { return err_code; } return NRF_SUCCESS; }
uint32_t ess_advertising_init(ble_advdata_t const * p_advdata, ble_advdata_t const * p_srdata, ess_adv_modes_config_t const * p_config, ess_advertising_evt_handler_t const evt_handler, ess_advertising_error_handler_t const error_handler) { uint32_t err_code; VERIFY_PARAM_NOT_NULL(p_advdata); VERIFY_PARAM_NOT_NULL(p_config); // m_adv_mode_current = BLE_ADV_MODE_IDLE; m_adv_mode_current = ESS_ADV_MODE_1; m_evt_handler = evt_handler; m_error_handler = error_handler; m_adv_modes_config = *p_config; ble_advertising_peer_address_clear(); // Prepare Whitelist. Address and IRK double pointers point to allocated arrays. m_whitelist.pp_addrs = mp_whitelist_addr; m_whitelist.pp_irks = mp_whitelist_irk; // Copy and set advertising data. memset(&m_advdata, 0, sizeof(m_advdata)); // Copy advertising data. m_advdata.name_type = p_advdata->name_type; m_advdata.include_appearance = p_advdata->include_appearance; m_advdata.flags = p_advdata->flags; m_advdata.short_name_len = p_advdata->short_name_len; /* if(p_advdata->uuids_complete != NULL) { m_advdata.uuids_complete = p_advdata->uuids_complete; } */ m_advdata.uuids_complete = p_advdata->uuids_complete; m_advdata.uuids_more_available = p_advdata->uuids_more_available; m_advdata.uuids_solicited = p_advdata->uuids_solicited; if(p_advdata->p_manuf_specific_data != NULL) { m_advdata.p_manuf_specific_data = &m_manuf_specific_data; m_manuf_specific_data.data.p_data = m_manuf_data_array; m_advdata.p_manuf_specific_data->company_identifier = p_advdata->p_manuf_specific_data->company_identifier; m_advdata.p_manuf_specific_data->data.size = p_advdata->p_manuf_specific_data->data.size; for(uint32_t i = 0; i < m_advdata.p_manuf_specific_data->data.size; i++) { m_manuf_data_array[i] = p_advdata->p_manuf_specific_data->data.p_data[i]; } } if(p_advdata->p_service_data_array != NULL) { m_service_data.data.p_data = m_service_data_array; m_advdata.p_service_data_array = &m_service_data; m_advdata.p_service_data_array->data.p_data = m_service_data_array; m_advdata.p_service_data_array->data.size = p_advdata->p_service_data_array->data.size; m_advdata.p_service_data_array->service_uuid = p_advdata->p_service_data_array->service_uuid; for(uint32_t i = 0; i < m_advdata.p_service_data_array->data.size; i++) { m_service_data_array[i] = p_advdata->p_service_data_array->data.p_data[i]; } m_advdata.service_data_count = p_advdata->service_data_count; } if(p_advdata->p_slave_conn_int != NULL) { m_advdata.p_slave_conn_int = &m_slave_conn_int; m_advdata.p_slave_conn_int->max_conn_interval = p_advdata->p_slave_conn_int->max_conn_interval; m_advdata.p_slave_conn_int->min_conn_interval = p_advdata->p_slave_conn_int->min_conn_interval; } if(p_advdata->p_tx_power_level != NULL) { m_advdata.p_tx_power_level = &m_tx_power_level; m_advdata.p_tx_power_level = p_advdata->p_tx_power_level; } err_code = ble_advdata_set(&m_advdata, p_srdata); return err_code; }
ret_code_t pm_id_addr_get(ble_gap_addr_t * p_addr) { VERIFY_MODULE_INITIALIZED(); VERIFY_PARAM_NOT_NULL(p_addr); return im_id_addr_get(p_addr); }
ret_code_t pm_privacy_set(pm_privacy_params_t const * p_privacy_params) { VERIFY_MODULE_INITIALIZED(); VERIFY_PARAM_NOT_NULL(p_privacy_params); return im_privacy_set(p_privacy_params); }
ret_code_t pm_peer_id_get(uint16_t conn_handle, pm_peer_id_t * p_peer_id) { VERIFY_PARAM_NOT_NULL(p_peer_id); * p_peer_id = im_peer_id_get_by_conn_handle(conn_handle); return NRF_SUCCESS; }
ret_code_t pm_conn_handle_get(pm_peer_id_t peer_id, uint16_t * p_conn_handle) { VERIFY_PARAM_NOT_NULL(p_conn_handle); * p_conn_handle = im_conn_handle_get(peer_id); return NRF_SUCCESS; }
uint32_t dfu_data_pkt_handle(dfu_update_packet_t * p_packet) { uint32_t data_length; uint32_t err_code; uint32_t * p_data; VERIFY_PARAM_NOT_NULL(p_packet); // Check pointer alignment. if (!is_word_aligned(p_packet->params.data_packet.p_data_packet)) { // The p_data_packet is not word aligned address. return NRF_ERROR_INVALID_ADDR; } switch (m_dfu_state) { case DFU_STATE_RDY: case DFU_STATE_RX_INIT_PKT: return NRF_ERROR_INVALID_STATE; case DFU_STATE_RX_DATA_PKT: data_length = p_packet->params.data_packet.packet_length * sizeof(uint32_t); if ((m_data_received + data_length) > m_image_size) { // The caller is trying to write more bytes into the flash than the size provided to // the dfu_image_size_set function. This is treated as a serious error condition and // an unrecoverable one. Hence point the variable mp_app_write_address to the top of // the flash area. This will ensure that all future application data packet writes // will be blocked because of the above check. m_data_received = 0xFFFFFFFF; return NRF_ERROR_DATA_SIZE; } // Valid peer activity detected. Hence restart the DFU timer. err_code = dfu_timer_restart(); VERIFY_SUCCESS(err_code); p_data = (uint32_t *)p_packet->params.data_packet.p_data_packet; err_code = pstorage_store(mp_storage_handle_active, (uint8_t *)p_data, data_length, m_data_received); VERIFY_SUCCESS(err_code); m_data_received += data_length; if (m_data_received != m_image_size) { // The entire image is not received yet. More data is expected. err_code = NRF_ERROR_INVALID_LENGTH; } else { // The entire image has been received. Return NRF_SUCCESS. err_code = NRF_SUCCESS; } break; default: err_code = NRF_ERROR_INVALID_STATE; break; } return err_code; }
ret_code_t nrf_ble_cgms_conn_handle_assign(nrf_ble_cgms_t * p_cgms, uint16_t conn_handle) { VERIFY_PARAM_NOT_NULL(p_cgms); p_cgms->conn_handle = conn_handle; return NRF_SUCCESS; }
ret_code_t pdb_write_buf_get(pm_peer_id_t peer_id, pm_peer_data_id_t data_id, uint32_t n_bufs, pm_peer_data_t * p_peer_data) { VERIFY_MODULE_INITIALIZED(); VERIFY_PARAM_NOT_NULL(p_peer_data); if ( !PM_PEER_DATA_ID_IS_VALID(data_id) || (n_bufs == 0) || (n_bufs > N_WRITE_BUFFERS) || !pds_peer_id_is_allocated(peer_id)) { return NRF_ERROR_INVALID_PARAM; } pdb_buffer_record_t * write_buffer_record; uint8_t * p_buffer_memory; write_buffer_record = write_buffer_record_find(peer_id, data_id); if ((write_buffer_record != NULL) && (write_buffer_record->n_bufs < n_bufs)) { // @TODO: Copy? // Existing buffer is too small. for (uint8_t i = 0; i < write_buffer_record->n_bufs; i++) { pm_buffer_release(&m_pdb.write_buffer, write_buffer_record->buffer_block_id + i); } write_buffer_record_invalidate(write_buffer_record); write_buffer_record = NULL; } else if ((write_buffer_record != NULL) && write_buffer_record->n_bufs > n_bufs) { // Release excess blocks. for (uint8_t i = n_bufs; i < write_buffer_record->n_bufs; i++) { pm_buffer_release(&m_pdb.write_buffer, write_buffer_record->buffer_block_id + i); } } if (write_buffer_record == NULL) { write_buffer_record_get(&write_buffer_record, peer_id, data_id); if (write_buffer_record == NULL) { return NRF_ERROR_BUSY; } } if (write_buffer_record->buffer_block_id == BUFFER_INVALID_ID) { write_buffer_record->buffer_block_id = pm_buffer_block_acquire(&m_pdb.write_buffer, n_bufs); if (write_buffer_record->buffer_block_id == BUFFER_INVALID_ID) { write_buffer_record_invalidate(write_buffer_record); return NRF_ERROR_BUSY; } } write_buffer_record->n_bufs = n_bufs; p_buffer_memory = pm_buffer_ptr_get(&m_pdb.write_buffer, write_buffer_record->buffer_block_id); if (p_buffer_memory == NULL) { return NRF_ERROR_INTERNAL; } peer_data_point_to_buffer(p_peer_data, data_id, p_buffer_memory, n_bufs); switch(data_id) { case PM_PEER_DATA_ID_BONDING: /* No action needed. */ break; case PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING: /* No action needed. */ break; case PM_PEER_DATA_ID_GATT_LOCAL: { uint32_t size_offset = sizeof(pm_peer_data_local_gatt_db_t); p_peer_data->data.p_local_gatt_db->p_data = &p_buffer_memory[size_offset]; p_peer_data->data.p_local_gatt_db->len = (PDB_WRITE_BUF_SIZE*n_bufs)-size_offset; } break; case PM_PEER_DATA_ID_GATT_REMOTE: { uint32_t size_offset = sizeof(pm_peer_data_remote_gatt_db_t); p_peer_data->data.p_remote_gatt_db->p_data = (ble_gatt_db_srv_t*)&(p_buffer_memory[size_offset]); p_peer_data->data.p_remote_gatt_db->service_count = ((PDB_WRITE_BUF_SIZE*n_bufs)-size_offset)/sizeof(ble_gatt_db_srv_t); } break; case PM_PEER_DATA_ID_APPLICATION: { p_peer_data->data.p_application_data = p_buffer_memory; } break; default: // Invalid data_id. This should have been picked up earlier. return NRF_ERROR_INTERNAL; } return NRF_SUCCESS; }