static bool is_cccd_configured(uint16_t conn_handle)
{
    uint32_t          err_code;
    uint8_t           cccd_value_buf[BLE_CCCD_VALUE_LEN];
    ble_gatts_value_t value;
    bool              is_ctrlpt_notif_enabled = false;

    value.len     = BLE_CCCD_VALUE_LEN;
    value.offset  = 0;
    value.p_value = cccd_value_buf;

    err_code = sd_ble_gatts_value_get(conn_handle,
                                      m_char_ctrlpt_handles.cccd_handle,
                                      &value);

    // TODO: Error codes should be sent back to application indicating that the
    // read of CCCD did not work. No application error handler is currently
    // implemented.
    (void)err_code;

    uint16_t cccd_value = uint16_decode(cccd_value_buf);
    is_ctrlpt_notif_enabled = ((cccd_value & BLE_GATT_HVX_NOTIFICATION) != 0);

    return is_ctrlpt_notif_enabled;
}
Beispiel #2
0
/**@brief     Function for checking if the CCCD of DFU Control point is configured for Notification.
 *
 * @details   This function checks if the CCCD of DFU Control Point characteristic is configured
 *            for Notification by the DFU Controller.
 *
 * @param[in] p_dfu DFU Service structure.
 *
 * @return    True if the CCCD of DFU Control Point characteristic is configured for Notification.
 *            False otherwise.
 */
static bool is_cccd_configured(ble_dfu_t * p_dfu)
{
    // Check if the CCCDs are configured.
    uint8_t  cccd_val_buf[BLE_CCCD_VALUE_LEN];
    ble_gatts_value_t gatts_value;

    // Initialize value struct.
    memset(&gatts_value, 0, sizeof(gatts_value));

    gatts_value.len     = BLE_CCCD_VALUE_LEN;
    gatts_value.offset  = 0;
    gatts_value.p_value = cccd_val_buf;

    // Check the CCCD Value of DFU Control Point.
    uint32_t err_code = sd_ble_gatts_value_get(p_dfu->conn_handle,
                                               p_dfu->dfu_ctrl_pt_handles.cccd_handle,
                                               &gatts_value);
    if (err_code != NRF_SUCCESS)
    {
        if (p_dfu->error_handler != NULL)
        {
            p_dfu->error_handler(err_code);
        }
        return false;
    }

    return ble_srv_is_notification_enabled(cccd_val_buf);
}
uint32_t mesh_srv_char_val_get(uint8_t index, uint8_t* data, uint16_t* len, ble_gap_addr_t* origin_addr)
{
    if (!is_initialized)
    {
        return NRF_ERROR_INVALID_STATE;
    }
    
    if (index > g_mesh_service.value_count || index == 0)
    {
        return NRF_ERROR_INVALID_ADDR;
    }
    
    *len = MAX_VALUE_LENGTH;
    
    uint32_t error_code = sd_ble_gatts_value_get(
        g_mesh_service.char_metadata[index - 1].char_value_handle, 
        0, len, data);
    
    if (error_code != NRF_SUCCESS)
    {
        return NRF_ERROR_INTERNAL;
    }
    
    if (origin_addr != NULL)
    {
        memcpy(origin_addr, 
            &g_mesh_service.char_metadata[index - 1].last_sender_addr, 
            sizeof(ble_gap_addr_t));
    }
    
    return NRF_SUCCESS;
}
Beispiel #4
0
/**@brief check if the cccd is configured
 *
 * @param[in]   p_sc_ctrlpt      SC Ctrlpt structure.
 * @return  true if the sc_control point's cccd is correctly configured, false otherwise.
 */
