Example #1
0
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;
}
Example #2
0
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;
    }
}
Example #3
0
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;
}
Example #4
0
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;
}
Example #5
0
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;
}
Example #6
0
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;
}
Example #7
0
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;
}
Example #8
0
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;
}
Example #9
0
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;
}
Example #10
0
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);
}
Example #11
0
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(&params, 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, &params);
}
Example #12
0
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;
}
Example #13
0
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;
}
Example #15
0
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);
}
Example #16
0
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;
}
Example #17
0
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;
}
Example #19
0
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;
}
Example #20
0
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;
}
Example #21
0
/**@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);
}
Example #22
0
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;
}
Example #23
0
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;
}
Example #24
0
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);
}
Example #25
0
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);
}
Example #26
0
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;
}
Example #27
0
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;
}
Example #28
0
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;
}
Example #29
0
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;
}
Example #30
0
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;
}