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

Adding characteristic (for purpose of long read) fails

I've added a custom service for transferring data. It shall contain one characteristic that will notify when data is available, and the other should be a long read characteristic (no notify). sd_ble_gatts_characteristic_add is failing (return 0x7) when I add the second characteristic.

I've made attr_char_value.max_len to 512. I am enabling attr_md.rd_auth = 1 to handle the long read as mentioned in the post devzone.nordicsemi.com/.../

Is this the right way, or are there any new preferred way to enable long read ?

Could someone please point out what is the invalid parameter ? I'm using sdk 14.1 with GCC compiler. The code is below:

static uint32_t sensor_data_char_add(ble_ksh_t * p_ksh, ble_ksh_init_t const * p_pke_init) {
ble_gatts_char_md_t char_md;
ble_gatts_attr_md_t cccd_md;
ble_gatts_attr_t    attr_char_value;
ble_uuid_t          ble_uuid;
ble_gatts_attr_md_t attr_md;

extern uint8_t sensor_data_buffer[BLE_KSH_MAX_DATA_CHAR_LEN];

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

BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);

cccd_md.vloc = BLE_GATTS_VLOC_STACK;

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

char_md.char_props.read = 1;
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;

ble_uuid.type = p_ksh->uuid_type;
ble_uuid.uuid = BLE_UUID_KSH_DATA_CHARACTERISTIC;

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

BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);

attr_md.vloc    = BLE_GATTS_VLOC_STACK;
attr_md.rd_auth = 1;
attr_md.wr_auth = 0;
attr_md.vlen    = 1;

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

attr_char_value.p_uuid    = &ble_uuid;
attr_char_value.p_attr_md = &attr_md;
attr_char_value.init_len  = sizeof(uint8_t);
attr_char_value.init_offs = 0;
attr_char_value.max_len   = BLE_GATTS_VAR_ATTR_LEN_MAX;
attr_char_value.p_value   = &sensor_data_buffer[0];

return sd_ble_gatts_characteristic_add(p_ksh->service_handle,
                                       &char_md,
                                       &attr_char_value,
                                       &p_ksh->data_handles);

}

Parents Reply Children
  • Thank you for the response @Hung Bui, I have some questions:

    1. Are there any other setup necessary to do related to GATT Client during initialization?

    2. Is the value 512 valid for the max length of the characteristic?

    3. I'm unable to understand the reason why cccd needs the write permission, when there is no need for a peer to write to it, since it doesnt support enabling notification. Are there other reasons cccd needs to be written ?

    1. Even though both read blob and read with authorization are not related, is this not the only way to send to the peer a long read sequence when the peer does a normal read ? My assumption was that I will have to enable read with authorization for this characteristic, and just before I reply, I will have to call the corresponding api that does long read (which turns out to be sd_ble_gattc_read instead of sd_ble_gatts_value_get from your answer). Is this the right way to make a long read happen ?

    2. Is my understanding correct that the peer has only one kind of read; and its the peripheral that decides to do a long/normal read ?

    1. Inorder to tell the stack that I have fresh data to be sent from the peripheral next time when a read is performed by a peer, the function to be used to set the fresh data is sd_ble_gatts_set_data() ? If so, this function takes a pointer to data with its length and offset. What significance does it have wrt the data pointer that was initially setup for this characteristic when it was created/added ? Can i point to this same buffer ?
  • :

    1. No. Why you talk about GATT client here? we are talking about gatt server.

    2. It should as it's defined in BLE_GATTS_VAR_ATTR_LEN_MAX isn't it.

    3. "The Client Characteristic Configuration declaration shall be readable and writable." It's defined in the spec (section 3.3.3.3 Vol 3 Part G Spec v4.0)

    4. I don't understand you. Authorization has nothing to do with long read. Have you looked at the sequence chart I mentioned in the answer ??

    5. Check the message sequence chart.

    6. You mean sd_ble_gatts_value_set? This function tells nothing to the peer device, it only update the value of the characteristic. You need to send a notification if you want to tell the peer device you have new data (using sd_ble_gatts_hvx() function). This function take a pointer and length and then update it to the buffer you declare when you initialize the characteristic. The buffer can be inside the stack if you use BLE_GATTS_VLOC_STACK. If you use BLE_GATTS_VLOC_USER, the it will be the buffer you provided as the initialize value of the characteristic.

Related