static bool is_cccd_configured(ble_sc_ctrlpt_t * p_sc_ctrlpt)
{
    uint32_t err_code;
    uint8_t  cccd_value_buf[BLE_CCCD_VALUE_LEN];
    bool     is_sccp_indic_enabled = false;
    ble_gatts_value_t gatts_value;

    // Initialize value struct.
    memset(&gatts_value, 0, sizeof(gatts_value));

    gatts_value.len     = BLE_CCCD_VALUE_LEN;
    gatts_value.offset  = 0;
    gatts_value.p_value = cccd_value_buf;

    err_code = sd_ble_gatts_value_get(p_sc_ctrlpt->conn_handle,
                                      p_sc_ctrlpt->sc_ctrlpt_handles.cccd_handle,
                                      &gatts_value);
    if (err_code != NRF_SUCCESS)
    {
        // Report error to application
        if (p_sc_ctrlpt->error_handler != NULL)
        {
            p_sc_ctrlpt->error_handler(err_code);
        }
    }

    is_sccp_indic_enabled = ble_srv_is_indication_enabled(cccd_value_buf);

    return is_sccp_indic_enabled;
}
Beispiel #5
0
uint32_t ble_hts_is_indication_enabled(ble_hts_t * p_hts, bool * p_indication_enabled)
{
    uint32_t err_code;
    uint8_t  cccd_value_buf[BLE_CCCD_VALUE_LEN];
    ble_gatts_value_t gatts_value;

    // Initialize value struct.
    memset(&gatts_value, 0, sizeof(gatts_value));

    gatts_value.len     = BLE_CCCD_VALUE_LEN;
    gatts_value.offset  = 0;
    gatts_value.p_value = cccd_value_buf;

    err_code = sd_ble_gatts_value_get(p_hts->conn_handle,
                                      p_hts->meas_handles.cccd_handle,
                                      &gatts_value);
    if (err_code == NRF_SUCCESS)
    {
        *p_indication_enabled = ble_srv_is_indication_enabled(cccd_value_buf);
    }
    if (err_code == BLE_ERROR_GATTS_SYS_ATTR_MISSING)
    {
        *p_indication_enabled = false;
        return NRF_SUCCESS;
    }
    return err_code;
}
ble_error_t nRF51GattServer::readValue(uint16_t charHandle, uint8_t buffer[], uint16_t *const lengthP)
{
    ASSERT( ERROR_NONE ==
            sd_ble_gatts_value_get(nrfCharacteristicHandles[charHandle].value_handle, 0, lengthP, buffer),
            BLE_ERROR_PARAM_OUT_OF_RANGE);

    return BLE_ERROR_NONE;
}
Beispiel #7
0
uint32_t ble_hids_outp_rep_get(ble_hids_t * p_hids,
                               uint8_t      rep_index,
                               uint16_t     len,
                               uint8_t      offset,
                               uint8_t *    p_outp_rep)
{
    return sd_ble_gatts_value_get(p_hids->outp_rep_array[rep_index].char_handles.value_handle,
                                  offset,
                                  &len,
                                  p_outp_rep);
}
Beispiel #8
0
uint32_t mesh_srv_char_md_get(mesh_metadata_char_t* metadata)
{
    if (!is_initialized)
    {
        return NRF_ERROR_INVALID_STATE;
    }

    uint8_t data_array[MESH_MD_CHAR_LEN];
    uint16_t len = MESH_MD_CHAR_LEN;
    ble_gatts_value_t ble_gatts_value_get;
    ble_gatts_value_get.len = len;
    ble_gatts_value_get.offset = 0;
    ble_gatts_value_get.p_value = data_array;

    uint32_t error_code = sd_ble_gatts_value_get(
        BLE_CONN_HANDLE_INVALID,
				g_mesh_service.ble_md_char_handles.value_handle,
				&ble_gatts_value_get);

		len = ble_gatts_value_get.len;

    if (error_code != NRF_SUCCESS)
    {
        return NRF_ERROR_INTERNAL;
    }

    if (len != MESH_MD_CHAR_LEN)
    {
        return NRF_ERROR_INTERNAL;
    }

    memcpy(&metadata->mesh_access_addr,
        &data_array[MESH_MD_CHAR_AA_OFFSET],
        sizeof(metadata->mesh_access_addr));

    memcpy(&metadata->mesh_adv_int_ms,
        &data_array[MESH_MD_CHAR_ADV_INT_OFFSET],
        sizeof(metadata->mesh_adv_int_ms));

    memcpy(&metadata->mesh_channel,
        &data_array[MESH_MD_CHAR_CH_OFFSET],
        sizeof(metadata->mesh_channel));

    memcpy(&metadata->mesh_value_count,
        &data_array[MESH_MD_CHAR_COUNT_OFFSET],
        sizeof(metadata->mesh_value_count));

    return NRF_SUCCESS;
}
ble_error_t nRF5xGattServer::read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP)
{
    ble_gatts_value_t value = {
        /* .len     = */ *lengthP,
        /* .offset  = */ 0,
        /* .p_value = */ buffer,
    };

    ASSERT_TRUE( ERROR_NONE ==
            sd_ble_gatts_value_get(connectionHandle, attributeHandle, &value),
            BLE_ERROR_PARAM_OUT_OF_RANGE);
    *lengthP = value.len;

    return BLE_ERROR_NONE;
}
Beispiel #10
0
uint32_t ble_ias_alert_level_get(ble_ias_t * p_ias, uint8_t * p_alert_level)
{
    ble_gatts_value_t gatts_value;

    // Initialize value struct.
    memset(&gatts_value, 0, sizeof(gatts_value));

    gatts_value.len     = sizeof(uint8_t);
    gatts_value.offset  = 0;
    gatts_value.p_value = p_alert_level;

    return sd_ble_gatts_value_get(p_ias->conn_handle,
                                  p_ias->alert_level_handles.value_handle,
                                  &gatts_value);
}
Beispiel #11
0
static bool is_cccd_configured(ble_dfu_t * p_dfu)
{
    uint8_t  cccd_val_buf[BLE_CCCD_VALUE_LEN];
    ble_gatts_value_t gatts_value = {0};

    gatts_value.len     = BLE_CCCD_VALUE_LEN;
    gatts_value.p_value = cccd_val_buf;

    // Check the CCCD Value of DFU Control Point.
    uint32_t err_code = sd_ble_gatts_value_get(m_conn_handle,
                                               p_dfu->dfu_ctrl_pt_handles.cccd_handle,
                                               &gatts_value);
    VERIFY_SUCCESS(err_code);

    return ble_srv_is_notification_enabled(cccd_val_buf);
}
Beispiel #12
0
uint32_t ble_hts_is_indication_enabled(ble_hts_t * p_hts, bool * p_indication_enabled)
{
    uint32_t err_code;
    uint8_t  cccd_value_buf[BLE_CCCD_VALUE_LEN];
    uint16_t len = BLE_CCCD_VALUE_LEN;
    
    err_code = sd_ble_gatts_value_get(p_hts->meas_handles.cccd_handle,
                                      0,
                                      &len,
                                      cccd_value_buf);
    if (err_code == NRF_SUCCESS)
    {
        *p_indication_enabled = ble_srv_is_indication_enabled(cccd_value_buf);
    }
    return err_code;
}
Beispiel #13
0
uint32_t ble_hids_outp_rep_get(ble_hids_t * p_hids,
                               uint8_t      rep_index,
                               uint16_t     len,
                               uint8_t      offset,
                               uint8_t    * p_outp_rep)
{
    ble_gatts_value_t gatts_value;

    // Initialize value struct.
    memset(&gatts_value, 0, sizeof(gatts_value));

    gatts_value.len     = len;
    gatts_value.offset  = offset;
    gatts_value.p_value = p_outp_rep;

    return sd_ble_gatts_value_get(p_hids->conn_handle,
                                  p_hids->outp_rep_array[rep_index].char_handles.value_handle,
                                  &gatts_value);
}
Beispiel #14
0
/**@brief     Function for checking if the CCCD of DFU Control point is configured for Notification.
 *
 * @details   This function checks if the CCCD of DFU Control Point characteristic is configured
 *            for Notification by the DFU Controller.
 *
 * @param[in] p_dfu DFU Service structure.
 *
 * @return    True if the CCCD of DFU Control Point characteristic is configured for Notification.
 *            False otherwise.
 */
