MCUXpresso SDK Documentation

Reading and writing characteristic descriptors

Reading and writing characteristic descriptors#

Two APIs are provided for these procedures which are very similar to Characteristic Read and Write.

The only difference is that the handle of the attribute to be read/written is provided through a pointer to an gattAttribute_t structure (same type as the gattCharacteristic_t.value field).

All of the following APIs have an enhanced counterpart of the form GattClient_Enhanced[procedure]. A bearerIdparameter was added to specify on which bearer the transaction should take place. A value of 0 for the bearer Id identifies the Unenhanced ATT bearer. Values higher than 0 are used to identify the Enhanced ATT bearer used for the ATT procedure.

bleResult_t GattClient_ReadCharacteristicDescriptor
(
    deviceId_t             deviceId,
    gattAttribute_t *      pIoDescriptor,
    uint16_t               maxReadBytes
);

The pIoDescriptor->handle is required (it may have been discovered previously by GattClient_DiscoverAllCharacteristicDescriptors). The GATT module fills the value that was read in the fields pIoDescriptor->aValue (must be linked to an allocated array) and pIoDescriptor->valueLength (size of the array).

Writing a descriptor is also performed similarly with this function:

bleResult_t GattClient_WriteCharacteristicDescriptor
(
    deviceId_t             deviceId,
    gattAttribute_t *      pDescriptor,
    uint16_t               valueLength,
    uint8_t *              aValue
);

Only the pDescriptor->handle must be filled before calling the function.

One of the most frequently written descriptors is the Client Characteristic Configuration Descriptor (CCCD). It has a well-defined UUID (gBleSig_CCCD_d) and a 2-byte long value that can be written to enable/disable notifications and/or indications.

In the following example, a Characteristic’s descriptors are discovered and its CCCD written to activate notifications.

static gattCharacteristic_t myChar;
myChar.value.handle = 0x00A0; /* Or maybe it was previously discovered? */
#define mcMaxDescriptors_c 5
static gattAttribute_t aDescriptors[mcMaxDescriptors_c];
myChar.aDescriptors = aDescriptors;
/* ... */
{
    bleResult_t result = GattClient_DiscoverAllCharacteristicDescriptors
    (
        deviceId,
        &myChar,
        0xFFFF,
        mcMaxDescriptors_c
    );
    if (gBleSuccess_c != result)
    {
        /* Handle error */
    }
}
/* ... */
void gattClientProcedureCallback
(
    deviceId_t                 deviceId,
    gattProcedureType_t        procedureType,
    gattProcedureResult_t      procedureResult,
    bleResult_t                error
)
{
    switch (procedureType)
    {
      /* ... */
      case gGattProcDiscoverAllCharacteristicDescriptors_c:
         if (gGattProcSuccess_c == procedureResult)
          {
           /* Find CCCD */
            for ( uint8_t j = 0; j < myChar.cNumDescriptors; j++)
               {
                if ((myChar.aDescriptors[j].uuidType == gBleUuidType16_c) && 
                    (gBleSig_CCCD_d == myChar.aDescriptors[j].uuid.uuid16))
                 {
                    uint8_t cccdValue[2];
                    packTwoByteValue(gCccdNotification_c, cccdValue);
                    bleResult_t result = GattClient_WriteCharacteristicDescriptor
                     (
                       deviceId,
                       &myChar. aDescriptors [j],
                       2,
                       (uint8_t*)&cccdValue
                     );
                    if (gBleSuccess_c != result)
                       {
                        /* Handle error */
                       }
                       break;
                     }
                }
            }
            else
            {
                /* Handle error */
                PRINT(error);
            }
            break;
        case gGattProcWriteCharacteristicDescriptor_c:
            if (gGattProcSuccess_c == procedureResult)
            {
                /* Notification successfully activated */
            }
            else
            {
                /* Handle error */
                PRINT(error);
            }
        /* ... */
    }
}

Parent topic:Client APIs