This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to enable indication and get CCCD value to check

Hi All,

I want to use DFU to update the firmware from master to peripheral over BLE ,  both master and peripheral are nrf52840. My purpose is that the master sends a command to make the peripheral enter bootloader.Therefore I need enable indication and write 0x01 to peripheral. "nrf connect" can do it.

But the problem is that I don't kown if the indication is enable on peripheral.I referred to other answers but failed becuase I can't excuess sd_ble_gatts_value_get() and  sd_ble_gatts_hvx() correctly, my programs are below.

 

//enable indication
static uint32_t cccd_configure(ble_hrs_c_t * p_ble_hrs_c, bool enable)
{
    NRF_LOG_INFO("Configuring CCCD. CCCD Handle = %x, Connection Handle = %x",
                  p_ble_hrs_c->peer_hrs_db.hrm_cccd_handle,
                  p_ble_hrs_c->conn_handle);

    nrf_ble_gq_req_t hrs_c_req;
    uint8_t          cccd[BLE_CCCD_VALUE_LEN];
    uint16_t         cccd_val = enable ? BLE_GATT_HVX_INDICATION : 0;

    cccd[0] = LSB_16(cccd_val);
    cccd[1] = MSB_16(cccd_val);

    memset(&hrs_c_req, 0, sizeof(hrs_c_req));

    hrs_c_req.type                        = NRF_BLE_GQ_REQ_GATTC_WRITE;
    hrs_c_req.error_handler.cb            = gatt_error_handler;
    hrs_c_req.error_handler.p_ctx         = p_ble_hrs_c;
    hrs_c_req.params.gattc_write.handle   = p_ble_hrs_c->peer_hrs_db.hrm_cccd_handle;
    hrs_c_req.params.gattc_write.len      = BLE_CCCD_VALUE_LEN;
	hrs_c_req.params.gattc_write.offset   = 0;
    hrs_c_req.params.gattc_write.p_value  = cccd;
    hrs_c_req.params.gattc_write.write_op = BLE_GATT_OP_WRITE_REQ;
	hrs_c_req.params.gattc_write.flags    = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE;
    return nrf_ble_gq_item_add(p_ble_hrs_c->p_gatt_queue, &hrs_c_req, p_ble_hrs_c->conn_handle);
}

ble_hrs_c_handles_assign

uint32_t ble_hrs_c_handles_assign(ble_hrs_c_t    * p_ble_hrs_c,
                                  uint16_t         conn_handle,
                                  const hrs_db_t * p_peer_hrs_handles)
{
    VERIFY_PARAM_NOT_NULL(p_ble_hrs_c);

    p_ble_hrs_c->conn_handle = conn_handle;
    if (p_peer_hrs_handles != NULL)
    {
        //p_ble_hrs_c->peer_hrs_db = *p_peer_hrs_handles;
		NRF_LOG_INFO("In handles assign");
		p_ble_hrs_c->peer_hrs_db.hrm_cccd_handle = p_peer_hrs_handles->hrm_cccd_handle;
		p_ble_hrs_c->peer_hrs_db.hrm_handle = p_peer_hrs_handles->hrm_handle;
    }

    return nrf_ble_gq_conn_handle_register(p_ble_hrs_c->p_gatt_queue, conn_handle);
}

when find the service and characteristics

 

static void hrs_c_evt_handler(ble_hrs_c_t * p_hrs_c, ble_hrs_c_evt_t * p_hrs_c_evt)
{
	
    ret_code_t err_code;
	bool       is_indication_enabled = true;
    switch (p_hrs_c_evt->evt_type)
    {
        case BLE_HRS_C_EVT_DISCOVERY_COMPLETE:
        {
            NRF_LOG_INFO("dfu service discovered.");

            err_code = ble_hrs_c_handles_assign(p_hrs_c,
                                                p_hrs_c_evt->conn_handle,
                                                &p_hrs_c_evt->params.peer_db);
            APP_ERROR_CHECK(err_code);

			err_code = cccd_configure(p_hrs_c,true);
            APP_ERROR_CHECK(err_code);
			ble_gatts_value_t gatt_value;
			uint8_t cccd_value;
			gatt_value.len = 2;
			gatt_value.p_value = &cccd_value;
			gatt_value.offset = 0;
			err_code = sd_ble_gatts_value_get(p_hrs_c_evt->conn_handle, p_hrs_c->peer_hrs_db.hrm_cccd_handle, &gatt_value);
			APP_ERROR_CHECK(err_code);
        } break;
        default:
            break;
    }
}

connection handle : 0, characteristics handle:0x16, cccd handle:0x17

sd_ble_gatts_value_get() returned error 5 

I have no idea where is wrong , please give me some advice

Thanks,