static bool is_cccd_configured(ble_dfu_t * p_dfu)
{
    // Check if the CCCDs are configured.
    uint16_t cccd_len = BLE_CCCD_VALUE_LEN;
    uint8_t  cccd_val_buf[BLE_CCCD_VALUE_LEN];

    // Check the CCCD Value of DFU Control Point.
    uint32_t err_code = sd_ble_gatts_value_get(p_dfu->dfu_ctrl_pt_handles.cccd_handle,
                                               0,
                                               &cccd_len,
                                               cccd_val_buf);
    if (err_code != NRF_SUCCESS)
    {
        if (p_dfu->error_handler != NULL)
        {
            p_dfu->error_handler(err_code);
        }
        return false;
    }

    return ble_srv_is_notification_enabled(cccd_val_buf);
}
/**
 * Private methods
 */
static void onWrite(ble_evt_t * p_ble_evt)
{
    ret_code_t err_code;
    
    ble_gatts_evt_write_t *p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
    
    // 値を取り出す
    uint8_t buf[GATT_MAX_DATA_LENGTH];
    
    ble_gatts_value_t gatts_value;
    memset(&gatts_value, 0 , sizeof(gatts_value));
    gatts_value.len     = p_evt_write->len;
    gatts_value.offset  = 0;
    gatts_value.p_value = buf;
    err_code = sd_ble_gatts_value_get(context.connection_handle, p_evt_write->handle, &gatts_value);
    APP_ERROR_CHECK(err_code);
    
    // キャラクタリスティクスごとの処理に振り分ける
    if(p_evt_write->handle == context.target_log_id_char_handle.value_handle && gatts_value.len == 1) {
        context.target_log_id = buf[0];
    }
}
Beispiel #16
0
uint32_t mesh_srv_char_val_get(uint8_t index, uint8_t* data, uint16_t* len, ble_gap_addr_t* origin_addr)
{
    if (!is_initialized)
    {
        return NRF_ERROR_INVALID_STATE;
    }

    if (index > g_mesh_service.value_count || index == 0)
    {
        return NRF_ERROR_INVALID_ADDR;
    }

    *len = MAX_VALUE_LENGTH;
    ble_gatts_value_t ble_gatts_value_get;
    ble_gatts_value_get.len = *(uint16_t*)len;
    ble_gatts_value_get.offset = 0;
    ble_gatts_value_get.p_value = data;
    uint32_t error_code = sd_ble_gatts_value_get(
				BLE_CONN_HANDLE_INVALID,
        g_mesh_service.char_metadata[index - 1].char_value_handle,
        &ble_gatts_value_get);

		*len = ble_gatts_value_get.len;

    if (error_code != NRF_SUCCESS)
    {
        return NRF_ERROR_INTERNAL;
    }

    if (origin_addr != NULL)
    {
        memcpy(origin_addr,
            &g_mesh_service.char_metadata[index - 1].last_sender_addr,
            sizeof(ble_gap_addr_t));
    }

    return NRF_SUCCESS;
}
/**@brief check if the cccd is configured
 *
 * @param[in]   p_sc_ctrlpt      SC Ctrlpt structure.
 * @return  true if the sc_control point's cccd is correctly configured, false otherwise.
 */
