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

[nRF8001] CCCD has no Write permission

I added a local service with a characteristic with the Notify permission set. On the device I'm connecting from to the nRF8001, I can see my custom characteristic has a 0x2902 (CCCD) descriptor. However, it has no permissions enabled, and thus I cannot write to it to enable notifications. If I try anyway, I don't get a PipeStatusEvent on the nRF8001.

The devices are not paired (using Bond), but only connected (using Connect).

What is wrong with my setup?

  • Would it be possible for you to switch to the D version of the chip as there are multiple bug fixes and additional features for the D version as compared to the C version. You can get breakout boards of the D version here. www.adafruit.com/.../1697

  • When you setup your characteristic ble_gatts_char_md_t, attach a cccd metadata definition to it, initialized like this:

    memset(&cccd_md, 0, sizeof(cccd_md));		
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);
    cccd_md.vloc = BLE_GATTS_VLOC_STACK;
    

    Then provide this to your characteristic metadata like this:

    char_md.char_props.write            = 1;
    char_md.char_props.write_wo_resp    = 1;
    char_md.char_props.notify           = 0;
    char_md.p_char_user_desc            = NULL;
    char_md.p_char_pf                   = NULL;
    char_md.p_user_desc_md              = NULL;
    char_md.p_cccd_md                   = &cccd_md;
    char_md.p_sccd_md                   = NULL;
    

    Notice I've also set the "write_wo_resp" field to 1 which skips the whole BLE_GATTS_AUTHORIZE_TYPE_WRITE step, which might be what you are hitting...

    Then also set no access rights on your attribute metdata, and give it write permission with wr_auth = 1;

    memset(&attr_md, 0, sizeof(attr_md));
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); 
    attr_md.vloc       = BLE_GATTS_VLOC_STACK;
    attr_md.rd_auth    = 0;
    attr_md.wr_auth    = 1;
    attr_md.vlen       = 1;
    
  • I think the poster is using an nRF8001. The CCCDs in the nRF8001 are handled automatically without any user code. The ability to Notify is mapped to a "Pipe". This "Pipe" becomes available when the peer enables/subscribes to Notifications/Indictions and the "Pipe" becomes unavailable when the peer has not enabled/unsubscribed to Notifications.

    You can use the Android based Master Control panel(Nordic) or iOS based lightblue or PC based Master control panel(Nordic) to test subscriptions/enable Notify/Indicate.

  • woops my bad, I missed the nRF8001 in the title of the post. So ignore what I said :-)

  • Hi all,

    Thanks for thinking along with me.

    Turns out everything works fine, but two things threw me off:

    1. Android told me the permissions on the descriptor were 0, but I actually do have permission to write to it. I don't know why it says I don't. I said I tried writing to it anyway, but didn't work, but that is because:
    2. I was reading the Android documentation wrong. It isn't enough to enable notifications on the characteristic through the built-in API method, but you have to explicitly write the ENABLE_NOTIFICATIONS value to the descriptor to make it work.

    And all is well now!

    Android snippet describing the code needed to make it work: developer.android.com/.../bluetooth-le.html

Related