Steven

  • I am not sure I understand you. In your screenshot, you have highlighted the buttonless DFU service, but your snippets looks like they are using the bl_app_hrs_c (which is a central) service.

    Are you trying to enable indications from a central, or are you trying to check whether a central have enabled indications?

    And is there a particular reason why you are using indications and not notifications?

    the sd_ble_gatts_value_get() is a gatt server call, which is intended for the peripheral to check the value of the characteristic. You can't use this on the central.

    If you want to check how to enable notifications, please check the unmodified ble_app_hrs_c (download and unzip a new SDK if you have changed a lot in the service's files).

    Look at how it uses ble_hrs_c_hrm_notif_enable(). It uses cccd_configure from ble_hrs_c.c. Please note the line:

    uint16_t         cccd_val = enable ? BLE_GATT_HVX_NOTIFICATION : 0;

    If you want to use indications instead of notifications, please change BLE_GATT_HVX_NOTIFICATION to BLE_GATT_HVX_INDICATION, but please check whether the peripheral supports indications at all before you do so. The ble_app_hrs example does not support indications by default (and if you change it, it no longer complies with the HRS service, which is determined by Bluetooth).

    Best regards,

    Edvin

  • Hi Edvin 

    Thanks for your quick reply.

    but your snippets looks like they are using the bl_app_hrs_c (which is a central) service.

    I just use the example of bl_app_hrs_c and changed UUIDs because I didn't find any example of DFU  in master(based on nrf52840). My purpose is that the master sends a command to make the peripheral enter bootloader. I would rewrite the codes when I understand more.

    The peripheral has bootloader(based on Buttonless Secure DFU Service) and I can use "nRF connect" to enter bootloader of peripheral (enable indication and write 0x01).My ultimate goal is to enable the master to control the  peripheral upgrade just like "nrf connect".

    Are you trying to enable indications from a central, or are you trying to check whether a central have enabled indications?

    And is there a particular reason why you are using indications and not notifications?

    Yes, I am trying to enable indications from a central, but I don't know if it works. Therefore I try to confirm it.

    I refer to the infomation(Subscribe for indications and write 0x01 into the characteristic) here.

    If you want to use indications instead of notifications, please change BLE_GATT_HVX_NOTIFICATION to BLE_GATT_HVX_INDICATION, but please check whether the peripheral supports indications at all before you do so.

    I think the peripheral supports indications because I can use "nrf connect" to enable indications and enter bootloader.

    All in all, I have found the service(0xfe59) and its characteristic(Buttonless DFU without bonds:0x03) but failed to write 0x01 to the peripheral. Therefore,I tried to check whether indications aren't enable or failed to write 0x01 into the characteristic.

    Best regards,

    Steven

  • Try to copy the ble_hrs_c_hrm_norif_enable() function and change it from notification to indication, as I described in the previous reply.

    If you want to test whether indications are already enabled, please try to read the characteristic description. The HRS example doesn't do this, and I don't think we have any central examples that does this, really. (Probably because it is easier to just enable the indication/notification again, which I recommend).

    What you need to do to read is to use the implementation from cccd_configure() in ble_hrs_c.c and change NRF_BLE_GQ_REQ_GATTC_WRITE to NRF_BLE_GX_REQ_GATTC_READ, and change all instances of:

    hrs_c_req.params.gattc_write. ...

    with 

    hrs_c_req.params.gattc_read. ...

    This will probably generate an event at a later point in time in your ble_evt_handler:

    case BLE_GATTC_EVT_READ_RSP:

    Look at the p_ble_evt->evt.gattc_evt.params.read_rsp struct (ble_gattc_evt_read_rsp_t) to implement this handler.

    BR,

    Edvin

  • Hi Edvin 

    Thanks for your reply.

    I still have two questions.

    Try to copy the ble_hrs_c_hrm_norif_enable() function and change it from notification to indication, as I described in the previous reply.

    1. To enable indications, the changes in cccd_configure() are:

    1. cccd_val = enable ? BLE_GATT_HVX_INDICATION : 0;
    
    // use my cccd handle
    2.hrs_c_req.params.gattc_write.handle = p_ble_hrs_c->peer_hrs_db.hrm_cccd_handle;
    
    // use my connection handle
    3. return nrf_ble_gq_item_add(p_ble_hrs_c->p_gatt_queue, &hrs_c_req, p_ble_hrs_c->conn_handle);

    Is that right?

    2.If I want to write 0x01 to the characteristic(Buttonless DFU without bonds:0x03) ,where can I get examples.

    Best regards,

    Steven

  • lolifrog said:
    Is that right?

     Yes. Does it return NRF_SUCCESS (0x00)? And do you see the callback later?

     

    lolifrog said:
    2.If I want to write 0x01 to the characteristic(Buttonless DFU without bonds:0x03) ,where can I get examples.

     Look at how the ble_app_uart_c writes to a characteristic using ble_nus_c_string_send().

    Best regards,

    Edvin

Related