/** * @file * @brief BACnet integer encode and decode helper functions * @author Steve Karg * @date 2004 * @copyright SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0 */ #include #include /* BACnet Stack defines - first */ #include "bacnet/bacdef.h" /* BACnet Stack API */ #include "bacnet/bacint.h" #ifndef BACNET_USE_SIGNED #define BACNET_USE_SIGNED 1 #endif int encode_unsigned16(uint8_t *apdu, uint16_t value) { if (apdu) { apdu[0] = (uint8_t)((value >> 8) & 0xFF); apdu[1] = (uint8_t)((value >> 0) & 0xFF); } return 2; } int decode_unsigned16(const uint8_t *apdu, uint16_t *value) { if (apdu && value) { *value = (uint16_t)apdu[0] << 8; *value |= (uint16_t)apdu[1]; } return 2; } int encode_unsigned24(uint8_t *apdu, uint32_t value) { if (apdu) { apdu[0] = (uint8_t)((value >> 16) & 0xFF); apdu[1] = (uint8_t)((value >> 8) & 0xFF); apdu[2] = (uint8_t)((value >> 0) & 0xFF); } return 3; } int decode_unsigned24(const uint8_t *apdu, uint32_t *value) { if (apdu && value) { *value = (uint32_t)apdu[0] << 16; *value |= (uint32_t)apdu[1] << 8; *value |= (uint32_t)apdu[2]; } return 3; } int encode_unsigned32(uint8_t *apdu, uint32_t value) { if (apdu) { apdu[0] = (uint8_t)((value >> 24) & 0xFF); apdu[1] = (uint8_t)((value >> 16) & 0xFF); apdu[2] = (uint8_t)((value >> 8) & 0xFF); apdu[3] = (uint8_t)((value >> 0) & 0xFF); } return 4; } int decode_unsigned32(const uint8_t *apdu, uint32_t *value) { if (apdu && value) { *value = (uint32_t)apdu[0] << 24; *value |= (uint32_t)apdu[1] << 16; *value |= (uint32_t)apdu[2] << 8; *value |= (uint32_t)apdu[3]; } return 4; } #ifdef UINT64_MAX /** * @brief Encode a 40-bit unsigned value into buffer * @param buffer - pointer to bytes for storing encoding * @param value - 40-bit value to encode * @return Returns the number of bytes encoded */ int encode_unsigned40(uint8_t *buffer, uint64_t value) { if (buffer) { buffer[0] = (uint8_t)((value >> 32) & 0xFF); buffer[1] = (uint8_t)((value >> 24) & 0xFF); buffer[2] = (uint8_t)((value >> 16) & 0xFF); buffer[3] = (uint8_t)((value >> 8) & 0xFF); buffer[4] = (uint8_t)((value >> 0) & 0xFF); } return 5; } /** * @brief Decode a 40-bit unsigned value from a buffer * @param buffer - pointer to bytes for used for decoding * @param value - pointer to 64-bit value to store the decoded value * @return Returns the number of bytes decoded */ int decode_unsigned40(const uint8_t *buffer, uint64_t *value) { if (buffer && value) { *value = (uint64_t)buffer[0] << 32; *value |= (uint64_t)buffer[1] << 24; *value |= (uint64_t)buffer[2] << 16; *value |= (uint64_t)buffer[3] << 8; *value |= (uint64_t)buffer[4]; } return 5; } /** * @brief Encode a 48-bit unsigned value into buffer * @param buffer - pointer to bytes for storing encoding * @param value - 48-bit value to encode * @return Returns the number of bytes encoded */ int encode_unsigned48(uint8_t *buffer, uint64_t value) { if (buffer) { buffer[0] = (uint8_t)((value >> 40) & 0xFF); buffer[1] = (uint8_t)((value >> 32) & 0xFF); buffer[2] = (uint8_t)((value >> 24) & 0xFF); buffer[3] = (uint8_t)((value >> 16) & 0xFF); buffer[4] = (uint8_t)((value >> 8) & 0xFF); buffer[5] = (uint8_t)((value >> 0) & 0xFF); } return 6; } /** * @brief Decode a 48-bit unsigned value from a buffer * @param buffer - pointer to bytes for used for decoding * @param value - pointer to 64-bit value to store the decoded value * @return Returns the number of bytes decoded */ int decode_unsigned48(const uint8_t *buffer, uint64_t *value) { if (buffer && value) { *value = (uint64_t)buffer[0] << 40; *value |= (uint64_t)buffer[1] << 32; *value |= (uint64_t)buffer[2] << 24; *value |= (uint64_t)buffer[3] << 16; *value |= (uint64_t)buffer[4] << 8; *value |= (uint64_t)buffer[5]; } return 6; } /** * @brief Encode a 56-bit unsigned value into buffer * @param buffer - pointer to bytes for storing encoding * @param value - 56-bit value to encode * @return Returns the number of bytes encoded */ int encode_unsigned56(uint8_t *buffer, uint64_t value) { if (buffer) { buffer[0] = (uint8_t)((value >> 48) & 0xFF); buffer[1] = (uint8_t)((value >> 40) & 0xFF); buffer[2] = (uint8_t)((value >> 32) & 0xFF); buffer[3] = (uint8_t)((value >> 24) & 0xFF); buffer[4] = (uint8_t)((value >> 16) & 0xFF); buffer[5] = (uint8_t)((value >> 8) & 0xFF); buffer[6] = (uint8_t)((value >> 0) & 0xFF); } return 7; } /** * @brief Decode a 56-bit unsigned value from a buffer * @param buffer - pointer to bytes for used for decoding * @param value - pointer to 64-bit value to store the decoded value * @return Returns the number of bytes decoded */ int decode_unsigned56(const uint8_t *buffer, uint64_t *value) { if (buffer && value) { *value = (uint64_t)buffer[0] << 48; *value |= (uint64_t)buffer[1] << 40; *value |= (uint64_t)buffer[2] << 32; *value |= (uint64_t)buffer[3] << 24; *value |= (uint64_t)buffer[4] << 16; *value |= (uint64_t)buffer[5] << 8; *value |= (uint64_t)buffer[6]; } return 7; } /** * @brief Encode a 64-bit unsigned value into buffer * @param buffer - pointer to bytes for storing encoding * @param value - 16-bit value to encode * @return Returns the number of bytes encoded */ int encode_unsigned64(uint8_t *buffer, uint64_t value) { if (buffer) { buffer[0] = (uint8_t)((value >> 56) & 0xFF); buffer[1] = (uint8_t)((value >> 48) & 0xFF); buffer[2] = (uint8_t)((value >> 40) & 0xFF); buffer[3] = (uint8_t)((value >> 32) & 0xFF); buffer[4] = (uint8_t)((value >> 24) & 0xFF); buffer[5] = (uint8_t)((value >> 16) & 0xFF); buffer[6] = (uint8_t)((value >> 8) & 0xFF); buffer[7] = (uint8_t)((value >> 0) & 0xFF); } return 8; } /** * @brief Decode a 64-bit unsigned value from a buffer * @param buffer - pointer to bytes for used for decoding * @param value - pointer to 64-bit value to store the decoded value * @return Returns the number of bytes decoded */ int decode_unsigned64(const uint8_t *buffer, uint64_t *value) { if (buffer && value) { *value = (uint64_t)buffer[0] << 56; *value |= (uint64_t)buffer[1] << 48; *value |= (uint64_t)buffer[2] << 40; *value |= (uint64_t)buffer[3] << 32; *value |= (uint64_t)buffer[4] << 24; *value |= (uint64_t)buffer[5] << 16; *value |= (uint64_t)buffer[6] << 8; *value |= (uint64_t)buffer[7]; } return 8; } #endif /** * @brief Determine the number of bytes in the value * length of unsigned is variable, as per 20.2.4 * @param value - pointer to 32-bit or 64-bit value * @return Returns the number of bytes */ int bacnet_unsigned_length(BACNET_UNSIGNED_INTEGER value) { int len = 0; /* return value */ if (value <= 0xFF) { len = 1; } else if (value <= 0xFFFF) { len = 2; } else if (value <= 0xFFFFFF) { len = 3; } else { #ifdef UINT64_MAX /* Avoid ULL to be compatible with C89. */ value = value >> 32; if (value == 0) { len = 4; } else if (value <= 0xFF) { len = 5; } else if (value <= 0xFFFF) { len = 6; } else if (value <= 0xFFFFFF) { len = 7; } else { len = 8; } #else len = 4; #endif } return len; } #if BACNET_USE_SIGNED int encode_signed8(uint8_t *apdu, int8_t value) { if (apdu) { apdu[0] = (uint8_t)value; } return 1; } int decode_signed8(const uint8_t *apdu, int32_t *value) { if (apdu && value) { /* negative - bit 7 is set */ if (apdu[0] & 0x80) { *value = 0xFFFFFF00; } else { *value = 0; } *value |= (int32_t)apdu[0] & 0xFF; } return 1; } int encode_signed16(uint8_t *apdu, int16_t value) { if (apdu) { apdu[0] = (uint8_t)((value >> 8) & 0xFF); apdu[1] = (uint8_t)((value >> 0) & 0xFF); } return 2; } int decode_signed16(const uint8_t *apdu, int32_t *value) { if (apdu && value) { /* negative - bit 7 is set */ if (apdu[0] & 0x80) { *value = 0xFFFF0000; } else { *value = 0; } *value |= (int32_t)apdu[0] << 8; *value |= (int32_t)apdu[1]; } return 2; } int encode_signed24(uint8_t *apdu, int32_t value) { if (apdu) { apdu[0] = (uint8_t)((value >> 16) & 0xFF); apdu[1] = (uint8_t)((value >> 8) & 0xFF); apdu[2] = (uint8_t)((value >> 0) & 0xFF); } return 3; } int decode_signed24(const uint8_t *apdu, int32_t *value) { if (apdu && value) { /* negative - bit 7 is set */ if (apdu[0] & 0x80) { *value = 0xFF000000; } else { *value = 0; } *value |= (int32_t)apdu[0] << 16; *value |= (int32_t)apdu[1] << 8; *value |= (int32_t)apdu[2]; } return 3; } int encode_signed32(uint8_t *apdu, int32_t value) { if (apdu) { apdu[0] = (uint8_t)((value >> 24) & 0xFF); apdu[1] = (uint8_t)((value >> 16) & 0xFF); apdu[2] = (uint8_t)((value >> 8) & 0xFF); apdu[3] = (uint8_t)((value >> 0) & 0xFF); } return 4; } int decode_signed32(const uint8_t *apdu, int32_t *value) { if (apdu && value) { *value = (int32_t)apdu[0] << 24; *value |= (int32_t)apdu[1] << 16; *value |= (int32_t)apdu[2] << 8; *value |= (int32_t)apdu[3]; } return 4; } /** * @brief Determines the number of bytes used by a BACnet Signed Integer * from clause 20.2.5 Encoding of an Signed Integer Value * @param value - signed value * @return number of bytes used by a BACnet Signed Integer */ int bacnet_signed_length(int32_t value) { int len; if ((value >= -128) && (value < 128)) { len = 1; } else if ((value >= -32768) && (value < 32768)) { len = 2; } else if ((value >= -8388608) && (value < 8388608)) { len = 3; } else { len = 4; } return len; } #endif