Skip to content

Commit

Permalink
move keeping track of encoding to codec a la TLV
Browse files Browse the repository at this point in the history
  • Loading branch information
Rob Walker committed May 28, 2020
1 parent 3425be3 commit f8679d5
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 98 deletions.
29 changes: 17 additions & 12 deletions src/app/chip-zcl/chip-zcl-buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,12 @@ typedef struct
* The data storage for our buffer.
*/
uint8_t * buffer;

/**
* The size of our data storage.
*/
uint16_t totalLength;
/**
* The current read/write position.
* The size of our buffer above.
*/
uint16_t currentPosition;
uint16_t bufferLength;

/**
* The length of the data that can be read from this buffer; nonzero only
* when it's ready to be read from.
Expand Down Expand Up @@ -85,10 +83,8 @@ uint8_t * chipZclBufferPointer(ChipZclBuffer_t * buffer);
void chipZclBufferFree(ChipZclBuffer_t * buffer);

/**
* Function that resets a buffer.
*
* After this call, the buffer is ready for reading or writing from the
* beginning again, depending on whether it was in reading more or writing mode.
* Function that resets a buffer to have its entire allocated length
* available for writing.
*
* @param buffer the buffer to reset.
*/
Expand All @@ -102,13 +98,22 @@ void chipZclBufferReset(ChipZclBuffer_t * buffer);
* @param buffer the buffer whose used length we want.
* @return The number of bytes the given buffer holds.
*/
uint16_t chipZclBufferUsedLength(ChipZclBuffer_t * buffer);
uint16_t chipZclBufferDataLength(ChipZclBuffer_t * buffer);

/**
* Indicates that we are done writing to a buffer and prepares it for reading.
*
* @param buffer the buffer we are done writing to.
* @param newLength the length of the written data
*/
void chipZclBufferSetDataLength(ChipZclBuffer_t * buffer, uint16_t newLength);

/**
* Function that returns available space remaining in the buffer after any
* data in the buffer.
*
* @param buffer the buffer we are interested in
*/
void chipZclBufferFinishWriting(ChipZclBuffer_t * buffer);
uint16_t chipZclBufferAvailableLength(ChipZclBuffer_t * buffer);

#endif // CHIP_ZCL_BUFFER
37 changes: 27 additions & 10 deletions src/app/chip-zcl/chip-zcl-codec.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,35 +30,52 @@
#include <stdbool.h>
#include <stdint.h>

/**
* Codec keeps track of an ongoing encode/decode session of a Buffer
*/
typedef struct ChipZclCodec_t
{
/**
* Buffer into/out of which this codec is co-dec'ing
*/
ChipZclBuffer_t * buffer;

/**
* The current read/write position.
*/
uint16_t cursor;

/**
* space available in the buffer for writing
*/
uint16_t available;

} ChipZclCodec_t;

/**
* @brief Starts the encoding process. if there is any kind of preamble of anything, this function is responsible for putting it
* there.
*/
ChipZclStatus_t chipZclCodecEncodeStart(ChipZclBuffer_t * buffer);
ChipZclStatus_t chipZclCodecInit(ChipZclCodec_t * codec, ChipZclBuffer_t * buffer);

/**
* @brief Encodes a single value of a given type.
*/
ChipZclStatus_t chipZclCodecEncode(ChipZclBuffer_t * buffer, ChipZclType_t type, void * ptr, uint16_t ptrLen);
ChipZclStatus_t chipZclCodecEncode(ChipZclCodec_t * codec, ChipZclType_t type, void * ptr, uint16_t ptrLen);

/**
* @brief Ends the encoding process. After this call the buffer is ready to go back to the lower layers.
*/
ChipZclStatus_t chipZclCodecEncodeEnd(ChipZclBuffer_t * buffer);
ChipZclStatus_t chipZclCodecEncodeEnd(ChipZclCodec_t * codec);

/**
* @brief Starts the decoding process. if there is any kind of preamble of anything, this function is responsible for decoding it.
*/
ChipZclStatus_t chipZclCodecDecodeStart(ChipZclBuffer_t * buffer);
ChipZclStatus_t chipZclCodecDecodeStart(ChipZclCodec_t * codec, ChipZclBuffer_t * buffer);

/**
* @brief Decodes a single value and puts it into the pointer. If retLen is not NULL, the size of decoded value is put there.
*/
ChipZclStatus_t chipZclCodecDecode(ChipZclBuffer_t * buffer, ChipZclType_t type, void * ptr, uint16_t ptrLen, uint16_t * retLen);

/**
* @brief Ends the decoding process. After this call, buffer should no longer be used for further decoding.
*/
ChipZclStatus_t chipZclCodecDecodeEnd(ChipZclBuffer_t * buffer);
ChipZclStatus_t chipZclCodecDecode(ChipZclCodec_t * codec, ChipZclType_t type, void * ptr, uint16_t ptrLen, uint16_t * retLen);

