BLE Write Request, Write Command, Signed Write Command & Prepare Write

Summary

In my article entitled “PSoC4 BLE Central Custom Profile w/LED & CapSense” a reader named Doug posted a question which asked about BLE Writes and the events that are created in PSoC 4 BLE.  This article attempts to answer those questions.  The bottom line is that the BLE Spec specifies four ways for a GATT Client to write to a GATT Server.  Each of those write types either have a response or not.  Inside of the PSoC BLE Stack each of them generate a different event.

Here is a summary of the BLE Write Events from my WICED BLE textbook chapter 4D.4

Inside of the PSoC Stack it will generate the following events:

Request Event PSoC 4 Response API
Write Request CYBLE_EVT_GATTS_WRITE_REQ No Response
Write Command CYBLE_EVT_GATTS_WRITE_CMD_REQ CyBle_GattsWriteRsp or CyBle_GattsErrorRsp
Signed Write CYBLE_EVT_GATTS_DATA_SIGNED_CMD_REQ CyBle_GattsWriteRsp or CyBle_GattsErrorRsp
Prepare Write CYBLE_EVT_GATTS_PREP_WRITE_REQ Out of scope for today
Execute Write CYBLE_EVT_GATTS_EXEC_WRITE_REQ Out of scope for today

Question(s)

Here are the original question(s):

Hi, I am having some problems understanding “write without response” setup.
In the “capsenseled” server project “CYBLE_EVT_GATTS_WRITE_REQ” is used instead of “CYBLE_EVT_GATTS_WRITE_CMD_REQ” in the event handler, but “write without response” is selected in the component setup.
According to this other project I am looking at ( https://www.digikey.com/eewiki/pages/viewpage.action?pageId=55574662 ) both are used with comments as follows

case CYBLE_EVT_GATTS_WRITE_REQ: //Write with response
case CYBLE_EVT_GATTS_WRITE_CMD_REQ: //Write without response

Why is “CYBLE_EVT_GATTS_WRITE_CMD_REQ” NOT used in the capsenseled project, and does “CYBLE_EVT_GATTS_WRITE_REQ” still function in a write without response setup?
Am I misunderstanding the definition of a response?
Is the “response” referring to an event that occurs within the server device, or is a response defined as a reply from the client device?

I am trying to set up a low power single button remote to report the state of the button, to be handled by the client which is connected to a larger power source and will possibly count edges, measure button press duration, or both, etc. Ideally the remote would be asleep except for when it needs to tell the client that the button has changed states, and would not spend any energy processing a response from the client.

BLE Spec

When you declare a Characteristic, you have a 1-byte bit field to specify the Characteristic Properties, that tells the GATT Client how it can write to the Characteristic.  Here is a screenshot from section 3.3.1 of the Bluetooth core spec:

And the legal values for the Characteristic Properties are in section 3.3.1.1

This table says that it is perfectly legal to perform a “Write without response” (which is really called “Write Command” in section 3.4.5.3) or a “Write” (which is really called “Write Request” in section 3.4.5.1) as long as you send a legal response (or none).  If you look at the project which is referenced in the Digikey article, you can see that the author did just that for the Characteristic “Number_Write”.

Write Command a.k.a. Write Without Response”

As I looked around at the spec for this article I discovered something which I did not previously know.  Specifically, a Write Command must fit in one packet… which means that the data written to the Characteristic must be no more than the ATT MTU – 3.  Here is the spec:

Write Request

A Write Request is a two sided request, meaning the GATT Server must either send a “Write Response” or an “Error Response”  Here is a screenshot from the spec.

Write Response

A Write Response is a stupid simple packet with just one possible value… 0x13 meaning that the write worked.  In the PSoC, you generate this packet by calling “CyBle_GattsWriteRsp” with the connection handle as the only parameter.

Error Response

The more interesting response is an error where you are allowed to send more information.  To generate an error response in PSoC you call CyBle_GattsErrorRsp with the connection handle and the error code.

The spec gives a list of legal error codes.  Here is a snapshot from the spec with a FEW of them.

The interesting thing about these error codes is that you are allowed to create you own “Application Errors” which will have your application semantics.

PSoC Creator has an enumerated list for the error codes (here is a short section from the BLE Component Datasheet)

Answers

OK… so that leaves me with giving specific answers to his questions.  My answer are embedded in bold:

Hi, I am having some problems understanding “write without response” setup.
In the “capsenseled” server project “CYBLE_EVT_GATTS_WRITE_REQ” is used instead of “CYBLE_EVT_GATTS_WRITE_CMD_REQ” in the event handler, but “write without response” is selected in the component setup.
According to this other project I am looking at ( https://www.digikey.com/eewiki/pages/viewpage.action?pageId=55574662 ) both are used with comments as follows

case CYBLE_EVT_GATTS_WRITE_REQ: //Write with response
case CYBLE_EVT_GATTS_WRITE_CMD_REQ: //Write without response

Why is “CYBLE_EVT_GATTS_WRITE_CMD_REQ” NOT used in the capsenseled project,

When I wrote that project originally I chose to only support no responses to writes.  There is no need to support both.  As the application developer you can choose to do either or both.

and does “CYBLE_EVT_GATTS_WRITE_REQ” still function in a write without response setup?

If the GATT Client sends you a CYBLE_EVT_GATTS_WRITE_REQ and you send a response it might turn out badly and you should not do that.
Am I misunderstanding the definition of a response?
Is the “response” referring to an event that occurs within the server device, or is a response defined as a reply from the client device?

Well..  sounds like the answer was yes… but hopefully it is no now.

I am trying to set up a low power single button remote to report the state of the button, to be handled by the client which is connected to a larger power source and will possibly count edges, measure button press duration, or both, etc. Ideally the remote would be asleep except for when it needs to tell the client that the button has changed states, and would not spend any energy processing a response from the client.

Sounds like “Write without response” is perfect for your application.