diff --git a/src/bacnet/bacdcode.c b/src/bacnet/bacdcode.c index 3974696c..b88ce03d 100644 --- a/src/bacnet/bacdcode.c +++ b/src/bacnet/bacdcode.c @@ -477,6 +477,51 @@ int bacnet_tag_number_decode( return len; } +/** + * @brief Encode a BACnet BACnet Tag Number and Value + * as defined in clause 20.2.1 General Rules for Encoding BACnet Tags + * + * @param apdu - buffer to hold the data to be encoded, or NULL for length + * @param apdu_size - number of bytes in the buffer + * @param tag - tag value to encode + * + * @return returns the number of apdu bytes consumed, + * or 0 if apdu_size is too small to fit the data + */ +int bacnet_tag_encode(uint8_t *apdu, uint32_t apdu_size, BACNET_TAG *tag) +{ + int apdu_len = 0; /* total length of the apdu, return value */ + + if (!tag) { + return 0; + } + if (tag->application) { + apdu_len = encode_tag(NULL, tag->number, false, tag->len_value_type); + } else if (tag->context) { + apdu_len = encode_tag(NULL, tag->number, true, tag->len_value_type); + } else if (tag->opening) { + apdu_len = encode_opening_tag(NULL, tag->number); + } else if (tag->closing) { + apdu_len = encode_closing_tag(NULL, tag->number); + } + if (apdu_len > apdu_size) { + apdu_len = 0; + } else { + if (tag->application) { + apdu_len = + encode_tag(apdu, tag->number, false, tag->len_value_type); + } else if (tag->context) { + apdu_len = encode_tag(apdu, tag->number, true, tag->len_value_type); + } else if (tag->opening) { + apdu_len = encode_opening_tag(apdu, tag->number); + } else if (tag->closing) { + apdu_len = encode_closing_tag(apdu, tag->number); + } + } + + return apdu_len; +} + /** * @brief Decode the BACnet Tag Number and Value * as defined in clause 20.2.1 General Rules For Encoding BACnet Tags @@ -1052,6 +1097,33 @@ bool decode_boolean(uint32_t len_value) return boolean_value; } +/** + * @brief Encode an application tagged boolean value. + * From clause 20.2.3 Encoding of a Boolean Value + * and 20.2.1 General Rules for Encoding BACnet Tags. + * + * @param apdu - buffer to hold the data to be encoded, or NULL for length + * @param apdu_size - number of bytes in the buffer + * @param value - value to encode. + * + * @return returns the number of apdu bytes consumed, + * or 0 if apdu_size is too small to fit the data + */ +int bacnet_boolean_application_encode( + uint8_t *apdu, uint32_t apdu_size, bool value) +{ + int apdu_len = 0; /* total length of the apdu, return value */ + + apdu_len = encode_application_boolean(NULL, value); + if (apdu_len > apdu_size) { + apdu_len = 0; + } else { + apdu_len = encode_application_boolean(apdu, value); + } + + return apdu_len; +} + /** * @brief Decode the Boolean Value when application encoded * From clause 20.2.3 Encoding of a Boolean Value @@ -1257,7 +1329,7 @@ int decode_bitstring( * @param apdu - buffer to hold the bytes * @param apdu_size - number of bytes in the buffer to decode * @param len_value - number of bytes in the unsigned value encoding - * @param value - the unsigned value decoded + * @param value - value to decode into * * @return number of bytes decoded, or zero if errors occur */ @@ -1296,6 +1368,33 @@ int bacnet_bitstring_decode(uint8_t *apdu, return len; } +/** + * @brief Encode an application tagged BACnet bit string value. + * From clause 20.2.10 Encoding of a Bit String Value. + * and 20.2.1 General Rules for Encoding BACnet Tags + * + * @param apdu - buffer to hold the data to be encoded, or NULL for length + * @param apdu_size - number of bytes in the buffer + * @param value - value to encode. + * + * @return returns the number of apdu bytes consumed, + * or 0 if apdu_size is too small to fit the data + */ +int bacnet_bitstring_application_encode( + uint8_t *apdu, uint32_t apdu_size, BACNET_BIT_STRING *value) +{ + int apdu_len = 0; /* total length of the apdu, return value */ + + apdu_len = encode_application_bitstring(NULL, value); + if (apdu_len > apdu_size) { + apdu_len = 0; + } else { + apdu_len = encode_application_bitstring(apdu, value); + } + + return apdu_len; +} + /** * @brief Decodes from bytes into a BACnet bit string value. * From clause 20.2.10 Encoding of a Bit String Value. @@ -1342,7 +1441,7 @@ int bacnet_bitstring_application_decode( * @param apdu - buffer to hold the bytes * @param apdu_size - number of bytes in the buffer to decode * @param tag_value - context tag number expected - * @param value - the character string value decoded + * @param value - decoded value, if decoded * * @return number of bytes decoded, or zero if tag number mismatch, or * #BACNET_STATUS_ERROR (-1) if malformed @@ -1567,7 +1666,7 @@ int decode_object_id( * @param apdu - buffer of data to be decoded * @param apdu_size - number of bytes in the buffer * @param object_type - decoded object type, if decoded - * @param object_instance - decoded object instance, if decoded + * @param instance - decoded object instance, if decoded * * @return the number of apdu bytes consumed, or 0 if apdu is too small */ @@ -1588,6 +1687,37 @@ int bacnet_object_id_decode(uint8_t *apdu, return 0; } +/** + * @brief Encode an application tagged BACnet object identifier value. + * From clause 20.2.14 Encoding of an Object Identifier Value + * and 20.2.1 General Rules for Encoding BACnet Tags + * + * @param apdu - buffer to hold the data to be encoded, or NULL for length + * @param apdu_size - number of bytes in the buffer + * @param value - value to encode + * + * @return returns the number of apdu bytes consumed, + * or 0 if apdu_size is too small to fit the data + */ +int bacnet_object_id_application_encode( + uint8_t *apdu, + uint32_t apdu_size, + BACNET_OBJECT_TYPE object_type, + uint32_t object_instance) +{ + int apdu_len = 0; /* total length of the apdu, return value */ + + apdu_len = encode_application_object_id(NULL, object_type, object_instance); + if (apdu_len > apdu_size) { + apdu_len = 0; + } else { + apdu_len = + encode_application_object_id(apdu, object_type, object_instance); + } + + return apdu_len; +} + /** * @brief Decode the BACnet Object Identifier Value when application encoded * as defined in clause 20.2.14 Encoding of an Object Identifier Value @@ -1878,7 +2008,7 @@ int encode_context_octet_string( * @param apdu_size - number of bytes in the buffer to decode * @param len_value - number of bytes in the unsigned value encoding, may be * zero - * @param value - the unsigned value decoded, or NULL for length + * @param value - the value decoded, or NULL for length * * @return number of bytes decoded (0..N), or BACNET_STATUS_ERROR on error */ @@ -1960,6 +2090,33 @@ int decode_context_octet_string( return len; } +/** + * @brief Encode an application tagged BACnet Octet String Value + * From clause 20.2.8 Encoding of an Octet String Value + * and 20.2.1 General Rules for Encoding BACnet Tags + * + * @param apdu - buffer to hold the data to be encoded, or NULL for length + * @param apdu_size - number of bytes in the buffer + * @param value - value to encode + * + * @return returns the number of apdu bytes consumed, + * or 0 if apdu_size is too small to fit the data + */ +int bacnet_octet_string_application_encode( + uint8_t *apdu, uint32_t apdu_size, BACNET_OCTET_STRING *value) +{ + int apdu_len = 0; /* total length of the apdu, return value */ + + apdu_len = encode_application_octet_string(NULL, value); + if (apdu_len > apdu_size) { + apdu_len = 0; + } else { + apdu_len = encode_application_octet_string(apdu, value); + } + + return apdu_len; +} + /** * @brief Decodes from bytes into a BACnet Octet String application encoding * from clause 20.2.8 Encoding of an Octet String Value @@ -2006,7 +2163,7 @@ int bacnet_octet_string_application_decode( * @param apdu - buffer to hold the bytes * @param apdu_size - number of bytes in the buffer to decode * @param tag_value - context tag number expected - * @param value - the octet string value decoded, or NULL for length + * @param value - the value decoded, or NULL for length * * @return number of bytes decoded, or zero if tag number mismatch, or * #BACNET_STATUS_ERROR (-1) if malformed @@ -2171,7 +2328,7 @@ int encode_context_character_string( * @param apdu - buffer to hold the bytes * @param apdu_size - number of bytes in the buffer to decode * @param len_value - number of bytes in the unsigned value encoding - * @param value - the unsigned value decoded + * @param value - the value decoded, if decoded * * @return number of bytes decoded, or zero if errors occur */ @@ -2220,6 +2377,33 @@ int decode_character_string( return bacnet_character_string_decode(apdu, apdu_size, len_value, value); } +/** + * @brief Encode an application tagged BACnet Character String value + * From clause 20.2.9 Encoding of a Character String Value + * and 20.2.1 General Rules for Encoding BACnet Tags + * + * @param apdu - buffer to hold the data to be encoded, or NULL for length + * @param apdu_size - number of bytes in the buffer + * @param value - value to encode + * + * @return returns the number of apdu bytes consumed, + * or 0 if apdu_size is too small to fit the data + */ +int bacnet_character_string_application_encode( + uint8_t *apdu, uint32_t apdu_size, BACNET_CHARACTER_STRING *value) +{ + int apdu_len = 0; /* total length of the apdu, return value */ + + apdu_len = encode_application_character_string(NULL, value); + if (apdu_len > apdu_size) { + apdu_len = 0; + } else { + apdu_len = encode_application_character_string(apdu, value); + } + + return apdu_len; +} + /** * @brief Decodes from bytes into a BACnet Character String value * from clause 20.2.9 Encoding of a Character String Value @@ -2266,7 +2450,7 @@ int bacnet_character_string_application_decode( * @param apdu - buffer to hold the bytes * @param apdu_size - number of bytes in the buffer to decode * @param tag_value - context tag number expected - * @param value - the character string value decoded + * @param value - the value decoded, if decoded * * @return number of bytes decoded, or zero if tag number mismatch, or * #BACNET_STATUS_ERROR (-1) if malformed @@ -2335,7 +2519,7 @@ int decode_context_character_string( * @param apdu - buffer to hold the bytes * @param apdu_size - number of bytes in the buffer to decode * @param len_value - number of bytes in the unsigned value encoding - * @param value - the unsigned value decoded + * @param value - the value decoded, if decoded * * @return number of bytes decoded, or zero if errors occur */ @@ -2429,7 +2613,7 @@ int bacnet_unsigned_decode(uint8_t *apdu, * @param apdu - buffer to hold the bytes * @param apdu_size - number of bytes in the buffer to decode * @param tag_value - context tag number expected - * @param value - the unsigned value decoded + * @param value - the value decoded, if decoded * * @return number of bytes decoded, zero if wrong tag number, * or #BACNET_STATUS_ERROR (-1) if malformed @@ -2463,6 +2647,33 @@ int bacnet_unsigned_context_decode(uint8_t *apdu, return apdu_len; } +/** + * @brief Encode an application tagged BACnet Unsigned value + * From clause 20.2.4 Encoding of an Unsigned Integer Value + * and 20.2.1 General Rules for Encoding BACnet Tags + * + * @param apdu - buffer to hold the data to be encoded, or NULL for length + * @param apdu_size - number of bytes in the buffer + * @param value - value to encode + * + * @return returns the number of apdu bytes consumed, + * or 0 if apdu_size is too small to fit the data + */ +int bacnet_unsigned_application_encode( + uint8_t *apdu, uint32_t apdu_size, BACNET_UNSIGNED_INTEGER value) +{ + int apdu_len = 0; /* total length of the apdu, return value */ + + apdu_len = encode_application_unsigned(NULL, value); + if (apdu_len > apdu_size) { + apdu_len = 0; + } else { + apdu_len = encode_application_unsigned(apdu, value); + } + + return apdu_len; +} + /** * @brief Decodes from bytes into a BACnet Unsigned value * from clause 20.2.4 Encoding of an Unsigned Integer Value @@ -2696,6 +2907,33 @@ int decode_enumerated(uint8_t *apdu, uint32_t len_value, uint32_t *value) return bacnet_enumerated_decode(apdu, apdu_size, len_value, value); } +/** + * @brief Encode an application tagged BACnet Enumerated value + * From clause 20.2.11 Encoding of an Enumerated Value + * and 20.2.1 General Rules for Encoding BACnet Tags + * + * @param apdu - buffer to hold the data to be encoded, or NULL for length + * @param apdu_size - number of bytes in the buffer + * @param value - bit string value to encode + * + * @return returns the number of apdu bytes consumed, + * or 0 if apdu_size is too small to fit the data + */ +int bacnet_enumerated_application_encode( + uint8_t *apdu, uint32_t apdu_size, uint32_t value) +{ + int apdu_len = 0; /* total length of the apdu, return value */ + + apdu_len = encode_application_enumerated(NULL, value); + if (apdu_len > apdu_size) { + apdu_len = 0; + } else { + apdu_len = encode_application_enumerated(apdu, value); + } + + return apdu_len; +} + /** * @brief Decodes from bytes into a BACnet Enumerated value * from clause 20.2.11 Encoding of an Enumerated Value @@ -2957,6 +3195,33 @@ int bacnet_signed_context_decode( return apdu_len; } +/** + * @brief Encode an application tagged BACnet Signed Integer Value + * From clause 20.2.5 Encoding of a Signed Integer Value + * and 20.2.1 General Rules for Encoding BACnet Tags + * + * @param apdu - buffer to hold the data to be encoded, or NULL for length + * @param apdu_size - number of bytes in the buffer + * @param value - value to encode + * + * @return returns the number of apdu bytes consumed, + * or 0 if apdu_size is too small to fit the data + */ +int bacnet_signed_application_encode( + uint8_t *apdu, uint32_t apdu_size, int32_t value) +{ + int apdu_len = 0; /* total length of the apdu, return value */ + + apdu_len = encode_application_signed(NULL, value); + if (apdu_len > apdu_size) { + apdu_len = 0; + } else { + apdu_len = encode_application_signed(apdu, value); + } + + return apdu_len; +} + /** * @brief Decode the BACnet Signed Integer Value when application encoded * as defined in clause 20.2.5 Encoding of a Signed Integer Value @@ -3183,7 +3448,7 @@ int encode_context_real(uint8_t *apdu, uint8_t tag_number, float value) * @param apdu - buffer to hold the bytes * @param apdu_size - number of bytes in the buffer to decode * @param len_value - number of bytes in the unsigned value encoding - * @param value - the signed value decoded + * @param value - the value decoded, if decoded * * @return number of bytes decoded, or zero if errors occur */ @@ -3207,7 +3472,7 @@ int bacnet_real_decode( * @param apdu - buffer to hold the bytes * @param apdu_size - number of bytes in the buffer to decode * @param tag_value - context tag number expected - * @param value - the signed value decoded + * @param value - the value decoded, if decoded * * @return number of bytes decoded, zero if wrong tag number, * or error (-1) if malformed @@ -3238,6 +3503,33 @@ int bacnet_real_context_decode( return apdu_len; } +/** + * @brief Encode an application tagged BACnet Real Number Value + * From clause 20.2.6 Encoding of a Real Number Value + * and 20.2.1 General Rules for Encoding BACnet Tags + * + * @param apdu - buffer to hold the data to be encoded, or NULL for length + * @param apdu_size - number of bytes in the buffer + * @param value - value to encode + * + * @return returns the number of apdu bytes consumed, + * or 0 if apdu_size is too small to fit the data + */ +int bacnet_real_application_encode( + uint8_t *apdu, uint32_t apdu_size, float value) +{ + int apdu_len = 0; /* total length of the apdu, return value */ + + apdu_len = encode_application_real(NULL, value); + if (apdu_len > apdu_size) { + apdu_len = 0; + } else { + apdu_len = encode_application_real(apdu, value); + } + + return apdu_len; +} + /** * @brief Decode an application tagged single precision floating value * From clause 20.2.6 Encoding of a Real Number Value @@ -3364,7 +3656,7 @@ int encode_context_double(uint8_t *apdu, uint8_t tag_number, double value) * @param apdu - buffer to hold the bytes * @param apdu_size - number of bytes in the buffer to decode * @param len_value - number of bytes in the unsigned value encoding - * @param value - the signed value decoded + * @param value - the value decoded * * @return number of bytes decoded, or zero if errors occur */ @@ -3388,7 +3680,7 @@ int bacnet_double_decode( * @param apdu - buffer to hold the bytes * @param apdu_size - number of bytes in the buffer to decode * @param tag_value - context tag number expected - * @param value - the signed value decoded + * @param value - the value decoded * * @return number of bytes decoded, zero if wrong tag number, * or error (-1) if malformed @@ -3419,6 +3711,33 @@ int bacnet_double_context_decode( return apdu_len; } +/** + * @brief Encode an application tagged Double Precision Real Number Value + * From clause 20.2.7 Encoding of a Double Precision Real Number Value + * and 20.2.1 General Rules for Encoding BACnet Tags + * + * @param apdu - buffer to hold the data to be encoded, or NULL for length + * @param apdu_size - number of bytes in the buffer + * @param value - value to encode + * + * @return returns the number of apdu bytes consumed, + * or 0 if apdu_size is too small to fit the data + */ +int bacnet_double_application_encode( + uint8_t *apdu, uint32_t apdu_size, double value) +{ + int apdu_len = 0; /* total length of the apdu, return value */ + + apdu_len = encode_application_double(NULL, value); + if (apdu_len > apdu_size) { + apdu_len = 0; + } else { + apdu_len = encode_application_double(apdu, value); + } + + return apdu_len; +} + /** * @brief Decode an application tagged double precision floating value. * From clause 20.2.7 Encoding of a Double Precision Real Number Value @@ -3567,7 +3886,7 @@ int encode_context_time(uint8_t *apdu, uint8_t tag_number, BACNET_TIME *btime) * @param apdu - buffer to hold the bytes * @param apdu_size - number of bytes in the buffer to decode * @param len_value - number of bytes encoded - * @param value - the unsigned value decoded + * @param value - the value decoded, if decoded * * @return number of bytes decoded, or zero if errors occur */ @@ -3598,7 +3917,7 @@ int bacnet_time_decode( * @param apdu - buffer to hold the bytes * @param apdu_size - number of bytes in the buffer to decode * @param tag_value - context tag number expected - * @param value - the unsigned value decoded + * @param value - the value decoded, if decoded * * @return number of bytes decoded, zero if wrong tag number, * or error (-1) if malformed @@ -3629,6 +3948,33 @@ int bacnet_time_context_decode( return apdu_len; } +/** + * @brief Encode an application tagged BACnet Time Value + * From clause 20.2.13 Encoding of a Time Value + * and 20.2.1 General Rules for Encoding BACnet Tags + * + * @param apdu - buffer to hold the data to be encoded, or NULL for length + * @param apdu_size - number of bytes in the buffer + * @param value - value to encode + * + * @return returns the number of apdu bytes consumed, + * or 0 if apdu_size is too small to fit the data + */ +int bacnet_time_application_encode( + uint8_t *apdu, uint32_t apdu_size, BACNET_TIME *value) +{ + int apdu_len = 0; /* total length of the apdu, return value */ + + apdu_len = encode_application_time(NULL, value); + if (apdu_len > apdu_size) { + apdu_len = 0; + } else { + apdu_len = encode_application_time(apdu, value); + } + + return apdu_len; +} + /** * @brief Decodes from bytes into a BACnet Time Value application encoded * from clause 20.2.13 Encoding of a Time Value @@ -3942,7 +4288,7 @@ int bacnet_date_decode( * @param apdu - buffer to hold the bytes * @param apdu_size - number of bytes in the buffer to decode * @param tag_value - context tag number expected - * @param value - the unsigned value decoded + * @param value - the value decoded, if decoded * * @return number of bytes decoded, zero if wrong tag number, * or error (-1) if malformed @@ -3973,6 +4319,33 @@ int bacnet_date_context_decode( return apdu_len; } +/** + * @brief Encode an application tagged BACnet Date Value + * From clause 20.2.12 Encoding of a Date Value + * and 20.2.1 General Rules for Encoding BACnet Tags + * + * @param apdu - buffer to hold the data to be encoded, or NULL for length + * @param apdu_size - number of bytes in the buffer + * @param value - value to encode + * + * @return returns the number of apdu bytes consumed, + * or 0 if apdu_size is too small to fit the data + */ +int bacnet_date_application_encode( + uint8_t *apdu, uint32_t apdu_size, BACNET_DATE *value) +{ + int apdu_len = 0; /* total length of the apdu, return value */ + + apdu_len = encode_application_date(NULL, value); + if (apdu_len > apdu_size) { + apdu_len = 0; + } else { + apdu_len = encode_application_date(apdu, value); + } + + return apdu_len; +} + /** * @brief Decodes from bytes into a BACnet Date Value application encoded * From clause 20.2.12 Encoding of a Date Value diff --git a/src/bacnet/bacdcode.h b/src/bacnet/bacdcode.h index 07562445..496b439e 100644 --- a/src/bacnet/bacdcode.h +++ b/src/bacnet/bacdcode.h @@ -73,6 +73,9 @@ BACNET_STACK_EXPORT int encode_opening_tag(uint8_t *apdu, uint8_t tag_number); BACNET_STACK_EXPORT int encode_closing_tag(uint8_t *apdu, uint8_t tag_number); + +BACNET_STACK_EXPORT +int bacnet_tag_encode(uint8_t *apdu, uint32_t apdu_size, BACNET_TAG *tag); BACNET_STACK_EXPORT int bacnet_tag_decode(uint8_t *apdu, uint32_t apdu_size, BACNET_TAG *tag); @@ -152,9 +155,13 @@ BACNET_STACK_EXPORT BACNET_STACK_DEPRECATED("Use bacnet_boolean_context_decode() instead") int decode_context_boolean2( uint8_t *apdu, uint8_t tag_number, bool *boolean_value); + +BACNET_STACK_EXPORT +int bacnet_boolean_application_encode( + uint8_t *apdu, uint32_t apdu_size, bool value); BACNET_STACK_EXPORT int bacnet_boolean_application_decode( - uint8_t *apdu, uint32_t apdu_len_max, bool *boolean_value); + uint8_t *apdu, uint32_t apdu_len_max, bool *value); BACNET_STACK_EXPORT int bacnet_boolean_context_decode(uint8_t *apdu, uint32_t apdu_len_max, @@ -181,11 +188,16 @@ int bacnet_bitstring_decode(uint8_t *apdu, uint32_t apdu_len_max, uint32_t len_value, BACNET_BIT_STRING *value); + +BACNET_STACK_EXPORT +int bacnet_bitstring_application_encode( + uint8_t *apdu, uint32_t apdu_size, BACNET_BIT_STRING *value); BACNET_STACK_EXPORT int bacnet_bitstring_application_decode( uint8_t *apdu, uint32_t apdu_len_max, BACNET_BIT_STRING *value); BACNET_STACK_EXPORT -int bacnet_bitstring_context_decode(uint8_t *apdu, +int bacnet_bitstring_context_decode( + uint8_t *apdu, uint32_t apdu_len_max, uint8_t tag_value, BACNET_BIT_STRING *value); @@ -204,6 +216,9 @@ BACNET_STACK_EXPORT int bacnet_real_context_decode( uint8_t *apdu, uint32_t apdu_len_max, uint8_t tag_value, float *value); BACNET_STACK_EXPORT +int bacnet_real_application_encode( + uint8_t *apdu, uint32_t apdu_size, float value); +BACNET_STACK_EXPORT int bacnet_real_application_decode( uint8_t *apdu, uint32_t apdu_len_max, float *value); @@ -222,6 +237,9 @@ BACNET_STACK_EXPORT int bacnet_double_context_decode( uint8_t *apdu, uint32_t apdu_len_max, uint8_t tag_value, double *value); BACNET_STACK_EXPORT +int bacnet_double_application_encode( + uint8_t *apdu, uint32_t apdu_size, double value); +BACNET_STACK_EXPORT int bacnet_double_application_decode( uint8_t *apdu, uint32_t apdu_len_max, double *value); @@ -257,13 +275,22 @@ int bacnet_object_id_decode(uint8_t *apdu, uint32_t len_value, BACNET_OBJECT_TYPE *object_type, uint32_t *instance); + BACNET_STACK_EXPORT -int bacnet_object_id_application_decode(uint8_t *apdu, +int bacnet_object_id_application_encode( + uint8_t *apdu, + uint32_t apdu_size, + BACNET_OBJECT_TYPE object_type, + uint32_t object_instance); +BACNET_STACK_EXPORT +int bacnet_object_id_application_decode( + uint8_t *apdu, uint32_t apdu_len_max, BACNET_OBJECT_TYPE *object_type, uint32_t *object_instance); BACNET_STACK_EXPORT -int bacnet_object_id_context_decode(uint8_t *apdu, +int bacnet_object_id_context_decode( + uint8_t *apdu, uint32_t apdu_len_max, uint8_t tag_value, BACNET_OBJECT_TYPE *object_type, @@ -290,11 +317,16 @@ int bacnet_octet_string_decode(uint8_t *apdu, uint32_t apdu_len_max, uint32_t len_value, BACNET_OCTET_STRING *value); + +BACNET_STACK_EXPORT +int bacnet_octet_string_application_encode( + uint8_t *apdu, uint32_t apdu_size, BACNET_OCTET_STRING *value); BACNET_STACK_EXPORT int bacnet_octet_string_application_decode( uint8_t *apdu, uint32_t apdu_len_max, BACNET_OCTET_STRING *value); BACNET_STACK_EXPORT -int bacnet_octet_string_context_decode(uint8_t *apdu, +int bacnet_octet_string_context_decode( + uint8_t *apdu, uint32_t apdu_len_max, uint8_t tag_value, BACNET_OCTET_STRING *value); @@ -327,11 +359,16 @@ int bacnet_character_string_decode(uint8_t *apdu, uint32_t apdu_len_max, uint32_t len_value, BACNET_CHARACTER_STRING *char_string); + +BACNET_STACK_EXPORT +int bacnet_character_string_application_encode( + uint8_t *apdu, uint32_t apdu_size, BACNET_CHARACTER_STRING *value); BACNET_STACK_EXPORT int bacnet_character_string_application_decode( uint8_t *apdu, uint32_t apdu_len_max, BACNET_CHARACTER_STRING *value); BACNET_STACK_EXPORT -int bacnet_character_string_context_decode(uint8_t *apdu, +int bacnet_character_string_context_decode( + uint8_t *apdu, uint32_t apdu_len_max, uint8_t tag_value, BACNET_CHARACTER_STRING *value); @@ -356,11 +393,16 @@ int bacnet_unsigned_decode(uint8_t *apdu, uint32_t apdu_max_len, uint32_t len_value, BACNET_UNSIGNED_INTEGER *value); + +BACNET_STACK_EXPORT +int bacnet_unsigned_application_encode( + uint8_t *apdu, uint32_t apdu_size, BACNET_UNSIGNED_INTEGER value); BACNET_STACK_EXPORT int bacnet_unsigned_application_decode( uint8_t *apdu, uint32_t apdu_len_max, BACNET_UNSIGNED_INTEGER *value); BACNET_STACK_EXPORT -int bacnet_unsigned_context_decode(uint8_t *apdu, +int bacnet_unsigned_context_decode( + uint8_t *apdu, uint32_t apdu_len_max, uint8_t tag_number, BACNET_UNSIGNED_INTEGER *value); @@ -377,15 +419,19 @@ int decode_signed(uint8_t *apdu, uint32_t len_value, int32_t *value); BACNET_STACK_DEPRECATED("Use bacnet_signed_context_decode() instead") BACNET_STACK_EXPORT int decode_context_signed(uint8_t *apdu, uint8_t tag_number, int32_t *value); + BACNET_STACK_EXPORT int bacnet_signed_decode( - uint8_t *apdu, uint32_t apdu_len_max, uint32_t len_value, int32_t *value); + uint8_t *apdu, uint32_t apdu_size, uint32_t len_value, int32_t *value); BACNET_STACK_EXPORT int bacnet_signed_context_decode( - uint8_t *apdu, uint32_t apdu_len_max, uint8_t tag_value, int32_t *value); + uint8_t *apdu, uint32_t apdu_size, uint8_t tag_value, int32_t *value); +BACNET_STACK_EXPORT +int bacnet_signed_application_encode( + uint8_t *apdu, uint32_t apdu_size, int32_t value); BACNET_STACK_EXPORT int bacnet_signed_application_decode( - uint8_t *apdu, uint32_t apdu_len_max, int32_t *value); + uint8_t *apdu, uint32_t apdu_size, int32_t *value); BACNET_STACK_EXPORT int encode_bacnet_enumerated(uint8_t *apdu, uint32_t value); @@ -404,6 +450,11 @@ int decode_context_enumerated( BACNET_STACK_EXPORT int bacnet_enumerated_decode( uint8_t *apdu, uint32_t apdu_max_len, uint32_t len_value, uint32_t *value); + + +BACNET_STACK_EXPORT +int bacnet_enumerated_application_encode( + uint8_t *apdu, uint32_t apdu_size, uint32_t value); BACNET_STACK_EXPORT int bacnet_enumerated_application_decode( uint8_t *apdu, uint32_t apdu_len_max, uint32_t *value); @@ -442,6 +493,9 @@ int bacnet_time_context_decode(uint8_t *apdu, uint8_t tag_value, BACNET_TIME *value); BACNET_STACK_EXPORT +int bacnet_time_application_encode( + uint8_t *apdu, uint32_t apdu_size, BACNET_TIME *value); +BACNET_STACK_EXPORT int bacnet_time_application_decode( uint8_t *apdu, uint32_t apdu_len_max, BACNET_TIME *value); @@ -468,6 +522,10 @@ int bacnet_date_decode(uint8_t *apdu, uint32_t apdu_len_max, uint32_t len_value, BACNET_DATE *value); + +BACNET_STACK_EXPORT +int bacnet_date_application_encode( + uint8_t *apdu, uint32_t apdu_size, BACNET_DATE *value); BACNET_STACK_EXPORT int bacnet_date_application_decode( uint8_t *apdu, uint32_t apdu_len_max, BACNET_DATE *value); diff --git a/src/bacnet/basic/object/device.c b/src/bacnet/basic/object/device.c index e601b114..d43ea2c0 100644 --- a/src/bacnet/basic/object/device.c +++ b/src/bacnet/basic/object/device.c @@ -82,7 +82,7 @@ extern bool Routed_Device_Write_Property_Local( /* may be overridden by outside table */ static object_functions_t *Object_Table; -/* clang format off */ +/* clang-format off */ static object_functions_t My_Object_Table[] = { { OBJECT_DEVICE, NULL /* Init - don't init Device or it will recourse! */, Device_Count, Device_Index_To_Instance, @@ -381,7 +381,7 @@ static object_functions_t My_Object_Table[] = { NULL /* Add_List_Element */, NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }, }; -/* clang format on */ +/* clang-format on */ /** Glue function to let the Device object, when called by a handler, * lookup which Object type needs to be invoked. @@ -476,7 +476,7 @@ void Device_Objects_Property_List(BACNET_OBJECT_TYPE object_type, return; } -/* clang format off */ +/* clang-format off */ /* These three arrays are used by the ReadPropertyMultiple handler */ static const int Device_Properties_Required[] = { PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE, @@ -506,7 +506,7 @@ static const int Device_Properties_Optional[] = { static const int Device_Properties_Proprietary[] = { -1 }; -/* clang format on */ +/* clang-format on */ void Device_Property_Lists( const int **pRequired, const int **pOptional, const int **pProprietary) diff --git a/src/bacnet/property.c b/src/bacnet/property.c index 12ab0aad..4e2ebfeb 100644 --- a/src/bacnet/property.c +++ b/src/bacnet/property.c @@ -1601,7 +1601,7 @@ unsigned property_list_special_count( /* standard properties that are arrays but not necessary supported in every object */ -/* clang format off */ +/* clang-format off */ static const int Properties_BACnetARRAY[] = { PROP_AUTHENTICATION_FACTORS, PROP_ASSIGNED_ACCESS_RIGHTS, PROP_PRIORITY_ARRAY, PROP_VALUE_SOURCE_ARRAY, PROP_COMMAND_TIME_ARRAY, @@ -1622,7 +1622,7 @@ static const int Properties_BACnetARRAY[] = { PROP_STAGES, PROP_STAGE_NAMES, PROP_TARGET_REFERENCES, PROP_MONITORED_OBJECTS, PROP_TAGS, -1 }; -/* clang format on */ +/* clang-format on */ /** * Function that returns the list of Required properties diff --git a/test/bacnet/bacdcode/src/main.c b/test/bacnet/bacdcode/src/main.c index 089926fc..6ddb4c4a 100644 --- a/test/bacnet/bacdcode/src/main.c +++ b/test/bacnet/bacdcode/src/main.c @@ -230,6 +230,87 @@ static void testBACDCodeTags(void) return; } +#if defined(CONFIG_ZTEST_NEW_API) +ZTEST(bacdcode_tests, testBACnetTagEncoder) +#else +static void testBACnetTagEncoder(void) +#endif +{ + uint8_t apdu[MAX_APDU] = { 0 }; + unsigned i = 0, j = 0, k = 0; + BACNET_TAG tag = { 0 }, test_tag = { 0 }; + int len, test_len, null_len; + + tag.application = true; + tag.opening = false; + tag.closing = false; + tag.context = false; + tag.len_value_type = 0; + tag.number = 0; + for (k = 0; k < 2; k++) { + for (j = 0; j < 8; j++) { + for (i = 0; i < 32; i++) { + null_len = bacnet_tag_encode(NULL, sizeof(apdu), &tag); + len = bacnet_tag_encode(&apdu[0], sizeof(apdu), &tag); + zassert_equal(len, null_len, NULL); + test_len = bacnet_tag_decode(apdu, len, &test_tag); + zassert_equal(len, test_len, NULL); + zassert_equal(tag.number, test_tag.number, NULL); + zassert_equal(tag.application, test_tag.application, NULL); + zassert_equal(tag.context, test_tag.context, NULL); + zassert_equal(tag.closing, test_tag.closing, NULL); + zassert_equal(tag.opening, test_tag.opening, NULL); + tag.len_value_type = BIT(i); + } + tag.number = BIT(i); + } + tag.context = true; + tag.application = false; + tag.len_value_type = 0; + tag.number = 0; + } + tag.opening = true; + tag.closing = false; + tag.application = false; + tag.context = false; + tag.len_value_type = 0; + tag.number = 0; + for (k = 0; k < 2; k++) { + for (j = 0; j < 8; j++) { + null_len = bacnet_tag_encode(NULL, sizeof(apdu), &tag); + len = bacnet_tag_encode(&apdu[0], sizeof(apdu), &tag); + zassert_equal(len, null_len, NULL); + test_len = bacnet_tag_decode(apdu, len, &test_tag); + zassert_equal(len, test_len, NULL); + zassert_equal(tag.number, test_tag.number, NULL); + zassert_equal(tag.application, test_tag.application, NULL); + zassert_equal(tag.context, test_tag.context, NULL); + zassert_equal(tag.closing, test_tag.closing, NULL); + zassert_equal(tag.opening, test_tag.opening, NULL); + tag.number = BIT(i); + } + tag.number = 0; + tag.opening = false; + tag.closing = true; + } + tag.number = BIT(7); + tag.len_value_type = BIT(31); + tag.opening = false; + tag.closing = false; + tag.application = true; + tag.context = false; + len = bacnet_tag_encode(&apdu[0], sizeof(apdu), &tag); + while (--len) { + test_len = bacnet_tag_decode(apdu, len, &test_tag); + zassert_equal(test_len, 0, NULL); + } + null_len = bacnet_tag_encode(NULL, sizeof(apdu), &tag); + while (--null_len) { + test_len = bacnet_tag_encode(&apdu[0], null_len, &tag); + zassert_equal(test_len, 0, NULL); + } +} + #if defined(CONFIG_ZTEST_NEW_API) ZTEST(bacdcode_tests, testBACDCodeEnumerated) #else @@ -281,6 +362,16 @@ static void testBACDCodeEnumerated(void) /* test the interesting values */ value = BIT(i); } + apdu_len = bacnet_enumerated_application_encode(apdu, sizeof(apdu), value); + null_len = bacnet_enumerated_application_encode(NULL, sizeof(apdu), value); + zassert_equal(apdu_len, null_len, NULL); + len = bacnet_enumerated_application_decode(apdu, apdu_len, &decoded_value); + zassert_equal(apdu_len, len, "len=%d apdu_len=%d", len, apdu_len); + zassert_equal(decoded_value, value, NULL); + while (--apdu_len) { + len = bacnet_enumerated_application_encode(apdu, apdu_len, value); + zassert_equal(len, 0, NULL); + } return; } @@ -339,6 +430,16 @@ static void testBACDCodeReal(void) len = bacnet_real_application_decode(apdu, apdu_len, NULL); zassert_equal(len, BACNET_STATUS_ERROR, NULL); } + apdu_len = bacnet_real_application_encode(apdu, sizeof(apdu), value); + null_len = bacnet_real_application_encode(NULL, sizeof(apdu), value); + zassert_equal(apdu_len, null_len, NULL); + len = bacnet_real_application_decode(apdu, apdu_len, &decoded_value); + zassert_equal(apdu_len, len, "len=%d apdu_len=%d", len, apdu_len); + zassert_false(islessgreater(decoded_value, value), NULL); + while (--apdu_len) { + len = bacnet_real_application_encode(apdu, apdu_len, value); + zassert_equal(len, 0, NULL); + } return; } @@ -398,6 +499,16 @@ static void testBACDCodeDouble(void) len = bacnet_double_application_decode(apdu, apdu_len, NULL); zassert_equal(len, BACNET_STATUS_ERROR, NULL); } + apdu_len = bacnet_double_application_encode(apdu, sizeof(apdu), value); + null_len = bacnet_double_application_encode(NULL, sizeof(apdu), value); + zassert_equal(apdu_len, null_len, NULL); + len = bacnet_double_application_decode(apdu, apdu_len, &decoded_value); + zassert_equal(apdu_len, len, "len=%d apdu_len=%d", len, apdu_len); + zassert_false(islessgreater(decoded_value, value), NULL); + while (--apdu_len) { + len = bacnet_double_application_encode(apdu, apdu_len, value); + zassert_equal(len, 0, NULL); + } return; } @@ -410,36 +521,49 @@ static void testBACnetDateDecodes(void) { uint8_t apdu[MAX_APDU]; uint8_t sample[10] = { 0xa4, 0xff, 0xff, 0xff, 0xff }; - int inLen; - int outLen; - int outLen2; + int len, test_len, null_len, apdu_len; + BACNET_DATE value; + BACNET_DATE test_value; - BACNET_DATE in; - BACNET_DATE out; - - in.day = 3; - in.month = 10; - in.wday = 5; - in.year = 1945; - - inLen = encode_application_date(apdu, &in); - outLen = decode_application_date(apdu, &out); - - zassert_equal(inLen, outLen, NULL); - zassert_equal(in.day, out.day, NULL); - zassert_equal(in.month, out.month, NULL); - zassert_equal(in.wday, out.wday, NULL); - zassert_equal(in.year, out.year, NULL); - - memset(&out, 0, sizeof(out)); - outLen = decode_application_date(sample, &out); + value.day = 3; + value.month = 10; + value.wday = 5; + value.year = 1945; + len = encode_application_date(apdu, &value); + test_len = decode_application_date(apdu, &test_value); + zassert_equal(len, test_len, NULL); + zassert_equal(value.day, test_value.day, NULL); + zassert_equal(value.month, test_value.month, NULL); + zassert_equal(value.wday, test_value.wday, NULL); + zassert_equal(value.year, test_value.year, NULL); + memset(&test_value, 0, sizeof(test_value)); + test_len = decode_application_date(sample, &test_value); /* try decoding sample data captured from a bacnet device - all wildcards */ - zassert_equal(5, outLen, NULL); - zassert_equal(0xff, out.day, NULL); - zassert_equal(0xff, out.month, NULL); - zassert_equal(0xff, out.wday, NULL); - zassert_equal(2155, out.year, NULL); + zassert_equal(5, test_len, NULL); + zassert_equal(0xff, test_value.day, NULL); + zassert_equal(0xff, test_value.month, NULL); + zassert_equal(0xff, test_value.wday, NULL); + zassert_equal(2155, test_value.year, NULL); + /* test new API for APDU size checking and NULL behavior */ + apdu_len = bacnet_date_application_encode(apdu, sizeof(apdu), &value); + null_len = bacnet_date_application_encode(NULL, sizeof(apdu), &value); + zassert_equal(apdu_len, null_len, NULL); + test_len = bacnet_date_application_decode(apdu, apdu_len, &test_value); + zassert_equal( + apdu_len, test_len, "test_len=%d apdu_len=%d", test_len, apdu_len); + zassert_equal(value.day, test_value.day, NULL); + zassert_equal(value.month, test_value.month, NULL); + zassert_equal(value.wday, test_value.wday, NULL); + zassert_equal(value.year, test_value.year, NULL); + while (--test_len) { + len = bacnet_date_application_decode(apdu, test_len, &test_value); + zassert_equal(len, BACNET_STATUS_ERROR, NULL); + } + while (--apdu_len) { + len = bacnet_date_application_encode(apdu, apdu_len, &value); + zassert_equal(len, 0, NULL); + } } #if defined(CONFIG_ZTEST_NEW_API) @@ -563,6 +687,18 @@ static void test_bacnet_unsigned_value_codec(BACNET_UNSIGNED_INTEGER value) test_len = bacnet_unsigned_application_decode(apdu, apdu_len, NULL); zassert_equal(test_len, BACNET_STATUS_ERROR, NULL); } + apdu_len = bacnet_unsigned_application_encode(apdu, sizeof(apdu), value); + null_len = bacnet_unsigned_application_encode(NULL, sizeof(apdu), value); + zassert_equal(apdu_len, null_len, NULL); + test_len = + bacnet_unsigned_application_decode(apdu, apdu_len, &decoded_value); + zassert_equal( + apdu_len, test_len, "test_len=%d apdu_len=%d", test_len, apdu_len); + zassert_equal(decoded_value, value, NULL); + while (--apdu_len) { + test_len = bacnet_unsigned_application_encode(apdu, apdu_len, value); + zassert_equal(test_len, 0, NULL); + } } #if defined(CONFIG_ZTEST_NEW_API) @@ -638,7 +774,7 @@ static void testBACnetUnsigned(void) static void testBACDCodeSignedValue(int32_t value) { int32_t decoded_value = 0; - int len = 0, null_len = 0, tag_len = 0, test_len = 0; + int len = 0, null_len = 0, tag_len = 0, test_len = 0, apdu_len = 0; uint8_t apdu[MAX_APDU] = { 0 }; BACNET_TAG tag = { 0 }; @@ -685,6 +821,17 @@ static void testBACDCodeSignedValue(int32_t value) test_len = bacnet_signed_application_decode(apdu, len, NULL); zassert_equal(test_len, BACNET_STATUS_ERROR, NULL); } + apdu_len = bacnet_signed_application_encode(apdu, sizeof(apdu), value); + null_len = bacnet_signed_application_encode(NULL, sizeof(apdu), value); + zassert_equal(apdu_len, null_len, NULL); + test_len = bacnet_signed_application_decode(apdu, apdu_len, &decoded_value); + zassert_equal( + apdu_len, test_len, "test_len=%d apdu_len=%d", test_len, apdu_len); + zassert_equal(decoded_value, value, NULL); + while (--apdu_len) { + test_len = bacnet_signed_application_encode(apdu, apdu_len, value); + zassert_equal(test_len, 0, NULL); + } return; } @@ -769,9 +916,9 @@ static void testBACDCodeOctetString(void) #endif { uint8_t apdu[MAX_APDU] = { 0 }; - BACNET_OCTET_STRING octet_string; - BACNET_OCTET_STRING test_octet_string; - uint8_t test_value[MAX_APDU] = { "" }; + BACNET_OCTET_STRING value; + BACNET_OCTET_STRING test_value; + uint8_t test_apdu[MAX_APDU] = { "" }; int i; /* for loop counter */ int apdu_len = 0, len = 0, null_len = 0, test_len = 0; uint8_t tag_number = 0; @@ -779,45 +926,61 @@ static void testBACDCodeOctetString(void) bool status = false; int diff = 0; /* for memcmp */ - status = octetstring_init(&octet_string, NULL, 0); + status = octetstring_init(&value, NULL, 0); zassert_true(status, NULL); - apdu_len = encode_application_octet_string(&apdu[0], &octet_string); - null_len = encode_application_octet_string(NULL, &octet_string); + apdu_len = encode_application_octet_string(&apdu[0], &value); + null_len = encode_application_octet_string(NULL, &value); zassert_equal(apdu_len, null_len, NULL); #if defined(BACNET_STACK_DEPRECATED_DISABLE) len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value); zassert_equal(tag_number, BACNET_APPLICATION_TAG_OCTET_STRING, NULL); - len += decode_octet_string(&apdu[len], len_value, &test_octet_string); + len += decode_octet_string(&apdu[len], len_value, &test_value); zassert_equal(apdu_len, len, NULL); diff = memcmp( - octetstring_value(&octet_string), &test_value[0], - octetstring_length(&octet_string)); + octetstring_value(&value), &test_apdu[0], octetstring_length(&value)); zassert_equal(diff, 0, NULL); #endif for (i = 0; i < (MAX_APDU - 6); i++) { - test_value[i] = '0' + (i % 10); - status = octetstring_init(&octet_string, test_value, i); + test_apdu[i] = '0' + (i % 10); + status = octetstring_init(&value, test_apdu, i); zassert_true(status, NULL); - apdu_len = encode_application_octet_string(apdu, &octet_string); - null_len = encode_application_octet_string(NULL, &octet_string); + apdu_len = encode_application_octet_string(apdu, &value); + null_len = encode_application_octet_string(NULL, &value); zassert_equal(apdu_len, null_len, NULL); #if defined(BACNET_STACK_DEPRECATED_DISABLE) len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value); zassert_equal(tag_number, BACNET_APPLICATION_TAG_OCTET_STRING, NULL); - len += decode_octet_string(&apdu[len], len_value, &test_octet_string); + len += decode_octet_string(&apdu[len], len_value, &test_value); zassert_equal(apdu_len, len, "test octet string=#%d\n", i); diff = memcmp( - octetstring_value(&octet_string), &test_value[0], - octetstring_length(&octet_string)); + octetstring_value(&value), &test_apdu[0], + octetstring_length(&value)); zassert_equal(diff, 0, "test octet string=#%d\n", i); #endif - test_len = bacnet_octet_string_application_decode( - apdu, apdu_len, &test_octet_string); + test_len = + bacnet_octet_string_application_decode(apdu, apdu_len, &test_value); zassert_equal( apdu_len, test_len, "apdu_len=%d test_len=%d i=%d", apdu_len, test_len, i); - zassert_true( - octetstring_value_same(&octet_string, &test_octet_string), NULL); + zassert_true(octetstring_value_same(&value, &test_value), NULL); + } + apdu_len = + bacnet_octet_string_application_encode(apdu, sizeof(apdu), &value); + null_len = + bacnet_octet_string_application_encode(NULL, sizeof(apdu), &value); + zassert_equal(apdu_len, null_len, NULL); + test_len = + bacnet_octet_string_application_decode(apdu, apdu_len, &test_value); + zassert_equal( + apdu_len, test_len, "test_len=%d apdu_len=%d", test_len, apdu_len); + zassert_true(octetstring_value_same(&value, &test_value), NULL); + while (--test_len) { + len = bacnet_octet_string_application_decode(apdu, test_len, NULL); + zassert_equal(len, BACNET_STATUS_ERROR, NULL); + } + while (--apdu_len) { + len = bacnet_octet_string_application_encode(apdu, apdu_len, &value); + zassert_equal(len, 0, NULL); } return; @@ -831,43 +994,43 @@ static void testBACDCodeCharacterString(void) { uint8_t apdu[MAX_APDU] = { 0 }; uint8_t encoded_apdu[MAX_APDU] = { 0 }; - BACNET_CHARACTER_STRING char_string; - BACNET_CHARACTER_STRING test_char_string; - char test_value[MAX_APDU] = { "" }; + BACNET_CHARACTER_STRING value; + BACNET_CHARACTER_STRING test_value; + char test_name[MAX_APDU] = { "" }; int i; /* for loop counter */ - int apdu_len = 0, len = 0, null_len = 0, tag_len; + int apdu_len = 0, len = 0, null_len = 0, tag_len, test_len; uint8_t tag_number = 0; uint32_t len_value = 0; int diff = 0; /* for comparison */ bool status = false; BACNET_TAG tag = { 0 }; - status = characterstring_init(&char_string, CHARACTER_ANSI_X34, NULL, 0); + status = characterstring_init(&value, CHARACTER_ANSI_X34, NULL, 0); zassert_true(status, NULL); - apdu_len = encode_application_character_string(&apdu[0], &char_string); - null_len = encode_application_character_string(NULL, &char_string); + apdu_len = encode_application_character_string(&apdu[0], &value); + null_len = encode_application_character_string(NULL, &value); zassert_equal(apdu_len, null_len, NULL); #if defined(BACNET_STACK_DEPRECATED_DISABLE) len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value); zassert_equal(tag_number, BACNET_APPLICATION_TAG_CHARACTER_STRING, NULL); - len += decode_character_string(&apdu[len], len_value, &test_char_string); + len += decode_character_string(&apdu[len], len_value, &test_value); zassert_equal(apdu_len, len, NULL); diff = memcmp( - characterstring_value(&char_string), &test_value[0], - characterstring_length(&char_string)); + characterstring_value(&value), &test_name[0], + characterstring_length(&value)); zassert_equal(diff, 0, NULL); #endif for (i = 0; i < MAX_CHARACTER_STRING_BYTES - 1; i++) { - test_value[i] = 'S'; - test_value[i + 1] = '\0'; - status = characterstring_init_ansi(&char_string, test_value); + test_name[i] = 'S'; + test_name[i + 1] = '\0'; + status = characterstring_init_ansi(&value, test_name); zassert_true(status, NULL); apdu_len = - encode_application_character_string(&encoded_apdu[0], &char_string); - null_len = encode_application_character_string(NULL, &char_string); + encode_application_character_string(&encoded_apdu[0], &value); + null_len = encode_application_character_string(NULL, &value); zassert_equal(apdu_len, null_len, NULL); len = bacnet_character_string_application_decode( - encoded_apdu, apdu_len, &test_char_string); + encoded_apdu, apdu_len, &test_value); zassert_equal(len, apdu_len, NULL); tag_len = bacnet_tag_decode(encoded_apdu, apdu_len, &tag); zassert_true(tag_len > 0, NULL); @@ -882,13 +1045,32 @@ static void testBACDCodeCharacterString(void) } zassert_equal(apdu_len, len, NULL); diff = memcmp( - characterstring_value(&char_string), &test_value[0], - characterstring_length(&char_string)); + characterstring_value(&value), &test_name[0], + characterstring_length(&value)); if (diff) { printf("test string=#%d\n", i); } zassert_equal(diff, 0, NULL); } + apdu_len = + bacnet_character_string_application_encode(apdu, sizeof(apdu), &value); + null_len = + bacnet_character_string_application_encode(NULL, sizeof(apdu), &value); + zassert_equal(apdu_len, null_len, NULL); + test_len = + bacnet_character_string_application_decode(apdu, apdu_len, &test_value); + zassert_equal( + apdu_len, test_len, "test_len=%d apdu_len=%d", test_len, apdu_len); + zassert_true(characterstring_same(&value, &test_value), NULL); + while (--test_len) { + len = bacnet_character_string_application_decode(apdu, test_len, NULL); + zassert_equal(len, BACNET_STATUS_ERROR, NULL); + } + while (--apdu_len) { + len = + bacnet_character_string_application_encode(apdu, apdu_len, &value); + zassert_equal(len, 0, NULL); + } return; } @@ -901,11 +1083,12 @@ static void testBACDCodeObject(void) { uint8_t object_apdu[32] = { 0 }; uint8_t encoded_apdu[32] = { 0 }; + uint8_t apdu[MAX_APDU] = { 0 }; BACNET_OBJECT_TYPE type = OBJECT_BINARY_INPUT; BACNET_OBJECT_TYPE decoded_type = OBJECT_ANALOG_OUTPUT; uint32_t instance = 123; uint32_t decoded_instance = 0; - int apdu_len = 0, len = 0, null_len = 0; + int apdu_len = 0, len = 0, null_len = 0, test_len = 0; uint8_t tag_number = 0; apdu_len = encode_bacnet_object_id(&encoded_apdu[0], type, instance); @@ -950,6 +1133,30 @@ static void testBACDCodeObject(void) zassert_equal(len, 0, NULL); } } + /* validate application API codec and APDU size too short */ + type = 1023; + instance = BACNET_MAX_INSTANCE; + apdu_len = + bacnet_object_id_application_encode(apdu, sizeof(apdu), type, instance); + null_len = + bacnet_object_id_application_encode(NULL, sizeof(apdu), type, instance); + zassert_equal(apdu_len, null_len, NULL); + test_len = bacnet_object_id_application_decode( + apdu, apdu_len, &decoded_type, &decoded_instance); + zassert_equal( + apdu_len, test_len, "test_len=%d apdu_len=%d", test_len, apdu_len); + zassert_equal(decoded_type, type, NULL); + zassert_equal(decoded_instance, instance, NULL); + while (--test_len) { + len = bacnet_object_id_application_decode( + apdu, test_len, &decoded_type, &decoded_instance); + zassert_equal(len, BACNET_STATUS_ERROR, NULL); + } + while (--apdu_len) { + len = + bacnet_object_id_application_encode(apdu, apdu_len, type, instance); + zassert_equal(len, 0, NULL); + } /* test context encoded */ type = OBJECT_BINARY_INPUT; instance = 123; @@ -1002,58 +1209,78 @@ static void testBACDCodeBitString(void) #endif { uint8_t bit = 0; - BACNET_BIT_STRING bit_string; - BACNET_BIT_STRING decoded_bit_string; + BACNET_BIT_STRING value; + BACNET_BIT_STRING test_value; uint8_t apdu[MAX_APDU] = { 0 }; uint32_t len_value = 0; uint8_t tag_number = 0; - int len = 0, null_len = 0; + int len, null_len, apdu_len, test_len; BACNET_TAG tag = { 0 }; - bitstring_init(&bit_string); + bitstring_init(&value); /* verify initialization */ - zassert_equal(bitstring_bits_used(&bit_string), 0, NULL); + zassert_equal(bitstring_bits_used(&value), 0, NULL); for (bit = 0; bit < (MAX_BITSTRING_BYTES * 8); bit++) { - zassert_false(bitstring_bit(&bit_string, bit), NULL); + zassert_false(bitstring_bit(&value, bit), NULL); } /* test encode/decode -- true */ for (bit = 0; bit < (MAX_BITSTRING_BYTES * 8); bit++) { - bitstring_set_bit(&bit_string, bit, true); - zassert_equal(bitstring_bits_used(&bit_string), (bit + 1), NULL); - zassert_true(bitstring_bit(&bit_string, bit), NULL); + bitstring_set_bit(&value, bit, true); + zassert_equal(bitstring_bits_used(&value), (bit + 1), NULL); + zassert_true(bitstring_bit(&value, bit), NULL); /* encode */ - len = encode_application_bitstring(&apdu[0], &bit_string); - null_len = encode_application_bitstring(NULL, &bit_string); + len = encode_application_bitstring(&apdu[0], &value); + null_len = encode_application_bitstring(NULL, &value); zassert_equal(len, null_len, NULL); /* decode */ len = bacnet_bitstring_application_decode( - apdu, null_len, &decoded_bit_string); + apdu, null_len, &test_value); zassert_equal( - bitstring_bits_used(&decoded_bit_string), (bit + 1), NULL); - zassert_true(bitstring_bit(&decoded_bit_string, bit), NULL); + bitstring_bits_used(&test_value), (bit + 1), NULL); + zassert_true(bitstring_bit(&test_value, bit), NULL); len = bacnet_tag_decode(apdu, len, &tag); zassert_true(len > 0, NULL); zassert_equal(tag.number, BACNET_APPLICATION_TAG_BIT_STRING, NULL); } /* test encode/decode -- false */ - bitstring_init(&bit_string); + bitstring_init(&value); for (bit = 0; bit < (MAX_BITSTRING_BYTES * 8); bit++) { - bitstring_set_bit(&bit_string, bit, false); - zassert_equal(bitstring_bits_used(&bit_string), (bit + 1), NULL); - zassert_false(bitstring_bit(&bit_string, bit), NULL); + bitstring_set_bit(&value, bit, false); + zassert_equal(bitstring_bits_used(&value), (bit + 1), NULL); + zassert_false(bitstring_bit(&value, bit), NULL); /* encode */ - len = encode_application_bitstring(&apdu[0], &bit_string); - null_len = encode_application_bitstring(NULL, &bit_string); + len = bacnet_bitstring_application_encode(apdu, sizeof(apdu), &value); + null_len = bacnet_bitstring_application_encode(NULL, sizeof(apdu), &value); zassert_equal(len, null_len, NULL); /* decode */ len = bacnet_bitstring_application_decode( - apdu, null_len, &decoded_bit_string); + apdu, null_len, &test_value); len = bacnet_tag_decode(apdu, len, &tag); zassert_true(len > 0, NULL); zassert_equal(tag.number, BACNET_APPLICATION_TAG_BIT_STRING, NULL); zassert_equal( - bitstring_bits_used(&decoded_bit_string), (bit + 1), NULL); - zassert_false(bitstring_bit(&decoded_bit_string, bit), NULL); + bitstring_bits_used(&test_value), (bit + 1), NULL); + zassert_false(bitstring_bit(&test_value, bit), NULL); + } + /* test APDU size limits */ + apdu_len = + bacnet_bitstring_application_encode(apdu, sizeof(apdu), &value); + null_len = + bacnet_bitstring_application_encode(NULL, sizeof(apdu), &value); + zassert_equal(apdu_len, null_len, NULL); + test_len = + bacnet_bitstring_application_decode(apdu, apdu_len, &test_value); + zassert_equal( + apdu_len, test_len, "test_len=%d apdu_len=%d", test_len, apdu_len); + zassert_true(bitstring_same(&value, &test_value), NULL); + while (--test_len) { + len = bacnet_bitstring_application_decode(apdu, test_len, NULL); + zassert_equal(len, BACNET_STATUS_ERROR, NULL); + } + while (--apdu_len) { + len = + bacnet_bitstring_application_encode(apdu, apdu_len, &value); + zassert_equal(len, 0, NULL); } } @@ -1786,18 +2013,21 @@ static void test_bacnet_array_encode(void) /** * @} */ - +/* clang-format off */ #if defined(CONFIG_ZTEST_NEW_API) ZTEST_SUITE(bacdcode_tests, NULL, NULL, NULL, NULL, NULL); #else void test_main(void) { ztest_test_suite( - bacdcode_tests, ztest_unit_test(testBACnetTagCodec), - ztest_unit_test(testBACDCodeTags), ztest_unit_test(testBACDCodeReal), + bacdcode_tests, ztest_unit_test(testBACnetTagEncoder), + ztest_unit_test(testBACnetTagCodec), + ztest_unit_test(testBACDCodeTags), + ztest_unit_test(testBACDCodeReal), ztest_unit_test(testBACDCodeUnsigned), ztest_unit_test(testBACnetUnsigned), - ztest_unit_test(testBACDCodeSigned), ztest_unit_test(testBACnetSigned), + ztest_unit_test(testBACDCodeSigned), + ztest_unit_test(testBACnetSigned), ztest_unit_test(testBACnetDateDecodes), ztest_unit_test(testBACnetDateRangeDecodes), ztest_unit_test(testBACDCodeEnumerated), @@ -1824,3 +2054,4 @@ void test_main(void) ztest_run_test_suite(bacdcode_tests); } #endif +/* clang-format on */