static bool is_cccd_configured(ble_sc_ctrlpt_t * p_sc_ctrlpt)
{
    uint32_t err_code;
    uint8_t  cccd_value_buf[BLE_CCCD_VALUE_LEN];
    uint16_t len                   = BLE_CCCD_VALUE_LEN;
    bool     is_sccp_indic_enabled = false;

    err_code = sd_ble_gatts_value_get(p_sc_ctrlpt->sc_ctrlpt_handles.cccd_handle,
                                      0,
                                      &len,
                                      cccd_value_buf);
    if (err_code != NRF_SUCCESS)
    {
        // Report error to application
        if (p_sc_ctrlpt->error_handler != NULL)
        {
            p_sc_ctrlpt->error_handler(err_code);
        }
    }

    is_sccp_indic_enabled = ble_srv_is_indication_enabled(cccd_value_buf);

    return is_sccp_indic_enabled;
}
Beispiel #18
0
/**@brief Handle execute write events to from the Queued Write module.
 *
 * @param[in]   p_bms   Bond Management Service structure.
 * @param[in]   p_qwr   Queued Write Structure.
 * @param[in]   p_evt   Event received from the Queued Writes module.
 *
 * @retval BLE_GATT_STATUS_SUCCESS                    If the received event is accepted.
 * @retval BLE_BMS_OPCODE_OPERATION_FAILED            If the received event is not relevant for any of this module's attributes.
 * @retval BLE_BMS_OPCODE_NOT_SUPPORTED               If the received opcode is not supported.
 */
