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

I can't write 1 to a protected CCCD

I recently added bonding and authentication to my application. I have two characteristics with CCCDs and they are both broken. One characteristic is "protected" (requires authorization) and the other is not.   

When I try to enable Indications to the "protected" characteristic, the BLE event handler receives a BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST, which I just pass through like this: 
} else if (req->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE) {
    NRF_LOG_INFO("Unhandled write. Allowing. writeHandle: %d writeOp: %d UUID:0x%x UUID_TYPE: %d", req->request.write.handle, req->request.write.op, req->request.write.uuid.uuid, req->request.write.uuid.type);
    
    auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
    auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
    auth_reply.params.write.update = 1;
    auth_reply.params.write.offset = req->request.write.offset;
    auth_reply.params.write.len = req->request.write.len;
    auth_reply.params.write.p_data = req->request.write.data;
    APP_ERROR_CHECK(sd_ble_gatts_rw_authorize_reply(conn_handle, &auth_reply));
}
But nothing happens. i.e. no event is passed to the BLE event handler. I thought something was supposed to happen when I used sd_ble_gatts_rw_authorize_reply. What is the correct way to detect a CCCD write in response to sd_ble_gatts_rw_authorize_reply?
On the other hand, when I enable notifications for the "unprotected" characteristic, the BLE event handler receives a BLE_GATTS_EVT_WRITE, but in on_write(), my condition for detecting whether it was the right service broke! This used to work before bonding/authorization, now it doesnt. 
 if (    (p_evt_write->handle == p_service->rx_handles.cccd_handle)
        &&  (p_evt_write->len == 2))
    {
After bonding/authorization, 
(p_evt_write->handle == p_service->rx_handles.cccd_handle)  = 0. So then what is the correct way to detect a CCCD write for this particular characteristic? 
Parents
  • Hi Andrew,

    There are two types of writes you can do here

    1) The first one is "Write with Authorization" where you will get BLE_GATTS_EVT_WRITE event and the application needs to review the request and write to the characteristic manually using sd_ble_gatts_value_set. You can see the message sequence chart for this here

    2) The second one is the "Write Request with Authorization" , where the application will get BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST like you mentioned in your question and you set the characteristic to the requested value (or some other value) and give the response to the peer as a write response. The MSC for this can be seen here.

    Since your BLE handler is getting BLE_GATTS_EVT_WRITE event, this clearly means that the peer is doing a Write command instead of using the Write Request.

    Write Command from peer (client)-> BLE_GATTS_EVT_WRITE event on our device (server)

    Write request from peer (client) -> BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST on our device (server)

Reply
  • Hi Andrew,

    There are two types of writes you can do here

    1) The first one is "Write with Authorization" where you will get BLE_GATTS_EVT_WRITE event and the application needs to review the request and write to the characteristic manually using sd_ble_gatts_value_set. You can see the message sequence chart for this here

    2) The second one is the "Write Request with Authorization" , where the application will get BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST like you mentioned in your question and you set the characteristic to the requested value (or some other value) and give the response to the peer as a write response. The MSC for this can be seen here.

    Since your BLE handler is getting BLE_GATTS_EVT_WRITE event, this clearly means that the peer is doing a Write command instead of using the Write Request.

    Write Command from peer (client)-> BLE_GATTS_EVT_WRITE event on our device (server)

    Write request from peer (client) -> BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST on our device (server)

Children
  • Thanks Aryan. That helped. I also found out that for my protected characteristic, given the following header:

    static void on_rw_authorize_req(health_data_service_t * p_service, ble_evt_t const * p_ble_evt)
    {
    ble_gatts_evt_rw_authorize_request_t const * req = &p_ble_evt->evt.gatts_evt.params.authorize_request;

    I had to read from 

    req->request.write.handle == p_service->rx_handles.cccd_handle
    not
    p_evt_write->handle == p_service->rx_handles.cccd_handle
    Nevermind the question about the unprotected characteristic. I was looking at the wrong characteristic number. 
Related