This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TI-BDS-PLUGIN 1.0.4 and string characteristics

I'm using the TI-BDS-PLUGIN 1.0.4 and am running into an issue related to string characteristics. I added a string characteristic with a field type of "UINT8S" and generated code via the plugin. When i look at the .h file, the length is defined as 1, which seems odd. Furthermore, when i look at the write callback method that was generated, it uses this length of 1 for the parameter copy, so i don't see how one could ever handle a string with more than one character. unless i misunderstand how a string should work in BLE, this seems not quite right. 

more generally speaking, when using field values of array or struct, the resulting length seems either to default to 20 or remain at 1.

How does one define the length of characteristics with the TI-BDS-PLUGIN 1.0.4? how would i support variable length? 

<Service UID="2af097e0-14d3-4243-86d8-772739f1e723" XMLFile="Services\com.test.service.test.xml" UUIDMode="Short">
      <UUIDDisplayMode>Short</UUIDDisplayMode>
      <CharacteristicFiles>
        <Characteristic UID="82e570b3-7c2f-488c-9836-3e83690c3676" XMLFile="Characteristics\org.bluetooth.characteristic.first_name.xml" UUIDMode="Short" />
      </CharacteristicFiles>
</Service>

#define T_FIRST_NAME_LEN                1

static bStatus_t test_WriteAttrCB( uint16_t connHandle, gattAttribute_t *pAttr,
                                        uint8_t *pValue, uint16_t len, uint16_t offset,
                                        uint8_t method )
{
  ...

  else if ( ! memcmp(pAttr->type.uuid, t_First_NameUUID, pAttr->type.len) )
  {
    if ( offset + len > T_FIRST_NAME_LEN )
    {
      status = ATT_ERR_INVALID_OFFSET;
    }
    else
    {
      // Copy pValue into the variable we point to from the attribute table.
      memcpy(pAttr->pValue + offset, pValue, len);

      // Only notify application if entire expected value is written
      if ( offset + len == T_FIRST_NAME_LEN)
        paramID = T_FIRST_NAME_ID;
    }
  }
  ...
}

  • Hi,

    We're looking into this and will get back to you soon.
  • Hi Pixbroker,

    Since BDS doesn't tell the plugin anything about the length of the string, the plugin just makes a guess. Admittedly, it should perhaps guess 20 rather than 1 for the length of a string, but the point is the length isn't part of the service description, and at some point one has to allocate some length.

    If you want to support variable length, you can simply manually change the defined length after code generation, and you can remove the check for whether length == expected length. You should also add a variable holding the latest received length.

    So, in your example:

    #define T_FIRST_NAME_LEN                40
    
    uint16_t t_First_NameValLen = 0; // Dynamically updated length
    
    
    bStatus_t Test_SetParameter(uint8_t param, uint8_t len, void *value)
    {
      bStatus_t ret = SUCCESS;
      switch ( param )
      {
        case T_FIRST_NAME_ID:
          if ( len <= T_FIRST_NAME_LEN ) 
          {
            memcpy(t_First_NameVal, value, len);
            t_First_NameValLen = len;
      ....
    
    
    bStatus_t Test_GetParameter( uint8_t param, uint16_t *len, void *value )
    {
      bStatus_t ret = SUCCESS;
      switch ( param )
      {
        case T_FIRST_NAME_ID:
          *len = MIN(*len, t_First_NameValLen);
          memcpy(value, t_First_NameVal, *len);
          break;
    ....
    
    
    static bStatus_t test_WriteAttrCB( uint16_t connHandle, gattAttribute_t *pAttr,
                                            uint8_t *pValue, uint16_t len, uint16_t offset,
                                            uint8_t method )
    {
      ...
    
      else if ( ! memcmp(pAttr->type.uuid, t_First_NameUUID, pAttr->type.len) )
      {
        if ( offset + len > T_FIRST_NAME_LEN )
        {
          status = ATT_ERR_INVALID_OFFSET;
        }
        else
        {
          // Copy pValue into the variable we point to from the attribute table.
          memcpy(pAttr->pValue + offset, pValue, len);
    
          // Update length variable
          t_First_NameValLen = offset+len;
    
          // Always notify application. Note: Long writes are concatenated before reaching here.
          paramID = T_FIRST_NAME_ID;
        }
      }
      ...
    }
    
    static bStatus_t Cool_and_Nice_Service_ReadAttrCB( uint16_t connHandle, gattAttribute_t *pAttr, 
                                           uint8_t *pValue, uint16_t *pLen, uint16_t offset,
                                           uint16_t maxLen, uint8_t method )
    {
      ... 
    
      if ( ! memcmp(pAttr->type.uuid, t_First_NameUUID, pAttr->type.len) )
      {
        if ( offset > t_First_NameValLen )  // Prevent malicious ATT ReadBlob offsets.
        {
          status = ATT_ERR_INVALID_OFFSET;
        }
        else
        {
          *pLen = MIN(maxLen, t_First_NameValLen - offset);  // Transmit as much as possible
          memcpy(pValue, pAttr->pValue + offset, *pLen);
        }
      }
    

    Note that I haven't tested this. And note also the API for GetParameter has been changed. the len parameter must be a pointer to a max length, and is replaced by the actual length after returning.

    I'll make an effort to make the plugin more intelligently decide whether a variable approach or a fixed size approach should be used for a char. Thanks for bringing this to our attention.

    Best regards,
    Aslak

  • Thank you for the answer. This makes sense and i was suspecting you would answer along these lines. Seems like a shortcoming in BDS rather than the plugin. BDS is mainly interesting when developing complex and large services to avoid manual code editing. Having to alter the generated code somewhat defeats the use of BDS, as in whenever the code gets regenerated, the edits will have to be re applied, or even altered. I know that BDS is not a TI product, so this is not the correct place to bring this up, but i assume you have more direct contact with the BDS developers than we do, so hopefully this conversation will make it's way to the right folks :)

    Thanks again for the answer and your work on the plugin. It is useful even with this limitation.
  • Hi,

    The output from the tool will probably never be adequate for an end-product, so some jiggering is to be expected.

    However, there is now a new version available - 1.0.5 - which adds support for variable length characteristic attributes and also fixes some of the 1 byte long variable length fields.

    Best regards,
    Aslak

  • Thank you very much for the quick fix! The variable length code now looks great. 

    Much aprechiated.