uint16_t on_qwr_exec_write(nrf_ble_bms_t * p_bms, nrf_ble_qwr_t * p_qwr, nrf_ble_qwr_evt_t * p_evt)
{
    ret_code_t           err_code;
    uint16_t             len = NRF_BLE_BMS_CTRLPT_MAX_LEN;
    uint8_t              mem_buffer[NRF_BLE_BMS_CTRLPT_MAX_LEN];
    nrf_ble_bms_ctrlpt_t ctrlpt;
    ble_gatts_value_t    ctrlpt_value;

    ctrlpt_value.len     = NRF_BLE_BMS_CTRLPT_MAX_LEN;
    ctrlpt_value.offset  = 0;
    ctrlpt_value.p_value = mem_buffer;

    const uint16_t ctrlpt_handle = p_bms->ctrlpt_handles.value_handle;
    err_code = sd_ble_gatts_value_get(p_bms->conn_handle, ctrlpt_handle, &ctrlpt_value);
    if (err_code != NRF_SUCCESS)
    {
        NRF_LOG_ERROR("Control point write: Operation failed.\r\n");
        return NRF_BLE_BMS_OPERATION_FAILED;
    }

    /* Decode operation */
    err_code = ctrlpt_decode(ctrlpt_value.p_value, len, &ctrlpt);
    if (err_code != NRF_SUCCESS)
    {
        NRF_LOG_ERROR("Control point write: Operation failed.\r\n");
        return NRF_BLE_BMS_OPERATION_FAILED;
    }

    /* Execute the requested operation. */
    ctrlpt_execute(p_bms, ctrlpt.op_code);

    /* Reset authorization status */
    p_bms->auth_status = NRF_BLE_BMS_AUTH_STATUS_DENIED;

    return BLE_GATT_STATUS_SUCCESS;
}
Beispiel #19
0
uint32_t ble_ias_alert_level_get(ble_ias_t * p_ias, uint8_t * p_alert_level)
{
    uint16_t len = sizeof(uint8_t);
    
    return sd_ble_gatts_value_get(p_ias->alert_level_handles.value_handle, 0, &len, p_alert_level);
}
Beispiel #20
0
static void on_ble_write(ble_cch_t * p_cch_service, ble_evt_t * p_ble_evt)
{
    // Decclare buffer variable to hold received data. The data can only be 32 bit long.
    uint32_t data_buffer;
    
		// Pupulate ble_gatts_value_t structure to hold received data and metadata.
    ble_gatts_value_t rx_data;
    rx_data.len = sizeof(uint32_t);
    rx_data.offset = 0;
    rx_data.p_value = (uint8_t*)&data_buffer;
    
    // Check if write event is performed on our characteristic or the CCCD
    if(p_ble_evt->evt.gatts_evt.params.write.handle == p_cch_service->charSTEP_handles.value_handle)
    {
        // Get stepper data
				sd_ble_gatts_value_get(p_cch_service->conn_handle, p_cch_service->charSTEP_handles.value_handle, &rx_data);
				
				if (rx_data.p_value[POSITION_byte] > MAX_STEPS)
					positionIwantToGo = MAX_STEPS;
				
				positionIwantToGo = rx_data.p_value[POSITION_byte];
				
				speed = SPEED_LIMIT + (0xff - rx_data.p_value[SPEED_byte]) * 40;
				//speed = rx_data.p_value[SPEED_byte] * 40;	
		}
		else if(p_ble_evt->evt.gatts_evt.params.write.handle == p_cch_service->charRGB_handles.value_handle)
    {
        // Get RGB data
				sd_ble_gatts_value_get(p_cch_service->conn_handle, p_cch_service->charRGB_handles.value_handle, &rx_data);
				
				if (rx_data.p_value[RED_byte] > 100)
					rx_data.p_value[RED_byte] = 100;
				if (rx_data.p_value[GREEN_byte] > 100)
					rx_data.p_value[GREEN_byte] = 100;
				if (rx_data.p_value[BLUE_byte] > 100)
					rx_data.p_value[BLUE_byte] = 100;
				
				setRGBled(rx_data.p_value[RED_byte], rx_data.p_value[GREEN_byte], rx_data.p_value[BLUE_byte]);		
		}
		else if(p_ble_evt->evt.gatts_evt.params.write.handle == p_cch_service->charR_handles.value_handle)
    {
        // Get RED data
				sd_ble_gatts_value_get(p_cch_service->conn_handle, p_cch_service->charR_handles.value_handle, &rx_data);
				
				if (rx_data.p_value[MLED_byte] > 100)
					rx_data.p_value[MLED_byte] = 100;
				
				setMled(rx_data.p_value[MLED_byte]);
		}
		else if(p_ble_evt->evt.gatts_evt.params.write.handle == p_cch_service->charSTEP_handles.cccd_handle)
    {
        // Get stepper cccd data
        sd_ble_gatts_value_get(p_cch_service->conn_handle, p_cch_service->charSTEP_handles.cccd_handle, &rx_data);
    }
		else if(p_ble_evt->evt.gatts_evt.params.write.handle == p_cch_service->charRGB_handles.cccd_handle)
    {
        // Get RGB cccd data
        sd_ble_gatts_value_get(p_cch_service->conn_handle, p_cch_service->charRGB_handles.cccd_handle, &rx_data);
    }
		else if(p_ble_evt->evt.gatts_evt.params.write.handle == p_cch_service->charR_handles.cccd_handle)
    {
        // Get R cccd data
        sd_ble_gatts_value_get(p_cch_service->conn_handle, p_cch_service->charR_handles.cccd_handle, &rx_data);
    }
}
Beispiel #21
0
uint32_t conn_mw_ble_gatts_value_set(uint8_t const * const p_rx_buf,
                                     uint32_t              rx_buf_len,
                                     uint8_t * const       p_tx_buf,
                                     uint32_t * const      p_tx_buf_len)
{
    SER_ASSERT_NOT_NULL(p_rx_buf);
    SER_ASSERT_NOT_NULL(p_tx_buf);
    SER_ASSERT_NOT_NULL(p_tx_buf_len);

    uint16_t          conn_handle;
    uint16_t          handle;
    uint8_t           attr_val_table[BLE_GATTS_VAR_ATTR_LEN_MAX];
    ble_gatts_value_t attr_val = 
    {
        .len = sizeof (attr_val_table),
        .offset = 0,
        .p_value = attr_val_table
    };
    ble_gatts_value_t * p_attr_val = &attr_val; 

    uint32_t err_code = NRF_SUCCESS;
    uint32_t sd_err_code;

    err_code = ble_gatts_value_set_req_dec(p_rx_buf, rx_buf_len, &conn_handle, &handle, &p_attr_val);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);
    
    sd_err_code = sd_ble_gatts_value_set(conn_handle, handle, p_attr_val);

    err_code = ble_gatts_value_set_rsp_enc(sd_err_code, p_tx_buf, p_tx_buf_len, p_attr_val);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);

    return err_code;
}

