Part Number: CC2652RB
Other Parts Discussed in Thread: CC2640, CC2650
We have a project based on the SimplePeripheral example. We have a few oft-changing values we want to be able to read over BLE, such as the device time from the CC2652's RTC. Rather than constantly updating a buffer to make sure these values are up-to-date when read, we instead want to be able fetch the data on demand when read. I have guessed that the proper way to do this is by returning blePending in SimplePeripheral_ReadAttrCB(), as such:
// See if request is regarding the Clock Characteristic Value
if ( ! memcmp(pAttr->type.uuid, MyService_ClockUUID, pAttr->type.len) )
{
if ( offset > MYSERVICE_CLOCK_LEN ) // Prevent malicious ATT ReadBlob offsets.
{
status = ATT_ERR_INVALID_OFFSET;
}
else
{
if ( pAppCBs && pAppCBs->pfnReadCb )
pAppCBs->pfnReadCb(connHandle, MYSERVICE_CLOCK_ID); // Call app function from stack task context.
return blePending;
}
}
where I've created pAppCBs->pfnReadCb() the same way the application callbacks are done for SimplePeripheral_WriteAttrCB(). This enqueues a message for our application task and is processed by SimplePeripheral_processAppMsg(), which calls the following function:
static void MyService_processValueReadEvt(MyServiceReadCharacteristic_t *pData)
{
switch(pData->paramID)
{
case MYSERVICE_CLOCK_ID:
{
bStatus_t status;
attReadRsp_t clockRsp;
uint16_t len;
clockRsp.pValue = (uint8 *)GATT_bm_alloc( pData->connHandle, ATT_READ_RSP, MYSERVICE_CLOCK_LEN, &len );
if ( clockRsp.pValue != NULL )
{
if (len != MYSERVICE_CLOCK_LEN)
{
GATT_bm_free( (gattMsg_t *)&clockRsp, ATT_READ_RSP );
// TODO: couldn't allocate enough memory, but we still have to tell the BLE stack something to end "blePending", right?
}
else
{
uint32_t time = Seconds_get();
memcpy(clockRsp.pValue, &time, len);
clockRsp.len = len;
status = ATT_ReadRsp(pData->connHandle, &clockRsp);
if ( status != SUCCESS )
{
GATT_bm_free( (gattMsg_t *)&clockRsp, ATT_READ_RSP );
// TODO: we failed to return the data for some reason; does the BLE stack still need us to do anything?
}
}
}
else
{
// TODO: couldn't allocate any memory, but we still have to tell the BLE stack something, right?
}
}
break;
My first question is: is this the right way to do this? I had to do some digging to find attReadRsp_t and ATT_ReadRsp(). I have tested this and it works, though, so I know I'm at least on the right track.
My second question is: assuming the above is correct, what do I need to be calling in place of the comments in the code? If I can't allocate the memory I need to send the Read Response back to the BLE stack, I'm assuming I still need to do something so it's not just blePending forever, right? And if ATT_ReadRsp() isn't successful, do we still need to do something to keep the stack from waiting for a success?