Feature/comments and review (#102)
* Added comments. Replaced -1 with BACNET_STATUS_ERROR macro. * Added some DogyGen comments * Added missing return value check for booleans. * Check used bits against unused bits in bitstrings. * Added missing return value check for bitstrings. * Added sanity checks and comments. * Fixed implicit type conv warning. * Chose to keep simpler C function methods. Co-authored-by: Steve Karg <steve@kargs.net> Co-authored-by: Steve Karg <skarg@users.sourceforge.net>
This commit is contained in:
+264
-55
@@ -90,9 +90,14 @@
|
||||
B'111' interpreted as Type = Closing Tag
|
||||
*/
|
||||
|
||||
/* from clause 20.1.2.4 max-segments-accepted */
|
||||
/* and clause 20.1.2.5 max-APDU-length-accepted */
|
||||
/* returns the encoded octet */
|
||||
/**
|
||||
* Encode the max APDU value and return the encoded octed.
|
||||
*
|
||||
* @param max_segs from clause 20.1.2.4 max-segments-accepted
|
||||
* @param max_apdu from clause 20.1.2.5 max-APDU-length-accepted
|
||||
*
|
||||
* @return The encoded octet
|
||||
*/
|
||||
uint8_t encode_max_segs_max_apdu(int max_segs, int max_apdu)
|
||||
{
|
||||
uint8_t octet = 0;
|
||||
@@ -136,9 +141,14 @@ uint8_t encode_max_segs_max_apdu(int max_segs, int max_apdu)
|
||||
return octet;
|
||||
}
|
||||
|
||||
/* from clause 20.1.2.4 max-segments-accepted */
|
||||
/* and clause 20.1.2.5 max-APDU-length-accepted */
|
||||
/* returns the encoded octet */
|
||||
/**
|
||||
* Decode the given octed into a maximum segments value.
|
||||
*
|
||||
* @param octed From clause 20.1.2.4 max-segments-accepted
|
||||
* and clause 20.1.2.5 max-APDU-length-accepted
|
||||
*
|
||||
* @return Returns the maximum segments value.
|
||||
*/
|
||||
int decode_max_segs(uint8_t octet)
|
||||
{
|
||||
int max_segs = 0;
|
||||
@@ -175,6 +185,14 @@ int decode_max_segs(uint8_t octet)
|
||||
return max_segs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the given octed into a maximum APDU value.
|
||||
*
|
||||
* @param octed From clause 20.1.2.4 max-segments-accepted
|
||||
* and clause 20.1.2.5 max-APDU-length-accepted
|
||||
*
|
||||
* @return Returns the maximum APDU value.
|
||||
*/
|
||||
int decode_max_apdu(uint8_t octet)
|
||||
{
|
||||
int max_apdu = 0;
|
||||
@@ -205,8 +223,18 @@ int decode_max_apdu(uint8_t octet)
|
||||
return max_apdu;
|
||||
}
|
||||
|
||||
/* from clause 20.2.1 General Rules for Encoding BACnet Tags */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
/**
|
||||
* Encode a BACnet tag and returns the number of bytes consumed.
|
||||
* (From clause 20.2.1 General Rules for Encoding BACnet Tags)
|
||||
*
|
||||
* @param apdu Pointer to the encode buffer.
|
||||
* @param tag_number Number of the tag to encode,
|
||||
* see BACNET_APPLICATION_TAG_X macros.
|
||||
* @param context_specific Indicates to encode in the given context.
|
||||
* @param len_value_type Indicates the length of the tag's content.
|
||||
*
|
||||
* @return Returns the number of apdu bytes consumed.
|
||||
*/
|
||||
int encode_tag(uint8_t *apdu,
|
||||
uint8_t tag_number,
|
||||
bool context_specific,
|
||||
@@ -249,8 +277,17 @@ int encode_tag(uint8_t *apdu,
|
||||
return len;
|
||||
}
|
||||
|
||||
/* from clause 20.2.1.3.2 Constructed Data */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
/**
|
||||
* Encode a BACnet opening tag and returns the number
|
||||
* of bytes consumed.
|
||||
* (From clause 20.2.1.3.2 Constructed Data.)
|
||||
*
|
||||
* @param apdu Pointer to the encode buffer.
|
||||
* @param tag_number Number of the tag to encode,
|
||||
* see BACNET_APPLICATION_TAG_X macros.
|
||||
*
|
||||
* @return Returns the number of apdu bytes consumed.
|
||||
*/
|
||||
int encode_opening_tag(uint8_t *apdu, uint8_t tag_number)
|
||||
{
|
||||
int len = 1;
|
||||
@@ -271,8 +308,17 @@ int encode_opening_tag(uint8_t *apdu, uint8_t tag_number)
|
||||
return len;
|
||||
}
|
||||
|
||||
/* from clause 20.2.1.3.2 Constructed Data */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
/**
|
||||
* Encode a BACnet closing tag and returns the number
|
||||
* of bytes consumed.
|
||||
* (From clause 20.2.1.3.2 Constructed Data.)
|
||||
*
|
||||
* @param apdu Pointer to the encode buffer.
|
||||
* @param tag_number Number of the tag to encode,
|
||||
* see BACNET_APPLICATION_TAG_X macros.
|
||||
*
|
||||
* @return Returns the number of apdu bytes consumed.
|
||||
*/
|
||||
int encode_closing_tag(uint8_t *apdu, uint8_t tag_number)
|
||||
{
|
||||
int len = 1;
|
||||
@@ -345,20 +391,45 @@ int bacnet_tag_number_decode(
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns if at the given pointer a
|
||||
* opening tag has been found.
|
||||
*
|
||||
* @param apdu Pointer to the tag number.
|
||||
*
|
||||
* @return true/false
|
||||
*/
|
||||
bool decode_is_opening_tag(uint8_t *apdu)
|
||||
{
|
||||
return (bool)((apdu[0] & 0x07) == 6);
|
||||
}
|
||||
|
||||
/* from clause 20.2.1.3.2 Constructed Data */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
/**
|
||||
* @brief Returns if at the given pointer a
|
||||
* closing tag has been found.
|
||||
*
|
||||
* @param apdu Pointer to the tag number.
|
||||
*
|
||||
* @return true/false
|
||||
*/
|
||||
bool decode_is_closing_tag(uint8_t *apdu)
|
||||
{
|
||||
return (bool)((apdu[0] & 0x07) == 7);
|
||||
}
|
||||
|
||||
/* from clause 20.2.1.3.2 Constructed Data */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
/**
|
||||
* @brief Decodes the tag number and the value,
|
||||
* that the APDU pointer is addressing.
|
||||
* (From clause 20.2.1.3.2 Constructed Data)
|
||||
*
|
||||
* @param apdu Pointer to the message buffer.
|
||||
* @param tag_number Pointer to a variable
|
||||
* taking the tag number.
|
||||
* @param value Pointer to a variable
|
||||
* taking the value.
|
||||
*
|
||||
* @return number of bytes decoded, or zero if errors occur
|
||||
*/
|
||||
int decode_tag_number_and_value(
|
||||
uint8_t *apdu, uint8_t *tag_number, uint32_t *value)
|
||||
{
|
||||
@@ -371,6 +442,7 @@ int decode_tag_number_and_value(
|
||||
/* tagged as uint32_t */
|
||||
if (apdu[len] == 255) {
|
||||
len++;
|
||||
value32 = 0;
|
||||
len += decode_unsigned32(&apdu[len], &value32);
|
||||
if (value) {
|
||||
*value = value32;
|
||||
@@ -379,6 +451,7 @@ int decode_tag_number_and_value(
|
||||
/* tagged as uint16_t */
|
||||
else if (apdu[len] == 254) {
|
||||
len++;
|
||||
value16 = 0;
|
||||
len += decode_unsigned16(&apdu[len], &value16);
|
||||
if (value) {
|
||||
*value = value16;
|
||||
@@ -392,6 +465,7 @@ int decode_tag_number_and_value(
|
||||
len++;
|
||||
}
|
||||
} else if (IS_OPENING_TAG(apdu[0]) && value) {
|
||||
/* opening tag */
|
||||
*value = 0;
|
||||
} else if (IS_CLOSING_TAG(apdu[0]) && value) {
|
||||
/* closing tag */
|
||||
@@ -466,16 +540,37 @@ int bacnet_tag_number_and_value_decode(
|
||||
return len;
|
||||
}
|
||||
|
||||
/* from clause 20.2.1.3.2 Constructed Data */
|
||||
/* returns true if the tag is context specific and matches */
|
||||
/**
|
||||
* @brief Returns true if the tag is context specific
|
||||
* and matches, as defined in clause 20.2.1.3.2 Constructed
|
||||
* Data.
|
||||
*
|
||||
* @param apdu Pointer to the tag begin.
|
||||
* @param tag_number Tag number, that has been decoded before.
|
||||
*
|
||||
* @return true on a match, false otherwise.
|
||||
*/
|
||||
bool decode_is_context_tag(uint8_t *apdu, uint8_t tag_number)
|
||||
{
|
||||
uint8_t my_tag_number = 0;
|
||||
|
||||
decode_tag_number(apdu, &my_tag_number);
|
||||
|
||||
return (bool)(IS_CONTEXT_SPECIFIC(*apdu) && (my_tag_number == tag_number));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the tag is context specific
|
||||
* and matches, as defined in clause 20.2.1.3.2 Constructed
|
||||
* Data. This function returns the tag length as well.
|
||||
*
|
||||
* @param apdu Pointer to the tag begin.
|
||||
* @param tag_number Tag number, that has been decoded before.
|
||||
* @param tag_length Pointer to a variable, taking the
|
||||
* length of the tag in bytes.
|
||||
*
|
||||
* @return true on a match, false otherwise.
|
||||
*/
|
||||
bool decode_is_context_tag_with_length(
|
||||
uint8_t *apdu, uint8_t tag_number, int *tag_length)
|
||||
{
|
||||
@@ -486,18 +581,35 @@ bool decode_is_context_tag_with_length(
|
||||
return (bool)(IS_CONTEXT_SPECIFIC(*apdu) && (my_tag_number == tag_number));
|
||||
}
|
||||
|
||||
/* from clause 20.2.1.3.2 Constructed Data */
|
||||
/* returns the true if the tag matches */
|
||||
/**
|
||||
* @brief Returns true if the tag does match and it
|
||||
* is an opening tag as well.
|
||||
* As defined in clause 20.2.1.3.2 Constructed Data.
|
||||
*
|
||||
* @param apdu Pointer to the tag begin.
|
||||
* @param tag_number Tag number, that has been decoded before.
|
||||
*
|
||||
* @return true on a match, false otherwise.
|
||||
*/
|
||||
bool decode_is_opening_tag_number(uint8_t *apdu, uint8_t tag_number)
|
||||
{
|
||||
uint8_t my_tag_number = 0;
|
||||
|
||||
decode_tag_number(apdu, &my_tag_number);
|
||||
|
||||
return (bool)(IS_OPENING_TAG(apdu[0]) && (my_tag_number == tag_number));
|
||||
}
|
||||
|
||||
/* from clause 20.2.1.3.2 Constructed Data */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
/**
|
||||
* @brief Returns true if the tag does match and it
|
||||
* is an closing tag as well.
|
||||
* As defined in clause 20.2.1.3.2 Constructed Data.
|
||||
*
|
||||
* @param apdu Pointer to the tag begin.
|
||||
* @param tag_number Tag number, that has been decoded before.
|
||||
*
|
||||
* @return true on a match, false otherwise.
|
||||
*/
|
||||
bool decode_is_closing_tag_number(uint8_t *apdu, uint8_t tag_number)
|
||||
{
|
||||
uint8_t my_tag_number = 0;
|
||||
@@ -506,28 +618,49 @@ bool decode_is_closing_tag_number(uint8_t *apdu, uint8_t tag_number)
|
||||
return (bool)(IS_CLOSING_TAG(apdu[0]) && (my_tag_number == tag_number));
|
||||
}
|
||||
|
||||
/* from clause 20.2.3 Encoding of a Boolean Value */
|
||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
/**
|
||||
* @brief Encode an boolean value.
|
||||
* From clause 20.2.3 Encoding of a Boolean Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags.
|
||||
*
|
||||
* @param apdu Pointer to the encode buffer.
|
||||
* @param boolean_value Boolean value to encode.
|
||||
*
|
||||
* @return returns the number of apdu bytes consumed
|
||||
*/
|
||||
int encode_application_boolean(uint8_t *apdu, bool boolean_value)
|
||||
{
|
||||
int len = 0;
|
||||
uint32_t len_value = 0;
|
||||
uint32_t len_value;
|
||||
|
||||
if (boolean_value) {
|
||||
len_value = 1;
|
||||
} else {
|
||||
len_value = 0;
|
||||
}
|
||||
|
||||
len =
|
||||
encode_tag(&apdu[0], BACNET_APPLICATION_TAG_BOOLEAN, false, len_value);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/* context tagged is encoded differently */
|
||||
/**
|
||||
* @brief Encode an boolean value in a context.
|
||||
* From clause 20.2.3 Encoding of a Boolean Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags.
|
||||
*
|
||||
* @param apdu Pointer to the encode buffer.
|
||||
* @param tag_number Tag number in which context
|
||||
* the value shall be encoded.
|
||||
* @param boolean_value Boolean value to encode.
|
||||
*
|
||||
* @return returns the number of apdu bytes consumed
|
||||
*/
|
||||
int encode_context_boolean(
|
||||
uint8_t *apdu, uint8_t tag_number, bool boolean_value)
|
||||
{
|
||||
int len = 0; /* return value */
|
||||
int len; /* return value */
|
||||
|
||||
len = encode_tag(&apdu[0], (uint8_t)tag_number, true, 1);
|
||||
apdu[len] = (bool)(boolean_value ? 1 : 0);
|
||||
@@ -536,6 +669,13 @@ int encode_context_boolean(
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decode an boolean value.
|
||||
*
|
||||
* @param apdu Pointer to the encode buffer.
|
||||
*
|
||||
* @return true/false
|
||||
*/
|
||||
bool decode_context_boolean(uint8_t *apdu)
|
||||
{
|
||||
bool boolean_value = false;
|
||||
@@ -547,6 +687,17 @@ bool decode_context_boolean(uint8_t *apdu)
|
||||
return boolean_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decode an boolean value in the context of a tag.
|
||||
*
|
||||
* @param apdu Pointer to the encode buffer.
|
||||
* @param tag_number Tag number in which context
|
||||
* the value shall be encoded.
|
||||
* @param boolean_value Pointer to a boolean variable
|
||||
* taking the value.
|
||||
*
|
||||
* @return The count of bytes decoded or BACNET_STATUS_ERROR.
|
||||
*/
|
||||
int decode_context_boolean2(
|
||||
uint8_t *apdu, uint8_t tag_number, bool *boolean_value)
|
||||
{
|
||||
@@ -564,33 +715,65 @@ int decode_context_boolean2(
|
||||
return len;
|
||||
}
|
||||
|
||||
/* from clause 20.2.3 Encoding of a Boolean Value */
|
||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
/**
|
||||
* @brief Check the length value and return the boolean meaning.
|
||||
* From clause 20.2.3 Encoding of a Boolean Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags.
|
||||
*
|
||||
* @param len_value Tag length value.
|
||||
*
|
||||
* @return true/false
|
||||
*/
|
||||
bool decode_boolean(uint32_t len_value)
|
||||
{
|
||||
bool boolean_value = false;
|
||||
bool boolean_value;
|
||||
|
||||
if (len_value) {
|
||||
boolean_value = true;
|
||||
} else {
|
||||
boolean_value = false;
|
||||
}
|
||||
|
||||
return boolean_value;
|
||||
}
|
||||
|
||||
/* from clause 20.2.2 Encoding of a Null Value */
|
||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
/**
|
||||
* @brief Encode a Null value.
|
||||
* From clause 20.2.2 Encoding of a Null Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags.
|
||||
*
|
||||
* @param apdu Pointer to the encode buffer.
|
||||
*
|
||||
* @return returns the number of apdu bytes consumed.
|
||||
*/
|
||||
int encode_application_null(uint8_t *apdu)
|
||||
{
|
||||
return encode_tag(&apdu[0], BACNET_APPLICATION_TAG_NULL, false, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode a Null value in a tag context.
|
||||
* From clause 20.2.2 Encoding of a Null Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags.
|
||||
*
|
||||
* @param apdu Pointer to the encode buffer.
|
||||
* @param tag_number Tag number in which context
|
||||
* the value shall be encoded.
|
||||
*
|
||||
* @return returns the number of apdu bytes consumed.
|
||||
*/
|
||||
int encode_context_null(uint8_t *apdu, uint8_t tag_number)
|
||||
{
|
||||
return encode_tag(&apdu[0], tag_number, true, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reverse the bits of the given byte.
|
||||
*
|
||||
* @param in_byte Byte to reverse.
|
||||
*
|
||||
* @return Byte with reversed bit order.
|
||||
*/
|
||||
static uint8_t byte_reverse_bits(uint8_t in_byte)
|
||||
{
|
||||
uint8_t out_byte = 0;
|
||||
@@ -623,35 +806,61 @@ static uint8_t byte_reverse_bits(uint8_t in_byte)
|
||||
return out_byte;
|
||||
}
|
||||
|
||||
/* from clause 20.2.10 Encoding of a Bit String Value */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
/**
|
||||
* @brief Decode a bit string value.
|
||||
* (From clause 20.2.10 Encoding of a Bit String Value.)
|
||||
*
|
||||
* @param apdu Pointer to the buffer holding the message data.
|
||||
* @param len_value Length of the Data to decode.
|
||||
* @param bit_string Pointer to the bit string variable,
|
||||
* taking the decoded result.
|
||||
*
|
||||
* @return Returns the number of apdu bytes consumed.
|
||||
*/
|
||||
int decode_bitstring(
|
||||
uint8_t *apdu, uint32_t len_value, BACNET_BIT_STRING *bit_string)
|
||||
uint8_t * apdu,
|
||||
uint32_t len_value,
|
||||
BACNET_BIT_STRING * bit_string)
|
||||
{
|
||||
int len = 0;
|
||||
uint8_t unused_bits = 0;
|
||||
uint32_t i = 0;
|
||||
uint32_t bytes_used = 0;
|
||||
int len = 0; /* Return value */
|
||||
uint8_t unused_bits;
|
||||
uint32_t i;
|
||||
uint32_t bytes_used;
|
||||
|
||||
bitstring_init(bit_string);
|
||||
if (len_value) {
|
||||
/* the first octet contains the unused bits */
|
||||
bytes_used = len_value - 1;
|
||||
if (bytes_used <= MAX_BITSTRING_BYTES) {
|
||||
len = 1;
|
||||
for (i = 0; i < bytes_used; i++) {
|
||||
bitstring_set_octet(
|
||||
bit_string, (uint8_t)i, byte_reverse_bits(apdu[len++]));
|
||||
if (apdu && bit_string) {
|
||||
/* Init/empty the string. */
|
||||
bitstring_init(bit_string);
|
||||
if (len_value) {
|
||||
/* The first octet contains the unused bits. */
|
||||
bytes_used = len_value - 1;
|
||||
if (bytes_used <= MAX_BITSTRING_BYTES) {
|
||||
len = 1;
|
||||
/* Copy the bytes in reversed bit order. */
|
||||
for (i = 0; i < bytes_used; i++) {
|
||||
bitstring_set_octet(bit_string, (uint8_t) i,
|
||||
byte_reverse_bits(apdu[len++]));
|
||||
}
|
||||
/* Erase the remaining unsed bits. */
|
||||
unused_bits = (uint8_t) (apdu[0] & 0x07);
|
||||
bitstring_set_bits_used(bit_string, (uint8_t) bytes_used,
|
||||
unused_bits);
|
||||
}
|
||||
unused_bits = (uint8_t)(apdu[0] & 0x07);
|
||||
bitstring_set_bits_used(
|
||||
bit_string, (uint8_t)bytes_used, unused_bits);
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decode a bit string value in the given context.
|
||||
* (From clause 20.2.10 Encoding of a Bit String Value.)
|
||||
*
|
||||
* @param apdu Pointer to the buffer holding the message data.
|
||||
* @param tag_number Tag number (context).
|
||||
* @param bit_string Pointer to the bit string variable,
|
||||
* taking the decoded result.
|
||||
*
|
||||
* @return Returns the number of bytes dcoded or BACNET_STATUS_ERROR.
|
||||
*/
|
||||
int decode_context_bitstring(
|
||||
uint8_t *apdu, uint8_t tag_number, BACNET_BIT_STRING *bit_string)
|
||||
{
|
||||
|
||||
+182
-84
@@ -41,6 +41,18 @@
|
||||
/** @file bacdevobjpropref.c BACnet Application Device Object (Property)
|
||||
* Reference */
|
||||
|
||||
/**
|
||||
* Encode a property reference for the device object.
|
||||
* Add an opening tag, encode the property and finally
|
||||
* add a closing tag as well.
|
||||
*
|
||||
* @param apdu Pointer to the buffer to encode to.
|
||||
* @param tag_number Tag number.
|
||||
* @param value Pointer to the object property reference,
|
||||
* used for encoding.
|
||||
*
|
||||
* @return Bytes encoded or 0 on failure.
|
||||
*/
|
||||
int bacapp_encode_context_device_obj_property_ref(uint8_t *apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE *value)
|
||||
@@ -48,28 +60,39 @@ int bacapp_encode_context_device_obj_property_ref(uint8_t *apdu,
|
||||
int len;
|
||||
int apdu_len = 0;
|
||||
|
||||
len = encode_opening_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
if (value) {
|
||||
len = encode_opening_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
|
||||
len = bacapp_encode_device_obj_property_ref(&apdu[apdu_len], value);
|
||||
apdu_len += len;
|
||||
len = bacapp_encode_device_obj_property_ref(&apdu[apdu_len], value);
|
||||
apdu_len += len;
|
||||
|
||||
len = encode_closing_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
len = encode_closing_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/* BACnetDeviceObjectPropertyReference ::= SEQUENCE {
|
||||
object-identifier [0] BACnetObjectIdentifier,
|
||||
property-identifier [1] BACnetPropertyIdentifier,
|
||||
property-array-index [2] Unsigned OPTIONAL,
|
||||
-- used only with array datatype
|
||||
-- if omitted with an array then
|
||||
-- the entire array is referenced
|
||||
device-identifier [3] BACnetObjectIdentifier OPTIONAL
|
||||
}
|
||||
*/
|
||||
/**
|
||||
* Encode a property reference for the device object.
|
||||
*
|
||||
* BACnetDeviceObjectPropertyReference ::= SEQUENCE {
|
||||
* object-identifier [0] BACnetObjectIdentifier,
|
||||
* property-identifier [1] BACnetPropertyIdentifier,
|
||||
* property-array-index [2] Unsigned OPTIONAL,
|
||||
* -- used only with array datatype
|
||||
* -- if omitted with an array then
|
||||
* -- the entire array is referenced
|
||||
* device-identifier [3] BACnetObjectIdentifier OPTIONAL
|
||||
* }
|
||||
*
|
||||
* @param apdu Pointer to the buffer to encode to.
|
||||
* @param value Pointer to the object property reference,
|
||||
* used for encoding.
|
||||
*
|
||||
* @return Bytes encoded.
|
||||
*/
|
||||
int bacapp_encode_device_obj_property_ref(
|
||||
uint8_t *apdu, BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE *value)
|
||||
{
|
||||
@@ -102,45 +125,56 @@ int bacapp_encode_device_obj_property_ref(
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/* BACnetDeviceObjectPropertyReference ::= SEQUENCE {
|
||||
object-identifier [0] BACnetObjectIdentifier,
|
||||
property-identifier [1] BACnetPropertyIdentifier,
|
||||
property-array-index [2] Unsigned OPTIONAL,
|
||||
-- used only with array datatype
|
||||
-- if omitted with an array then
|
||||
-- the entire array is referenced
|
||||
device-identifier [3] BACnetObjectIdentifier OPTIONAL
|
||||
}
|
||||
*/
|
||||
/**
|
||||
* Decode a property reference of a device object.
|
||||
*
|
||||
* BACnetDeviceObjectPropertyReference ::= SEQUENCE {
|
||||
* object-identifier [0] BACnetObjectIdentifier,
|
||||
* property-identifier [1] BACnetPropertyIdentifier,
|
||||
* property-array-index [2] Unsigned OPTIONAL,
|
||||
* -- used only with array datatype
|
||||
* -- if omitted with an array then
|
||||
* -- the entire array is referenced
|
||||
* device-identifier [3] BACnetObjectIdentifier OPTIONAL
|
||||
* }
|
||||
*
|
||||
* @param apdu Pointer to the buffer containing the data to decode.
|
||||
* @param value Pointer to the object property reference,
|
||||
* used to decode the data into.
|
||||
*
|
||||
* @return Bytes decoded or BACNET_STATUS_ERROR on failure.
|
||||
*/
|
||||
int bacapp_decode_device_obj_property_ref(
|
||||
uint8_t *apdu, BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE *value)
|
||||
{
|
||||
int len;
|
||||
int apdu_len = 0;
|
||||
uint32_t enumValue;
|
||||
uint32_t enumValue = 0;
|
||||
|
||||
/* object-identifier [0] BACnetObjectIdentifier */
|
||||
if (-1 ==
|
||||
(len = decode_context_object_id(&apdu[apdu_len], 0,
|
||||
&value->objectIdentifier.type,
|
||||
&value->objectIdentifier.instance))) {
|
||||
return -1;
|
||||
len =
|
||||
decode_context_object_id(&apdu[apdu_len], 0,
|
||||
&value->objectIdentifier.type,
|
||||
&value->objectIdentifier.instance);
|
||||
if (len == BACNET_STATUS_ERROR) {
|
||||
return BACNET_STATUS_ERROR;
|
||||
}
|
||||
apdu_len += len;
|
||||
/* property-identifier [1] BACnetPropertyIdentifier */
|
||||
if (-1 ==
|
||||
(len = decode_context_enumerated(&apdu[apdu_len], 1, &enumValue))) {
|
||||
return -1;
|
||||
len =
|
||||
decode_context_enumerated(&apdu[apdu_len], 1, &enumValue);
|
||||
if (len == BACNET_STATUS_ERROR) {
|
||||
return BACNET_STATUS_ERROR;
|
||||
}
|
||||
value->propertyIdentifier = (BACNET_PROPERTY_ID)enumValue;
|
||||
apdu_len += len;
|
||||
/* property-array-index [2] Unsigned OPTIONAL */
|
||||
if (decode_is_context_tag(&apdu[apdu_len], 2) &&
|
||||
!decode_is_closing_tag(&apdu[apdu_len])) {
|
||||
if (-1 ==
|
||||
(len = decode_context_unsigned(
|
||||
&apdu[apdu_len], 2, &value->arrayIndex))) {
|
||||
return -1;
|
||||
len = decode_context_unsigned(
|
||||
&apdu[apdu_len], 2, &value->arrayIndex);
|
||||
if (len == BACNET_STATUS_ERROR) {
|
||||
return BACNET_STATUS_ERROR;
|
||||
}
|
||||
apdu_len += len;
|
||||
} else {
|
||||
@@ -164,7 +198,19 @@ int bacapp_decode_device_obj_property_ref(
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int bacapp_decode_context_device_obj_property_ref(uint8_t *apdu,
|
||||
/**
|
||||
* Decode the opening tag and the property reference of
|
||||
* an device object and check for the closing tag as well.
|
||||
*
|
||||
* @param apdu Pointer to the buffer containing the data to decode.
|
||||
* @param tag_number Tag number
|
||||
* @param value Pointer to the object property reference,
|
||||
* used to decode the data into.
|
||||
*
|
||||
* @return Bytes decoded or BACNET_STATUS_ERROR on failure.
|
||||
*/
|
||||
int bacapp_decode_context_device_obj_property_ref(
|
||||
uint8_t *apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE *value)
|
||||
{
|
||||
@@ -175,51 +221,77 @@ int bacapp_decode_context_device_obj_property_ref(uint8_t *apdu,
|
||||
len++;
|
||||
section_length =
|
||||
bacapp_decode_device_obj_property_ref(&apdu[len], value);
|
||||
|
||||
if (section_length == -1) {
|
||||
len = -1;
|
||||
if (section_length == BACNET_STATUS_ERROR) {
|
||||
len = BACNET_STATUS_ERROR;
|
||||
} else {
|
||||
len += section_length;
|
||||
if (decode_is_closing_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
} else {
|
||||
len = -1;
|
||||
len = BACNET_STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
len = -1;
|
||||
len = BACNET_STATUS_ERROR;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/* BACnetDeviceObjectReference ::= SEQUENCE {
|
||||
device-identifier [0] BACnetObjectIdentifier OPTIONAL,
|
||||
object-identifier [1] BACnetObjectIdentifier
|
||||
}*/
|
||||
/**
|
||||
* Encode the opening tag and the device object reference
|
||||
* and finally for the closing tag as well.
|
||||
*
|
||||
* BACnetDeviceObjectReference ::= SEQUENCE {
|
||||
* device-identifier [0] BACnetObjectIdentifier OPTIONAL,
|
||||
* object-identifier [1] BACnetObjectIdentifier
|
||||
* }
|
||||
*
|
||||
* @param apdu Pointer to the buffer used for encoding.
|
||||
* @param tag_number Tag number
|
||||
* @param value Pointer to the device object reference,
|
||||
* used to encode.
|
||||
*
|
||||
* @return Bytes encoded or 0 on failure.
|
||||
*/
|
||||
int bacapp_encode_context_device_obj_ref(
|
||||
uint8_t *apdu, uint8_t tag_number, BACNET_DEVICE_OBJECT_REFERENCE *value)
|
||||
uint8_t *apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DEVICE_OBJECT_REFERENCE *value)
|
||||
{
|
||||
int len;
|
||||
int apdu_len = 0;
|
||||
|
||||
len = encode_opening_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
if (value) {
|
||||
len = encode_opening_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
|
||||
len = bacapp_encode_device_obj_ref(&apdu[apdu_len], value);
|
||||
apdu_len += len;
|
||||
len = bacapp_encode_device_obj_ref(&apdu[apdu_len], value);
|
||||
apdu_len += len;
|
||||
|
||||
len = encode_closing_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
len = encode_closing_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/* BACnetDeviceObjectReference ::= SEQUENCE {
|
||||
device-identifier [0] BACnetObjectIdentifier OPTIONAL,
|
||||
object-identifier [1] BACnetObjectIdentifier
|
||||
}*/
|
||||
/**
|
||||
* Encode the device object reference.
|
||||
*
|
||||
* BACnetDeviceObjectReference ::= SEQUENCE {
|
||||
* device-identifier [0] BACnetObjectIdentifier OPTIONAL,
|
||||
* object-identifier [1] BACnetObjectIdentifier
|
||||
* }
|
||||
*
|
||||
* @param apdu Pointer to the buffer used for encoding.
|
||||
* @param value Pointer to the device object reference,
|
||||
* used to encode.
|
||||
*
|
||||
* @return Bytes encoded or 0 on failure.
|
||||
*/
|
||||
int bacapp_encode_device_obj_ref(
|
||||
uint8_t *apdu, BACNET_DEVICE_OBJECT_REFERENCE *value)
|
||||
uint8_t * apdu,
|
||||
BACNET_DEVICE_OBJECT_REFERENCE * value)
|
||||
{
|
||||
int len;
|
||||
int apdu_len = 0;
|
||||
@@ -234,19 +306,31 @@ int bacapp_encode_device_obj_ref(
|
||||
apdu_len += len;
|
||||
}
|
||||
/* object-identifier [1] BACnetObjectIdentifier */
|
||||
len = encode_context_object_id(&apdu[apdu_len], 1,
|
||||
value->objectIdentifier.type, value->objectIdentifier.instance);
|
||||
len =
|
||||
encode_context_object_id(&apdu[apdu_len], 1,
|
||||
value->objectIdentifier.type, value->objectIdentifier.instance);
|
||||
apdu_len += len;
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/* BACnetDeviceObjectReference ::= SEQUENCE {
|
||||
device-identifier [0] BACnetObjectIdentifier OPTIONAL,
|
||||
object-identifier [1] BACnetObjectIdentifier
|
||||
}*/
|
||||
/**
|
||||
* Decode the device object reference.
|
||||
*
|
||||
* BACnetDeviceObjectReference ::= SEQUENCE {
|
||||
* device-identifier [0] BACnetObjectIdentifier OPTIONAL,
|
||||
* object-identifier [1] BACnetObjectIdentifier
|
||||
* }
|
||||
*
|
||||
* @param apdu Pointer to the buffer containing the data to decode.
|
||||
* @param value Pointer to the object object reference,
|
||||
* that shall be decoded.
|
||||
*
|
||||
* @return Bytes decoded or BACNET_STATUS_ERROR on failure.
|
||||
*/
|
||||
int bacapp_decode_device_obj_ref(
|
||||
uint8_t *apdu, BACNET_DEVICE_OBJECT_REFERENCE *value)
|
||||
uint8_t * apdu,
|
||||
BACNET_DEVICE_OBJECT_REFERENCE * value)
|
||||
{
|
||||
int len;
|
||||
int apdu_len = 0;
|
||||
@@ -254,11 +338,12 @@ int bacapp_decode_device_obj_ref(
|
||||
/* device-identifier [0] BACnetObjectIdentifier OPTIONAL */
|
||||
if (decode_is_context_tag(&apdu[apdu_len], 0) &&
|
||||
!decode_is_closing_tag(&apdu[apdu_len])) {
|
||||
if (-1 ==
|
||||
(len = decode_context_object_id(&apdu[apdu_len], 0,
|
||||
&value->deviceIdentifier.type,
|
||||
&value->deviceIdentifier.instance))) {
|
||||
return -1;
|
||||
len =
|
||||
decode_context_object_id(&apdu[apdu_len], 0,
|
||||
&value->deviceIdentifier.type,
|
||||
&value->deviceIdentifier.instance);
|
||||
if (len == BACNET_STATUS_ERROR) {
|
||||
return BACNET_STATUS_ERROR;
|
||||
}
|
||||
apdu_len += len;
|
||||
} else {
|
||||
@@ -266,19 +351,33 @@ int bacapp_decode_device_obj_ref(
|
||||
value->deviceIdentifier.instance = BACNET_NO_DEV_ID;
|
||||
}
|
||||
/* object-identifier [1] BACnetObjectIdentifier */
|
||||
if (-1 ==
|
||||
(len = decode_context_object_id(&apdu[apdu_len], 1,
|
||||
&value->objectIdentifier.type,
|
||||
&value->objectIdentifier.instance))) {
|
||||
return -1;
|
||||
len =
|
||||
decode_context_object_id(&apdu[apdu_len], 1,
|
||||
&value->objectIdentifier.type,
|
||||
&value->objectIdentifier.instance);
|
||||
if (len == BACNET_STATUS_ERROR) {
|
||||
return BACNET_STATUS_ERROR;
|
||||
}
|
||||
apdu_len += len;
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the context device object reference. Check for
|
||||
* an opening tag and a closing tag as well.
|
||||
*
|
||||
* @param apdu Pointer to the buffer containing the data to decode.
|
||||
* @param tag_number Tag number
|
||||
* @param value Pointer to the context device object reference,
|
||||
* that shall be decoded.
|
||||
*
|
||||
* @return Bytes decoded or BACNET_STATUS_ERROR on failure.
|
||||
*/
|
||||
int bacapp_decode_context_device_obj_ref(
|
||||
uint8_t *apdu, uint8_t tag_number, BACNET_DEVICE_OBJECT_REFERENCE *value)
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DEVICE_OBJECT_REFERENCE * value)
|
||||
{
|
||||
int len = 0;
|
||||
int section_length;
|
||||
@@ -286,19 +385,18 @@ int bacapp_decode_context_device_obj_ref(
|
||||
if (decode_is_opening_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
section_length = bacapp_decode_device_obj_ref(&apdu[len], value);
|
||||
|
||||
if (section_length == -1) {
|
||||
len = -1;
|
||||
if (section_length == BACNET_STATUS_ERROR) {
|
||||
len = BACNET_STATUS_ERROR;
|
||||
} else {
|
||||
len += section_length;
|
||||
if (decode_is_closing_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
} else {
|
||||
len = -1;
|
||||
len = BACNET_STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
len = -1;
|
||||
len = BACNET_STATUS_ERROR;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
+385
-94
@@ -48,65 +48,105 @@
|
||||
#define BACNET_STRING_UTF8_VALIDATION 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Initialize a bit string.
|
||||
*
|
||||
* @param bit_string Pointer to the bit string structure.
|
||||
*/
|
||||
void bitstring_init(BACNET_BIT_STRING *bit_string)
|
||||
{
|
||||
int i;
|
||||
|
||||
bit_string->bits_used = 0;
|
||||
for (i = 0; i < MAX_BITSTRING_BYTES; i++) {
|
||||
bit_string->value[i] = 0;
|
||||
if (bit_string) {
|
||||
bit_string->bits_used = 0;
|
||||
for (i = 0; i < MAX_BITSTRING_BYTES; i++) {
|
||||
bit_string->value[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set bits in the bit string.
|
||||
*
|
||||
* @param bit_string Pointer to the bit string structure.
|
||||
* @param bit_number Number of the bit [0..(MAX_BITSTRING_BYTES*8)-1]
|
||||
* @param value Value 0/1
|
||||
*/
|
||||
void bitstring_set_bit(
|
||||
BACNET_BIT_STRING *bit_string, uint8_t bit_number, bool value)
|
||||
{
|
||||
uint8_t byte_number = bit_number / 8;
|
||||
uint8_t bit_mask = 1;
|
||||
|
||||
if (byte_number < MAX_BITSTRING_BYTES) {
|
||||
/* set max bits used */
|
||||
if (bit_string->bits_used < (bit_number + 1)) {
|
||||
bit_string->bits_used = bit_number + 1;
|
||||
}
|
||||
bit_mask = bit_mask << (bit_number - (byte_number * 8));
|
||||
if (value) {
|
||||
bit_string->value[byte_number] |= bit_mask;
|
||||
} else {
|
||||
bit_string->value[byte_number] &= (~(bit_mask));
|
||||
if (bit_string) {
|
||||
if (byte_number < MAX_BITSTRING_BYTES) {
|
||||
/* set max bits used */
|
||||
if (bit_string->bits_used < (bit_number + 1)) {
|
||||
bit_string->bits_used = bit_number + 1;
|
||||
}
|
||||
bit_mask = bit_mask << (bit_number - (byte_number * 8));
|
||||
if (value) {
|
||||
bit_string->value[byte_number] |= bit_mask;
|
||||
} else {
|
||||
bit_string->value[byte_number] &= (~(bit_mask));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value of a single bit
|
||||
* out of the bit string.
|
||||
*
|
||||
* @param bit_string Pointer to the bit string structure.
|
||||
* @param bit_number Number of the bit [0..(MAX_BITSTRING_BYTES*8)-1]
|
||||
*
|
||||
* @return Value 0/1
|
||||
*/
|
||||
bool bitstring_bit(BACNET_BIT_STRING *bit_string, uint8_t bit_number)
|
||||
{
|
||||
bool value = false;
|
||||
uint8_t byte_number = bit_number / 8;
|
||||
uint8_t bit_mask = 1;
|
||||
|
||||
if (bit_number < (MAX_BITSTRING_BYTES * 8)) {
|
||||
bit_mask = bit_mask << (bit_number - (byte_number * 8));
|
||||
if (bit_string->value[byte_number] & bit_mask) {
|
||||
value = true;
|
||||
if (bit_string) {
|
||||
if (bit_number < (MAX_BITSTRING_BYTES * 8)) {
|
||||
bit_mask = bit_mask << (bit_number - (byte_number * 8));
|
||||
if (bit_string->value[byte_number] & bit_mask) {
|
||||
value = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of bits used.
|
||||
*
|
||||
* @param bit_string Pointer to the bit string structure.
|
||||
*
|
||||
* @return Bits used [0..(MAX_BITSTRING_BYTES*8)-1]
|
||||
*/
|
||||
uint8_t bitstring_bits_used(BACNET_BIT_STRING *bit_string)
|
||||
{
|
||||
return bit_string->bits_used;
|
||||
return (bit_string ? bit_string->bits_used : 0);
|
||||
}
|
||||
|
||||
/* returns the number of bytes that a bit string is using */
|
||||
/**
|
||||
* Returns the number of bytes that a bit string is using.
|
||||
*
|
||||
* @param bit_string Pointer to the bit string structure.
|
||||
*
|
||||
* @return Bytes used [0..MAX_BITSTRING_BYTES]
|
||||
*/
|
||||
uint8_t bitstring_bytes_used(BACNET_BIT_STRING *bit_string)
|
||||
{
|
||||
uint8_t len = 0; /* return value */
|
||||
uint8_t used_bytes = 0;
|
||||
uint8_t last_bit = 0;
|
||||
|
||||
if (bit_string->bits_used) {
|
||||
if (bit_string && bit_string->bits_used) {
|
||||
last_bit = bit_string->bits_used - 1;
|
||||
used_bytes = last_bit / 8;
|
||||
/* add one for the first byte */
|
||||
@@ -117,6 +157,14 @@ uint8_t bitstring_bytes_used(BACNET_BIT_STRING *bit_string)
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an octed at the given bit position.
|
||||
*
|
||||
* @param bit_string Pointer to the bit string structure.
|
||||
* @param octet_index Byte index of the octed [0..MAX_BITSTRING_BYTES-1]
|
||||
*
|
||||
* @return Value of the octed.
|
||||
*/
|
||||
uint8_t bitstring_octet(BACNET_BIT_STRING *bit_string, uint8_t octet_index)
|
||||
{
|
||||
uint8_t octet = 0;
|
||||
@@ -130,6 +178,15 @@ uint8_t bitstring_octet(BACNET_BIT_STRING *bit_string, uint8_t octet_index)
|
||||
return octet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an octed at the given bit position.
|
||||
*
|
||||
* @param bit_string Pointer to the bit string structure.
|
||||
* @param index Byte index of the octed [0..MAX_BITSTRING_BYTES-1]
|
||||
* @param octet Octet value
|
||||
*
|
||||
* @return true on success, false otherwise.
|
||||
*/
|
||||
bool bitstring_set_octet(
|
||||
BACNET_BIT_STRING *bit_string, uint8_t index, uint8_t octet)
|
||||
{
|
||||
@@ -145,13 +202,25 @@ bool bitstring_set_octet(
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the amount of bits used in the bit
|
||||
* string structure.
|
||||
*
|
||||
* @param bit_string Pointer to the bit string structure.
|
||||
* @param bytes_used Count of bytes used.
|
||||
* @param unused_bits Count of remaining unused bits in
|
||||
* the last byte.
|
||||
*
|
||||
* @return true on success or false on error.
|
||||
*/
|
||||
bool bitstring_set_bits_used(
|
||||
BACNET_BIT_STRING *bit_string, uint8_t bytes_used, uint8_t unused_bits)
|
||||
BACNET_BIT_STRING * bit_string,
|
||||
uint8_t bytes_used,
|
||||
uint8_t unused_bits)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
if (bit_string) {
|
||||
/* FIXME: check that bytes_used is at least one? */
|
||||
if (bit_string && bytes_used) {
|
||||
bit_string->bits_used = bytes_used * 8;
|
||||
bit_string->bits_used -= unused_bits;
|
||||
status = true;
|
||||
@@ -160,6 +229,13 @@ bool bitstring_set_bits_used(
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the capcity of the bit string.
|
||||
*
|
||||
* @param bit_string Pointer to the bit string structure.
|
||||
*
|
||||
* @return Capacitiy in bits [0..(MAX_BITSTRING_BYTES*8)]
|
||||
*/
|
||||
uint8_t bitstring_bits_capacity(BACNET_BIT_STRING *bit_string)
|
||||
{
|
||||
if (bit_string) {
|
||||
@@ -169,6 +245,14 @@ uint8_t bitstring_bits_capacity(BACNET_BIT_STRING *bit_string)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy bits from one bit string to another.
|
||||
*
|
||||
* @param dest Pointer to the destination bit string structure.
|
||||
* @param src Pointer to the source bit string structure.
|
||||
*
|
||||
* @return true on success, false otherwise.
|
||||
*/
|
||||
bool bitstring_copy(BACNET_BIT_STRING *dest, BACNET_BIT_STRING *src)
|
||||
{
|
||||
unsigned i;
|
||||
@@ -185,25 +269,34 @@ bool bitstring_copy(BACNET_BIT_STRING *dest, BACNET_BIT_STRING *src)
|
||||
return status;
|
||||
}
|
||||
|
||||
/* returns true if the same length and contents */
|
||||
/**
|
||||
* Returns true if the same length and contents.
|
||||
*
|
||||
* @param bitstring1 Pointer to the first bit string structure.
|
||||
* @param bitstring2 Pointer to the second bit string structure.
|
||||
*
|
||||
* @return true if the content of both bit strings are
|
||||
* the same, false otherwise.
|
||||
*/
|
||||
bool bitstring_same(
|
||||
BACNET_BIT_STRING *bitstring1, BACNET_BIT_STRING *bitstring2)
|
||||
{
|
||||
int i = 0; /* loop counter */
|
||||
int i; /* loop counter */
|
||||
int bytes_used = 0;
|
||||
uint8_t compare_mask = 0;
|
||||
|
||||
if (bitstring1 && bitstring2) {
|
||||
bytes_used = (int)(bitstring1->bits_used / 8);
|
||||
if ((bitstring1->bits_used == bitstring2->bits_used) &&
|
||||
(bitstring1->bits_used / 8 <= MAX_BITSTRING_BYTES)) {
|
||||
bytes_used = (int)(bitstring1->bits_used / 8);
|
||||
compare_mask = 0xFF >> (8 - (bitstring1->bits_used % 8));
|
||||
|
||||
(bytes_used <= MAX_BITSTRING_BYTES)) {
|
||||
/* compare fully used bytes */
|
||||
for (i = 0; i < bytes_used; i++) {
|
||||
if (bitstring1->value[i] != bitstring2->value[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/* compare only the relevant bits of last partly used byte */
|
||||
compare_mask = 0xFF >> (8 - (bitstring1->bits_used % 8));
|
||||
if ((bitstring1->value[bytes_used] & compare_mask) !=
|
||||
(bitstring2->value[bytes_used] & compare_mask)) {
|
||||
return false;
|
||||
@@ -217,9 +310,18 @@ bool bitstring_same(
|
||||
}
|
||||
|
||||
#if PRINT_ENABLED
|
||||
/* converts an null terminated ASCII string to an bitstring.
|
||||
Expects "1,0,1,0,1,1" or "101011" as the bits
|
||||
returns true if successfully converted and fits; false if too long */
|
||||
/**
|
||||
* Converts an null terminated ASCII string to an bitstring.
|
||||
*
|
||||
* Expects "1,0,1,0,1,1" or "101011" as the bits
|
||||
*
|
||||
* @param bit_string Pointer to the bit string structure.
|
||||
* @param ascii Pointer to a zero terminated string, made up from
|
||||
* '0' and '1' like "010010011", that shall be
|
||||
* converted into a bit string.
|
||||
*
|
||||
* @return true if successfully converted and fits; false if too long.
|
||||
*/
|
||||
bool bitstring_init_ascii(BACNET_BIT_STRING *bit_string, const char *ascii)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
@@ -262,8 +364,19 @@ bool bitstring_init_ascii(BACNET_BIT_STRING *bit_string, const char *ascii)
|
||||
#endif
|
||||
|
||||
#define CHARACTER_STRING_CAPACITY (MAX_CHARACTER_STRING_BYTES - 1)
|
||||
/* returns false if the string exceeds capacity
|
||||
initialize by using value=NULL */
|
||||
/**
|
||||
* Initialize a BACnet characater string.
|
||||
* Returns false if the string exceeds capacity.
|
||||
* Initialize by using value=NULL
|
||||
*
|
||||
* @param char_string Pointer to the BACnet string
|
||||
* @param encoding Encoding that shall be used
|
||||
* like CHARACTER_UTF8
|
||||
* @param value C-string used to initialize the object
|
||||
* @param length C-String length in characters.
|
||||
*
|
||||
* @return true on success, false if the string exceeds capacity.
|
||||
*/
|
||||
bool characterstring_init(BACNET_CHARACTER_STRING *char_string,
|
||||
uint8_t encoding,
|
||||
const char *value,
|
||||
@@ -299,6 +412,17 @@ bool characterstring_init(BACNET_CHARACTER_STRING *char_string,
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a BACnet characater string.
|
||||
* Returns false if the string exceeds capacity.
|
||||
* Initialize by using value=NULL
|
||||
*
|
||||
* @param char_string Pointer to the BACnet string
|
||||
* @param value C-string used to initialize the object
|
||||
* @param tmax C-String length in characters.
|
||||
*
|
||||
* @return true/false
|
||||
*/
|
||||
bool characterstring_init_ansi_safe(
|
||||
BACNET_CHARACTER_STRING *char_string, const char *value, size_t tmax)
|
||||
{
|
||||
@@ -306,6 +430,16 @@ bool characterstring_init_ansi_safe(
|
||||
value ? strnlen(value, tmax) : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a BACnet characater string.
|
||||
* Returns false if the string exceeds capacity.
|
||||
* Initialize by using value=NULL
|
||||
*
|
||||
* @param char_string Pointer to the BACnet string
|
||||
* @param value C-string used to initialize the object
|
||||
*
|
||||
* @return true/false
|
||||
*/
|
||||
bool characterstring_init_ansi(
|
||||
BACNET_CHARACTER_STRING *char_string, const char *value)
|
||||
{
|
||||
@@ -313,34 +447,64 @@ bool characterstring_init_ansi(
|
||||
char_string, CHARACTER_ANSI_X34, value, value ? strlen(value) : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a character string.
|
||||
*
|
||||
* @param dest Pointer to the destination string.
|
||||
* @param src Pointer to the source string.
|
||||
*
|
||||
* @return true/false
|
||||
*/
|
||||
bool characterstring_copy(
|
||||
BACNET_CHARACTER_STRING *dest, BACNET_CHARACTER_STRING *src)
|
||||
{
|
||||
return characterstring_init(dest, characterstring_encoding(src),
|
||||
characterstring_value(src), characterstring_length(src));
|
||||
}
|
||||
|
||||
bool characterstring_ansi_copy(
|
||||
char *dest, size_t dest_max_len, BACNET_CHARACTER_STRING *src)
|
||||
{
|
||||
size_t i; /* counter */
|
||||
|
||||
if (dest && src && (src->encoding == CHARACTER_ANSI_X34) &&
|
||||
(src->length < dest_max_len)) {
|
||||
for (i = 0; i < dest_max_len; i++) {
|
||||
if (i < src->length) {
|
||||
dest[i] = src->value[i];
|
||||
} else {
|
||||
dest[i] = 0;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
if (dest && src) {
|
||||
return characterstring_init(dest, characterstring_encoding(src),
|
||||
characterstring_value(src), characterstring_length(src));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* returns true if the character encoding and string contents are the same */
|
||||
/**
|
||||
* Copy a character string into a C-string.
|
||||
*
|
||||
* @param dest Pointer to the destination C-string buffer.
|
||||
* @param dest_max_len Size of the destination C-string buffer.
|
||||
* @param src Pointer to the source BACnet string.
|
||||
*
|
||||
* @return true/false
|
||||
*/
|
||||
bool characterstring_ansi_copy(
|
||||
char *dest, size_t dest_max_len, BACNET_CHARACTER_STRING *src)
|
||||
{
|
||||
size_t i; /* counter */
|
||||
|
||||
if (dest && src) {
|
||||
if ((src->encoding == CHARACTER_ANSI_X34) && (src->length < dest_max_len)) {
|
||||
for (i = 0; i < dest_max_len; i++) {
|
||||
if (i < src->length) {
|
||||
dest[i] = src->value[i];
|
||||
} else {
|
||||
dest[i] = 0;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the character encoding and string
|
||||
* contents are the same.
|
||||
*
|
||||
* @param dest Pointer to the first string to test.
|
||||
* @param src Pointer to the second string to test.
|
||||
*
|
||||
* @return true if the character encoding and string contents are the same
|
||||
*/
|
||||
bool characterstring_same(
|
||||
BACNET_CHARACTER_STRING *dest, BACNET_CHARACTER_STRING *src)
|
||||
{
|
||||
@@ -348,12 +512,14 @@ bool characterstring_same(
|
||||
bool same_status = false;
|
||||
|
||||
if (src && dest) {
|
||||
if ((src->length == dest->length) &&
|
||||
(src->encoding == dest->encoding)) {
|
||||
if ((src->encoding == dest->encoding) &&
|
||||
(src->length == dest->length) &&
|
||||
(src->length <= MAX_CHARACTER_STRING_BYTES)) {
|
||||
same_status = true;
|
||||
for (i = 0; (i < src->length) && same_status; i++) {
|
||||
for (i = 0; i < src->length; i++) {
|
||||
if (src->value[i] != dest->value[i]) {
|
||||
same_status = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -370,18 +536,29 @@ bool characterstring_same(
|
||||
return same_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the BACnet string and the C-string
|
||||
* contents are the same.
|
||||
*
|
||||
* @param dest Pointer to the first string to test.
|
||||
* @param src Pointer to the second string to test.
|
||||
*
|
||||
* @return true if the character encoding and string contents are the same
|
||||
*/
|
||||
bool characterstring_ansi_same(BACNET_CHARACTER_STRING *dest, const char *src)
|
||||
{
|
||||
size_t i; /* counter */
|
||||
bool same_status = false;
|
||||
|
||||
if (src && dest) {
|
||||
if ((dest->length == strlen(src)) &&
|
||||
(dest->encoding == CHARACTER_ANSI_X34)) {
|
||||
if ((dest->encoding == CHARACTER_ANSI_X34) &&
|
||||
(dest->length == strlen(src)) &&
|
||||
(dest->length <= MAX_CHARACTER_STRING_BYTES)) {
|
||||
same_status = true;
|
||||
for (i = 0; (i < dest->length) && same_status; i++) {
|
||||
for (i = 0; i < dest->length; i++) {
|
||||
if (src[i] != dest->value[i]) {
|
||||
same_status = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -400,7 +577,18 @@ bool characterstring_ansi_same(BACNET_CHARACTER_STRING *dest, const char *src)
|
||||
return same_status;
|
||||
}
|
||||
|
||||
/* returns false if the string exceeds capacity */
|
||||
/**
|
||||
* Append some characters to the end of the characterstring
|
||||
*
|
||||
* @param char_string Pointer to the BACnet string to which
|
||||
* the content of the C-string shall be added.
|
||||
* @param value Pointer to the C-String to be added.
|
||||
* @param length Count of characters to add.
|
||||
*
|
||||
* @param src Pointer to the first string to test.
|
||||
*
|
||||
* @return false if the string exceeds capacity.
|
||||
*/
|
||||
bool characterstring_append(
|
||||
BACNET_CHARACTER_STRING *char_string, const char *value, size_t length)
|
||||
{
|
||||
@@ -420,9 +608,14 @@ bool characterstring_append(
|
||||
return status;
|
||||
}
|
||||
|
||||
/* This function sets a new length without changing the value.
|
||||
If length exceeds capacity, no modification happens and
|
||||
function returns false. */
|
||||
/**
|
||||
* @brief This function sets a new length without changing
|
||||
* the value. If length exceeds capacity, no modification
|
||||
* happens and function returns false.
|
||||
*
|
||||
* @return true on success, false if the string exceeds
|
||||
* capacity.
|
||||
*/
|
||||
bool characterstring_truncate(
|
||||
BACNET_CHARACTER_STRING *char_string, size_t length)
|
||||
{
|
||||
@@ -587,8 +780,8 @@ bool characterstring_printable(BACNET_CHARACTER_STRING *char_string)
|
||||
|
||||
#if BACNET_STRING_UTF8_VALIDATION
|
||||
/* Basic UTF-8 manipulation routines
|
||||
by Jeff Bezanson
|
||||
placed in the public domain Fall 2005 */
|
||||
* by Jeff Bezanson
|
||||
* placed in the public domain Fall 2005 */
|
||||
static const char trailingBytesForUTF8[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@@ -601,19 +794,33 @@ static const char trailingBytesForUTF8[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 };
|
||||
|
||||
/* based on the valid_utf8 routine from the PCRE library by Philip Hazel
|
||||
length is in bytes, since without knowing whether the string is valid
|
||||
it's hard to know how many characters there are! */
|
||||
/**
|
||||
* @brief Based on the valid_utf8 routine from the PCRE library by Philip Hazel
|
||||
* length is in bytes, since without knowing whether the string is valid
|
||||
* it's hard to know how many characters there are!
|
||||
*
|
||||
* @param str Pointer to the character string.
|
||||
* @param length Count of bytes to check. The count of bytes
|
||||
* does not necessarily match the count of chars.
|
||||
*
|
||||
* @return true if the string is valid, false otherwise.
|
||||
*/
|
||||
bool utf8_isvalid(const char *str, size_t length)
|
||||
{
|
||||
const unsigned char *p, *pend = (unsigned char *)str + length;
|
||||
const unsigned char *p, *pend;
|
||||
unsigned char c;
|
||||
size_t ab;
|
||||
|
||||
/* empty string is valid */
|
||||
/* An empty string is valid. */
|
||||
if (length == 0) {
|
||||
return true;
|
||||
}
|
||||
/* Check pointer. */
|
||||
if (!str) {
|
||||
return false;
|
||||
}
|
||||
/* Check characters. */
|
||||
pend = (unsigned char *) str + length;
|
||||
for (p = (const unsigned char *)str; p < pend; p++) {
|
||||
c = *p;
|
||||
/* null in middle of string */
|
||||
@@ -696,26 +903,45 @@ bool utf8_isvalid(const char *str, size_t length)
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Check if the character string is valid or not.
|
||||
*
|
||||
* @param char_string Pointer to the character string.
|
||||
*
|
||||
* @return true if the string is valid, false otherwise.
|
||||
*/
|
||||
bool characterstring_valid(BACNET_CHARACTER_STRING *char_string)
|
||||
{
|
||||
bool valid = false; /* return value */
|
||||
|
||||
if (char_string->encoding < MAX_CHARACTER_STRING_ENCODING) {
|
||||
if (char_string->encoding == CHARACTER_UTF8) {
|
||||
if (utf8_isvalid(char_string->value, char_string->length)) {
|
||||
if (char_string) {
|
||||
if (char_string->encoding < MAX_CHARACTER_STRING_ENCODING) {
|
||||
if (char_string->encoding == CHARACTER_UTF8) {
|
||||
/*UTF8 check*/
|
||||
if (utf8_isvalid(char_string->value, char_string->length)) {
|
||||
valid = true;
|
||||
}
|
||||
} else {
|
||||
/*non UTF8*/
|
||||
valid = true;
|
||||
}
|
||||
} else {
|
||||
valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
#if BACNET_USE_OCTETSTRING
|
||||
/* returns false if the string exceeds capacity
|
||||
initialize by using value=NULL */
|
||||
/**
|
||||
* @brief Initialize an octed string with the given bytes or
|
||||
* zeros, if NULL for the value is provided.
|
||||
*
|
||||
* @param octet_string Pointer to the octed string.
|
||||
* @param value Pointer to the bytes to be copied to the octed
|
||||
* string or NULL to initialize the octed string.
|
||||
* @param length Count of bytes used to fill the octed string.
|
||||
*
|
||||
* @return true on success, false if the string exceeds capacity.
|
||||
*/
|
||||
bool octetstring_init(
|
||||
BACNET_OCTET_STRING *octet_string, uint8_t *value, size_t length)
|
||||
{
|
||||
@@ -746,8 +972,12 @@ bool octetstring_init(
|
||||
}
|
||||
|
||||
#if PRINT_ENABLED
|
||||
/* converts an null terminated ASCII Hex string to an octet string.
|
||||
returns true if successfully converted and fits; false if too long */
|
||||
/** @brief Converts an null terminated ASCII Hex string to an octet string.
|
||||
*
|
||||
* @param octet_string Pointer to the octed string.
|
||||
* @param ascii_hex Pointer to the HEx-ASCII string.
|
||||
*
|
||||
* @return true if successfully converted and fits; false if too long */
|
||||
bool octetstring_init_ascii_hex(
|
||||
BACNET_OCTET_STRING *octet_string, const char *ascii_hex)
|
||||
{
|
||||
@@ -756,7 +986,7 @@ bool octetstring_init_ascii_hex(
|
||||
uint8_t value = 0;
|
||||
char hex_pair_string[3] = "";
|
||||
|
||||
if (octet_string) {
|
||||
if (octet_string && ascii_hex) {
|
||||
octet_string->length = 0;
|
||||
if (ascii_hex[0] == 0) {
|
||||
/* nothing to decode, so success! */
|
||||
@@ -793,14 +1023,31 @@ bool octetstring_init_ascii_hex(
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Copy an octed string from source to destination.
|
||||
*
|
||||
* @param dest Pointer to the destination octed string.
|
||||
* @param src Pointer to the source octed string.
|
||||
*
|
||||
* @return true on success, false otherwise.
|
||||
*/
|
||||
bool octetstring_copy(BACNET_OCTET_STRING *dest, BACNET_OCTET_STRING *src)
|
||||
{
|
||||
return octetstring_init(
|
||||
dest, octetstring_value(src), octetstring_length(src));
|
||||
}
|
||||
|
||||
/* returns the number of bytes copied, or 0 if the dest
|
||||
cannot hold entire octetstring value */
|
||||
/**
|
||||
* @brief Copy bytes from the octed string to a byte buffer.
|
||||
*
|
||||
* @param dest Pointer to the byte buffer.
|
||||
* @param length Bytes to be copied from the
|
||||
* octed string to the buffer.
|
||||
* @param src Pointer to the octed string.
|
||||
*
|
||||
* @return Returns the number of bytes copied, or 0 if
|
||||
* the dest cannot hold entire octetstring value.
|
||||
*/
|
||||
size_t octetstring_copy_value(
|
||||
uint8_t *dest, size_t length, BACNET_OCTET_STRING *src)
|
||||
{
|
||||
@@ -819,7 +1066,15 @@ size_t octetstring_copy_value(
|
||||
return bytes_copied;
|
||||
}
|
||||
|
||||
/* returns false if the string exceeds capacity */
|
||||
/**
|
||||
* @brief Append bytes to the end of the octed string.
|
||||
*
|
||||
* @param octet_string Pointer to the octed string.
|
||||
* @param value Pointer to the byte buffer to be appended.
|
||||
* @param length Bytes to be appended.
|
||||
*
|
||||
* @return false if the string exceeds capacity.
|
||||
*/
|
||||
bool octetstring_append(
|
||||
BACNET_OCTET_STRING *octet_string, uint8_t *value, size_t length)
|
||||
{
|
||||
@@ -839,9 +1094,16 @@ bool octetstring_append(
|
||||
return status;
|
||||
}
|
||||
|
||||
/* This function sets a new length without changing the value.
|
||||
If length exceeds capacity, no modification happens and
|
||||
function returns false. */
|
||||
/**
|
||||
* @brief This function sets a new length without changing the value.
|
||||
* If length exceeds capacity, no modification happens and the
|
||||
* function returns false.
|
||||
*
|
||||
* @param octet_string Pointer to the octed string.
|
||||
* @param length New length the octed string is trucated to.
|
||||
*
|
||||
* @return tur on success, false otherwise.
|
||||
*/
|
||||
bool octetstring_truncate(BACNET_OCTET_STRING *octet_string, size_t length)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
@@ -856,7 +1118,14 @@ bool octetstring_truncate(BACNET_OCTET_STRING *octet_string, size_t length)
|
||||
return status;
|
||||
}
|
||||
|
||||
/* returns a pointer to the value. */
|
||||
/**
|
||||
* @brief Returns a pointer to the value (data) of
|
||||
* the given octed string.
|
||||
*
|
||||
* @param octet_string Pointer to the octed string.
|
||||
*
|
||||
* @return Value as a pointer to a byte array or NULL on error.
|
||||
*/
|
||||
uint8_t *octetstring_value(BACNET_OCTET_STRING *octet_string)
|
||||
{
|
||||
uint8_t *value = NULL;
|
||||
@@ -868,33 +1137,55 @@ uint8_t *octetstring_value(BACNET_OCTET_STRING *octet_string)
|
||||
return value;
|
||||
}
|
||||
|
||||
/* returns the length. */
|
||||
/**
|
||||
* @brief Returns the length in bytes of
|
||||
* the given octed string.
|
||||
*
|
||||
* @param octet_string Pointer to the octed string.
|
||||
*
|
||||
* @return Length in bytes. Returns always 0 on error.
|
||||
*/
|
||||
size_t octetstring_length(BACNET_OCTET_STRING *octet_string)
|
||||
{
|
||||
size_t length = 0;
|
||||
|
||||
if (octet_string) {
|
||||
/* FIXME: validate length is within bounds? */
|
||||
length = octet_string->length;
|
||||
/* Force length to be within bounds. */
|
||||
if (length > MAX_OCTET_STRING_BYTES) {
|
||||
length = MAX_OCTET_STRING_BYTES;
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/* returns the maximum capacity. */
|
||||
/**
|
||||
* @brief Returns the maximum capacity of an octed string.
|
||||
*
|
||||
* @param octet_string Pointer to the octed string.
|
||||
*
|
||||
* @return Capacity in bytes. Returns always 0 on error.
|
||||
*/
|
||||
size_t octetstring_capacity(BACNET_OCTET_STRING *octet_string)
|
||||
{
|
||||
size_t length = 0;
|
||||
|
||||
if (octet_string) {
|
||||
/* FIXME: validate length is within bounds? */
|
||||
length = MAX_OCTET_STRING_BYTES;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/* returns true if the same length and contents */
|
||||
/**
|
||||
* @brief Returns true if the same length and contents.
|
||||
*
|
||||
* @param octet_string1 Pointer to the first octed string.
|
||||
* @param octet_string2 Pointer to the second octed string.
|
||||
*
|
||||
* @return true if the octed strings are the same, false otherwise.
|
||||
*/
|
||||
bool octetstring_value_same(
|
||||
BACNET_OCTET_STRING *octet_string1, BACNET_OCTET_STRING *octet_string2)
|
||||
{
|
||||
|
||||
@@ -226,6 +226,9 @@ int cl_decode_apdu(uint8_t *apdu,
|
||||
case BACNET_APPLICATION_TAG_BOOLEAN:
|
||||
len = decode_context_boolean2(
|
||||
&apdu[dec_len], 4, &bcl->Value.type.Boolean);
|
||||
if (len < 0) {
|
||||
return BACNET_STATUS_REJECT;
|
||||
}
|
||||
break;
|
||||
case BACNET_APPLICATION_TAG_UNSIGNED_INT:
|
||||
len = decode_context_unsigned(&apdu[dec_len], 4, &unsigned_value);
|
||||
@@ -256,6 +259,9 @@ int cl_decode_apdu(uint8_t *apdu,
|
||||
case BACNET_APPLICATION_TAG_BIT_STRING:
|
||||
len = decode_context_bitstring(
|
||||
&apdu[dec_len], 4, &bcl->Value.type.Bit_String);
|
||||
if (len < 0) {
|
||||
return BACNET_STATUS_REJECT;
|
||||
}
|
||||
break;
|
||||
case BACNET_APPLICATION_TAG_ENUMERATED:
|
||||
len = decode_context_enumerated(
|
||||
|
||||
+1
-1
@@ -507,7 +507,7 @@ int event_notify_decode_service_request(
|
||||
/* tag 9 - ackRequired */
|
||||
section_length =
|
||||
decode_context_boolean2(&apdu[len], 9, &data->ackRequired);
|
||||
if (section_length == -1) {
|
||||
if (section_length == BACNET_STATUS_ERROR) {
|
||||
return -1;
|
||||
}
|
||||
len += section_length;
|
||||
|
||||
Reference in New Issue
Block a user