uint32_t conn_mw_ble_gatts_value_get(uint8_t const * const p_rx_buf,
                                     uint32_t              rx_buf_len,
                                     uint8_t * const       p_tx_buf,
                                     uint32_t * const      p_tx_buf_len)
{
    SER_ASSERT_NOT_NULL(p_rx_buf);
    SER_ASSERT_NOT_NULL(p_tx_buf);
    SER_ASSERT_NOT_NULL(p_tx_buf_len);

    uint16_t   conn_handle;
    uint16_t   handle;
    uint8_t    val[BLE_GATTS_VAR_ATTR_LEN_MAX];
    ble_gatts_value_t attr_value;
    ble_gatts_value_t * p_attr_value = &attr_value;

    attr_value.p_value = val;

    uint32_t err_code = NRF_SUCCESS;
    uint32_t sd_err_code;

    err_code = ble_gatts_value_get_req_dec(p_rx_buf, rx_buf_len, &conn_handle, &handle, &p_attr_value);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);

    sd_err_code = sd_ble_gatts_value_get(conn_handle, handle, p_attr_value);

    err_code = ble_gatts_value_get_rsp_enc(sd_err_code, p_tx_buf, p_tx_buf_len, p_attr_value);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);

    return err_code;
}
Beispiel #22
0
/**@brief Function for handling the @ref BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: BLE_GATTS_AUTHORIZE_TYPE_WRITE:  event from the SoftDevice.
 *
 * @param[in] p_escs     Eddystone Configuration Service structure.
 * @param[in] p_ble_evt Pointer to the event received from BLE stack.
 */
