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

Why stack doesn't point to new value after sd_ble_gatts_rw_authorize_reply

Hi, I'm trying to implement GATTS Queued Writes: App handled, no attributes require authorization variant #2 VLOC_USER.

According to the documentation values in ATT table are set to the new values after the BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST{WRITE, EXEC_WRITE_REQ_NOW}.

Ok, but how? What does "Application traverses its queue and executes the write operations(memcpy)" mean?

I thought that call to the sd_ble_gatts_rw_authorize_reply() after BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST{WRITE, EXEC_WRITE_REQ_NOW} with

reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
reply.params.write.update = 1;
reply.params.write.len = length;
reply.params.write.p_data = &data;

would do the work and ATT table would point to the new value with new length. But that doesn't make sense because this function doesn't know which attribute value to modify (because it doesn't accept attribute handle in any way). Am I right?

Then what are these .update .len .p_data for?

Why should I in process of receiving data as a response to the BLE_GATTS_EVT_RW_AUTORIZE_EQUEST{WRITE, PREP_WRITE_REQ} call sd_ble_gatts_rw_authorize_reply() with .update = 1 and .len and .p_data could be ommited?

After investigation I've realized that only way I can point ATT table to the new value is by calling sd_ble_gatts_value_set() but that isn't right according to the documented Message sequence chart.

Update:

It seemed to work unless more data came.

For clarification i'm using std::vector vec to store received data and it is also the same vector used to create char with sd_ble_gatts_characteristic_add. Naturally when I receive more data vector grows and changes it's vec.data() pointer (memory where data is stored). I've used sd_ble_gatts_value_set() to let the stack know about new pointer to the memory with

ble_gatts_value_t value;
memset(&value, 0, sizeof(value));
value.len = vec.size();
value.p_value = vec.data();
sd_ble_gatts_value_set(connHandle, charHandle, &value);

This works for 32 bytes of written data (if I perform read after write from client I can see updated data). But when I write 42 bytes everything seems to be ok except that last two bytes are modified by stack! Before call to the sd_ble_gatts_value_set() content of vec is exactly as it should be filled with new 42 bytes (sent by client). But right after call to the sd_ble_gatts_value_set() last two bytes are modified!!

Why sd_ble_gatts_value_set() modifies the source of data?

Parents
  • "Application traverses its queue and executes the write operations(memcpy)" is very unclear. I recommend using sd_ble_gatts_value_set() to set the attribute values, as it seems you are doing now. So variant #1 and variant #2 are very similar actually. I have reported this as a documentation improvement.

    When you reply with sd_ble_user_mem_reply(p_ble_evt->evt.gattc_evt.conn_handle, NULL); you have to set the attribute values, the SoftDevice will not have any place to store the values you reply to sd_ble_gatts_rw_authorize_reply() until EXEC_WRITE_REQ_NOW is received.

    .update has to be 1 when type is BLE_GATTS_AUTHORIZE_TYPE_WRITE

    .p_data is actually sent back to the peer, see "Prepare write response" in the Bluetooth spec for more information.

Reply
  • "Application traverses its queue and executes the write operations(memcpy)" is very unclear. I recommend using sd_ble_gatts_value_set() to set the attribute values, as it seems you are doing now. So variant #1 and variant #2 are very similar actually. I have reported this as a documentation improvement.

    When you reply with sd_ble_user_mem_reply(p_ble_evt->evt.gattc_evt.conn_handle, NULL); you have to set the attribute values, the SoftDevice will not have any place to store the values you reply to sd_ble_gatts_rw_authorize_reply() until EXEC_WRITE_REQ_NOW is received.

    .update has to be 1 when type is BLE_GATTS_AUTHORIZE_TYPE_WRITE

    .p_data is actually sent back to the peer, see "Prepare write response" in the Bluetooth spec for more information.

Children
No Data
Related