diff --git a/.gitignore b/.gitignore index d21e9484..94aa176e 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ html/ # VS Code workspace files *.code-workspace *.orig +settings.json \ No newline at end of file diff --git a/n_helpers.c b/n_helpers.c index 3b32488d..28ef2178 100644 --- a/n_helpers.c +++ b/n_helpers.c @@ -86,20 +86,154 @@ NOTE_C_STATIC int ytodays(int year); static const char BINARY_EOP = '\n'; +//**************************************************************************/ +/*! + @brief Get the length of the data stored on the Notecard. If there's no data + stored on the Notecard, then `*len` will return 0. + + @param len [out] the length of the decoded contents of the Notecard's binary + data store. + + @returns An error string on error and NULL on success. + */ +/**************************************************************************/ +const char * NoteBinaryDataDecodedLength(uint32_t *len) +{ + // Validate parameter(s) + if (!len) { + NOTE_C_LOG_ERROR("len cannot be NULL"); + return ERRSTR("len cannot be NULL", c_err); + } + + // Issue a "card.binary" request. + J *rsp = NoteRequestResponse(NoteNewRequest("card.binary")); + if (!rsp) { + NOTE_C_LOG_ERROR("unable to issue binary request"); + return ERRSTR("unable to issue binary request", c_err); + } + + // Ensure the transaction doesn't return an error and confirm the binary + // feature is available. + if (NoteResponseError(rsp)) { + const char *err = JGetString(rsp, "err"); + NOTE_C_LOG_ERROR(err); + JDelete(rsp); + NOTE_C_LOG_ERROR("unexpected error received during handshake"); + return ERRSTR("unexpected error received during handshake", c_bad); + } + + // Examine "length" from the response to evaluate the length of the decoded + // data residing on the Notecard. + *len = JGetInt(rsp, "length"); + JDelete(rsp); + + return NULL; +} + +//**************************************************************************/ +/*! + @brief Get the required buffer length to receive the entire binary object + stored on the Notecard. + + @param len [out] the length required to hold the entire contents of the + Notecard's binary data store. If there's no data stored on the + Notecard, then `*len` will return 0. + + @returns An error string on error and NULL on success. + */ +/**************************************************************************/ +const char * NoteBinaryDataEncodedLength(uint32_t *len) +{ + // Validate parameter(s) + if (!len) { + NOTE_C_LOG_ERROR("size cannot be NULL"); + return ERRSTR("size cannot be NULL", c_err); + } + + // Issue a "card.binary" request. + J *rsp = NoteRequestResponse(NoteNewRequest("card.binary")); + if (!rsp) { + NOTE_C_LOG_ERROR("unable to issue binary request"); + return ERRSTR("unable to issue binary request", c_err); + } + + // Ensure the transaction doesn't return an error and confirm the binary + // feature is available. + if (NoteResponseError(rsp)) { + const char *err = JGetString(rsp, "err"); + NOTE_C_LOG_ERROR(err); + JDelete(rsp); + NOTE_C_LOG_ERROR("unexpected error received during handshake"); + return ERRSTR("unexpected error received during handshake", c_bad); + } + + // Examine "cobs" from the response to evaluate the space required to hold + // the COBS-encoded data to be received from the Notecard. + long int cobs = JGetInt(rsp, "cobs"); + JDelete(rsp); + if (!cobs) { + // If cobs is 0, the required buffer length is 0 because there's nothing + // to receive. + *len = 0; + } else { + // Otherwise, the required length is cobs + 1: the binary data plus + // 1 byte for the terminating newline. + *len = cobs + 1; + } + + return NULL; +} + +//**************************************************************************/ +/*! + @brief Reset the Notecard's binary buffer. + + @returns NULL on success, else an error string pointer. + + @note This operation is necessary to clear the Notecard's binary buffer after + a binary object is received from the Notecard, or if the Notecard's + binary buffer has been left in an unknown state due to an error arising + from a binary transfer to the Notecard. + */ +/**************************************************************************/ +const char * NoteBinaryDataReset(void) +{ + J *req = NoteNewRequest("card.binary"); + if (req) { + JAddBoolToObject(req, "delete", true); + + // Ensure the transaction doesn't return an error. + J *rsp = NoteRequestResponse(req); + if (NoteResponseError(rsp)) { + NOTE_C_LOG_ERROR(JGetString(rsp,"err")); + JDelete(rsp); + NOTE_C_LOG_ERROR("failed to reset binary buffer"); + return ERRSTR("failed to reset binary buffer", c_err); + } + } else { + NOTE_C_LOG_ERROR("unable to allocate request"); + return ERRSTR("unable to allocate request", c_mem); + } + + return NULL; +} + //**************************************************************************/ /*! @brief Decode a binary payload received from the Notecard. + @param inBuf The binary payload. @param inLen The length of the binary payload. @param outBuf The buffer to write the decoded payload to. This can be the same address as inBuf, allowing for in-place decoding. @param outLen On input, holds the length of outBuf. On output, holds the length of the decoded data. + @returns NULL on success, else an error string pointer. -*/ + */ /**************************************************************************/ -const char *NoteBinaryDecode(const uint8_t *inBuf, uint32_t inLen, - uint8_t *outBuf, uint32_t *outLen) +const char * NoteBinaryDecode(const uint8_t *inBuf, uint32_t inLen, + uint8_t *outBuf, uint32_t *outLen) { if (inBuf == NULL || outBuf == NULL || outLen == NULL) { NOTE_C_LOG_ERROR("NULL parameter"); @@ -118,18 +252,21 @@ const char *NoteBinaryDecode(const uint8_t *inBuf, uint32_t inLen, //**************************************************************************/ /*! + @brief Binary encode a buffer to prepare it for transmission to the Notecard. + @param inBuf The data to encode. @param inLen The length of the data to encode. @param outBuf The buffer to write the encoded data to. This can be the same address as inBuf, allowing for in-place encoding. @param outLen On input, holds the length of outBuf. On output, holds the length of the encoded data. + @returns NULL on success, else an error string pointer. -*/ + */ /**************************************************************************/ -const char *NoteBinaryEncode(const uint8_t *inBuf, uint32_t inLen, - uint8_t *outBuf, uint32_t *outLen) +const char * NoteBinaryEncode(const uint8_t *inBuf, uint32_t inLen, + uint8_t *outBuf, uint32_t *outLen) { if (inBuf == NULL || outBuf == NULL || outLen == NULL) { NOTE_C_LOG_ERROR("NULL parameter"); @@ -150,60 +287,86 @@ const char *NoteBinaryEncode(const uint8_t *inBuf, uint32_t inLen, //**************************************************************************/ /*! - @brief Given an input buffer and its length, compute the exact number of - bytes required to binary encode that buffer. - @param buf The buffer to encode. - @param len The length of the buffer. - @note This function iterates over the entire buffer to compute the result. - For a constant-time alternative, see NoteBinaryEncodedMaxLength. - @returns The required buffer size to hold the encoded data. -*/ + @brief Compute the maximum decoded data length guaranteed + to fit into a fixed-size buffer, after being encoded. + + This API is designed for a space constrained environment, where a + working buffer has been allocated to facilitate binary transactions. + + There are two primary use cases: + + 1. When data is retrieved from the Notecard, it must be requested in + terms of the unencoded offset and length. However, the data is + encoded prior to transmission, and, as a result, the buffer must be + capable of receiving the encoded (larger) data. This API returns a + length that is safe to request from the Notecard, because the + resulting encoded data is guaranteed to fit in the provided buffer. + 2. When data is transmitted to the Notecard, this API can be used to + verify whether or not unencoded data of a given length will fit in + the provided buffer after encoding. + + @param size The size of the fixed-size buffer. + + @returns The max length of unencoded data certain to fit in the fixed-size + buffer, after being encoded. + */ /**************************************************************************/ -uint32_t NoteBinaryEncodedLength(const uint8_t *buf, uint32_t len) +uint32_t NoteBinaryMaxDecodedLength(uint32_t bufferSize) { - return cobsEncodedLength(buf, len); + return cobsGuaranteedFit(bufferSize); } //**************************************************************************/ /*! - @brief Given an input buffer's length, compute the maximum output buffer size - needed to binary encode the input buffer. - @param len The length of the input buffer. + @brief Compute the maximum buffer size needed to encode + any unencoded buffer of the given length. + + @param unencodedLength The length of an unencoded buffer. + @returns The max required buffer size to hold the encoded data. -*/ + */ /**************************************************************************/ -uint32_t NoteBinaryEncodedMaxLength(uint32_t len) +uint32_t NoteBinaryMaxEncodedLength(uint32_t unencodedLength) { - return cobsEncodedMaxLength(len); + return cobsEncodedMaxLength(unencodedLength); } //**************************************************************************/ /*! @brief Receive a large binary object from the Notecard's binary buffer + @param buffer A buffer to hold the binary object @param bufLen The total length of the provided buffer - @param dataLen An out parameter to hold the length of the decoded data in the - output buffer. + @param decodedOffset The offset to the decoded binary data already residing + on the Notecard + @param decodedLen [in/out] The length of the decoded data to fetch from the + Notecard. If you wish to fetch the entire buffer from the + given offset, set this value to `NOTE_C_BINARY_RX_ALL`. + This parameter will return the bytes actually received from + the Notecard. + @returns NULL on success, else an error string pointer. - @note Buffers are decoded in place. The original contents of the buffer - will be modified. - @note To determine the necessary size for the buffer, use - NoteBinaryRequiredRxBuffer. -*/ + + @note The buffer must be large enough to hold the encoded value of the + data store contents from the requested offset for the specified length. + To determine the necessary buffer size for a given data length, use + `(NoteBinaryMaxEncodedLength() + 1)`, or if you wish to consume the + entire buffer use `NoteBinaryDataEncodedLength()` instead. + */ /**************************************************************************/ -const char * NoteBinaryReceive(uint8_t * buffer, size_t bufLen, - size_t * dataLen) +const char * NoteBinaryReceive(uint8_t * buffer, uint32_t bufLen, + uint32_t decodedOffset, uint32_t * decodedLen) { - size_t requiredRxBufLen = 0; - const char *err = NoteBinaryRequiredRxBuffer(&requiredRxBufLen); - if (err) { - return err; + // Validate parameter(s) + if (!buffer) { + NOTE_C_LOG_ERROR("NULL buffer"); + return ERRSTR("NULL buffer", c_err); } - if (!requiredRxBufLen) { - NOTE_C_LOG_ERROR("no data on notecard"); - return ERRSTR("no data on notecard", c_err); + if (!decodedLen) { + NOTE_C_LOG_ERROR("decodedLen cannot be NULL"); + return ERRSTR("decodedLen cannot be NULL", c_err); } - if (requiredRxBufLen > bufLen) { + if (bufLen < (cobsEncodedMaxLength(*decodedLen) + 1)) { NOTE_C_LOG_ERROR("insufficient buffer size"); return ERRSTR("insufficient buffer size", c_err); } @@ -215,10 +378,8 @@ const char * NoteBinaryReceive(uint8_t * buffer, size_t bufLen, char status[NOTE_MD5_HASH_STRING_SIZE] = {0}; J *req = NoteNewRequest("card.binary.get"); if (req) { - // This field must exactly match the number of binary bytes the Notecard - // will send. This doesn't include the terminating newline, hence the - // -1. - JAddIntToObject(req, "cobs", requiredRxBufLen - 1); + JAddIntToObject(req, "offset", decodedOffset); + JAddIntToObject(req, "length", *decodedLen); // Ensure the transaction doesn't return an error. J *rsp = NoteRequestResponse(req); @@ -241,7 +402,7 @@ const char * NoteBinaryReceive(uint8_t * buffer, size_t bufLen, // Read raw bytes from the active interface into a predefined buffer uint32_t available = 0; - err = _ChunkedReceive(buffer, &bufLen, false, 60000, &available); + const char *err = _ChunkedReceive(buffer, &bufLen, false, 60000, &available); // Release Notecard Mutex _UnlockNote(); @@ -263,13 +424,13 @@ const char * NoteBinaryReceive(uint8_t * buffer, size_t bufLen, --bufLen; uint32_t decLen = bufLen; - // Decode it in-place, which is safe because decoding shrinks + // Decode it in place, which is safe because decoding shrinks err = NoteBinaryDecode(buffer, bufLen, buffer, &decLen); if (err) { return err; } - // Return the decoded length in the dataLen out parameter. - *dataLen = decLen; + // Return the decoded length in the decodedLen out parameter. + *decodedLen = decLen; // Put a hard marker at the end of the decoded portion of the buffer. This // enables easier human reasoning when interrogating the buffer, if the @@ -290,117 +451,34 @@ const char * NoteBinaryReceive(uint8_t * buffer, size_t bufLen, //**************************************************************************/ /*! - @brief Get the required buffer size to receive the binary object stored on - the Notecard. If there's no data to stored on the Notecard, *size will - be 0. - @param size Out parameter to hold the required size. - @returns An error string on error and NULL on success. -*/ -/**************************************************************************/ -const char * NoteBinaryRequiredRxBuffer(size_t *size) -{ - // Issue a "card.binary" request. - J *rsp = NoteRequestResponse(NoteNewRequest("card.binary")); - if (!rsp) { - NOTE_C_LOG_ERROR("unable to issue binary request"); - return ERRSTR("unable to issue binary request", c_err); - } - - // Ensure the transaction doesn't return an error and confirm the binary - // feature is available. - if (NoteResponseError(rsp)) { - const char *err = JGetString(rsp, "err"); - NOTE_C_LOG_ERROR(err); - JDelete(rsp); - NOTE_C_LOG_ERROR("unexpected error received during handshake"); - return ERRSTR("unexpected error received during handshake", c_bad); - } - - // Examine "cobs" from the response to evaluate the space required to hold - // the COBS-encoded data received from the Notecard. - long int cobs = JGetInt(rsp, "cobs"); - JDelete(rsp); - if (!cobs) { - // If cobs is 0, the required buffer length is 0 because there's nothing - // to receive. - *size = 0; - } else { - // Otherwise, the required length is cobs + 1: the binary data plus - // 1 byte for the terminating newline. - *size = cobs + 1; - } + @brief Transmit a large binary object to the Notecard's binary buffer - return NULL; -} + @param unencodedData A buffer with data to encode in place + @param unencodedLen The length of the data in the buffer + @param bufLen The total length of the buffer (see notes) + @param notecardOffset The offset where the data buffer should be appended + to the decoded binary data already residing on the + Notecard. This does not provide random access, but + rather ensures alignment across sequential writes. -//**************************************************************************/ -/*! - @brief Given the length of a binary payload, calculate the buffer size needed - to COBS-encode that payload in-place in the buffer, plus an additional - byte for an end-of-packet character (i.e. a newline). Because COBS - encoding adds some overhead, this size will be larger than the length - of the payload. - @param dataLen The length of the binary payload. - @returns The required buffer size in bytes. -*/ -/**************************************************************************/ -size_t NoteBinaryRequiredTxBuffer(size_t dataLen) -{ - return (NoteBinaryEncodedMaxLength(dataLen) + 1); -} - -//**************************************************************************/ -/*! - @brief Reset the Notecard's binary buffer @returns NULL on success, else an error string pointer. - @note This operation is not necessary during typical use, but is useful - when the Notecard's binary buffer is in an unknown state. The buffer - will be automatically reset when a binary object is either received, - or transmitted with the offset parameter set to zero (0). -*/ -/**************************************************************************/ -const char * NoteBinaryReset(void) -{ - J *req = NoteNewRequest("card.binary"); - if (req) { - JAddBoolToObject(req, "delete", true); - // Ensure the transaction doesn't return an error. - J *rsp = NoteRequestResponse(req); - if (NoteResponseError(rsp)) { - NOTE_C_LOG_ERROR(JGetString(rsp,"err")); - JDelete(rsp); - NOTE_C_LOG_ERROR("failed to reset binary buffer"); - return ERRSTR("failed to reset binary buffer", c_err); - } - } else { - NOTE_C_LOG_ERROR("unable to allocate request"); - return ERRSTR("unable to allocate request", c_mem); - } - - return NULL; -} - -//**************************************************************************/ -/*! - @brief Transmit a large binary object to the Notecard's binary buffer - @param data A buffer with data to encode in place - @param dataLen The length of the data in the buffer - @param bufLen The total length of the buffer - @param offset The offset where the `data` buffer should be appended to the - unencoded binary data already residing on the Notecard. This - does not provide random access, but rather ensures alignment - between the callers expectation and Notecard. - @returns NULL on success, else an error string pointer. @note Buffers are encoded in place, the buffer _MUST_ be larger than the data to be encoded. The original contents of the buffer will be modified. - @note You may use `NoteBinaryRequiredTxBuffer()` to calculate the required size - for the buffer pointed to by the `data` parameter. -*/ + Use `(NoteBinaryMaxEncodedLength() + 1)` to calculate the required size + for the buffer pointed to by the `bufLen` parameter, which MUST + accommodate the encoded data and newline terminator. + */ /**************************************************************************/ -const char * NoteBinaryTransmit(uint8_t * data, size_t dataLen, size_t bufLen, - size_t offset) +const char * NoteBinaryTransmit(uint8_t *unencodedData, uint32_t unencodedLen, + uint32_t bufLen, uint32_t notecardOffset) { + // Validate parameter(s) + if (!unencodedData) { + NOTE_C_LOG_ERROR("unencodedData cannot be NULL"); + return ERRSTR("unencodedData cannot be NULL", c_err); + } + // Issue a "card.binary" request. J *rsp = NoteRequestResponse(NoteNewRequest("card.binary")); if (!rsp) { @@ -424,8 +502,8 @@ const char * NoteBinaryTransmit(uint8_t * data, size_t dataLen, size_t bufLen, // Examine "length" and "max" from the response to evaluate the unencoded // space available to "card.binary.put" on the Notecard. - const size_t len = JGetInt(rsp,"length"); - const size_t max = JGetInt(rsp,"max"); + const long len = JGetInt(rsp,"length"); + const long max = JGetInt(rsp,"max"); JDelete(rsp); if (!max) { NOTE_C_LOG_ERROR("unexpected response: max is zero or not present"); @@ -435,39 +513,40 @@ const char * NoteBinaryTransmit(uint8_t * data, size_t dataLen, size_t bufLen, // Validate the index provided by the caller, against the `length` value // returned from the Notecard to ensure the caller and Notecard agree on // how much data is residing on the Notecard. - if (offset != len) { + if ((long)notecardOffset != len) { NOTE_C_LOG_ERROR("notecard data length is misaligned with offset"); return ERRSTR("notecard data length is misaligned with offset", c_mem); } - // When `offset` is zero, the entire buffer is available - const size_t remaining = (offset ? (max - len) : max); - if (dataLen > remaining) { + // When offset is zero, the Notecard's entire binary buffer is available + const uint32_t remaining = (notecardOffset ? (max - len) : max); + if (unencodedLen > remaining) { NOTE_C_LOG_ERROR("buffer size exceeds available memory"); return ERRSTR("buffer size exceeds available memory", c_mem); } // Calculate MD5 char hashString[NOTE_MD5_HASH_STRING_SIZE] = {0}; - NoteMD5HashString(data, dataLen, hashString, NOTE_MD5_HASH_STRING_SIZE); + NoteMD5HashString(unencodedData, unencodedLen, hashString, NOTE_MD5_HASH_STRING_SIZE); // Shift the data to the end of the buffer. Next, we'll encode the data, // outputting the encoded data to the front of the buffer. - const size_t dataShift = (bufLen - dataLen); - memmove(data + dataShift, data, dataLen); - - // outLen holds the buffer size available for encoding. The -1 accounts for - // one byte of space we need to save for a newline to mark the end of the - // packet. When NoteBinaryEncode returns, outLen will hold the encoded - // length. - uint32_t encLen = bufLen - 1; - err = NoteBinaryEncode(data + dataShift, dataLen, data, &encLen); + const uint32_t dataShift = (bufLen - unencodedLen); + memmove(unencodedData + dataShift, unencodedData, unencodedLen); + + // `encLen` holds the buffer size available for encoding. The `- 1` accounts + // for one byte of space we need to save for a newline to mark the end of + // the packet. When `NoteBinaryEncode()` returns, `encLen` will hold the + // encoded length. + uint32_t encLen = (bufLen - 1); + uint8_t * const encodedData = unencodedData; + err = NoteBinaryEncode(unencodedData + dataShift, unencodedLen, encodedData, &encLen); if (err) { return err; } // Append the \n, which marks the end of a packet. - data[encLen] = '\n'; + encodedData[encLen] = '\n'; const size_t NOTE_C_BINARY_RETRIES = 3; for (size_t i = 0 ; i < NOTE_C_BINARY_RETRIES ; ++i) { @@ -478,8 +557,8 @@ const char * NoteBinaryTransmit(uint8_t * data, size_t dataLen, size_t bufLen, J *req = NoteNewRequest("card.binary.put"); if (req) { JAddIntToObject(req, "cobs", encLen); - if (offset) { - JAddIntToObject(req, "offset", offset); + if (notecardOffset) { + JAddIntToObject(req, "offset", notecardOffset); } JAddStringToObject(req, "status", hashString); @@ -490,25 +569,25 @@ const char * NoteBinaryTransmit(uint8_t * data, size_t dataLen, size_t bufLen, // On errors, we restore the caller's input buffer by COBS // decoding it. The caller is then able to retry transmission // with their original pointer to this buffer. - NoteBinaryDecode(data, encLen, data, (uint32_t *)&bufLen); + NoteBinaryDecode(encodedData, encLen, unencodedData, &bufLen); return ERRSTR("failed to initialize binary transaction", c_err); } } else { NOTE_C_LOG_ERROR("unable to allocate request"); _UnlockNote(); - NoteBinaryDecode(data, encLen, data, (uint32_t *)&bufLen); + NoteBinaryDecode(encodedData, encLen, unencodedData, &bufLen); return ERRSTR("unable to allocate request", c_mem); } // Immediately send the COBS binary. - const char *err = _ChunkedTransmit(data, (encLen + 1), false); + const char *err = _ChunkedTransmit(encodedData, (encLen + 1), false); // Release Notecard Mutex _UnlockNote(); // Ensure transaction was successful if (err) { - NoteBinaryDecode(data, encLen, data, (uint32_t *)&bufLen); + NoteBinaryDecode(encodedData, encLen, unencodedData, &bufLen); return ERRSTR(err, c_err); } @@ -516,7 +595,7 @@ const char * NoteBinaryTransmit(uint8_t * data, size_t dataLen, size_t bufLen, rsp = NoteRequestResponse(NoteNewRequest("card.binary")); if (!rsp) { NOTE_C_LOG_ERROR("unable to validate request"); - NoteBinaryDecode(data, encLen, data, (uint32_t *)&bufLen); + NoteBinaryDecode(encodedData, encLen, unencodedData, &bufLen); return ERRSTR("unable to validate request", c_err); } @@ -532,13 +611,13 @@ const char * NoteBinaryTransmit(uint8_t * data, size_t dataLen, size_t bufLen, continue; } NOTE_C_LOG_ERROR("binary data invalid"); - NoteBinaryDecode(data, encLen, data, (uint32_t *)&bufLen); + NoteBinaryDecode(encodedData, encLen, unencodedData, &bufLen); return ERRSTR("binary data invalid", c_bad); } else { JDelete(rsp); NOTE_C_LOG_ERROR("unexpected error received during " "confirmation"); - NoteBinaryDecode(data, encLen, data, (uint32_t *)&bufLen); + NoteBinaryDecode(encodedData, encLen, unencodedData, &bufLen); return ERRSTR("unexpected error received during confirmation", c_bad); } @@ -1684,7 +1763,7 @@ bool NotePayloadRetrieveAfterSleep(NotePayloadDesc *desc) return false; } - // Allocate a buffer for the payload. (We can't decode in-place because we + // Allocate a buffer for the payload. (We can't decode in place because we // can't risk overwriting memory if the actual payload is even slightly // different.) uint32_t allocLen = JB64DecodeLen(payload); diff --git a/n_hooks.c b/n_hooks.c index 05b7bea1..26059018 100644 --- a/n_hooks.c +++ b/n_hooks.c @@ -175,8 +175,8 @@ i2cReceiveFn hookI2CReceive = NULL; // Internal hooks typedef bool (*nNoteResetFn) (void); typedef const char * (*nTransactionFn) (char *, char **); -typedef const char * (*nReceiveFn) (uint8_t *, size_t *, bool, size_t, uint32_t *); -typedef const char * (*nTransmitFn) (uint8_t *, size_t, bool); +typedef const char * (*nReceiveFn) (uint8_t *, uint32_t *, bool, size_t, uint32_t *); +typedef const char * (*nTransmitFn) (uint8_t *, uint32_t, bool); static nNoteResetFn notecardReset = NULL; static nTransactionFn notecardTransaction = NULL; static nReceiveFn notecardChunkedReceive = NULL; @@ -877,7 +877,8 @@ const char *NoteJSONTransaction(char *request, char **response) @returns A c-string with an error, or `NULL` if no error ocurred. */ /**************************************************************************/ -const char *NoteChunkedReceive(uint8_t *buffer, size_t *size, bool delay, size_t timeoutMs, uint32_t *available) +const char *NoteChunkedReceive(uint8_t *buffer, uint32_t *size, bool delay, + size_t timeoutMs, uint32_t *available) { if (notecardChunkedReceive == NULL || hookActiveInterface == interfaceNone) { return "i2c or serial interface must be selected"; @@ -895,7 +896,7 @@ const char *NoteChunkedReceive(uint8_t *buffer, size_t *size, bool delay, size_t @returns A c-string with an error, or `NULL` if no error ocurred. */ /**************************************************************************/ -const char *NoteChunkedTransmit(uint8_t *buffer, size_t size, bool delay) +const char *NoteChunkedTransmit(uint8_t *buffer, uint32_t size, bool delay) { if (notecardChunkedTransmit == NULL || hookActiveInterface == interfaceNone) { return "i2c or serial interface must be selected"; diff --git a/n_i2c.c b/n_i2c.c index e1026093..48b78a02 100644 --- a/n_i2c.c +++ b/n_i2c.c @@ -137,9 +137,9 @@ const char *i2cNoteTransaction(char *request, char **response) } // Receive the Notecard response - size_t jsonbufLen = 0; + uint32_t jsonbufLen = 0; do { - size_t jsonbufAvailLen = (jsonbufAllocLen - jsonbufLen); + uint32_t jsonbufAvailLen = (jsonbufAllocLen - jsonbufLen); // Append into the json buffer const char *err = i2cChunkedReceive((uint8_t *)(jsonbuf + jsonbufLen), &jsonbufAvailLen, true, (NOTECARD_TRANSACTION_TIMEOUT_SEC * 1000), &available); @@ -296,7 +296,7 @@ bool i2cNoteReset() @returns A c-string with an error, or `NULL` if no error ocurred. */ /**************************************************************************/ -const char *i2cChunkedReceive(uint8_t *buffer, size_t *size, bool delay, size_t timeoutMs, uint32_t *available) +const char *i2cChunkedReceive(uint8_t *buffer, uint32_t *size, bool delay, size_t timeoutMs, uint32_t *available) { // Load buffer with chunked I2C values size_t received = 0; @@ -383,7 +383,7 @@ const char *i2cChunkedReceive(uint8_t *buffer, size_t *size, bool delay, size_t @returns A c-string with an error, or `NULL` if no error ocurred. */ /**************************************************************************/ -const char *i2cChunkedTransmit(uint8_t *buffer, size_t size, bool delay) +const char *i2cChunkedTransmit(uint8_t *buffer, uint32_t size, bool delay) { // Transmit the request in chunks, but also in segments so as not to // overwhelm the notecard's interrupt buffers diff --git a/n_lib.h b/n_lib.h index fb4383f2..14d3d72e 100644 --- a/n_lib.h +++ b/n_lib.h @@ -81,10 +81,10 @@ const char *i2cNoteTransaction(char *request, char **response); bool i2cNoteReset(void); const char *serialNoteTransaction(char *request, char **response); bool serialNoteReset(void); -const char *i2cChunkedReceive(uint8_t *buffer, size_t *size, bool delay, size_t timeoutMs, uint32_t *available); -const char *i2cChunkedTransmit(uint8_t *buffer, size_t size, bool delay); -const char *serialChunkedReceive(uint8_t *buffer, size_t *size, bool delay, size_t timeoutMs, uint32_t *available); -const char *serialChunkedTransmit(uint8_t *buffer, size_t size, bool delay); +const char *i2cChunkedReceive(uint8_t *buffer, uint32_t *size, bool delay, size_t timeoutMs, uint32_t *available); +const char *i2cChunkedTransmit(uint8_t *buffer, uint32_t size, bool delay); +const char *serialChunkedReceive(uint8_t *buffer, uint32_t *size, bool delay, size_t timeoutMs, uint32_t *available); +const char *serialChunkedTransmit(uint8_t *buffer, uint32_t size, bool delay); // Hooks void NoteLockNote(void); @@ -101,8 +101,8 @@ const char *NoteI2CTransmit(uint16_t DevAddress, uint8_t* pBuffer, uint16_t Size const char *NoteI2CReceive(uint16_t DevAddress, uint8_t* pBuffer, uint16_t Size, uint32_t *avail); bool NoteHardReset(void); const char *NoteJSONTransaction(char *request, char **response); -const char *NoteChunkedReceive(uint8_t *buffer, size_t *size, bool delay, size_t timeoutMs, uint32_t *available); -const char *NoteChunkedTransmit(uint8_t *buffer, size_t size, bool delay); +const char *NoteChunkedReceive(uint8_t *buffer, uint32_t *size, bool delay, size_t timeoutMs, uint32_t *available); +const char *NoteChunkedTransmit(uint8_t *buffer, uint32_t size, bool delay); bool NoteIsDebugOutputActive(void); // Utilities diff --git a/n_serial.c b/n_serial.c index fabafedc..e63a7f5b 100644 --- a/n_serial.c +++ b/n_serial.c @@ -60,7 +60,7 @@ const char *serialNoteTransaction(char *request, char **response) // alloc so we can be assured that it can be null-terminated. This must be // the case because json parsing requires a null-terminated string. uint32_t available = 0; - size_t jsonbufAllocLen = ALLOC_CHUNK; + uint32_t jsonbufAllocLen = ALLOC_CHUNK; uint8_t *jsonbuf = (uint8_t *)_Malloc(jsonbufAllocLen + 1); if (jsonbuf == NULL) { #ifdef ERRDBG @@ -70,9 +70,9 @@ const char *serialNoteTransaction(char *request, char **response) } // Receive the Notecard response - size_t jsonbufLen = 0; + uint32_t jsonbufLen = 0; do { - size_t jsonbufAvailLen = (jsonbufAllocLen - jsonbufLen); + uint32_t jsonbufAvailLen = (jsonbufAllocLen - jsonbufLen); // Append into the json buffer const char *err = serialChunkedReceive((uint8_t *)(jsonbuf + jsonbufLen), &jsonbufAvailLen, true, (NOTECARD_TRANSACTION_TIMEOUT_SEC * 1000), &available); @@ -200,7 +200,7 @@ bool serialNoteReset() @returns A c-string with an error, or `NULL` if no error ocurred. */ /**************************************************************************/ -const char *serialChunkedReceive(uint8_t *buffer, size_t *size, bool delay, size_t timeoutMs, uint32_t *available) +const char *serialChunkedReceive(uint8_t *buffer, uint32_t *size, bool delay, size_t timeoutMs, uint32_t *available) { size_t received = 0; bool overflow = (received >= *size); @@ -261,13 +261,22 @@ const char *serialChunkedReceive(uint8_t *buffer, size_t *size, bool delay, size @returns A c-string with an error, or `NULL` if no error ocurred. */ /**************************************************************************/ -const char *serialChunkedTransmit(uint8_t *buffer, size_t size, bool delay) +const char *serialChunkedTransmit(uint8_t *buffer, uint32_t size, bool delay) { // Transmit the request in segments so as not to overwhelm the Notecard's // interrupt buffers uint32_t segOff = 0; uint32_t segLeft = size; + if (sizeof(size_t) != 4) { // Give the compiler a hint to eliminate the code + // Ensure truncation does not occur on 16-bit microcontrollers + const size_t castSize = (size_t)size; + if (castSize != size) { + NOTE_C_LOG_ERROR("Cannot transmit provided size; limit to `size_t`"); + return "Cannot transmit provided size; limit to `size_t`"; + } + } + while (true) { size_t segLen = segLeft; if (segLen > CARD_REQUEST_SERIAL_SEGMENT_MAX_LEN) { diff --git a/note.h b/note.h index 596b8f5b..e78757c9 100644 --- a/note.h +++ b/note.h @@ -317,19 +317,20 @@ void NoteMD5HashToString(unsigned char *hash, char *strbuf, unsigned long buflen // High-level helper functions that are both useful and serve to show developers // how to call the API -const char * NoteBinaryReceive(uint8_t * buffer, size_t bufLen, - size_t * dataLen); -const char * NoteBinaryRequiredRxBuffer(size_t * size); -size_t NoteBinaryRequiredTxBuffer(size_t dataLen); -const char * NoteBinaryReset(void); -const char * NoteBinaryTransmit(uint8_t * data, size_t dataLen, size_t bufLen, - size_t offset); -const char *NoteBinaryDecode(const uint8_t *inBuf, uint32_t inLen, - uint8_t *outBuf, uint32_t *outLen); -const char *NoteBinaryEncode(const uint8_t *inBuf, uint32_t inLen, - uint8_t *outBuf, uint32_t *outLen); -uint32_t NoteBinaryEncodedLength(const uint8_t *buf, uint32_t len); -uint32_t NoteBinaryEncodedMaxLength(uint32_t len); +#define NOTE_C_BINARY_RX_ALL 0 +const char * NoteBinaryDataDecodedLength(uint32_t *len); +const char * NoteBinaryDataEncodedLength(uint32_t *len); +const char * NoteBinaryDataReset(void); +const char * NoteBinaryDecode(const uint8_t *inBuf, uint32_t inLen, + uint8_t *outBuf, uint32_t *outLen); +const char * NoteBinaryEncode(const uint8_t *inBuf, uint32_t inLen, + uint8_t *outBuf, uint32_t *outLen); +uint32_t NoteBinaryMaxDecodedLength(uint32_t bufferSize); +uint32_t NoteBinaryMaxEncodedLength(uint32_t unencodedLength); +const char * NoteBinaryReceive(uint8_t *buffer, uint32_t bufLen, + uint32_t decodedOffset, uint32_t *decodedLen); +const char * NoteBinaryTransmit(uint8_t *unencodedData, uint32_t unencodedLen, + uint32_t bufLen, uint32_t notecardOffset); uint32_t NoteSetSTSecs(uint32_t secs); bool NoteTimeValid(void); bool NoteTimeValidST(void); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c9154d55..3b621ef1 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -144,10 +144,15 @@ add_test(serialChunkedTransmit_test) add_test(i2cNoteQueryLength_test) add_test(i2cChunkedReceive_test) add_test(i2cChunkedTransmit_test) +add_test(NoteBinaryDataDecodedLength_test) +add_test(NoteBinaryDataEncodedLength_test) +add_test(NoteBinaryDataReset_test) +add_test(NoteBinaryDecode_test) +add_test(NoteBinaryEncode_test) +add_test(NoteBinaryMaxEncodedLength_test) +add_test(NoteBinaryMaxDecodedLength_test) add_test(NoteBinaryReceive_test) add_test(NoteBinaryTransmit_test) -add_test(NoteBinaryRequiredRxBuffer_test) -add_test(NoteBinaryReset_test) if(NOTE_C_COVERAGE) find_program(LCOV lcov REQUIRED) diff --git a/test/src/NoteBinaryDataDecodedLength_test.cpp b/test/src/NoteBinaryDataDecodedLength_test.cpp new file mode 100644 index 00000000..3a0dccb8 --- /dev/null +++ b/test/src/NoteBinaryDataDecodedLength_test.cpp @@ -0,0 +1,135 @@ +/*! + * @file NoteBinaryDataDecodedLength_test.cpp + * + * Written by the Blues Inc. team. + * + * Copyright (c) 2023 Blues Inc. MIT License. Use of this source code is + * governed by licenses granted by the copyright holder including that found in + * the + * LICENSE + * file. + * + */ + +#ifdef NOTE_C_TEST + +#include +#include "fff.h" + +#include "n_lib.h" + +DEFINE_FFF_GLOBALS +FAKE_VALUE_FUNC(J *, NoteRequestResponse, J *) + +const size_t len = 10; + +namespace +{ + +SCENARIO("NoteBinaryDataDecodedLength") +{ + RESET_FAKE(NoteRequestResponse); + + NoteSetFnDefault(malloc, free, NULL, NULL); + + uint32_t size = 1; + + GIVEN("Bad parameters are supplied") { + WHEN("Length is NULL") { + const char *err = NoteBinaryDataDecodedLength(NULL); + + THEN("An error is returned") { + CHECK(err != NULL); + } + } + } + + GIVEN("The card.binary request fails") { + NoteRequestResponse_fake.custom_fake = [](J *req) -> J * { + JDelete(req); + + return NULL; + }; + + WHEN("NoteBinaryDataDecodedLength is called") { + const char *err = NoteBinaryDataDecodedLength(&size); + + REQUIRE(NoteRequestResponse_fake.call_count > 0); + THEN("An error is returned") { + CHECK(err != NULL); + } + } + } + + GIVEN("The response to the card.binary request has an error") { + NoteRequestResponse_fake.custom_fake = [](J *req) -> J * { + JDelete(req); + J *rsp = JCreateObject(); + JAddStringToObject(rsp, "err", "some error"); + + return rsp; + }; + + WHEN("NoteBinaryDataDecodedLength is called") { + const char *err = NoteBinaryDataDecodedLength(&size); + + REQUIRE(NoteRequestResponse_fake.call_count > 0); + THEN("An error is returned") { + CHECK(err != NULL); + } + } + } + + GIVEN("The response to the card.binary request indicates there's nothing to" + " read") { + NoteRequestResponse_fake.custom_fake = [](J *req) -> J * { + JDelete(req); + J *rsp = JCreateObject(); + JAddIntToObject(rsp, "length", 0); + + return rsp; + }; + + WHEN("NoteBinaryDataDecodedLength is called") { + const char *err = NoteBinaryDataDecodedLength(&size); + + REQUIRE(NoteRequestResponse_fake.call_count > 0); + THEN("An error is not returned") { + CHECK(err == NULL); + } + + THEN("The size out parameter is 0") { + CHECK(size == 0); + } + } + } + + GIVEN("The response to the card.binary request indicates there's data " + "to read") { + NoteRequestResponse_fake.custom_fake = [](J *req) -> J * { + JDelete(req); + J *rsp = JCreateObject(); + JAddIntToObject(rsp, "length", len); + + return rsp; + }; + + WHEN("NoteBinaryDataDecodedLength is called") { + const char *err = NoteBinaryDataDecodedLength(&size); + + REQUIRE(NoteRequestResponse_fake.call_count > 0); + THEN("An error is not returned") { + CHECK(err == NULL); + } + + THEN("The size out parameter is the length value in the " + "card.binary response") { + CHECK(size == len); + } + } + } +} + +} + +#endif // NOTE_C_TEST diff --git a/test/src/NoteBinaryRequiredRxBuffer_test.cpp b/test/src/NoteBinaryDataEncodedLength_test.cpp similarity index 71% rename from test/src/NoteBinaryRequiredRxBuffer_test.cpp rename to test/src/NoteBinaryDataEncodedLength_test.cpp index 3ac263b8..605e6cf4 100644 --- a/test/src/NoteBinaryRequiredRxBuffer_test.cpp +++ b/test/src/NoteBinaryDataEncodedLength_test.cpp @@ -1,5 +1,5 @@ /*! - * @file NoteBinaryRequiredRxBuffer_test.cpp + * @file NoteBinaryDataEncodedLength_test.cpp * * Written by the Blues Inc. team. * @@ -21,18 +21,28 @@ DEFINE_FFF_GLOBALS FAKE_VALUE_FUNC(J *, NoteRequestResponse, J *) -const size_t cobsLen = 10; +const uint32_t cobsLen = 10; namespace { -SCENARIO("NoteBinaryRequiredRxBuffer") +SCENARIO("NoteBinaryDataEncodedLength") { RESET_FAKE(NoteRequestResponse); NoteSetFnDefault(malloc, free, NULL, NULL); - size_t size = 1; + uint32_t size = 1; + + GIVEN("Bad parameters are supplied") { + WHEN("Length is NULL") { + const char *err = NoteBinaryDataEncodedLength(NULL); + + THEN("An error is returned") { + CHECK(err != NULL); + } + } + } GIVEN("The card.binary request fails") { NoteRequestResponse_fake.custom_fake = [](J *req) -> J * { @@ -41,8 +51,8 @@ SCENARIO("NoteBinaryRequiredRxBuffer") return NULL; }; - WHEN("NoteBinaryRequiredRxBuffer is called") { - const char *err = NoteBinaryRequiredRxBuffer(&size); + WHEN("NoteBinaryDataEncodedLength is called") { + const char *err = NoteBinaryDataEncodedLength(&size); THEN("An error is returned") { CHECK(err != NULL); @@ -59,8 +69,8 @@ SCENARIO("NoteBinaryRequiredRxBuffer") return rsp; }; - WHEN("NoteBinaryRequiredRxBuffer is called") { - const char *err = NoteBinaryRequiredRxBuffer(&size); + WHEN("NoteBinaryDataEncodedLength is called") { + const char *err = NoteBinaryDataEncodedLength(&size); THEN("An error is returned") { CHECK(err != NULL); @@ -78,8 +88,8 @@ SCENARIO("NoteBinaryRequiredRxBuffer") return rsp; }; - WHEN("NoteBinaryRequiredRxBuffer is called") { - const char *err = NoteBinaryRequiredRxBuffer(&size); + WHEN("NoteBinaryDataEncodedLength is called") { + const char *err = NoteBinaryDataEncodedLength(&size); THEN("An error is not returned") { CHECK(err == NULL); @@ -101,14 +111,14 @@ SCENARIO("NoteBinaryRequiredRxBuffer") return rsp; }; - WHEN("NoteBinaryRequiredRxBuffer is called") { - const char *err = NoteBinaryRequiredRxBuffer(&size); + WHEN("NoteBinaryDataEncodedLength is called") { + const char *err = NoteBinaryDataEncodedLength(&size); THEN("An error is not returned") { CHECK(err == NULL); } - THEN("The size out parameter is the size in the card.binary " + THEN("The size out parameter is the cobs value in the card.binary " "response, plus 1 for the trailing newline") { CHECK(size == cobsLen + 1); } diff --git a/test/src/NoteBinaryReset_test.cpp b/test/src/NoteBinaryDataReset_test.cpp similarity index 82% rename from test/src/NoteBinaryReset_test.cpp rename to test/src/NoteBinaryDataReset_test.cpp index dd625fe7..2ea6f5fe 100644 --- a/test/src/NoteBinaryReset_test.cpp +++ b/test/src/NoteBinaryDataReset_test.cpp @@ -1,5 +1,5 @@ /*! - * @file NoteBinaryReset_test.cpp + * @file NoteBinaryDataReset_test.cpp * * Written by the Blues Inc. team. * @@ -25,7 +25,7 @@ FAKE_VALUE_FUNC(J *, NoteRequestResponse, J *) namespace { -SCENARIO("NoteBinaryReset") +SCENARIO("NoteBinaryDataReset") { RESET_FAKE(NoteNewRequest); RESET_FAKE(NoteRequestResponse); @@ -43,8 +43,8 @@ SCENARIO("NoteBinaryReset") NoteNewRequest_fake.custom_fake = NULL; NoteNewRequest_fake.return_val = NULL; - WHEN("NoteBinaryReset is called") { - const char *err = NoteBinaryReset(); + WHEN("NoteBinaryDataReset is called") { + const char *err = NoteBinaryDataReset(); THEN("An error is returned") { CHECK(err != NULL); @@ -61,8 +61,8 @@ SCENARIO("NoteBinaryReset") return rsp; }; - WHEN("NoteBinaryReset is called") { - const char *err = NoteBinaryReset(); + WHEN("NoteBinaryDataReset is called") { + const char *err = NoteBinaryDataReset(); THEN("An error is returned") { CHECK(err != NULL); @@ -71,8 +71,8 @@ SCENARIO("NoteBinaryReset") } GIVEN("The response to the card.binary indicates success") { - WHEN("NoteBinaryReset is called") { - const char *err = NoteBinaryReset(); + WHEN("NoteBinaryDataReset is called") { + const char *err = NoteBinaryDataReset(); THEN("An error is not returned") { CHECK(err == NULL); diff --git a/test/src/NoteBinaryDecode_test.cpp b/test/src/NoteBinaryDecode_test.cpp new file mode 100644 index 00000000..0dee3060 --- /dev/null +++ b/test/src/NoteBinaryDecode_test.cpp @@ -0,0 +1,95 @@ +/*! + * @file NoteBinaryDecode_test.cpp + * + * Written by the Blues Inc. team. + * + * Copyright (c) 2023 Blues Inc. MIT License. Use of this source code is + * governed by licenses granted by the copyright holder including that found in + * the + * LICENSE + * file. + * + */ + +#ifdef NOTE_C_TEST + +#include +#include "fff.h" + +#include "n_lib.h" + +DEFINE_FFF_GLOBALS +FAKE_VALUE_FUNC(uint32_t, cobsDecode, uint8_t *, uint32_t, uint8_t, uint8_t *) + +uint8_t inBuf[12]; +uint32_t inLen; +uint8_t outBuf[10]; +uint32_t outLen; + +namespace +{ + +SCENARIO("NoteBinaryDecode") +{ + RESET_FAKE(cobsDecode); + uint32_t inLen = sizeof(inBuf); + uint32_t outLen = sizeof(outBuf); + + GIVEN("Bad parameters are supplied") { + WHEN("inBuf is NULL") { + const char *err = NoteBinaryDecode(NULL, inLen, outBuf, &outLen); + + THEN("An error is returned") { + CHECK(err != NULL); + } + } + WHEN("outBuf is NULL") { + const char *err = NoteBinaryDecode(inBuf, inLen, NULL, &outLen); + + THEN("An error is returned") { + CHECK(err != NULL); + } + } + WHEN("outLen is NULL") { + const char *err = NoteBinaryDecode(inBuf, inLen, outBuf, NULL); + + THEN("An error is returned") { + CHECK(err != NULL); + } + } + WHEN("outLen is less than the size required for the worst-case decoding") { + uint32_t badOutLen = (cobsGuaranteedFit(inLen) - 1); + const char *err = NoteBinaryDecode(inBuf, inLen, outBuf, &badOutLen); + + THEN("An error is returned") { + CHECK(err != NULL); + } + } + } + + GIVEN("Parameters are in order") { + const uint32_t EXPECTED_RESULT = 79; + cobsDecode_fake.return_val = EXPECTED_RESULT; + const char *err = NoteBinaryDecode(inBuf, inLen, outBuf, &outLen); + + THEN("cobsDecode is invoked") { + CHECK(cobsDecode_fake.call_count > 0); + } + + WHEN("cobsDecode is invoked") { + THEN("The parameters are passed without modification") { + CHECK(cobsDecode_fake.arg0_history[0] == inBuf); + CHECK(cobsDecode_fake.arg1_history[0] == inLen); + CHECK(cobsDecode_fake.arg3_history[0] == outBuf); + } + + THEN("The result is returned without modification") { + CHECK(EXPECTED_RESULT == outLen); + } + } + } +} + +} + +#endif // NOTE_C_TEST diff --git a/test/src/NoteBinaryEncode_test.cpp b/test/src/NoteBinaryEncode_test.cpp new file mode 100644 index 00000000..cc29822f --- /dev/null +++ b/test/src/NoteBinaryEncode_test.cpp @@ -0,0 +1,97 @@ +/*! + * @file NoteBinaryEncode_test.cpp + * + * Written by the Blues Inc. team. + * + * Copyright (c) 2023 Blues Inc. MIT License. Use of this source code is + * governed by licenses granted by the copyright holder including that found in + * the + * LICENSE + * file. + * + */ + +#ifdef NOTE_C_TEST + +#include + +#include +#include "fff.h" + +#include "n_lib.h" + +DEFINE_FFF_GLOBALS +FAKE_VALUE_FUNC(uint32_t, cobsEncode, uint8_t *, uint32_t, uint8_t, uint8_t *) + +uint8_t inBuf[10] = "Hi there!"; +uint32_t inLen; +uint8_t outBuf[12]; +uint32_t outLen; + +namespace +{ + +SCENARIO("NoteBinaryEncode") +{ + RESET_FAKE(cobsEncode); + uint32_t inLen = strlen((const char *)inBuf); + uint32_t outLen = sizeof(outBuf); + + GIVEN("Bad parameters are supplied") { + WHEN("inBuf is NULL") { + const char *err = NoteBinaryEncode(NULL, inLen, outBuf, &outLen); + + THEN("An error is returned") { + CHECK(err != NULL); + } + } + WHEN("outBuf is NULL") { + const char *err = NoteBinaryEncode(inBuf, inLen, NULL, &outLen); + + THEN("An error is returned") { + CHECK(err != NULL); + } + } + WHEN("outLen is NULL") { + const char *err = NoteBinaryEncode(inBuf, inLen, outBuf, NULL); + + THEN("An error is returned") { + CHECK(err != NULL); + } + } + WHEN("outLen is less than the size required for in place encoding") { + uint32_t badOutLen = (cobsEncodedLength(inBuf, inLen) - 1); + const char *err = NoteBinaryEncode(inBuf, inLen, outBuf, &badOutLen); + + THEN("An error is returned") { + CHECK(err != NULL); + } + } + } + + GIVEN("Parameters are in order") { + const uint32_t EXPECTED_RESULT = 79; + cobsEncode_fake.return_val = EXPECTED_RESULT; + const char *err = NoteBinaryEncode(inBuf, inLen, outBuf, &outLen); + + THEN("cobsEncode is invoked") { + CHECK(cobsEncode_fake.call_count > 0); + } + + WHEN("cobsEncode is invoked") { + THEN("The parameters are passed without modification") { + CHECK(cobsEncode_fake.arg0_history[0] == inBuf); + CHECK(cobsEncode_fake.arg1_history[0] == inLen); + CHECK(cobsEncode_fake.arg3_history[0] == outBuf); + } + + THEN("The result is returned without modification") { + CHECK(EXPECTED_RESULT == outLen); + } + } + } +} + +} + +#endif // NOTE_C_TEST diff --git a/test/src/NoteBinaryMaxDecodedLength_test.cpp b/test/src/NoteBinaryMaxDecodedLength_test.cpp new file mode 100644 index 00000000..81894220 --- /dev/null +++ b/test/src/NoteBinaryMaxDecodedLength_test.cpp @@ -0,0 +1,56 @@ +/*! + * @file NoteBinaryMaxDecodedLength_test.cpp + * + * Written by the Blues Inc. team. + * + * Copyright (c) 2023 Blues Inc. MIT License. Use of this source code is + * governed by licenses granted by the copyright holder including that found in + * the + * LICENSE + * file. + * + */ + +#ifdef NOTE_C_TEST + +#include +#include "fff.h" + +#include "n_lib.h" + +DEFINE_FFF_GLOBALS +FAKE_VALUE_FUNC(uint32_t, cobsGuaranteedFit, uint32_t) + +const uint32_t bufferSize = 10; + +namespace +{ + +SCENARIO("NoteBinaryMaxDecodedLength") +{ + RESET_FAKE(cobsGuaranteedFit); + + GIVEN("Parameters are in order") { + const uint32_t EXPECTED_RESULT = 79; + cobsGuaranteedFit_fake.return_val = EXPECTED_RESULT; + const uint32_t result = NoteBinaryMaxDecodedLength(bufferSize); + + THEN("cobsGuaranteedFit is invoked") { + CHECK(cobsGuaranteedFit_fake.call_count > 0); + } + + WHEN("cobsGuaranteedFit is invoked") { + THEN("The parameters are passed without modification") { + CHECK(cobsGuaranteedFit_fake.arg0_history[0] == bufferSize); + } + + THEN("The result is returned without modification") { + CHECK(EXPECTED_RESULT == result); + } + } + } +} + +} + +#endif // NOTE_C_TEST diff --git a/test/src/NoteBinaryMaxEncodedLength_test.cpp b/test/src/NoteBinaryMaxEncodedLength_test.cpp new file mode 100644 index 00000000..fb3227dc --- /dev/null +++ b/test/src/NoteBinaryMaxEncodedLength_test.cpp @@ -0,0 +1,56 @@ +/*! + * @file NoteBinaryMaxEncodedLength_test.cpp + * + * Written by the Blues Inc. team. + * + * Copyright (c) 2023 Blues Inc. MIT License. Use of this source code is + * governed by licenses granted by the copyright holder including that found in + * the + * LICENSE + * file. + * + */ + +#ifdef NOTE_C_TEST + +#include +#include "fff.h" + +#include "n_lib.h" + +DEFINE_FFF_GLOBALS +FAKE_VALUE_FUNC(uint32_t, cobsEncodedMaxLength, uint32_t) + +const uint32_t unencodedLen = 10; + +namespace +{ + +SCENARIO("NoteBinaryMaxEncodedLength") +{ + RESET_FAKE(cobsEncodedMaxLength); + + GIVEN("Parameters are in order") { + const uint32_t EXPECTED_RESULT = 79; + cobsEncodedMaxLength_fake.return_val = EXPECTED_RESULT; + const uint32_t result = NoteBinaryMaxEncodedLength(unencodedLen); + + THEN("cobsEncodedMaxLength is invoked") { + CHECK(cobsEncodedMaxLength_fake.call_count > 0); + } + + WHEN("cobsEncodedMaxLength is invoked") { + THEN("The parameters are passed without modification") { + CHECK(cobsEncodedMaxLength_fake.arg0_history[0] == unencodedLen); + } + + THEN("The result is returned without modification") { + CHECK(EXPECTED_RESULT == result); + } + } + } +} + +} + +#endif // NOTE_C_TEST diff --git a/test/src/NoteBinaryReceive_test.cpp b/test/src/NoteBinaryReceive_test.cpp index 201fa8bd..e85edf72 100644 --- a/test/src/NoteBinaryReceive_test.cpp +++ b/test/src/NoteBinaryReceive_test.cpp @@ -20,9 +20,9 @@ DEFINE_FFF_GLOBALS FAKE_VALUE_FUNC(J *, NoteNewRequest, const char *) -FAKE_VALUE_FUNC(const char *, NoteBinaryRequiredRxBuffer, size_t *) +FAKE_VALUE_FUNC(const char *, NoteBinaryDataEncodedLength, uint32_t *) FAKE_VALUE_FUNC(J *, NoteRequestResponse, J *) -FAKE_VALUE_FUNC(const char *, NoteChunkedReceive, uint8_t *, size_t *, bool, +FAKE_VALUE_FUNC(const char *, NoteChunkedReceive, uint8_t *, uint32_t *, bool, size_t, uint32_t *) FAKE_VOID_FUNC(NoteLockNote) FAKE_VOID_FUNC(NoteUnlockNote) @@ -34,11 +34,11 @@ FAKE_VOID_FUNC(NoteUnlockNote) // If a lambda captures anything, it can't be converted in this way, and you get // a compiler error. uint8_t buf[32]; -size_t bufLen = sizeof(buf); -size_t dataLen = 0; +uint32_t bufLen = sizeof(buf); +uint32_t dataLen = 0; char rawMsg[] = "Hello Blues!"; -size_t rawMsgLen = strlen(rawMsg); +uint32_t rawMsgLen = strlen(rawMsg); namespace { @@ -46,12 +46,14 @@ namespace SCENARIO("NoteBinaryReceive") { RESET_FAKE(NoteNewRequest); - RESET_FAKE(NoteBinaryRequiredRxBuffer); + RESET_FAKE(NoteBinaryDataEncodedLength); RESET_FAKE(NoteRequestResponse); RESET_FAKE(NoteChunkedReceive); RESET_FAKE(NoteLockNote); RESET_FAKE(NoteUnlockNote); + const uint32_t OFFSET_ZERO = 0; + NoteSetFnDefault(malloc, free, NULL, NULL); // These fakes are the default. Tests below may override them to exercise @@ -59,7 +61,7 @@ SCENARIO("NoteBinaryReceive") NoteNewRequest_fake.custom_fake = [](const char *req) -> J* { return JCreateObject(); }; - NoteBinaryRequiredRxBuffer_fake.custom_fake = [](size_t *size) + NoteBinaryDataEncodedLength_fake.custom_fake = [](uint32_t *size) -> const char * { *size = bufLen; @@ -76,60 +78,14 @@ SCENARIO("NoteBinaryReceive") return rsp; }; - GIVEN("NoteBinaryRequiredRxBuffer fails") { - NoteBinaryRequiredRxBuffer_fake.custom_fake = [](size_t *size) - -> const char * { - *size = 0; - - return NULL; - }; - - WHEN("NoteBinaryReceive is called") { - const char *err = NoteBinaryReceive(buf, bufLen, &dataLen); - - THEN("An error is returned") { - CHECK(err != NULL); - } - } - } - - GIVEN("NoteBinaryRequiredRxBuffer indicates there's no binary data") { - NoteBinaryRequiredRxBuffer_fake.custom_fake = NULL; - NoteBinaryRequiredRxBuffer_fake.return_val = "some error"; - - WHEN("NoteBinaryReceive is called") { - const char *err = NoteBinaryReceive(buf, bufLen, &dataLen); - - THEN("An error is returned") { - CHECK(err != NULL); - } - } - } - - GIVEN("The receive buffer isn't big enough") { - NoteBinaryRequiredRxBuffer_fake.custom_fake = [](size_t *size) - -> const char * { - *size = bufLen + 1; - - return NULL; - }; - - WHEN("NoteBinaryReceive is called") { - const char *err = NoteBinaryReceive(buf, bufLen, &dataLen); - - THEN("An error is returned") { - CHECK(err != NULL); - } - } - } - GIVEN("Allocating the card.binary.get request fails") { NoteNewRequest_fake.custom_fake = NULL; NoteNewRequest_fake.return_val = NULL; WHEN("NoteBinaryReceive is called") { - const char *err = NoteBinaryReceive(buf, bufLen, &dataLen); + const char *err = NoteBinaryReceive(buf, bufLen, OFFSET_ZERO, &dataLen); + REQUIRE(NoteNewRequest_fake.call_count > 0); THEN("An error is returned") { CHECK(err != NULL); } @@ -146,8 +102,9 @@ SCENARIO("NoteBinaryReceive") }; WHEN("NoteBinaryReceive is called") { - const char *err = NoteBinaryReceive(buf, bufLen, &dataLen); + const char *err = NoteBinaryReceive(buf, bufLen, OFFSET_ZERO, &dataLen); + REQUIRE(NoteRequestResponse_fake.call_count > 0); THEN("An error is returned") { CHECK(err != NULL); } @@ -158,8 +115,9 @@ SCENARIO("NoteBinaryReceive") NoteChunkedReceive_fake.return_val = "some error"; WHEN("NoteBinaryReceive is called") { - const char *err = NoteBinaryReceive(buf, bufLen, &dataLen); + const char *err = NoteBinaryReceive(buf, bufLen, OFFSET_ZERO, &dataLen); + REQUIRE(NoteChunkedReceive_fake.call_count > 0); THEN("An error is returned") { CHECK(err != NULL); } @@ -168,7 +126,7 @@ SCENARIO("NoteBinaryReceive") GIVEN("NoteChunkedReceive indicates there's unexpectedly more data " "available") { - NoteChunkedReceive_fake.custom_fake = [](uint8_t *, size_t *, bool, + NoteChunkedReceive_fake.custom_fake = [](uint8_t *, uint32_t *, bool, size_t, uint32_t *available) -> const char* { *available = 1; @@ -176,8 +134,9 @@ SCENARIO("NoteBinaryReceive") }; WHEN("NoteBinaryReceive is called") { - const char *err = NoteBinaryReceive(buf, bufLen, &dataLen); + const char *err = NoteBinaryReceive(buf, bufLen, OFFSET_ZERO, &dataLen); + REQUIRE(NoteChunkedReceive_fake.call_count > 0); THEN("An error is returned") { CHECK(err != NULL); } @@ -185,7 +144,7 @@ SCENARIO("NoteBinaryReceive") } GIVEN("The binary payload is received") { - NoteChunkedReceive_fake.custom_fake = [](uint8_t *buffer, size_t *size, + NoteChunkedReceive_fake.custom_fake = [](uint8_t *buffer, uint32_t *size, bool, size_t, uint32_t *available) -> const char* { uint32_t outLen = *size; NoteBinaryEncode((uint8_t *)rawMsg, rawMsgLen, buffer, &outLen); @@ -207,8 +166,10 @@ SCENARIO("NoteBinaryReceive") }; WHEN("NoteBinaryReceive is called") { - const char *err = NoteBinaryReceive(buf, bufLen, &dataLen); + const char *err = NoteBinaryReceive(buf, bufLen, OFFSET_ZERO, &dataLen); + REQUIRE(NoteChunkedReceive_fake.call_count > 0); + REQUIRE(NoteRequestResponse_fake.call_count > 0); THEN("An error is returned") { CHECK(err != NULL); } @@ -217,8 +178,9 @@ SCENARIO("NoteBinaryReceive") AND_GIVEN("The computed MD5 matches the status field") { WHEN("NoteBinaryReceive is called") { - const char *err = NoteBinaryReceive(buf, bufLen, &dataLen); + const char *err = NoteBinaryReceive(buf, bufLen, OFFSET_ZERO, &dataLen); + REQUIRE(NoteChunkedReceive_fake.call_count > 0); THEN("No error is returned") { CHECK(err == NULL); } @@ -235,66 +197,8 @@ SCENARIO("NoteBinaryReceive") } } } - - // GIVEN("The initial card.binary request fails") { - // NoteRequestResponse_fake.return_val = NULL; - - // WHEN("NoteBinaryReceive is called") { - // const char *err = NoteBinaryReceive(buf, size); - - // THEN("An error is returned") { - // CHECK(err != NULL); - // } - // } - // } - - // GIVEN("The response to the initial card.binary request has an error") { - // J *rsp = JCreateObject(); - // JAddStringToObject(rsp, "err", "some error"); - // NoteRequestResponse_fake.return_val = rsp; - - // WHEN("NoteBinaryReceive is called") { - // const char *err = NoteBinaryReceive(buf, size); - - // THEN("An error is returned") { - // CHECK(err != NULL); - // } - // } - // } - - // GIVEN("The response to the initial card.binary request indicates there's no" - // "binary data to read") { - // J *rsp = JCreateObject(); - // JAddIntToObject(rsp, "cobs", 0); - // NoteRequestResponse_fake.return_val = rsp; - - // WHEN("NoteBinaryReceive is called") { - // const char *err = NoteBinaryReceive(buf, size); - - // THEN("An error is returned") { - // CHECK(err != NULL); - // } - // } - // } - - // GIVEN("The response to the initial card.binary request indicates there's" - // "more data to read than will fit in the provided buffer") { - // J *rsp = JCreateObject(); - // JAddIntToObject(rsp, "cobs", size + 1); - // NoteRequestResponse_fake.return_val = rsp; - - // WHEN("NoteBinaryReceive is called") { - // const char *err = NoteBinaryReceive(buf, size); - - // THEN("An error is returned") { - // CHECK(err != NULL); - // } - // } - // } - - THEN("The Notecard is locked and unlocked the same number of times") { - CHECK(NoteLockNote_fake.call_count == NoteUnlockNote_fake.call_count); - } + CHECK(NoteLockNote_fake.call_count > 0); + CHECK(NoteLockNote_fake.call_count == NoteUnlockNote_fake.call_count); } } diff --git a/test/src/NoteBinaryTransmit_test.cpp b/test/src/NoteBinaryTransmit_test.cpp index a55a3f76..701e0929 100644 --- a/test/src/NoteBinaryTransmit_test.cpp +++ b/test/src/NoteBinaryTransmit_test.cpp @@ -22,13 +22,13 @@ DEFINE_FFF_GLOBALS FAKE_VALUE_FUNC(J *, NoteNewRequest, const char *) FAKE_VALUE_FUNC(J *, NoteRequestResponse, J *) FAKE_VALUE_FUNC(bool, NoteRequest, J *) -FAKE_VALUE_FUNC(const char *, NoteChunkedTransmit, uint8_t *, size_t, bool) +FAKE_VALUE_FUNC(const char *, NoteChunkedTransmit, uint8_t *, uint32_t, bool) FAKE_VOID_FUNC(NoteLockNote) FAKE_VOID_FUNC(NoteUnlockNote) uint8_t buf[32] = {0xDE, 0xAD, 0xBE, 0xEF}; -size_t dataLen = 4; -size_t bufLen = sizeof(buf); +uint32_t dataLen = 4; +uint32_t bufLen = sizeof(buf); namespace { @@ -180,7 +180,13 @@ SCENARIO("NoteBinaryTransmit") return rsp; }; - uint32_t newBufLen = NoteBinaryEncodedLength(buf, dataLen); + + // Discover the actual encoded length of the data + const uint32_t tempBufLen = cobsEncodedMaxLength(dataLen); + uint8_t *tempBuf = (uint8_t *)malloc(tempBufLen); + uint32_t newBufLen = tempBufLen; + REQUIRE(!NoteBinaryEncode(buf, dataLen, tempBuf, &newBufLen)); + free(tempBuf); WHEN("NoteBinaryTransmit is called") { const char *err = NoteBinaryTransmit(buf, dataLen, newBufLen, 0); diff --git a/test/src/i2cChunkedReceive_test.cpp b/test/src/i2cChunkedReceive_test.cpp index ee280129..755efcd9 100644 --- a/test/src/i2cChunkedReceive_test.cpp +++ b/test/src/i2cChunkedReceive_test.cpp @@ -51,7 +51,7 @@ SCENARIO("i2cChunkedReceive") GIVEN("0 is specified for the output buffer length") { uint8_t buf[] = {0xAB}; - size_t zeroSize = 0; + uint32_t zeroSize = 0; AND_GIVEN("NoteI2CReceive reports that here are bytes available from " "the Notecard") { @@ -80,7 +80,7 @@ SCENARIO("i2cChunkedReceive") GIVEN("NoteI2CReceive returns an error") { uint8_t buf[] = {0xAB}; - size_t size = sizeof(buf); + uint32_t size = sizeof(buf); NoteI2CReceive_fake.return_val = "some error"; WHEN("i2cChunkedReceive is called") { @@ -95,7 +95,7 @@ SCENARIO("i2cChunkedReceive") GIVEN("The output buffer is too small") { uint8_t buf[NOTE_I2C_MAX_DEFAULT] = {0}; - size_t size = sizeof(buf); + uint32_t size = sizeof(buf); NoteI2CReceive_fake.custom_fake = NoteI2CReceiveInfinite; WHEN("i2cChunkedReceive is called") { @@ -128,7 +128,7 @@ SCENARIO("i2cChunkedReceive") GIVEN("The output buffer is sufficiently large") { uint8_t buf[NOTE_I2C_MAX_DEFAULT * 3] = {0}; - size_t size = sizeof(buf); + uint32_t size = sizeof(buf); NoteI2CReceive_fake.custom_fake = [](uint16_t, uint8_t *buf, uint16_t size, uint32_t *available) -> const char* { @@ -229,7 +229,7 @@ SCENARIO("i2cChunkedReceive") GIVEN("End-of-packet (\\n) is received, but NoteI2CReceive indicates more " "is still available to read") { uint8_t buf[NOTE_I2C_MAX_DEFAULT * 3] = {0}; - size_t size = sizeof(buf); + uint32_t size = sizeof(buf); size_t numBytesExpected = NOTE_I2C_MAX_DEFAULT * 2; // On the first call, NoteI2CReceive reports back that @@ -306,7 +306,7 @@ SCENARIO("i2cChunkedReceive") return NULL; }; uint8_t buf[NOTE_I2C_MAX_DEFAULT] = {0}; - size_t size = sizeof(buf); + uint32_t size = sizeof(buf); WHEN("i2cChunkedReceive is called") { const char *err = i2cChunkedReceive(buf, &size, true, timeoutMs, @@ -388,7 +388,7 @@ SCENARIO("i2cChunkedReceive") SET_CUSTOM_FAKE_SEQ(NoteI2CReceive, recvFakeSequence, 3); uint8_t buf[NOTE_I2C_MAX_DEFAULT] = {0}; - size_t size = sizeof(buf); + uint32_t size = sizeof(buf); WHEN("i2cChunkedReceive is called") { const char *err = i2cChunkedReceive(buf, &size, true, timeoutMs, diff --git a/test/src/i2cNoteTransaction_test.cpp b/test/src/i2cNoteTransaction_test.cpp index c40ce892..efb9738a 100644 --- a/test/src/i2cNoteTransaction_test.cpp +++ b/test/src/i2cNoteTransaction_test.cpp @@ -23,9 +23,9 @@ DEFINE_FFF_GLOBALS FAKE_VALUE_FUNC(void *, NoteMalloc, size_t) FAKE_VOID_FUNC(NoteLockI2C) FAKE_VOID_FUNC(NoteUnlockI2C) -FAKE_VALUE_FUNC(const char *, i2cChunkedTransmit, uint8_t *, size_t, bool) +FAKE_VALUE_FUNC(const char *, i2cChunkedTransmit, uint8_t *, uint32_t, bool) FAKE_VALUE_FUNC(const char *, i2cNoteQueryLength, uint32_t *, size_t) -FAKE_VALUE_FUNC(const char *, i2cChunkedReceive, uint8_t *, size_t *, bool, +FAKE_VALUE_FUNC(const char *, i2cChunkedReceive, uint8_t *, uint32_t *, bool, size_t, uint32_t *) namespace @@ -126,7 +126,7 @@ TEST_CASE("i2cNoteTransaction") "the Notecard") { // Write out the number of bytes reported available on the prior // call to i2cNoteQueryLength and report no more bytes available. - i2cChunkedReceive_fake.custom_fake = [](uint8_t *buf, size_t *size, bool, size_t, + i2cChunkedReceive_fake.custom_fake = [](uint8_t *buf, uint32_t *size, bool, size_t, uint32_t *available) -> const char* { memset(buf, 'a', *available - 1); buf[*available - 1] = '\n'; @@ -168,7 +168,7 @@ TEST_CASE("i2cNoteTransaction") // On the first call to i2cChunkedReceive, a string of a's is // written to the output buffer, and the Notecard reports that there // are still ALLOC_CHUNK bytes to read. - auto firstChunk = [](uint8_t *buf, size_t *size, bool, size_t, + auto firstChunk = [](uint8_t *buf, uint32_t *size, bool, size_t, uint32_t *available) -> const char* { memset(buf, 'a', *available); *size = *available; @@ -179,7 +179,7 @@ TEST_CASE("i2cNoteTransaction") // On the second call, the remaining ALLOC_CHUNK bytes are written // out, which is a string of a's terminated with a newline. // available is set to 0, indicating there's nothing left to read. - auto secondChunk = [](uint8_t *buf, size_t *size, bool, size_t, + auto secondChunk = [](uint8_t *buf, uint32_t *size, bool, size_t, uint32_t *available) -> const char* { memset(buf, 'a', *available - 1); buf[*available - 1] = '\n'; @@ -188,7 +188,7 @@ TEST_CASE("i2cNoteTransaction") return NULL; }; - const char *(*recvFakeSequence[])(uint8_t *, size_t *, bool, + const char *(*recvFakeSequence[])(uint8_t *, uint32_t *, bool, size_t, uint32_t *) = { firstChunk, secondChunk diff --git a/test/src/serialChunkedReceive_test.cpp b/test/src/serialChunkedReceive_test.cpp index c550c59d..63d177ed 100644 --- a/test/src/serialChunkedReceive_test.cpp +++ b/test/src/serialChunkedReceive_test.cpp @@ -50,7 +50,7 @@ SCENARIO("serialChunkedReceive") NoteGetMs_fake.custom_fake = NoteGetMsIncrement; uint8_t buf[] = {0xDE, 0xAD, 0xBE, 0xEF, 0x00}; - size_t size = sizeof(buf); + uint32_t size = sizeof(buf); bool delay = false; const size_t timeoutMs = 3000; // 37 is not significant. serialChunkedReceive will return either a 1 or 0 @@ -174,7 +174,7 @@ SCENARIO("serialChunkedReceive") GIVEN("A 0-length output buffer is provided") { WHEN("serialChunkedReceive is called") { uint32_t originalAvailable = available; - size_t zeroSize = 0; + uint32_t zeroSize = 0; const char *err = serialChunkedReceive(buf, &zeroSize, delay, timeoutMs, &available); diff --git a/test/src/serialNoteTransaction_test.cpp b/test/src/serialNoteTransaction_test.cpp index da0357ba..01c2bc1f 100644 --- a/test/src/serialNoteTransaction_test.cpp +++ b/test/src/serialNoteTransaction_test.cpp @@ -24,8 +24,8 @@ FAKE_VALUE_FUNC(bool, NoteSerialAvailable) FAKE_VALUE_FUNC(char, NoteSerialReceive) FAKE_VALUE_FUNC(long unsigned int, NoteGetMs) FAKE_VOID_FUNC(NoteSerialTransmit, uint8_t *, size_t, bool) -FAKE_VALUE_FUNC(const char *, serialChunkedTransmit, uint8_t *, size_t, bool); -FAKE_VALUE_FUNC(const char *, serialChunkedReceive, uint8_t *, size_t *, bool, size_t, uint32_t *) +FAKE_VALUE_FUNC(const char *, serialChunkedTransmit, uint8_t *, uint32_t, bool); +FAKE_VALUE_FUNC(const char *, serialChunkedReceive, uint8_t *, uint32_t *, bool, size_t, uint32_t *) namespace { @@ -53,14 +53,14 @@ void NoteSerialTransmitAppend(uint8_t *buf, size_t len, bool) transmitBufLen += len; } -const char *serialChunkedTransmitAppend(uint8_t *buf, size_t len, bool) +const char *serialChunkedTransmitAppend(uint8_t *buf, uint32_t len, bool) { NoteSerialTransmitAppend(buf, len, true); return NULL; } -const char *serialChunkedReceiveNothing(uint8_t *, size_t *size, bool, size_t, +const char *serialChunkedReceiveNothing(uint8_t *, uint32_t *size, bool, size_t, uint32_t *available) { *size = 0; @@ -69,7 +69,7 @@ const char *serialChunkedReceiveNothing(uint8_t *, size_t *size, bool, size_t, return NULL; } -const char *serialChunkedReceiveOneAndDone(uint8_t *buf, size_t *size, bool, +const char *serialChunkedReceiveOneAndDone(uint8_t *buf, uint32_t *size, bool, size_t, uint32_t *available) { *buf = '\n'; @@ -83,7 +83,7 @@ const char *serialChunkedReceiveOneAndDone(uint8_t *buf, size_t *size, bool, size_t serialChunkedReceiveMultipleLeft = SERIAL_CHUNKED_RECEIVE_MULTIPLE_SIZE; -const char *serialChunkedReceiveMultiple(uint8_t *buf, size_t *size, bool, +const char *serialChunkedReceiveMultiple(uint8_t *buf, uint32_t *size, bool, size_t, uint32_t *available) { memset(buf, 1, *size);