static void on_long_write(nrf_ble_escs_t * p_escs, ble_evt_t * p_ble_evt)
{
    static uint16_t write_evt_uuid;
    static bool write_evt_uuid_set = false;
    uint32_t err_code;

    VERIFY_PARAM_NOT_NULL_VOID(p_escs);
    VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt);

    ble_gatts_evt_write_t * p_evt_write =
        &p_ble_evt->evt.gatts_evt.params.authorize_request.request.write;
    ble_gatts_rw_authorize_reply_params_t reply = {0};

    if (p_evt_write->op == BLE_GATTS_OP_PREP_WRITE_REQ)
    {
        err_code = get_evt_type_for_handle(p_evt_write->handle, &write_evt_uuid);
        APP_ERROR_CHECK(err_code);

        write_evt_uuid_set = true;

        reply.type                     = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
        reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
        reply.params.write.update      = 0;
        reply.params.write.offset      = 0;
        reply.params.write.len         = p_evt_write->len;
        reply.params.write.p_data      = NULL;

        err_code = sd_ble_gatts_rw_authorize_reply(p_escs->conn_handle, &reply);
        APP_ERROR_CHECK(err_code);
    }

    else if (p_evt_write->op == BLE_GATTS_OP_EXEC_WRITE_REQ_NOW)
    {
        uint8_t           value_buffer[ESCS_ADV_SLOT_CHAR_LENGTH_MAX] = {0};
        ble_gatts_value_t value =
        {
            .len = sizeof(value_buffer),
            .offset = 0,
            .p_value = &(value_buffer[0])
        };

        ASSERT(write_evt_uuid_set);
        write_evt_uuid_set = false;

        reply.type                     = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
        reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
        reply.params.write.update      = 0;
        reply.params.write.offset      = 0;
        reply.params.write.len         = p_evt_write->len;
        reply.params.write.p_data      = NULL;

        err_code = sd_ble_gatts_rw_authorize_reply(p_escs->conn_handle, &reply);
        APP_ERROR_CHECK(err_code);

        // Now that the value has been accepted using 'sd_ble_gatts_rw_authorize_reply', it can be found in the database.
        err_code = sd_ble_gatts_value_get(  p_escs->conn_handle,
                                            p_escs->rw_adv_slot_handles.value_handle,
                                            &value);
        APP_ERROR_CHECK(err_code);

        p_escs->write_evt_handler(p_escs,
                                  write_evt_uuid,
                                  p_evt_write->handle,
                                  value.p_value,
                                  value.len);
    }
    else
    {
    }
}
*/
/**************************************************************************/
ble_error_t nRF51GattServer::readValue(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP)
{
    return readValue(BLE_CONN_HANDLE_INVALID, attributeHandle, buffer, lengthP);
}

ble_error_t nRF51GattServer::readValue(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP)
{
    ble_gatts_value_t value = {
        .len     = *lengthP,
        .offset  = 0,
        .p_value = buffer,
    };

    APP_ERROR_CHECK( sd_ble_gatts_value_get(connectionHandle, nrfCharacteristicHandles[attributeHandle].value_handle, &value) );
    *lengthP = value.len;

    return BLE_ERROR_NONE;
}

/**************************************************************************/
/*!
    @brief  Updates the value of a characteristic, based on the service
            and characteristic index fields

    @param[in]  charHandle
                The handle of the GattCharacteristic to write to
    @param[in]  buffer
                Data to use when updating the characteristic's value
                (raw byte array in LSB format)
/**************************************************************************/
ble_error_t nRF5xGattServer::read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP)
{
    return read(BLE_CONN_HANDLE_INVALID, attributeHandle, buffer, lengthP);
}

ble_error_t nRF5xGattServer::read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP)
{
    ble_gatts_value_t value = {
        .len     = *lengthP,
        .offset  = 0,
        .p_value = buffer,
    };

    ASSERT_TRUE( ERROR_NONE ==
            sd_ble_gatts_value_get(connectionHandle, attributeHandle, &value),
            BLE_ERROR_PARAM_OUT_OF_RANGE);
    *lengthP = value.len;

    return BLE_ERROR_NONE;
}

/**************************************************************************/
/*!
    @brief  Updates the value of a characteristic, based on the service
            and characteristic index fields

    @param[in]  charHandle
                The handle of the GattCharacteristic to write to
    @param[in]  buffer
                Data to use when updating the characteristic's value