Changing the length of an Attribute

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

PSoC Creator, the BLE component has the ability to configure the length (and type) of an Attribute (when configuring the corresponding Characteristic). Will this length then be fixed for that Characteristic, that is, all Attribute's has a predefined type and length by (custom or official) specification? Or can an Attribute's length be changed in real time? Or does the Attribute database store data-length pairs, and the length we type in PSoC Creator specify a maximum allowed length?

   

Consider the attribute type "utf8s". Is this a null-terminated string?

   

 

   

I thought the function CyBle_GattsWriteAttributeValue() could define the length of the Attribute in addition to data, but it responds negative if the argument has a length stricly larger than the one defined in PSoC Creator!

0 Likes
1 Solution
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

Attributes have a defined length, and it cannot be changed during runtime. It might be possible to do this when no other device is connected, though (but I suspect there is not API for this). These descriptors are used by the connected devices to find out how to transfer data correctly, so its quite difficult to do so after connecting.

View solution in original post

0 Likes
11 Replies
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

Attributes have a defined length, and it cannot be changed during runtime. It might be possible to do this when no other device is connected, though (but I suspect there is not API for this). These descriptors are used by the connected devices to find out how to transfer data correctly, so its quite difficult to do so after connecting.

0 Likes
Anonymous
Not applicable

Does this mean that the Cypress GATT allocates memory to hold all attributes? I've always been thinking that CyBle_GattsWriteAttributeValue()  wrote a pointer to data + length into the ATT database (and therefore I could update the length of the data as well).

0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

*WriteAttributeValue has a length so the GATT stack knows how much of the data is valid (in case of strings), or how much to copy over.

Anonymous
Not applicable

Yes, but does CyBle_GattsWriteAttributeValue() copy the data into the ATT database (and hence has allocated all memory for us), or do the ATT database contain pointers into memory provided by the user application?

0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

When I read the documenation correctly, its a "copy" operation. Its says that you can even specify where in the attribute you want to have your values written to (the 'offset'), so it needs to be a copy.

0 Likes
Anonymous
Not applicable

OK, but if each attribute has a fixed size (depending on some specification by Bluetooth SIG or custom for its corresponding GATT value), why is there no size #define's in BLE_custom.h? It should not be necessary, and it is bad practice, to define one size two places: one in BLE component and one in code.

0 Likes
Anonymous
Not applicable

An update:

   

 

   

The generated files BLE_gatt.h and BLE_gatt.c give us some interesting details:

   
        
  • The variable static uint8 cyBle_attValues[] holds the allocated memory for the values in the ATT database. So CyBle_GattsWriteAttributeValue() copies the given data into this.
  •     
  • The length of an ATT handle can be retrieved by the CYBLE_GATT_DB_ATTR_GET_ATTR_GEN_LEN() macro.
  •    
0 Likes
Anonymous
Not applicable

speedycat, were you ever able to find a way to update the length programmatically at runtime? Or even upon reboot?

   

It would be great to be able to have Characteristics that have a variable length because you do not want to expose extra data that is not relevant (e.g. the last bytes of a previous device name)

0 Likes
Anonymous
Not applicable

Hello! As hli said above, it is not possible to change the length programmatically at runtime. This might be required by the Bluetooth SIG specification, or it might be something Cypress has decided. The Cypress BLE stack will respond to a client read; you as a developer will only get notified by event (CYBLE_EVT_GATTS_READ_CHAR_VAL_ACCESS_REQ) when a client read happens (and you can prevent the read, see doc of that event).

   

 

   

I find it really strange that changing the length is not allowed. I can't see the reason why. If this is something Cypress has forced upon us, they should fix it immediately. The data for ATT (i.e. GATT) is implemented as an array at compile time, that may be the reason behind not be able to change the length, but this could just be the maximum length we developers defines. As you say, the device name length can be changed (actually Apple requires the device name to be modifiable). We solved this by using null terminated strings. I don't think null terminated strings correct according to the Bluetooth SIG specification. There is no size information of an ATT attribute, the only way for a client to know the length is to read the attribute (i.e. characteristic) until there is nothing more to read. I suggest you to contact Cypress support directly (so they make this possible).

0 Likes
Anonymous
Not applicable

The length defined in the BLE component's GATT database structure for a given characteristic is mainly for buffering purposes, since all attribute value data is stored by the stack in the cyBle_attValues pool. However, the cyBle_attValuesLen array also contains an additional length value which describes how much data is actually stored in the relevant section of the value data pool. While this cannot be greater than the defined characteristic length, it can be less.

   

Here's a brief summary of how GATT data is defined and stored by the BLE component (see BLE_gatt.c for source detail):

   
        
  • cyBle_gattDB is an array of CYBLE_GATTS_DB_T structs, each of which defines the handle, permissions, container size (max length), and full (16-bit) or partial (128-bit) UUID. If necessary, these entries also contain a pointer to the cyBle_attValuesLen array entry containing additional relevant data. This "additional relevant data" is one of:     
            
    • A complete 128-bit UUID (see cyBle_attUuid128 array)
    •       
    • A characteristic value (see cyBle_attValues byte pool)
    •       
    • A client characteristic configuration descriptor value (see cyBle_attValuesCCCD byte pool)
    •      
  •     
  • cyBle_attValuesLen is an array of length/pointer sets describing:     
            
    • How much data is stored (e.g. actual value length, not just max length)
    •       
    • Where the data is actually stored (e.g. 128-bit UUID array index or attribute data byte pool offset)
    •      
  •     
  • cyBle_attUuid128 is an array of 16-byte arrays, each containing a 128-bit UUID
  •     
  • cyBle_attValues is a pool of pre-allocated RAM for attribute value data
  •     
  • cyBle_attValuesCCCD is a pool kept separate from other attribute value data so that it may be written to flash by the CyBle_StoreBondingData API, allowing CCCD values per bonded device to be retained across power-cycles/resets
  •    
   

Note the following key points:

   
        
  1. The maximum characteristic value length (defined in the BLE component configurator) is stored in the cyBle_gattDB entry as the 2nd to last value, the 16-bit hex number right before the (void *) pointer to cyBle_attValuesLen.
  2.     
  3. The actual characteristic value length (initialized to maximum but modifiable with CyBle_GattsWriteAttributeValue) is stored in the cyBle_attValuesLen entry as the first value, the 16-bit hex number right before the (void *) pointer to cyBle_attValues.
  4.    
   

A read request from a remote GATT client will return as much data as is described in the cyBle_attValuesLen structure, not as much as is allowed in the cyBle_gattDB structure.

0 Likes
Anonymous
Not applicable

So the size of an attribute can actually be changed by modifying cyBle_attValuesLen ?

0 Likes