#endif // CHIP_ZCL_CODEC
5 changes: 0 additions & 5 deletions src/app/chip-zcl/chip-zcl.h
Original file line number Diff line number Diff line change
Expand Up @@ -976,9 +976,6 @@ void chipZclEventSetDelayMs(Event * event, uint32_t delay);
// Endpoint Management
ChipZclEndpointId_t chipZclEndpointIndexToId(ChipZclEndpointIndex_t index, const ChipZclClusterSpec_t * clusterSpec);

// Toplevel functions
ChipZclStatus_t chipZclDecode(ChipZclBuffer_t * buffer);

// Some platform CHIP_ZCL_STATUS_INSUFFICIENT_SPACE
#define MEMSET(d, v, l) memset(d, v, l)
#define MEMCOPY(d, s, l) memcpy(d, s, l)
Expand Down Expand Up @@ -1116,8 +1113,6 @@ void chipZclEncodeZclHeader(ChipZclBuffer_t * buffer, ChipZclCommandContext_t *
*/
void chipZclDecodeZclHeader(ChipZclBuffer_t * buffer, ChipZclCommandContext_t * context);

ChipZclCommandContext_t * createCommandContext(ChipZclEndpointId_t endpointId, ChipZclClusterId_t clusterId);

ChipZclStatus_t chipZclProcessIncoming(uint8_t * buffer, uint16_t bufferLength);

#endif // CHIP_ZCL_MASTER_HEADER
10 changes: 6 additions & 4 deletions src/app/plugin/binding-mock/mock.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,12 @@ void chipZclReverseClusterSpec(const ChipZclClusterSpec_t * s1, ChipZclClusterSp
ChipZclBuffer_t * chipZclBufferAlloc(uint16_t allocatedLength)
{
ChipZclBuffer_t * buffer = (ChipZclBuffer_t *) malloc(sizeof(ChipZclBuffer_t) + allocatedLength);
buffer->buffer = (uint8_t *) (buffer + 1);
buffer->dataLength = 0;
buffer->currentPosition = 0;
buffer->totalLength = allocatedLength;
if (NULL != buffer)
{
buffer->buffer = (uint8_t *) (buffer + 1);
buffer->dataLength = 0;
buffer->bufferLength = allocatedLength;
}
return buffer;
}

Expand Down
142 changes: 100 additions & 42 deletions src/app/plugin/codec-simple/codec-simple.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,30 +31,64 @@
* @brief Starts the encoding process. if there is any kind of preamble of anything, this function is responsible for putting it
* there.
*/
ChipZclStatus_t chipZclCodecEncodeStart(ChipZclBuffer_t * buffer)
ChipZclStatus_t chipZclCodecEncodeStart(ChipZclCodec_t * me, ChipZclBuffer_t * buffer)
{
me->buffer = buffer;
me->cursor = chipZclBufferDataLength(buffer);
me->available = chipZclBufferAvailableLength(buffer);

return CHIP_ZCL_STATUS_SUCCESS;
}

static ChipZclStatus_t put(ChipZclCodec_t * me, void * ptr, uint16_t ptrLen)
{
if (me->available < ptrLen)
{
return CHIP_ZCL_STATUS_FAILURE;
}

memmove(chipZclBufferPointer(me->buffer) + me->cursor, ptr, ptrLen);
me->cursor += ptrLen;
me->available -= ptrLen;

return CHIP_ZCL_STATUS_SUCCESS;
}

static ChipZclStatus_t get(ChipZclCodec_t * me, void * ptr, uint16_t ptrLen)
{
if (me->available < ptrLen)
{
return CHIP_ZCL_STATUS_FAILURE;
}

memmove(ptr, chipZclBufferPointer(me->buffer) + me->cursor, ptrLen);
me->cursor += ptrLen;
me->available -= ptrLen;

return CHIP_ZCL_STATUS_SUCCESS;
}

/**
* @brief Encodes a single value of a given type.
*/
ChipZclStatus_t chipZclCodecEncode(ChipZclBuffer_t * buffer, ChipZclType_t type, void * ptr, uint16_t ptrLen)
ChipZclStatus_t chipZclCodecEncode(ChipZclCodec_t * me, ChipZclType_t type, void * ptr, uint16_t ptrLen)
{
switch (type)
{
case CHIP_ZCL_STRUCT_TYPE_INTEGER:
memcpy(&(buffer->buffer[buffer->currentPosition]), ptr, ptrLen);
buffer->currentPosition += ptrLen;
return CHIP_ZCL_STATUS_SUCCESS;
return put(me, ptr, ptrLen);

case CHIP_ZCL_STRUCT_TYPE_STRING:
// In this simple case, length is encoded as the first 2 bytes.
memcpy(&(buffer->buffer[buffer->currentPosition]), &ptrLen, 2);
buffer->currentPosition += 2;
memcpy(&(buffer->buffer[buffer->currentPosition]), ptr, ptrLen);
buffer->currentPosition += ptrLen;
return CHIP_ZCL_STATUS_SUCCESS;
{
ChipZclStatus_t status = put(me, &ptrLen, 2);

if (CHIP_ZCL_STATUS_SUCCESS != status)
{
return status;
}
}
return put(me, ptr, ptrLen);

default:
return CHIP_ZCL_STATUS_FAILURE;
Expand All @@ -64,42 +98,59 @@ ChipZclStatus_t chipZclCodecEncode(ChipZclBuffer_t * buffer, ChipZclType_t type,
/**
* @brief Ends the encoding process. After this call the buffer is ready to go back to the lower layers.
*/
ChipZclStatus_t chipZclCodecEncodeEnd(ChipZclBuffer_t * buffer)
ChipZclStatus_t chipZclCodecEncodeEnd(ChipZclCodec_t * me)
{
chipZclBufferSetDataLength(me->buffer, me->cursor);
return CHIP_ZCL_STATUS_SUCCESS;
}

/**
* @brief Starts the decoding process. if there is any kind of preamble of anything, this function is responsible for decoding it.
*/
ChipZclStatus_t chipZclCodecDecodeStart(ChipZclBuffer_t * buffer)
ChipZclStatus_t chipZclCodecDecodeStart(ChipZclCodec_t * me, ChipZclBuffer_t * buffer)
{
me->buffer = buffer;
me->available = chipZclBufferDataLength(buffer);
me->cursor = 0;
return CHIP_ZCL_STATUS_SUCCESS;
}

/**
* @brief Decodes a single value and puts it into the pointer. If retLen is not NULL, the size of decoded value is put there.
*/
ChipZclStatus_t chipZclCodecDecode(ChipZclBuffer_t * buffer, ChipZclType_t type, void * ptr, uint16_t ptrLen, uint16_t * retLen)
ChipZclStatus_t chipZclCodecDecode(ChipZclCodec_t * me, ChipZclType_t type, void * ptr, uint16_t ptrLen, uint16_t * retLen)
{
uint16_t encodedLength;
uint16_t dummy;
if (NULL == retLen)
{
retLen = &dummy;
}

switch (type)
{
case CHIP_ZCL_STRUCT_TYPE_INTEGER:
memcpy(ptr, &(buffer->buffer[buffer->currentPosition]), ptrLen);
if (retLen != NULL)
*retLen = ptrLen;
buffer->currentPosition += ptrLen;
return CHIP_ZCL_STATUS_SUCCESS;
*retLen = ptrLen;
return get(me, ptr, *retLen);

case CHIP_ZCL_STRUCT_TYPE_STRING:
memcpy(&encodedLength, &(buffer->buffer[buffer->currentPosition]), 2);
buffer->currentPosition += 2;
if (encodedLength > ptrLen)
// gotta read length first
{
ChipZclStatus_t status;

*retLen = 0;
status = get(me, retLen, 2);

if (CHIP_ZCL_STATUS_SUCCESS != status)
{
return status;
}
}
if (*retLen > ptrLen)
{
return CHIP_ZCL_STATUS_FAILURE;
memmove(ptr, &(buffer->buffer[buffer->currentPosition]), encodedLength);
buffer->currentPosition += encodedLength;
return CHIP_ZCL_STATUS_SUCCESS;
}
return get(me, ptr, *retLen);

default:
return CHIP_ZCL_STATUS_FAILURE;
}
Expand All @@ -108,50 +159,57 @@ ChipZclStatus_t chipZclCodecDecode(ChipZclBuffer_t * buffer, ChipZclType_t type,
/**
* @brief Ends the decoding process. After this call, buffer should no longer be used for further decoding.
*/
ChipZclStatus_t chipZclCodecDecodeEnd(ChipZclBuffer_t * buffer)
ChipZclStatus_t chipZclCodecDecodeEnd(ChipZclCodec_t * me)
{
chipZclBufferSetDataLength(me->buffer, me->cursor);
return CHIP_ZCL_STATUS_SUCCESS;
}

void chipZclEncodeZclHeader(ChipZclBuffer_t * buffer, ChipZclCommandContext_t * context)
{
ChipZclCodec_t codec;
uint8_t mask = 0;
if (context->clusterSpecific)
{
mask |= 0x01;
}
if (context->mfgSpecific)
{
mask |= 0x02;
}

chipZclCodecEncodeStart(buffer);
chipZclCodecEncode(buffer, CHIP_ZCL_STRUCT_TYPE_INTEGER, &mask, sizeof(mask));
chipZclCodecEncode(buffer, CHIP_ZCL_STRUCT_TYPE_INTEGER, &(context->endpointId), sizeof(context->endpointId));
chipZclCodecEncode(buffer, CHIP_ZCL_STRUCT_TYPE_INTEGER, &(context->commandId), sizeof(context->commandId));
chipZclCodecEncode(buffer, CHIP_ZCL_STRUCT_TYPE_INTEGER, &(context->direction), sizeof(context->direction));
chipZclCodecEncodeStart(&codec, buffer);
chipZclCodecEncode(&codec, CHIP_ZCL_STRUCT_TYPE_INTEGER, &mask, sizeof(mask));
chipZclCodecEncode(&codec, CHIP_ZCL_STRUCT_TYPE_INTEGER, &(context->endpointId), sizeof(context->endpointId));
chipZclCodecEncode(&codec, CHIP_ZCL_STRUCT_TYPE_INTEGER, &(context->commandId), sizeof(context->commandId));
chipZclCodecEncode(&codec, CHIP_ZCL_STRUCT_TYPE_INTEGER, &(context->direction), sizeof(context->direction));
if (mask & 0x01)
{
chipZclCodecEncode(buffer, CHIP_ZCL_STRUCT_TYPE_INTEGER, &(context->clusterId), sizeof(context->clusterId));
chipZclCodecEncode(&codec, CHIP_ZCL_STRUCT_TYPE_INTEGER, &(context->clusterId), sizeof(context->clusterId));
}
if (mask & 0x02)
{
chipZclCodecEncode(buffer, CHIP_ZCL_STRUCT_TYPE_INTEGER, &(context->mfgCode), sizeof(context->mfgCode));
chipZclCodecEncode(&codec, CHIP_ZCL_STRUCT_TYPE_INTEGER, &(context->mfgCode), sizeof(context->mfgCode));
}
chipZclCodecEncodeEnd(buffer);
chipZclCodecEncodeEnd(&codec);
}

/**
* This function takes the buffer and decodes it into ZCL header data in the context.
*/
void chipZclDecodeZclHeader(ChipZclBuffer_t * buffer, ChipZclCommandContext_t * context)
{
ChipZclCodec_t codec;
uint8_t mask = 0;
chipZclCodecDecodeStart(buffer);
chipZclCodecDecode(buffer, CHIP_ZCL_STRUCT_TYPE_INTEGER, &mask, sizeof(mask), NULL);
chipZclCodecDecode(buffer, CHIP_ZCL_STRUCT_TYPE_INTEGER, &(context->endpointId), sizeof(context->endpointId), NULL);
chipZclCodecDecode(buffer, CHIP_ZCL_STRUCT_TYPE_INTEGER, &(context->commandId), sizeof(context->commandId), NULL);
chipZclCodecDecode(buffer, CHIP_ZCL_STRUCT_TYPE_INTEGER, &(context->direction), sizeof(context->direction), NULL);
chipZclCodecDecodeStart(&codec, buffer);
chipZclCodecDecode(&codec, CHIP_ZCL_STRUCT_TYPE_INTEGER, &mask, sizeof(mask), NULL);
chipZclCodecDecode(&codec, CHIP_ZCL_STRUCT_TYPE_INTEGER, &(context->endpointId), sizeof(context->endpointId), NULL);
chipZclCodecDecode(&codec, CHIP_ZCL_STRUCT_TYPE_INTEGER, &(context->commandId), sizeof(context->commandId), NULL);
chipZclCodecDecode(&codec, CHIP_ZCL_STRUCT_TYPE_INTEGER, &(context->direction), sizeof(context->direction), NULL);
if (mask & 0x01)
{
context->clusterSpecific = true;
chipZclCodecDecode(buffer, CHIP_ZCL_STRUCT_TYPE_INTEGER, &(context->clusterId), sizeof(context->clusterId), NULL);
chipZclCodecDecode(&codec, CHIP_ZCL_STRUCT_TYPE_INTEGER, &(context->clusterId), sizeof(context->clusterId), NULL);
}
else
{
Expand All @@ -160,11 +218,11 @@ void chipZclDecodeZclHeader(ChipZclBuffer_t * buffer, ChipZclCommandContext_t *
if (mask & 0x02)
{
context->mfgSpecific = true;
chipZclCodecDecode(buffer, CHIP_ZCL_STRUCT_TYPE_INTEGER, &(context->mfgCode), sizeof(context->mfgCode), NULL);
chipZclCodecDecode(&codec, CHIP_ZCL_STRUCT_TYPE_INTEGER, &(context->mfgCode), sizeof(context->mfgCode), NULL);
}
else
{
context->mfgSpecific = false;
}
chipZclCodecDecodeEnd(buffer);
chipZclCodecDecodeEnd(&codec);
}
Loading

0 comments on commit f8679d5

Please sign in to comment.