diff --git a/src/app/chip-zcl/chip-zcl-buffer.h b/src/app/chip-zcl/chip-zcl-buffer.h index 224b915b46c404..7da21edcc4e42d 100644 --- a/src/app/chip-zcl/chip-zcl-buffer.h +++ b/src/app/chip-zcl/chip-zcl-buffer.h @@ -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. @@ -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. */ @@ -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 diff --git a/src/app/chip-zcl/chip-zcl-codec.h b/src/app/chip-zcl/chip-zcl-codec.h index fadb1127a0bcdd..5c8c1cffbfe82c 100644 --- a/src/app/chip-zcl/chip-zcl-codec.h +++ b/src/app/chip-zcl/chip-zcl-codec.h @@ -30,35 +30,52 @@ #include #include +/** + * 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 diff --git a/src/app/chip-zcl/chip-zcl.h b/src/app/chip-zcl/chip-zcl.h index 8c4e7e7761abe2..055912a7a480a5 100644 --- a/src/app/chip-zcl/chip-zcl.h +++ b/src/app/chip-zcl/chip-zcl.h @@ -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) @@ -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 diff --git a/src/app/plugin/binding-mock/mock.c b/src/app/plugin/binding-mock/mock.c index 4d1116e7e71cee..06e371b44c5c0c 100644 --- a/src/app/plugin/binding-mock/mock.c +++ b/src/app/plugin/binding-mock/mock.c @@ -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; } diff --git a/src/app/plugin/codec-simple/codec-simple.c b/src/app/plugin/codec-simple/codec-simple.c index 6b6fc7a10727bd..16743d3a8f63ad 100644 --- a/src/app/plugin/codec-simple/codec-simple.c +++ b/src/app/plugin/codec-simple/codec-simple.c @@ -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; @@ -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; } @@ -108,33 +159,39 @@ 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); } /** @@ -142,16 +199,17 @@ void chipZclEncodeZclHeader(ChipZclBuffer_t * buffer, ChipZclCommandContext_t * */ 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 { @@ -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); } diff --git a/src/app/plugin/core-api/core-api.c b/src/app/plugin/core-api/core-api.c index 844ab4989ca4b6..d2d503060aa3f2 100644 --- a/src/app/plugin/core-api/core-api.c +++ b/src/app/plugin/core-api/core-api.c @@ -19,6 +19,25 @@ #include "chip-zcl.h" +ChipZclStatus_t chipZclClusterCommandParse(ChipZclCommandContext_t * context); + +ChipZclStatus_t chipZclProcessIncoming(uint8_t * rawBuffer, uint16_t rawBufferLength) +{ + ChipZclBuffer_t buffer = { rawBuffer, rawBufferLength, rawBufferLength }; + + ChipZclCommandContext_t context = { 0 }; + + ChipZclStatus_t status; + + status = chipZclDecodeZclHeader(&buffer, &context); + + if (CHIP_ZCL_STATUS_SUCCESS != status) + { + return status; + } + return chipZclClusterCommandParse(&context); +} + /** * Function that returns a pointer to the raw buffer. */ @@ -30,36 +49,28 @@ uint8_t * chipZclBufferPointer(ChipZclBuffer_t * buffer) /** * Function that returns the size of the used portion of the buffer. */ -uint16_t chipZclBufferUsedLength(ChipZclBuffer_t * buffer) +uint16_t chipZclBufferDataLength(ChipZclBuffer_t * buffer) { return buffer->dataLength; } -void chipZclBufferReset(ChipZclBuffer_t * buffer) -{ - buffer->currentPosition = 0; -} - -void chipZclBufferFinishWriting(ChipZclBuffer_t * buffer) +/** + * returns space available for writing after any data already in the buffer + */ +uint16_t chipZclBufferAvailableLength(ChipZclBuffer_t * buffer) { - buffer->dataLength = buffer->currentPosition; - buffer->currentPosition = 0; + return buffer->bufferLength - buffer->dataLength; } -void chipZclBufferClear(ChipZclBuffer_t * buffer) +/** + * sets data length for a buffer that's being written to + */ +void chipZclBufferSetDataLength(ChipZclBuffer_t * buffer, uint16_t newLength) { - buffer->currentPosition = 0; - buffer->dataLength = 0; + buffer->dataLength = newLength; } -ChipZclStatus_t chipZclClusterCommandParse(ChipZclCommandContext_t * context); - -ChipZclStatus_t chipZclProcessIncoming(uint8_t * rawBuffer, uint16_t rawBufferLength) +void chipZclBufferReset(ChipZclBuffer_t * buffer) { - ChipZclBuffer_t buffer = { rawBuffer, 0, 0, rawBufferLength }; - - ChipZclCommandContext_t context = { 0 }; - - chipZclDecodeZclHeader(&buffer, &context); - return chipZclClusterCommandParse(&context); + buffer->dataLength = 0; } diff --git a/src/app/plugin/test-on-off/cluster-cmd-on-off-test.c b/src/app/plugin/test-on-off/cluster-cmd-on-off-test.c index a19ad2872d22c5..860167edaf0c11 100644 --- a/src/app/plugin/test-on-off/cluster-cmd-on-off-test.c +++ b/src/app/plugin/test-on-off/cluster-cmd-on-off-test.c @@ -92,17 +92,14 @@ int testClusterCmdOnOff(void) // Encode the header into the buffer chipZclEncodeZclHeader(buffer, &context); - chipZclBufferFinishWriting(buffer); if (testEncodingDecoding(buffer, &context) != 0) { return 1; } - chipZclBufferReset(buffer); - uint8_t * rawBuffer = chipZclBufferPointer(buffer); - uint16_t bufferLength = chipZclBufferUsedLength(buffer); + uint16_t bufferLength = chipZclBufferDataLength(buffer); printf("Buffer for processing is ready, length: %d\n", bufferLength);