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

Reply to read request with sd_ble_gatts_rw_authorize_reply(...) with data greater than 20 bytes

Hello,

This is my first time working on BLE and Nordic, so this might sound strange. I am trying to update data on the fly when the central requests char data.

I have been setting the is_defered_read bit in the char config so I get the event BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST and it works well.

I have then inserted code in on_rw_authorize_request() with something like:

else if (p_auth_req->type == BLE_GATTS_AUTHORIZE_TYPE_READ)
{
	NRF_LOG_INFO("Constructing configuration data");
	protobufFormatCB_t formatter = GetCfgServiceFormatter();
	uint8_t formatResult = 0;
	uint8_t data[BLE_PARAMETER_SERVICE_CONFIGURATION_DATA_DATA_MAX_LENGTH];
	memset(data, 0, sizeof(data));
	size_t len = 0;
	if (p_parameter_service->conn_handle != BLE_CONN_HANDLE_INVALID)
	{
		formatResult = formatter.cb(
					formatter.obj_addr,
					data,
					sizeof(data), &len);
					
	}

	ble_gatts_rw_authorize_reply_params_t params;
	params.type = BLE_GATTS_AUTHORIZE_TYPE_READ;
	params.params.read.gatt_status = formatResult
			? BLE_GATT_STATUS_SUCCESS
			: BLE_GATT_STATUS_ATTERR_UNLIKELY_ERROR;
	params.params.read.update = 1;
	params.params.read.offset = p_auth_req->request.read.offset;
	params.params.read.len = (int16_t)len;
	//params.params.read.len = 20;	//Passed 20 bytes, receiving NRF_ERROR_INVALID_PARAM
	params.params.read.p_data = data;

	uint32_t error_code = sd_ble_gatts_rw_authorize_reply(p_parameter_service->conn_handle, &params);
	if(error_code){
		NRF_LOG_ERROR("Error constructing data: %i", error_code);
	}
}

It seems that whenever the lenght is greater than 20 bytes, sd_ble_gatts_rw_authorize_reply returns 7 (invalid params). This seems tied to the MTU somehow, but I haven't found where yet.

What is strange is that I am able the send the whole (110bytes) message via sd_ble_gatts_value_set(...) or sd_ble_gatts_hvx(...), but would rather compute it on the fly with the central request.

I'm sure this is an easy fix, please enlighten me.. :)

Parents
  • The default ATT MTU is 23 bytes and the default LL payload is 27 bytes. So you can have 20 bytes of data in each packet. You can increase the ATT MTU, then the data will be fragmented into multiple LL packets and reassembled on the other side of the link. If you in addition increase the LL payload size you can send larger pieces of data without fragmentation. One typically increases both. For example and ATT MTU of 247, and a LL payload of 251 (this is max).

    See this for how to increase the ATT MTU.

Reply
  • The default ATT MTU is 23 bytes and the default LL payload is 27 bytes. So you can have 20 bytes of data in each packet. You can increase the ATT MTU, then the data will be fragmented into multiple LL packets and reassembled on the other side of the link. If you in addition increase the LL payload size you can send larger pieces of data without fragmentation. One typically increases both. For example and ATT MTU of 247, and a LL payload of 251 (this is max).

    See this for how to increase the ATT MTU.

Children
Related