refactored the encode and decode of unsigned16 and unsigned32.
This commit is contained in:
+97
-130
@@ -35,15 +35,12 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "bacdef.h"
|
||||||
#include "bacdcode.h"
|
#include "bacdcode.h"
|
||||||
#include "bacenum.h"
|
#include "bacenum.h"
|
||||||
#include "bits.h"
|
#include "bits.h"
|
||||||
#include "bigend.h"
|
#include "bigend.h"
|
||||||
|
|
||||||
#ifndef MAX_APDU
|
|
||||||
#define MAX_APDU 480
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// NOTE: byte order plays a role in decoding multibyte values
|
// NOTE: byte order plays a role in decoding multibyte values
|
||||||
// http://www.unixpapa.com/incnote/byteorder.html
|
// http://www.unixpapa.com/incnote/byteorder.html
|
||||||
|
|
||||||
@@ -121,36 +118,91 @@ uint8_t encode_max_segs_max_apdu(int max_segs, int max_apdu)
|
|||||||
return octet;
|
return octet;
|
||||||
}
|
}
|
||||||
|
|
||||||
int encode_bacnet_unsigned16(uint8_t * apdu, uint16_t value)
|
int encode_unsigned16(uint8_t * apdu, uint16_t value)
|
||||||
{
|
{
|
||||||
int len = 0; // return value
|
union {
|
||||||
|
uint8_t byte[2];
|
||||||
|
uint16_t value;
|
||||||
|
} short_data = {{0}};
|
||||||
|
|
||||||
if (value < 0x100) {
|
short_data.value = value;
|
||||||
apdu[0] = value;
|
if (big_endian()) {
|
||||||
apdu[1] = 0;
|
apdu[0] = short_data.byte[0];
|
||||||
len = 2;
|
apdu[1] = short_data.byte[1];
|
||||||
} else {
|
} else {
|
||||||
apdu[0] = value / 0x100;
|
apdu[0] = short_data.byte[1];
|
||||||
apdu[1] = value - (apdu[0] * 0x100);
|
apdu[1] = short_data.byte[0];
|
||||||
len = 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int decode_unsigned16(uint8_t * apdu, uint16_t *value)
|
int decode_unsigned16(uint8_t * apdu, uint16_t *value)
|
||||||
{
|
{
|
||||||
int len = 0; // return value
|
union {
|
||||||
|
uint8_t byte[2];
|
||||||
|
uint16_t value;
|
||||||
|
} short_data = {{0}};
|
||||||
|
|
||||||
if (value)
|
if (big_endian()) {
|
||||||
{
|
short_data.byte[0] = apdu[0];
|
||||||
*value = (apdu[len] * 0x100) + apdu[len + 1];
|
short_data.byte[1] = apdu[1];
|
||||||
len = 2;
|
} else {
|
||||||
|
short_data.byte[1] = apdu[0];
|
||||||
|
short_data.byte[0] = apdu[1];
|
||||||
}
|
}
|
||||||
|
if (value)
|
||||||
|
*value = short_data.value;
|
||||||
|
|
||||||
return len;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int encode_unsigned32(uint8_t * apdu, uint32_t value)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
uint8_t byte[4];
|
||||||
|
uint32_t value;
|
||||||
|
} long_data = {{0}};
|
||||||
|
|
||||||
|
long_data.value = value;
|
||||||
|
if (big_endian()) {
|
||||||
|
apdu[0] = long_data.byte[0];
|
||||||
|
apdu[1] = long_data.byte[1];
|
||||||
|
apdu[2] = long_data.byte[2];
|
||||||
|
apdu[3] = long_data.byte[3];
|
||||||
|
} else {
|
||||||
|
apdu[0] = long_data.byte[3];
|
||||||
|
apdu[1] = long_data.byte[2];
|
||||||
|
apdu[2] = long_data.byte[1];
|
||||||
|
apdu[3] = long_data.byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
int decode_unsigned32(uint8_t * apdu, uint32_t *value)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
uint8_t byte[4];
|
||||||
|
uint32_t value;
|
||||||
|
} long_data = {{0}};
|
||||||
|
|
||||||
|
if (big_endian()) {
|
||||||
|
long_data.byte[0] = apdu[0];
|
||||||
|
long_data.byte[1] = apdu[1];
|
||||||
|
long_data.byte[2] = apdu[2];
|
||||||
|
long_data.byte[3] = apdu[3];
|
||||||
|
} else {
|
||||||
|
long_data.byte[3] = apdu[0];
|
||||||
|
long_data.byte[2] = apdu[1];
|
||||||
|
long_data.byte[1] = apdu[2];
|
||||||
|
long_data.byte[0] = apdu[3];
|
||||||
|
}
|
||||||
|
if (value)
|
||||||
|
*value = long_data.value;
|
||||||
|
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
// from clause 20.2.1 General Rules for Encoding BACnet Tags
|
// from clause 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
@@ -158,16 +210,6 @@ int encode_tag(uint8_t * apdu, uint8_t tag_number, bool context_specific,
|
|||||||
uint32_t len_value_type)
|
uint32_t len_value_type)
|
||||||
{
|
{
|
||||||
int len = 1; // return value
|
int len = 1; // return value
|
||||||
union {
|
|
||||||
uint8_t byte[2];
|
|
||||||
uint16_t value;
|
|
||||||
} short_data = { {
|
|
||||||
0}};
|
|
||||||
union {
|
|
||||||
uint8_t byte[4];
|
|
||||||
uint32_t value;
|
|
||||||
} long_data = { {
|
|
||||||
0}};
|
|
||||||
|
|
||||||
apdu[0] = 0;
|
apdu[0] = 0;
|
||||||
if (context_specific)
|
if (context_specific)
|
||||||
@@ -190,36 +232,13 @@ int encode_tag(uint8_t * apdu, uint8_t tag_number, bool context_specific,
|
|||||||
else {
|
else {
|
||||||
apdu[0] |= 5;
|
apdu[0] |= 5;
|
||||||
if (len_value_type <= 253) {
|
if (len_value_type <= 253) {
|
||||||
apdu[len] = len_value_type;
|
apdu[len++] = len_value_type;
|
||||||
len++;
|
|
||||||
} else if (len_value_type <= 65535) {
|
} else if (len_value_type <= 65535) {
|
||||||
apdu[len] = 254;
|
apdu[len++] = 254;
|
||||||
len++;
|
len += encode_unsigned16(&apdu[len], len_value_type);
|
||||||
short_data.value = len_value_type;
|
|
||||||
if (big_endian()) {
|
|
||||||
apdu[len + 0] = short_data.byte[0];
|
|
||||||
apdu[len + 1] = short_data.byte[1];
|
|
||||||
} else {
|
|
||||||
apdu[len + 0] = short_data.byte[1];
|
|
||||||
apdu[len + 1] = short_data.byte[0];
|
|
||||||
}
|
|
||||||
len += 2;
|
|
||||||
} else {
|
} else {
|
||||||
apdu[len] = 255;
|
apdu[len++] = 255;
|
||||||
len++;
|
len += encode_unsigned32(&apdu[len], len_value_type);
|
||||||
long_data.value = len_value_type;
|
|
||||||
if (big_endian()) {
|
|
||||||
apdu[len + 0] = long_data.byte[0];
|
|
||||||
apdu[len + 1] = long_data.byte[1];
|
|
||||||
apdu[len + 2] = long_data.byte[2];
|
|
||||||
apdu[len + 3] = long_data.byte[3];
|
|
||||||
} else {
|
|
||||||
apdu[len + 0] = long_data.byte[3];
|
|
||||||
apdu[len + 1] = long_data.byte[2];
|
|
||||||
apdu[len + 2] = long_data.byte[1];
|
|
||||||
apdu[len + 3] = long_data.byte[0];
|
|
||||||
}
|
|
||||||
len += 4;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,16 +348,8 @@ int decode_tag_number_and_value(uint8_t * apdu,
|
|||||||
uint8_t * tag_number, uint32_t * value)
|
uint8_t * tag_number, uint32_t * value)
|
||||||
{
|
{
|
||||||
int len = 1;
|
int len = 1;
|
||||||
union {
|
uint16_t value16;
|
||||||
uint8_t byte[2];
|
uint32_t value32;
|
||||||
uint16_t value;
|
|
||||||
} short_data = { {
|
|
||||||
0}};
|
|
||||||
union {
|
|
||||||
uint8_t byte[4];
|
|
||||||
uint32_t value;
|
|
||||||
} long_data = { {
|
|
||||||
0}};
|
|
||||||
|
|
||||||
len = decode_tag_number(&apdu[0], tag_number);
|
len = decode_tag_number(&apdu[0], tag_number);
|
||||||
// decode the value
|
// decode the value
|
||||||
@@ -346,36 +357,16 @@ int decode_tag_number_and_value(uint8_t * apdu,
|
|||||||
// tagged as uint32_t
|
// tagged as uint32_t
|
||||||
if (apdu[len] == 255) {
|
if (apdu[len] == 255) {
|
||||||
len++;
|
len++;
|
||||||
if (big_endian()) {
|
len += decode_unsigned32(&apdu[len], &value32);
|
||||||
long_data.byte[0] = apdu[len + 0];
|
|
||||||
long_data.byte[1] = apdu[len + 1];
|
|
||||||
long_data.byte[2] = apdu[len + 2];
|
|
||||||
long_data.byte[3] = apdu[len + 3];
|
|
||||||
} else {
|
|
||||||
long_data.byte[3] = apdu[len + 0];
|
|
||||||
long_data.byte[2] = apdu[len + 1];
|
|
||||||
long_data.byte[1] = apdu[len + 2];
|
|
||||||
long_data.byte[0] = apdu[len + 3];
|
|
||||||
}
|
|
||||||
if (value)
|
if (value)
|
||||||
*value = long_data.value;
|
*value = value32;
|
||||||
len += 4;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
// tagged as uint16_t
|
// tagged as uint16_t
|
||||||
else if (apdu[len] == 254) {
|
else if (apdu[len] == 254) {
|
||||||
len++;
|
len++;
|
||||||
if (big_endian()) {
|
len += decode_unsigned16(&apdu[len], &value16);
|
||||||
short_data.byte[0] = apdu[len + 0];
|
|
||||||
short_data.byte[1] = apdu[len + 1];
|
|
||||||
} else {
|
|
||||||
short_data.byte[1] = apdu[len + 0];
|
|
||||||
short_data.byte[0] = apdu[len + 1];
|
|
||||||
}
|
|
||||||
if (value)
|
if (value)
|
||||||
*value = short_data.value;
|
*value = value16;
|
||||||
len += 2;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
// no tag - must be uint8_t
|
// no tag - must be uint8_t
|
||||||
else {
|
else {
|
||||||
@@ -502,55 +493,29 @@ int encode_tagged_real(uint8_t * apdu, float value)
|
|||||||
|
|
||||||
// from clause 20.2.14 Encoding of an Object Identifier Value
|
// from clause 20.2.14 Encoding of an Object Identifier Value
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int decode_object_id(uint8_t * apdu, int *object_type, uint32_t *instance)
|
int decode_object_id(uint8_t *apdu, int *object_type, uint32_t *instance)
|
||||||
{
|
{
|
||||||
union {
|
uint32_t value = 0;
|
||||||
uint8_t byte[4];
|
int len = 0;
|
||||||
uint32_t value;
|
|
||||||
} my_data;
|
|
||||||
|
|
||||||
if (big_endian()) {
|
len = decode_unsigned32(apdu,&value);
|
||||||
my_data.byte[0] = apdu[0];
|
*object_type = ((value >> 22) & 0x3FF);
|
||||||
my_data.byte[1] = apdu[1];
|
*instance = (value & 0x3FFFFF);
|
||||||
my_data.byte[2] = apdu[2];
|
|
||||||
my_data.byte[3] = apdu[3];
|
|
||||||
} else {
|
|
||||||
my_data.byte[0] = apdu[3];
|
|
||||||
my_data.byte[1] = apdu[2];
|
|
||||||
my_data.byte[2] = apdu[1];
|
|
||||||
my_data.byte[3] = apdu[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
*object_type = ((my_data.value >> 22) & 0x3FF);
|
return len;
|
||||||
*instance = (my_data.value & 0x3FFFFF);
|
|
||||||
|
|
||||||
return 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// from clause 20.2.14 Encoding of an Object Identifier Value
|
// from clause 20.2.14 Encoding of an Object Identifier Value
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_bacnet_object_id(uint8_t * apdu, int object_type, uint32_t instance)
|
int encode_bacnet_object_id(uint8_t * apdu, int object_type, uint32_t instance)
|
||||||
{
|
{
|
||||||
union {
|
uint32_t value = 0;
|
||||||
uint8_t byte[4];
|
int len = 0;
|
||||||
uint32_t value;
|
|
||||||
} my_data;
|
|
||||||
|
|
||||||
my_data.value = ((object_type & 0x3FF) << 22) | (instance & 0x3FFFFF);
|
value = ((object_type & 0x3FF) << 22) | (instance & 0x3FFFFF);
|
||||||
|
len = encode_unsigned32(apdu,value);
|
||||||
|
|
||||||
if (big_endian()) {
|
return len;
|
||||||
apdu[0] = my_data.byte[0];
|
|
||||||
apdu[1] = my_data.byte[1];
|
|
||||||
apdu[2] = my_data.byte[2];
|
|
||||||
apdu[3] = my_data.byte[3];
|
|
||||||
} else {
|
|
||||||
apdu[0] = my_data.byte[3];
|
|
||||||
apdu[1] = my_data.byte[2];
|
|
||||||
apdu[2] = my_data.byte[1];
|
|
||||||
apdu[3] = my_data.byte[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
return 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// from clause 20.2.14 Encoding of an Object Identifier Value
|
// from clause 20.2.14 Encoding of an Object Identifier Value
|
||||||
@@ -664,6 +629,7 @@ int decode_character_string(uint8_t * apdu, uint32_t len_value,
|
|||||||
// from clause 20.2.4 Encoding of an Unsigned Integer Value
|
// from clause 20.2.4 Encoding of an Unsigned Integer Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
|
// FIXME: What about endian?
|
||||||
int encode_bacnet_unsigned(uint8_t * apdu, unsigned int value)
|
int encode_bacnet_unsigned(uint8_t * apdu, unsigned int value)
|
||||||
{
|
{
|
||||||
int len = 0; // return value
|
int len = 0; // return value
|
||||||
@@ -724,6 +690,7 @@ int encode_tagged_unsigned(uint8_t * apdu, unsigned int value)
|
|||||||
// from clause 20.2.4 Encoding of an Unsigned Integer Value
|
// from clause 20.2.4 Encoding of an Unsigned Integer Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
|
// FIXME: What about endian?
|
||||||
int decode_unsigned(uint8_t * apdu, uint32_t len_value, unsigned *value)
|
int decode_unsigned(uint8_t * apdu, uint32_t len_value, unsigned *value)
|
||||||
{
|
{
|
||||||
int len = 0; // return value
|
int len = 0; // return value
|
||||||
|
|||||||
@@ -136,8 +136,11 @@ int decode_date(uint8_t * apdu, int *year, int *month, int *day,
|
|||||||
int *wday);
|
int *wday);
|
||||||
|
|
||||||
// two octet unsigned16
|
// two octet unsigned16
|
||||||
int encode_bacnet_unsigned16(uint8_t * apdu, uint16_t value);
|
int encode_unsigned16(uint8_t * apdu, uint16_t value);
|
||||||
int decode_unsigned16(uint8_t * apdu, uint16_t *value);
|
int decode_unsigned16(uint8_t * apdu, uint16_t *value);
|
||||||
|
// four octet unsigned32
|
||||||
|
int encode_unsigned32(uint8_t * apdu, uint32_t value);
|
||||||
|
int decode_unsigned32(uint8_t * apdu, uint32_t *value);
|
||||||
|
|
||||||
// from clause 20.1.2.4 max-segments-accepted
|
// from clause 20.1.2.4 max-segments-accepted
|
||||||
// and clause 20.1.2.5 max-APDU-length-accepted
|
// and clause 20.1.2.5 max-APDU-length-accepted
|
||||||
|
|||||||
Reference in New Issue
Block a user