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

Maximum data length for a notification drops from 20 to 10 bytes?

In previous SDK (or softdevice?) version, the maximum data length for a notification was 20 bytes.

With SDK V10 and softdevice 8, the following code returns error NRF_ERROR_DATA_SIZE if the length is greather than 10 bytes.

err_code = sd_ble_gatts_value_set(p_watch->conn_handle,
                                  p_watch->command_handles.value_handle,
                                  &gatts_value);    

Is there a new limitation on the maximum data length for notification or am I missing something?

EDIT

This is how I am defining the characteristic. When BLE_RESPONSE_MAX_LENGTH is set to 10 everything is fine, but when it is set to 20, the NRF_ERROR_DATA_SIZE is throw when I try to send a notification.

/**@brief Add Response characteristic.
 *
 * @param[in]   p_watch        Watch Service structure.
 * @param[in]   p_watch_init   Information needed to initialize the service.
 *
 * @return      NRF_SUCCESS on success, otherwise an error code.
 */
static uint32_t response_char_add(ble_watch_t * p_watch, const ble_watch_init_t * p_watch_init)
{
    uint32_t            err_code;
    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;
    uint32_t            initial_value = 0;
    uint8_t             encoded_buffer[BLE_RESPONSE_MAX_LENGTH] = {0};
    
    // Add notification support
    if (p_watch->is_notification_supported_response_char)
    {
        memset(&cccd_md, 0, sizeof(cccd_md));
    
        // According to BAS_SPEC_V10, the read operation on cccd should be possible without
        // authentication.
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);//TODO : confirm write access
        cccd_md.vloc = BLE_GATTS_VLOC_STACK;
    }
    
    memset(&char_md, 0, sizeof(char_md));
            
    char_md.p_char_user_desc  = NULL;
    char_md.char_props.read   = 1;
    char_md.char_props.notify = (p_watch->is_notification_supported_response_char) ? 1 : 0;
    char_md.p_char_pf         = NULL;
    char_md.p_user_desc_md    = NULL;
    char_md.p_cccd_md         = (p_watch->is_notification_supported_response_char) ? &cccd_md : NULL;
    char_md.p_sccd_md         = NULL;                
    
    ble_uuid.type = p_watch->uuid_type;
    ble_uuid.uuid = BLE_UUID_WATCH_RESPONSE_CHAR;
    
    memset(&attr_md, 0, sizeof(attr_md));

    //BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&attr_md.read_perm);
    //BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&attr_md.write_perm);    
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&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    = 0;
    attr_md.vlen       = 0;
            
    unix_time_encode(initial_value,encoded_buffer);
    
    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     = BLE_RESPONSE_MAX_LENGTH;
    attr_char_value.init_offs    = 0;
    attr_char_value.max_len      = BLE_RESPONSE_MAX_LENGTH;
    attr_char_value.p_value      = encoded_buffer;
    
    err_code = sd_ble_gatts_characteristic_add(p_watch->service_handle, 
                                               &char_md,
                                               &attr_char_value,
                                               &p_watch->response_handles);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }
        
    return NRF_SUCCESS;
}

And this is how I send the notification

/**@brief Response characteristic update
 *
 * @param[in]   p_watch  watch Service structure.
 * @param[in]   value    New value to update.
 */
uint32_t ble_response_update(ble_watch_t * p_watch, uint8_t * p_data_buffer)
{
    ble_gatts_value_t gatts_value;  
    uint32_t          err_code = NRF_SUCCESS;
    uint8_t           encoded_buffer[BLE_RESPONSE_MAX_LENGTH] = {0x00};

    memcpy(encoded_buffer,p_data_buffer, BLE_RESPONSE_MAX_LENGTH);
    uint16_t len = BLE_RESPONSE_MAX_LENGTH;
                    
    // Initialize value struct.
    memset(&gatts_value, 0, sizeof(gatts_value));

    gatts_value.len     = len;
    gatts_value.offset  = 0;
    gatts_value.p_value = encoded_buffer;
        
    // Update database
    err_code = sd_ble_gatts_value_set(p_watch->conn_handle,
                                      p_watch->command_handles.value_handle,
                                      &gatts_value);    
    
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }
        
    // Send value if connected and notifying
    if ((p_watch->conn_handle != BLE_CONN_HANDLE_INVALID) && p_watch->is_notification_supported_response_char)
    {
        ble_gatts_hvx_params_t hvx_params;
        memset(&hvx_params, 0, sizeof(hvx_params));
                    
        hvx_params.handle   = p_watch->response_handles.value_handle;
        hvx_params.type     = BLE_GATT_HVX_NOTIFICATION;
        hvx_params.offset   = 0;
        hvx_params.p_len    = &len;
        hvx_params.p_data   = encoded_buffer;
        
        err_code = sd_ble_gatts_hvx(p_watch->conn_handle, &hvx_params);                
    }
    else
    {
        err_code = NRF_ERROR_INVALID_STATE;
    }

    return err_code;
}

EDIT 2

Capture from Keil to depict the problem when sending notification with BLE_RESPONSE_MAX_LENGTH set to 20

image description

Best regards

Related