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

Variable length not working?

/**@brief Attribute metadata. */
typedef struct
{
  ble_gap_conn_sec_mode_t read_perm;       /**< Read permissions. */
  ble_gap_conn_sec_mode_t write_perm;      /**< Write permissions. */
  uint8_t                 vlen       :1;   /**< Variable length attribute. */
  uint8_t                 vloc       :2;   /**< Value location, see @ref BLE_GATTS_VLOCS.*/
  uint8_t                 rd_auth    :1;   /**< Read Authorization and value will be requested from the application on every read operation. */ 
  uint8_t                 wr_auth    :1;   /**< Write Authorization will be requested from the application on every Write Request operation (but not Write Command). */
} ble_gatts_attr_md_t;

Whenever I set .vlen to true the softdevice fails with error 7 on the call to: sd_ble_gatts_characteristic_add

Is this functionality implemented, and are there any examples using it?

  • I greatly appreciate that you can tell exactly what the cause is, but I also tend to think that it's quite difficult to look up this kind of information. Is it just me not doing my homework, or is everybody else completely aware that you have to set this bit, in order to use a user descriptor.

    I hope at least it's a combination of the two :-)

  • Since we provide a GAP/GATT level API we do rely on API users having an understanding of the specification at those levels.

    In GATT 3.3.3.2: "If the Writable Auxiliary bit of the Characteristic Properties is set then this characteristic descriptor can be written".

    I agree that we could be a bit more explicit regarding these sort of pitfalls, but we don't want to replicate the whole specification in our documentation either, so it's a tough balance to strike.

  • Ohh, and sorry for the mysterious memory dump, but I think this is the only way that I can back up my postings. You wouldn't get much out of looking at the code I use, as it is quite "alien" compared to plain C.

    This is what I'm currently working at, and my guess it that it probably wouldn't make much sense:

    class StandardInCD: public Characteristic<String20> {
    public:
    	StandardInCD(UUID uuid) : Characteristic(uuid, "StandardIn") {
    		_handler_func = NULL;
    		CharacteristicMetadata.Properties.SetWrite(true);
    //		CharacteristicMetadata.GetUserDescriptorMetadata()->SetVariableLength(true);
    		Metadata.SetVariableLength(true);
    //		CharacteristicMetadata.GetUserDescriptorMetadata()->SetValueLocation(GattsAttributeMetadata::ValueLocation::Stack);
    //		SetMaximumLength(20);
    //		SetInitialLength(0);
    	}
    
    	virtual void OnValueWrittenEvent(ble_gatts_evt_write_t& writeEvent) {
    		std::string stackstring((char*)writeEvent.data, writeEvent.len);
    		TraceLine(stackstring.c_str());
    		string result = s_Commands->ExecuteCommand(stackstring);
    		TraceLine(result.c_str());
    	}
    
    	void SetValueHandlerFunc (std::function<void (uint8_t*, uint16_t length)> handler_func)
    	{
    		_handler_func = handler_func;
    	}
    
    private:
    	std::function<void (uint8_t*, uint16_t length)> _handler_func;
    };
    
    
Related