ran the indent program on the source files to make them consistent.

This commit is contained in:
skarg
2006-02-18 22:34:36 +00:00
parent 21b373c75c
commit b1d46ffa8c
72 changed files with 10446 additions and 11551 deletions
+27 -71
View File
@@ -37,15 +37,12 @@
#include "bacdef.h" #include "bacdef.h"
// encode service // encode service
int abort_encode_apdu( int abort_encode_apdu(uint8_t * apdu,
uint8_t *apdu, uint8_t invoke_id, uint8_t abort_reason)
uint8_t invoke_id,
uint8_t abort_reason)
{ {
int apdu_len = 0; // total length of the apdu, return value int apdu_len = 0; // total length of the apdu, return value
if (apdu) if (apdu) {
{
apdu[0] = PDU_TYPE_ABORT; apdu[0] = PDU_TYPE_ABORT;
apdu[1] = invoke_id; apdu[1] = invoke_id;
apdu[2] = abort_reason; apdu[2] = abort_reason;
@@ -56,16 +53,12 @@ int abort_encode_apdu(
} }
// decode the service request only // decode the service request only
int abort_decode_service_request( int abort_decode_service_request(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, uint8_t * invoke_id, uint8_t * abort_reason)
unsigned apdu_len,
uint8_t *invoke_id,
uint8_t *abort_reason)
{ {
int len = 0; int len = 0;
if (apdu_len) if (apdu_len) {
{
if (invoke_id) if (invoke_id)
*invoke_id = apdu[0]; *invoke_id = apdu[0];
if (abort_reason) if (abort_reason)
@@ -76,28 +69,20 @@ int abort_decode_service_request(
} }
// decode the whole APDU - mainly used for unit testing // decode the whole APDU - mainly used for unit testing
int abort_decode_apdu( int abort_decode_apdu(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, uint8_t * invoke_id, uint8_t * abort_reason)
unsigned apdu_len,
uint8_t *invoke_id,
uint8_t *abort_reason)
{ {
int len = 0; int len = 0;
if (!apdu) if (!apdu)
return -1; return -1;
// optional checking - most likely was already done prior to this call // optional checking - most likely was already done prior to this call
if (apdu_len) if (apdu_len) {
{
if (apdu[0] != PDU_TYPE_ABORT) if (apdu[0] != PDU_TYPE_ABORT)
return -1; return -1;
if (apdu_len > 1) if (apdu_len > 1) {
{ len = abort_decode_service_request(&apdu[1],
len = abort_decode_service_request( apdu_len - 1, invoke_id, abort_reason);
&apdu[1],
apdu_len - 1,
invoke_id,
abort_reason);
} }
} }
@@ -111,7 +96,7 @@ int abort_decode_apdu(
void testAbort(Test * pTest) void testAbort(Test * pTest)
{ {
uint8_t apdu[480] = {0}; uint8_t apdu[480] = { 0 };
int len = 0; int len = 0;
int apdu_len = 0; int apdu_len = 0;
uint8_t invoke_id = 0; uint8_t invoke_id = 0;
@@ -119,70 +104,41 @@ void testAbort(Test * pTest)
uint8_t test_invoke_id = 0; uint8_t test_invoke_id = 0;
uint8_t test_abort_reason = 0; uint8_t test_abort_reason = 0;
len = abort_encode_apdu( len = abort_encode_apdu(&apdu[0], invoke_id, abort_reason);
&apdu[0],
invoke_id,
abort_reason);
ct_test(pTest, len != 0); ct_test(pTest, len != 0);
apdu_len = len; apdu_len = len;
len = abort_decode_apdu( len = abort_decode_apdu(&apdu[0],
&apdu[0], apdu_len, &test_invoke_id, &test_abort_reason);
apdu_len,
&test_invoke_id,
&test_abort_reason);
ct_test(pTest, len != -1); ct_test(pTest, len != -1);
ct_test(pTest, test_invoke_id == invoke_id); ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest, test_abort_reason == abort_reason); ct_test(pTest, test_abort_reason == abort_reason);
// change type to get negative response // change type to get negative response
apdu[0] = PDU_TYPE_REJECT; apdu[0] = PDU_TYPE_REJECT;
len = abort_decode_apdu( len = abort_decode_apdu(&apdu[0],
&apdu[0], apdu_len, &test_invoke_id, &test_abort_reason);
apdu_len,
&test_invoke_id,
&test_abort_reason);
ct_test(pTest, len == -1); ct_test(pTest, len == -1);
// test NULL APDU // test NULL APDU
len = abort_decode_apdu( len = abort_decode_apdu(NULL,
NULL, apdu_len, &test_invoke_id, &test_abort_reason);
apdu_len,
&test_invoke_id,
&test_abort_reason);
ct_test(pTest, len == -1); ct_test(pTest, len == -1);
// force a zero length // force a zero length
len = abort_decode_apdu( len = abort_decode_apdu(&apdu[0],
&apdu[0], 0, &test_invoke_id, &test_abort_reason);
0,
&test_invoke_id,
&test_abort_reason);
ct_test(pTest, len == 0); ct_test(pTest, len == 0);
// check them all... // check them all...
for ( for (invoke_id = 0; invoke_id < 255; invoke_id++) {
invoke_id = 0; for (abort_reason = 0; abort_reason < 255; abort_reason++) {
invoke_id < 255; len = abort_encode_apdu(&apdu[0], invoke_id, abort_reason);
invoke_id++)
{
for (
abort_reason = 0;
abort_reason < 255;
abort_reason++)
{
len = abort_encode_apdu(
&apdu[0],
invoke_id,
abort_reason);
apdu_len = len; apdu_len = len;
ct_test(pTest, len != 0); ct_test(pTest, len != 0);
len = abort_decode_apdu( len = abort_decode_apdu(&apdu[0],
&apdu[0], apdu_len, &test_invoke_id, &test_abort_reason);
apdu_len,
&test_invoke_id,
&test_abort_reason);
ct_test(pTest, len != -1); ct_test(pTest, len != -1);
ct_test(pTest, test_invoke_id == invoke_id); ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest, test_abort_reason == abort_reason); ct_test(pTest, test_abort_reason == abort_reason);
+7 -17
View File
@@ -41,31 +41,21 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
int abort_encode_apdu( int abort_encode_apdu(uint8_t * apdu,
uint8_t *apdu, uint8_t invoke_id, uint8_t abort_reason);
uint8_t invoke_id,
uint8_t abort_reason);
int abort_decode_service_request( int abort_decode_service_request(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, uint8_t * invoke_id, uint8_t * abort_reason);
unsigned apdu_len,
uint8_t *invoke_id,
uint8_t *abort_reason);
int abort_decode_apdu( int abort_decode_apdu(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, uint8_t * invoke_id, uint8_t * abort_reason);
unsigned apdu_len,
uint8_t *invoke_id,
uint8_t *abort_reason);
#ifdef TEST #ifdef TEST
#include "ctest.h" #include "ctest.h"
void testAbort(Test * pTest); void testAbort(Test * pTest);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+60 -116
View File
@@ -44,8 +44,7 @@
// occurs in BACnet. A device id is bound to a MAC address. // occurs in BACnet. A device id is bound to a MAC address.
// The normal method is using Who-Is, and using the data from I-Am // The normal method is using Who-Is, and using the data from I-Am
static struct Address_Cache_Entry static struct Address_Cache_Entry {
{
bool valid; bool valid;
bool bind_request; bool bind_request;
uint32_t device_id; uint32_t device_id;
@@ -53,23 +52,18 @@ static struct Address_Cache_Entry
BACNET_ADDRESS address; BACNET_ADDRESS address;
} Address_Cache[MAX_ADDRESS_CACHE]; } Address_Cache[MAX_ADDRESS_CACHE];
void address_copy( void address_copy(BACNET_ADDRESS * dest, BACNET_ADDRESS * src)
BACNET_ADDRESS *dest,
BACNET_ADDRESS *src)
{ {
unsigned i = 0; // counter unsigned i = 0; // counter
if (dest && src) if (dest && src) {
{ for (i = 0; i < MAX_MAC_LEN; i++) {
for (i = 0; i < MAX_MAC_LEN; i++)
{
dest->mac[i] = src->mac[i]; dest->mac[i] = src->mac[i];
} }
dest->mac_len = src->mac_len; dest->mac_len = src->mac_len;
dest->net = src->net; dest->net = src->net;
dest->len = src->len; dest->len = src->len;
for (i = 0; i < MAX_MAC_LEN; i++) for (i = 0; i < MAX_MAC_LEN; i++) {
{
dest->adr[i] = src->adr[i]; dest->adr[i] = src->adr[i];
} }
} }
@@ -77,17 +71,14 @@ void address_copy(
return; return;
} }
void address_remove_device( void address_remove_device(uint32_t device_id)
uint32_t device_id)
{ {
unsigned i; unsigned i;
for (i = 0; i < MAX_ADDRESS_CACHE; i++) for (i = 0; i < MAX_ADDRESS_CACHE; i++) {
{
if ((Address_Cache[i].valid || if ((Address_Cache[i].valid ||
Address_Cache[i].bind_request) && Address_Cache[i].bind_request) &&
(Address_Cache[i].device_id == device_id)) (Address_Cache[i].device_id == device_id)) {
{
Address_Cache[i].valid = false; Address_Cache[i].valid = false;
break; break;
} }
@@ -100,8 +91,7 @@ void address_init(void)
{ {
unsigned i; unsigned i;
for (i = 0; i < MAX_ADDRESS_CACHE; i++) for (i = 0; i < MAX_ADDRESS_CACHE; i++) {
{
Address_Cache[i].valid = false; Address_Cache[i].valid = false;
Address_Cache[i].bind_request = false; Address_Cache[i].bind_request = false;
} }
@@ -109,19 +99,15 @@ void address_init(void)
return; return;
} }
bool address_get_by_device( bool address_get_by_device(uint32_t device_id,
uint32_t device_id, unsigned *max_apdu, BACNET_ADDRESS * src)
unsigned *max_apdu,
BACNET_ADDRESS *src)
{ {
unsigned i; unsigned i;
bool found = false; // return value bool found = false; // return value
for (i = 0; i < MAX_ADDRESS_CACHE; i++) for (i = 0; i < MAX_ADDRESS_CACHE; i++) {
{
if (Address_Cache[i].valid && if (Address_Cache[i].valid &&
(Address_Cache[i].device_id == device_id)) (Address_Cache[i].device_id == device_id)) {
{
address_copy(src, &Address_Cache[i].address); address_copy(src, &Address_Cache[i].address);
*max_apdu = Address_Cache[i].max_apdu; *max_apdu = Address_Cache[i].max_apdu;
found = true; found = true;
@@ -132,37 +118,30 @@ bool address_get_by_device(
return found; return found;
} }
void address_add( void address_add(uint32_t device_id,
uint32_t device_id, unsigned max_apdu, BACNET_ADDRESS * src)
unsigned max_apdu,
BACNET_ADDRESS *src)
{ {
unsigned i; unsigned i;
bool found = false; // return value bool found = false; // return value
// existing device - update address // existing device - update address
for (i = 0; i < MAX_ADDRESS_CACHE; i++) for (i = 0; i < MAX_ADDRESS_CACHE; i++) {
{
if (Address_Cache[i].valid && if (Address_Cache[i].valid &&
(Address_Cache[i].device_id == device_id)) (Address_Cache[i].device_id == device_id)) {
{ address_copy(&Address_Cache[i].address, src);
address_copy(&Address_Cache[i].address,src);
Address_Cache[i].max_apdu = max_apdu; Address_Cache[i].max_apdu = max_apdu;
found = true; found = true;
break; break;
} }
} }
// new device // new device
if (!found) if (!found) {
{ for (i = 0; i < MAX_ADDRESS_CACHE; i++) {
for (i = 0; i < MAX_ADDRESS_CACHE; i++) if (!Address_Cache[i].valid) {
{
if (!Address_Cache[i].valid)
{
Address_Cache[i].valid = true; Address_Cache[i].valid = true;
Address_Cache[i].device_id = device_id; Address_Cache[i].device_id = device_id;
Address_Cache[i].max_apdu = max_apdu; Address_Cache[i].max_apdu = max_apdu;
address_copy(&Address_Cache[i].address,src); address_copy(&Address_Cache[i].address, src);
break; break;
} }
} }
@@ -173,20 +152,16 @@ void address_add(
// returns true if device is already bound // returns true if device is already bound
// also returns the address and max apdu if already bound // also returns the address and max apdu if already bound
bool address_bind_request( bool address_bind_request(uint32_t device_id,
uint32_t device_id, unsigned *max_apdu, BACNET_ADDRESS * src)
unsigned *max_apdu,
BACNET_ADDRESS *src)
{ {
unsigned i; unsigned i;
bool found = false; // return value bool found = false; // return value
// existing device - update address // existing device - update address
for (i = 0; i < MAX_ADDRESS_CACHE; i++) for (i = 0; i < MAX_ADDRESS_CACHE; i++) {
{
if (Address_Cache[i].valid && if (Address_Cache[i].valid &&
(Address_Cache[i].device_id == device_id)) (Address_Cache[i].device_id == device_id)) {
{
found = true; found = true;
address_copy(src, &Address_Cache[i].address); address_copy(src, &Address_Cache[i].address);
*max_apdu = Address_Cache[i].max_apdu; *max_apdu = Address_Cache[i].max_apdu;
@@ -194,18 +169,14 @@ bool address_bind_request(
} }
// already have a bind request active for this puppy // already have a bind request active for this puppy
else if (Address_Cache[i].bind_request && else if (Address_Cache[i].bind_request &&
(Address_Cache[i].device_id == device_id)) (Address_Cache[i].device_id == device_id)) {
{
return found; return found;
} }
} }
if (!found) if (!found) {
{ for (i = 0; i < MAX_ADDRESS_CACHE; i++) {
for (i = 0; i < MAX_ADDRESS_CACHE; i++) if (!(Address_Cache[i].bind_request || Address_Cache[i].valid)) {
{
if (!(Address_Cache[i].bind_request || Address_Cache[i].valid))
{
Address_Cache[i].bind_request = true; Address_Cache[i].bind_request = true;
Address_Cache[i].device_id = device_id; Address_Cache[i].device_id = device_id;
// now would be a good time to do a Who-Is request // now would be a good time to do a Who-Is request
@@ -217,38 +188,31 @@ bool address_bind_request(
return found; return found;
} }
void address_add_binding( void address_add_binding(uint32_t device_id,
uint32_t device_id, unsigned max_apdu, BACNET_ADDRESS * src)
unsigned max_apdu,
BACNET_ADDRESS *src)
{ {
unsigned i; unsigned i;
bool found = false; // return value bool found = false; // return value
// existing device - update address // existing device - update address
for (i = 0; i < MAX_ADDRESS_CACHE; i++) for (i = 0; i < MAX_ADDRESS_CACHE; i++) {
{
if (Address_Cache[i].valid && if (Address_Cache[i].valid &&
(Address_Cache[i].device_id == device_id)) (Address_Cache[i].device_id == device_id)) {
{ address_copy(&Address_Cache[i].address, src);
address_copy(&Address_Cache[i].address,src);
Address_Cache[i].max_apdu = max_apdu; Address_Cache[i].max_apdu = max_apdu;
found = true; found = true;
break; break;
} }
} }
// add new device - but only if bind requested // add new device - but only if bind requested
if (!found) if (!found) {
{ for (i = 0; i < MAX_ADDRESS_CACHE; i++) {
for (i = 0; i < MAX_ADDRESS_CACHE; i++) if (!Address_Cache[i].valid && Address_Cache[i].bind_request) {
{
if (!Address_Cache[i].valid && Address_Cache[i].bind_request)
{
Address_Cache[i].valid = true; Address_Cache[i].valid = true;
Address_Cache[i].bind_request = false; Address_Cache[i].bind_request = false;
Address_Cache[i].device_id = device_id; Address_Cache[i].device_id = device_id;
Address_Cache[i].max_apdu = max_apdu; Address_Cache[i].max_apdu = max_apdu;
address_copy(&Address_Cache[i].address,src); address_copy(&Address_Cache[i].address, src);
break; break;
} }
} }
@@ -257,18 +221,13 @@ void address_add_binding(
return; return;
} }
bool address_get_by_index( bool address_get_by_index(unsigned index,
unsigned index, uint32_t * device_id, unsigned *max_apdu, BACNET_ADDRESS * src)
uint32_t *device_id,
unsigned *max_apdu,
BACNET_ADDRESS *src)
{ {
bool found = false; // return value bool found = false; // return value
if (index < MAX_ADDRESS_CACHE) if (index < MAX_ADDRESS_CACHE) {
{ if (Address_Cache[index].valid) {
if (Address_Cache[index].valid)
{
address_copy(src, &Address_Cache[index].address); address_copy(src, &Address_Cache[index].address);
*device_id = Address_Cache[index].device_id; *device_id = Address_Cache[index].device_id;
*max_apdu = Address_Cache[index].max_apdu; *max_apdu = Address_Cache[index].max_apdu;
@@ -284,8 +243,7 @@ unsigned address_count(void)
unsigned i; unsigned i;
unsigned count = 0; // return value unsigned count = 0; // return value
for (i = 0; i < MAX_ADDRESS_CACHE; i++) for (i = 0; i < MAX_ADDRESS_CACHE; i++) {
{
if (Address_Cache[i].valid) if (Address_Cache[i].valid)
count++; count++;
} }
@@ -293,9 +251,7 @@ unsigned address_count(void)
return count; return count;
} }
bool address_match( bool address_match(BACNET_ADDRESS * dest, BACNET_ADDRESS * src)
BACNET_ADDRESS *dest,
BACNET_ADDRESS *src)
{ {
unsigned i; unsigned i;
unsigned max_len; unsigned max_len;
@@ -306,8 +262,7 @@ bool address_match(
max_len = dest->mac_len; max_len = dest->mac_len;
if (max_len > MAX_MAC_LEN) if (max_len > MAX_MAC_LEN)
max_len = MAX_MAC_LEN; max_len = MAX_MAC_LEN;
for (i = 0; i < max_len; i++) for (i = 0; i < max_len; i++) {
{
if (dest->mac[i] != src->mac[i]) if (dest->mac[i] != src->mac[i])
match = false; match = false;
} }
@@ -318,8 +273,7 @@ bool address_match(
max_len = dest->len; max_len = dest->len;
if (max_len > MAX_MAC_LEN) if (max_len > MAX_MAC_LEN)
max_len = MAX_MAC_LEN; max_len = MAX_MAC_LEN;
for (i = 0; i < max_len; i++) for (i = 0; i < max_len; i++) {
{
if (dest->adr[i] != src->adr[i]) if (dest->adr[i] != src->adr[i])
match = false; match = false;
} }
@@ -332,21 +286,17 @@ bool address_match(
#include <string.h> #include <string.h>
#include "ctest.h" #include "ctest.h"
static void set_address( static void set_address(unsigned index, BACNET_ADDRESS * dest)
unsigned index,
BACNET_ADDRESS *dest)
{ {
unsigned i; unsigned i;
for (i = 0; i < MAX_MAC_LEN; i++) for (i = 0; i < MAX_MAC_LEN; i++) {
{
dest->mac[i] = index; dest->mac[i] = index;
} }
dest->mac_len = MAX_MAC_LEN; dest->mac_len = MAX_MAC_LEN;
dest->net = 7; dest->net = 7;
dest->len = MAX_MAC_LEN; dest->len = MAX_MAC_LEN;
for (i = 0; i < MAX_MAC_LEN; i++) for (i = 0; i < MAX_MAC_LEN; i++) {
{
dest->adr[i] = index; dest->adr[i] = index;
} }
} }
@@ -361,42 +311,36 @@ void testAddress(Test * pTest)
uint32_t test_device_id = 0; uint32_t test_device_id = 0;
unsigned test_max_apdu = 0; unsigned test_max_apdu = 0;
for (i = 0; i < MAX_ADDRESS_CACHE; i++) for (i = 0; i < MAX_ADDRESS_CACHE; i++) {
{ set_address(i, &src);
set_address(i,&src);
device_id = i * 255; device_id = i * 255;
address_add( address_add(device_id, max_apdu, &src);
device_id,
max_apdu,
&src);
count = address_count(); count = address_count();
ct_test(pTest, count == (i + 1)); ct_test(pTest, count == (i + 1));
} }
for (i = 0; i < MAX_ADDRESS_CACHE; i++) for (i = 0; i < MAX_ADDRESS_CACHE; i++) {
{
device_id = i * 255; device_id = i * 255;
ct_test(pTest, address_get_by_device(device_id, &test_max_apdu, ct_test(pTest, address_get_by_device(device_id, &test_max_apdu,
&test_address)); &test_address));
set_address(i,&src); set_address(i, &src);
ct_test(pTest, test_max_apdu == max_apdu); ct_test(pTest, test_max_apdu == max_apdu);
ct_test(pTest, address_match(&test_address,&src)); ct_test(pTest, address_match(&test_address, &src));
ct_test(pTest, address_get_by_index(i, &test_device_id, ct_test(pTest, address_get_by_index(i, &test_device_id,
&test_max_apdu,&test_address)); &test_max_apdu, &test_address));
ct_test(pTest, test_device_id == device_id); ct_test(pTest, test_device_id == device_id);
ct_test(pTest, test_max_apdu == max_apdu); ct_test(pTest, test_max_apdu == max_apdu);
ct_test(pTest, address_match(&test_address,&src)); ct_test(pTest, address_match(&test_address, &src));
ct_test(pTest, address_count() == MAX_ADDRESS_CACHE); ct_test(pTest, address_count() == MAX_ADDRESS_CACHE);
} }
for (i = 0; i < MAX_ADDRESS_CACHE; i++) for (i = 0; i < MAX_ADDRESS_CACHE; i++) {
{
device_id = i * 255; device_id = i * 255;
address_remove_device(device_id); address_remove_device(device_id);
ct_test(pTest, !address_get_by_device(device_id, &test_max_apdu, ct_test(pTest, !address_get_by_device(device_id, &test_max_apdu,
&test_address)); &test_address));
count = address_count(); count = address_count();
ct_test(pTest, count == (MAX_ADDRESS_CACHE-i-1)); ct_test(pTest, count == (MAX_ADDRESS_CACHE - i - 1));
} }
} }
+15 -32
View File
@@ -43,49 +43,32 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
void address_init(void); void address_init(void);
void address_copy( void address_copy(BACNET_ADDRESS * dest, BACNET_ADDRESS * src);
BACNET_ADDRESS *dest,
BACNET_ADDRESS *src);
void address_add( void address_add(uint32_t device_id,
uint32_t device_id, unsigned max_apdu, BACNET_ADDRESS * src);
unsigned max_apdu,
BACNET_ADDRESS *src);
void address_remove_device( void address_remove_device(uint32_t device_id);
uint32_t device_id);
bool address_get_by_device( bool address_get_by_device(uint32_t device_id,
uint32_t device_id, unsigned *max_apdu, BACNET_ADDRESS * src);
unsigned *max_apdu,
BACNET_ADDRESS *src);
bool address_get_by_index( bool address_get_by_index(unsigned index,
unsigned index, uint32_t * device_id, unsigned *max_apdu, BACNET_ADDRESS * src);
uint32_t *device_id,
unsigned *max_apdu,
BACNET_ADDRESS *src);
unsigned address_count(void); unsigned address_count(void);
bool address_match( bool address_match(BACNET_ADDRESS * dest, BACNET_ADDRESS * src);
BACNET_ADDRESS *dest,
BACNET_ADDRESS *src);
bool address_bind_request( bool address_bind_request(uint32_t device_id,
uint32_t device_id, unsigned *max_apdu, BACNET_ADDRESS * src);
unsigned *max_apdu,
BACNET_ADDRESS *src);
void address_add_binding( void address_add_binding(uint32_t device_id,
uint32_t device_id, unsigned max_apdu, BACNET_ADDRESS * src);
unsigned max_apdu,
BACNET_ADDRESS *src);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+85 -133
View File
@@ -44,8 +44,8 @@
#include "iam.h" #include "iam.h"
/* a simple table for crossing the services supported */ /* a simple table for crossing the services supported */
static BACNET_SERVICES_SUPPORTED confirmed_service_supported[MAX_BACNET_CONFIRMED_SERVICE] = static BACNET_SERVICES_SUPPORTED
{ confirmed_service_supported[MAX_BACNET_CONFIRMED_SERVICE] = {
SERVICE_SUPPORTED_ACKNOWLEDGE_ALARM, SERVICE_SUPPORTED_ACKNOWLEDGE_ALARM,
SERVICE_SUPPORTED_CONFIRMED_COV_NOTIFICATION, SERVICE_SUPPORTED_CONFIRMED_COV_NOTIFICATION,
SERVICE_SUPPORTED_CONFIRMED_EVENT_NOTIFICATION, SERVICE_SUPPORTED_CONFIRMED_EVENT_NOTIFICATION,
@@ -79,8 +79,8 @@ static BACNET_SERVICES_SUPPORTED confirmed_service_supported[MAX_BACNET_CONFIRME
}; };
/* a simple table for crossing the services supported */ /* a simple table for crossing the services supported */
static BACNET_SERVICES_SUPPORTED unconfirmed_service_supported[MAX_BACNET_UNCONFIRMED_SERVICE] = static BACNET_SERVICES_SUPPORTED
{ unconfirmed_service_supported[MAX_BACNET_UNCONFIRMED_SERVICE] = {
SERVICE_SUPPORTED_I_AM, SERVICE_SUPPORTED_I_AM,
SERVICE_SUPPORTED_I_HAVE, SERVICE_SUPPORTED_I_HAVE,
SERVICE_SUPPORTED_UNCONFIRMED_COV_NOTIFICATION, SERVICE_SUPPORTED_UNCONFIRMED_COV_NOTIFICATION,
@@ -95,11 +95,9 @@ static BACNET_SERVICES_SUPPORTED unconfirmed_service_supported[MAX_BACNET_UNCONF
// Confirmed Function Handlers // Confirmed Function Handlers
// If they are not set, they are handled by a reject message // If they are not set, they are handled by a reject message
static confirmed_function static confirmed_function Confirmed_Function[MAX_BACNET_CONFIRMED_SERVICE];
Confirmed_Function[MAX_BACNET_CONFIRMED_SERVICE];
void apdu_set_confirmed_handler( void apdu_set_confirmed_handler(BACNET_CONFIRMED_SERVICE service_choice,
BACNET_CONFIRMED_SERVICE service_choice,
confirmed_function pFunction) confirmed_function pFunction)
{ {
if (service_choice < MAX_BACNET_CONFIRMED_SERVICE) if (service_choice < MAX_BACNET_CONFIRMED_SERVICE)
@@ -107,8 +105,7 @@ void apdu_set_confirmed_handler(
} }
/* returns true if the handler is set */ /* returns true if the handler is set */
bool apdu_confirmed_handler( bool apdu_confirmed_handler(BACNET_CONFIRMED_SERVICE service_choice)
BACNET_CONFIRMED_SERVICE service_choice)
{ {
bool status = false; bool status = false;
if ((service_choice < MAX_BACNET_CONFIRMED_SERVICE) && if ((service_choice < MAX_BACNET_CONFIRMED_SERVICE) &&
@@ -124,13 +121,10 @@ bool apdu_service_supported(BACNET_SERVICES_SUPPORTED service_supported)
bool status = false; bool status = false;
bool found = false; bool found = false;
if (service_supported < MAX_BACNET_SERVICES_SUPPORTED) if (service_supported < MAX_BACNET_SERVICES_SUPPORTED) {
{
/* is it a confirmed service? */ /* is it a confirmed service? */
for (i = 0; i < MAX_BACNET_CONFIRMED_SERVICE; i++) for (i = 0; i < MAX_BACNET_CONFIRMED_SERVICE; i++) {
{ if (confirmed_service_supported[i] == service_supported) {
if (confirmed_service_supported[i] == service_supported)
{
if (apdu_confirmed_handler(i)) if (apdu_confirmed_handler(i))
status = true; status = true;
found = true; found = true;
@@ -138,13 +132,10 @@ bool apdu_service_supported(BACNET_SERVICES_SUPPORTED service_supported)
} }
} }
if (!found) if (!found) {
{
/* is it an unconfirmed service? */ /* is it an unconfirmed service? */
for (i = 0; i < MAX_BACNET_UNCONFIRMED_SERVICE; i++) for (i = 0; i < MAX_BACNET_UNCONFIRMED_SERVICE; i++) {
{ if (unconfirmed_service_supported[i] == service_supported) {
if (unconfirmed_service_supported[i] == service_supported)
{
if (apdu_unconfirmed_handler(i)) if (apdu_unconfirmed_handler(i))
status = true; status = true;
break; break;
@@ -158,8 +149,8 @@ bool apdu_service_supported(BACNET_SERVICES_SUPPORTED service_supported)
// Allow the APDU handler to automatically reject // Allow the APDU handler to automatically reject
static confirmed_function Unrecognized_Service_Handler; static confirmed_function Unrecognized_Service_Handler;
void apdu_set_unrecognized_service_handler_handler( void apdu_set_unrecognized_service_handler_handler(confirmed_function
confirmed_function pFunction) pFunction)
{ {
Unrecognized_Service_Handler = pFunction; Unrecognized_Service_Handler = pFunction;
} }
@@ -167,21 +158,18 @@ void apdu_set_unrecognized_service_handler_handler(
// Unconfirmed Function Handlers // Unconfirmed Function Handlers
// If they are not set, they are not handled // If they are not set, they are not handled
static unconfirmed_function static unconfirmed_function
Unconfirmed_Function[MAX_BACNET_UNCONFIRMED_SERVICE] = Unconfirmed_Function[MAX_BACNET_UNCONFIRMED_SERVICE] = {
{
NULL NULL
}; };
void apdu_set_unconfirmed_handler( void apdu_set_unconfirmed_handler(BACNET_UNCONFIRMED_SERVICE
BACNET_UNCONFIRMED_SERVICE service_choice, service_choice, unconfirmed_function pFunction)
unconfirmed_function pFunction)
{ {
if (service_choice < MAX_BACNET_UNCONFIRMED_SERVICE) if (service_choice < MAX_BACNET_UNCONFIRMED_SERVICE)
Unconfirmed_Function[service_choice] = pFunction; Unconfirmed_Function[service_choice] = pFunction;
} }
bool apdu_unconfirmed_handler( bool apdu_unconfirmed_handler(BACNET_UNCONFIRMED_SERVICE service_choice)
BACNET_UNCONFIRMED_SERVICE service_choice)
{ {
bool status = false; bool status = false;
@@ -191,15 +179,14 @@ bool apdu_unconfirmed_handler(
return status; return status;
} }
// Confirmed ACK Function Handlers // Confirmed ACK Function Handlers
static void *Confirmed_ACK_Function[MAX_BACNET_CONFIRMED_SERVICE]; static void *Confirmed_ACK_Function[MAX_BACNET_CONFIRMED_SERVICE];
void apdu_set_confirmed_simple_ack_handler( void apdu_set_confirmed_simple_ack_handler(BACNET_CONFIRMED_SERVICE
BACNET_CONFIRMED_SERVICE service_choice, service_choice, confirmed_simple_ack_function pFunction)
confirmed_simple_ack_function pFunction)
{ {
switch (service_choice) switch (service_choice) {
{
case SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM: case SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM:
case SERVICE_CONFIRMED_COV_NOTIFICATION: case SERVICE_CONFIRMED_COV_NOTIFICATION:
case SERVICE_CONFIRMED_EVENT_NOTIFICATION: case SERVICE_CONFIRMED_EVENT_NOTIFICATION:
@@ -220,19 +207,17 @@ void apdu_set_confirmed_simple_ack_handler(
case SERVICE_CONFIRMED_VT_CLOSE: case SERVICE_CONFIRMED_VT_CLOSE:
// Security Services // Security Services
case SERVICE_CONFIRMED_REQUEST_KEY: case SERVICE_CONFIRMED_REQUEST_KEY:
Confirmed_ACK_Function[service_choice] = (void *)pFunction; Confirmed_ACK_Function[service_choice] = (void *) pFunction;
break; break;
default: default:
break; break;
} }
} }
void apdu_set_confirmed_ack_handler( void apdu_set_confirmed_ack_handler(BACNET_CONFIRMED_SERVICE
BACNET_CONFIRMED_SERVICE service_choice, service_choice, confirmed_ack_function pFunction)
confirmed_ack_function pFunction)
{ {
switch (service_choice) switch (service_choice) {
{
case SERVICE_CONFIRMED_GET_ALARM_SUMMARY: case SERVICE_CONFIRMED_GET_ALARM_SUMMARY:
case SERVICE_CONFIRMED_GET_ENROLLMENT_SUMMARY: case SERVICE_CONFIRMED_GET_ENROLLMENT_SUMMARY:
case SERVICE_CONFIRMED_GET_EVENT_INFORMATION: case SERVICE_CONFIRMED_GET_EVENT_INFORMATION:
@@ -252,18 +237,16 @@ void apdu_set_confirmed_ack_handler(
case SERVICE_CONFIRMED_VT_DATA: case SERVICE_CONFIRMED_VT_DATA:
// Security Services // Security Services
case SERVICE_CONFIRMED_AUTHENTICATE: case SERVICE_CONFIRMED_AUTHENTICATE:
Confirmed_ACK_Function[service_choice] = (void *)pFunction; Confirmed_ACK_Function[service_choice] = (void *) pFunction;
break; break;
default: default:
break; break;
} }
} }
static error_function static error_function Error_Function[MAX_BACNET_CONFIRMED_SERVICE];
Error_Function[MAX_BACNET_CONFIRMED_SERVICE];
void apdu_set_error_handler( void apdu_set_error_handler(BACNET_CONFIRMED_SERVICE service_choice,
BACNET_CONFIRMED_SERVICE service_choice,
error_function pFunction) error_function pFunction)
{ {
if (service_choice < MAX_BACNET_CONFIRMED_SERVICE) if (service_choice < MAX_BACNET_CONFIRMED_SERVICE)
@@ -272,39 +255,35 @@ void apdu_set_error_handler(
static abort_function Abort_Function; static abort_function Abort_Function;
void apdu_set_abort_handler( void apdu_set_abort_handler(abort_function pFunction)
abort_function pFunction)
{ {
Abort_Function = pFunction; Abort_Function = pFunction;
} }
static reject_function Reject_Function; static reject_function Reject_Function;
void apdu_set_reject_handler( void apdu_set_reject_handler(reject_function pFunction)
reject_function pFunction)
{ {
Reject_Function = pFunction; Reject_Function = pFunction;
} }
uint16_t apdu_decode_confirmed_service_request( uint16_t apdu_decode_confirmed_service_request(uint8_t * apdu, // APDU data
uint8_t *apdu, // APDU data
uint16_t apdu_len, uint16_t apdu_len,
BACNET_CONFIRMED_SERVICE_DATA *service_data, BACNET_CONFIRMED_SERVICE_DATA * service_data,
uint8_t *service_choice, uint8_t * service_choice,
uint8_t **service_request, uint8_t ** service_request, uint16_t * service_request_len)
uint16_t *service_request_len)
{ {
uint16_t len = 0; // counts where we are in PDU uint16_t len = 0; // counts where we are in PDU
service_data->segmented_message = (apdu[0] & BIT3) ? true : false; service_data->segmented_message = (apdu[0] & BIT3) ? true : false;
service_data->more_follows = (apdu[0] & BIT2) ? true : false; service_data->more_follows = (apdu[0] & BIT2) ? true : false;
service_data->segmented_response_accepted = (apdu[0] & BIT1) ? true : false; service_data->segmented_response_accepted =
(apdu[0] & BIT1) ? true : false;
service_data->max_segs = decode_max_segs(apdu[1]); service_data->max_segs = decode_max_segs(apdu[1]);
service_data->max_resp = decode_max_apdu(apdu[1]); service_data->max_resp = decode_max_apdu(apdu[1]);
service_data->invoke_id = apdu[2]; service_data->invoke_id = apdu[2];
len = 3; len = 3;
if (service_data->segmented_message) if (service_data->segmented_message) {
{
service_data->sequence_number = apdu[len++]; service_data->sequence_number = apdu[len++];
service_data->proposed_window_number = apdu[len++]; service_data->proposed_window_number = apdu[len++];
} }
@@ -315,14 +294,12 @@ uint16_t apdu_decode_confirmed_service_request(
return len; return len;
} }
void apdu_handler( void apdu_handler(BACNET_ADDRESS * src, // source address
BACNET_ADDRESS *src, // source address bool data_expecting_reply, uint8_t * apdu, // APDU data
bool data_expecting_reply,
uint8_t *apdu, // APDU data
uint16_t apdu_len) uint16_t apdu_len)
{ {
BACNET_CONFIRMED_SERVICE_DATA service_data = {0}; BACNET_CONFIRMED_SERVICE_DATA service_data = { 0 };
BACNET_CONFIRMED_SERVICE_ACK_DATA service_ack_data = {0}; BACNET_CONFIRMED_SERVICE_ACK_DATA service_ack_data = { 0 };
uint8_t invoke_id = 0; uint8_t invoke_id = 0;
uint8_t service_choice = 0; uint8_t service_choice = 0;
uint8_t *service_request = NULL; uint8_t *service_request = NULL;
@@ -334,40 +311,31 @@ void apdu_handler(
int error_class = 0; int error_class = 0;
uint8_t reason = 0; uint8_t reason = 0;
(void)data_expecting_reply; (void) data_expecting_reply;
if (apdu) if (apdu) {
{
// PDU Type // PDU Type
switch (apdu[0] & 0xF0) switch (apdu[0] & 0xF0) {
{
case PDU_TYPE_CONFIRMED_SERVICE_REQUEST: case PDU_TYPE_CONFIRMED_SERVICE_REQUEST:
len = apdu_decode_confirmed_service_request( len = apdu_decode_confirmed_service_request(&apdu[0], // APDU data
&apdu[0], // APDU data
apdu_len, apdu_len,
&service_data, &service_data,
&service_choice, &service_choice, &service_request, &service_request_len);
&service_request,
&service_request_len);
/* When network communications are completely disabled, /* When network communications are completely disabled,
only DeviceCommunicationControl and ReinitializeDevice APDUs only DeviceCommunicationControl and ReinitializeDevice APDUs
shall be processed and no messages shall be initiated.*/ shall be processed and no messages shall be initiated. */
if (dcc_communication_disabled() && if (dcc_communication_disabled() &&
((service_choice != SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL) && ((service_choice !=
(service_choice != SERVICE_CONFIRMED_REINITIALIZE_DEVICE))) SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL)
&& (service_choice !=
SERVICE_CONFIRMED_REINITIALIZE_DEVICE)))
break; break;
if ((service_choice < MAX_BACNET_CONFIRMED_SERVICE) && if ((service_choice < MAX_BACNET_CONFIRMED_SERVICE) &&
(Confirmed_Function[service_choice])) (Confirmed_Function[service_choice]))
Confirmed_Function[service_choice]( Confirmed_Function[service_choice] (service_request,
service_request, service_request_len, src, &service_data);
service_request_len,
src,
&service_data);
else if (Unrecognized_Service_Handler) else if (Unrecognized_Service_Handler)
Unrecognized_Service_Handler( Unrecognized_Service_Handler(service_request,
service_request, service_request_len, src, &service_data);
service_request_len,
src,
&service_data);
break; break;
case PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST: case PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST:
if (dcc_communication_disabled()) if (dcc_communication_disabled())
@@ -375,20 +343,16 @@ void apdu_handler(
service_choice = apdu[1]; service_choice = apdu[1];
service_request = &apdu[2]; service_request = &apdu[2];
service_request_len = apdu_len - 2; service_request_len = apdu_len - 2;
if (service_choice < MAX_BACNET_UNCONFIRMED_SERVICE) if (service_choice < MAX_BACNET_UNCONFIRMED_SERVICE) {
{
if (Unconfirmed_Function[service_choice]) if (Unconfirmed_Function[service_choice])
Unconfirmed_Function[service_choice]( Unconfirmed_Function[service_choice] (service_request,
service_request, service_request_len, src);
service_request_len,
src);
} }
break; break;
case PDU_TYPE_SIMPLE_ACK: case PDU_TYPE_SIMPLE_ACK:
invoke_id = apdu[1]; invoke_id = apdu[1];
service_choice = apdu[2]; service_choice = apdu[2];
switch (service_choice) switch (service_choice) {
{
case SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM: case SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM:
case SERVICE_CONFIRMED_COV_NOTIFICATION: case SERVICE_CONFIRMED_COV_NOTIFICATION:
case SERVICE_CONFIRMED_EVENT_NOTIFICATION: case SERVICE_CONFIRMED_EVENT_NOTIFICATION:
@@ -409,11 +373,9 @@ void apdu_handler(
case SERVICE_CONFIRMED_VT_CLOSE: case SERVICE_CONFIRMED_VT_CLOSE:
// Security Services // Security Services
case SERVICE_CONFIRMED_REQUEST_KEY: case SERVICE_CONFIRMED_REQUEST_KEY:
if (Confirmed_ACK_Function[service_choice]) if (Confirmed_ACK_Function[service_choice]) {
{
((confirmed_simple_ack_function) ((confirmed_simple_ack_function)
Confirmed_ACK_Function[service_choice])( Confirmed_ACK_Function[service_choice]) (src,
src,
invoke_id); invoke_id);
} }
tsm_free_invoke_id(invoke_id); tsm_free_invoke_id(invoke_id);
@@ -423,20 +385,20 @@ void apdu_handler(
} }
break; break;
case PDU_TYPE_COMPLEX_ACK: case PDU_TYPE_COMPLEX_ACK:
service_ack_data.segmented_message = (apdu[0] & BIT3) ? true : false; service_ack_data.segmented_message =
service_ack_data.more_follows = (apdu[0] & BIT2) ? true : false; (apdu[0] & BIT3) ? true : false;
service_ack_data.more_follows =
(apdu[0] & BIT2) ? true : false;
invoke_id = service_ack_data.invoke_id = apdu[1]; invoke_id = service_ack_data.invoke_id = apdu[1];
len = 2; len = 2;
if (service_ack_data.segmented_message) if (service_ack_data.segmented_message) {
{
service_ack_data.sequence_number = apdu[len++]; service_ack_data.sequence_number = apdu[len++];
service_ack_data.proposed_window_number = apdu[len++]; service_ack_data.proposed_window_number = apdu[len++];
} }
service_choice = apdu[len++]; service_choice = apdu[len++];
service_request = &apdu[len]; service_request = &apdu[len];
service_request_len = apdu_len - len; service_request_len = apdu_len - len;
switch (service_choice) switch (service_choice) {
{
case SERVICE_CONFIRMED_GET_ALARM_SUMMARY: case SERVICE_CONFIRMED_GET_ALARM_SUMMARY:
case SERVICE_CONFIRMED_GET_ENROLLMENT_SUMMARY: case SERVICE_CONFIRMED_GET_ENROLLMENT_SUMMARY:
case SERVICE_CONFIRMED_GET_EVENT_INFORMATION: case SERVICE_CONFIRMED_GET_EVENT_INFORMATION:
@@ -455,13 +417,10 @@ void apdu_handler(
case SERVICE_CONFIRMED_VT_DATA: case SERVICE_CONFIRMED_VT_DATA:
// Security Services // Security Services
case SERVICE_CONFIRMED_AUTHENTICATE: case SERVICE_CONFIRMED_AUTHENTICATE:
if (Confirmed_ACK_Function[service_choice]) if (Confirmed_ACK_Function[service_choice]) {
{
((confirmed_ack_function) ((confirmed_ack_function)
Confirmed_ACK_Function[service_choice])( Confirmed_ACK_Function[service_choice])
service_request, (service_request, service_request_len, src,
service_request_len,
src,
&service_ack_data); &service_ack_data);
} }
tsm_free_invoke_id(invoke_id); tsm_free_invoke_id(invoke_id);
@@ -479,20 +438,20 @@ void apdu_handler(
invoke_id = apdu[1]; invoke_id = apdu[1];
service_choice = apdu[2]; service_choice = apdu[2];
len = 3; len = 3;
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
/* FIXME: we could validate that the tag is enumerated... */ /* FIXME: we could validate that the tag is enumerated... */
len += decode_enumerated(&apdu[len],len_value, &error_class); len += decode_enumerated(&apdu[len], len_value, &error_class);
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
/* FIXME: we could validate that the tag is enumerated... */ /* FIXME: we could validate that the tag is enumerated... */
len += decode_enumerated(&apdu[len],len_value, &error_code); len += decode_enumerated(&apdu[len], len_value, &error_code);
if (service_choice < MAX_BACNET_CONFIRMED_SERVICE) if (service_choice < MAX_BACNET_CONFIRMED_SERVICE) {
{
if (Error_Function[service_choice]) if (Error_Function[service_choice])
Error_Function[service_choice]( Error_Function[service_choice] (src,
src, invoke_id, error_class, error_code);
invoke_id,
error_class,
error_code);
} }
tsm_free_invoke_id(invoke_id); tsm_free_invoke_id(invoke_id);
break; break;
@@ -500,20 +459,14 @@ void apdu_handler(
invoke_id = apdu[1]; invoke_id = apdu[1];
reason = apdu[2]; reason = apdu[2];
if (Reject_Function) if (Reject_Function)
Reject_Function( Reject_Function(src, invoke_id, reason);
src,
invoke_id,
reason);
tsm_free_invoke_id(invoke_id); tsm_free_invoke_id(invoke_id);
break; break;
case PDU_TYPE_ABORT: case PDU_TYPE_ABORT:
invoke_id = apdu[1]; invoke_id = apdu[1];
reason = apdu[2]; reason = apdu[2];
if (Abort_Function) if (Abort_Function)
Abort_Function( Abort_Function(src, invoke_id, reason);
src,
invoke_id,
reason);
tsm_free_invoke_id(invoke_id); tsm_free_invoke_id(invoke_id);
break; break;
default: default:
@@ -522,4 +475,3 @@ void apdu_handler(
} }
return; return;
} }
+43 -68
View File
@@ -43,8 +43,7 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
typedef struct _confirmed_service_data typedef struct _confirmed_service_data {
{
bool segmented_message; bool segmented_message;
bool more_follows; bool more_follows;
bool segmented_response_accepted; bool segmented_response_accepted;
@@ -53,16 +52,15 @@ typedef struct _confirmed_service_data
uint8_t invoke_id; uint8_t invoke_id;
uint8_t sequence_number; uint8_t sequence_number;
uint8_t proposed_window_number; uint8_t proposed_window_number;
} BACNET_CONFIRMED_SERVICE_DATA; } BACNET_CONFIRMED_SERVICE_DATA;
typedef struct _confirmed_service_ack_data typedef struct _confirmed_service_ack_data {
{
bool segmented_message; bool segmented_message;
bool more_follows; bool more_follows;
uint8_t invoke_id; uint8_t invoke_id;
uint8_t sequence_number; uint8_t sequence_number;
uint8_t proposed_window_number; uint8_t proposed_window_number;
} BACNET_CONFIRMED_SERVICE_ACK_DATA; } BACNET_CONFIRMED_SERVICE_ACK_DATA;
// generic unconfirmed function handler // generic unconfirmed function handler
// Suitable to handle the following services: // Suitable to handle the following services:
@@ -70,10 +68,8 @@ typedef struct _confirmed_service_ack_data
// Unconfirmed_Event_Notification, Unconfirmed_Private_Transfer, // Unconfirmed_Event_Notification, Unconfirmed_Private_Transfer,
// Unconfirmed_Text_Message, Time_Synchronization, Who_Has, // Unconfirmed_Text_Message, Time_Synchronization, Who_Has,
// UTC_Time_Synchronization // UTC_Time_Synchronization
typedef void (*unconfirmed_function)( typedef void (*unconfirmed_function) (uint8_t * service_request,
uint8_t *service_request, uint16_t len, BACNET_ADDRESS * src);
uint16_t len,
BACNET_ADDRESS *src);
// generic confirmed function handler // generic confirmed function handler
// Suitable to handle the following services: // Suitable to handle the following services:
@@ -91,100 +87,79 @@ typedef void (*unconfirmed_function)(
// Confirmed_Text_Message, Reinitialize_Device, // Confirmed_Text_Message, Reinitialize_Device,
// VT_Open, VT_Close, VT_Data_Handler, // VT_Open, VT_Close, VT_Data_Handler,
// Authenticate, Request_Key // Authenticate, Request_Key
typedef void (*confirmed_function)( typedef void (*confirmed_function) (uint8_t * service_request,
uint8_t *service_request,
uint16_t service_len, uint16_t service_len,
BACNET_ADDRESS *src, BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA *service_data); BACNET_CONFIRMED_SERVICE_DATA * service_data);
// generic confirmed simple ack function handler // generic confirmed simple ack function handler
typedef void (*confirmed_simple_ack_function)( typedef void (*confirmed_simple_ack_function) (BACNET_ADDRESS * src,
BACNET_ADDRESS *src,
uint8_t invoke_id); uint8_t invoke_id);
// generic confirmed ack function handler // generic confirmed ack function handler
typedef void (*confirmed_ack_function)( typedef void (*confirmed_ack_function) (uint8_t * service_request,
uint8_t *service_request,
uint16_t service_len, uint16_t service_len,
BACNET_ADDRESS *src, BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_ACK_DATA *service_data); BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data);
// generic error reply function // generic error reply function
typedef void (*error_function)( typedef void (*error_function) (BACNET_ADDRESS * src,
BACNET_ADDRESS *src,
uint8_t invoke_id, uint8_t invoke_id,
BACNET_ERROR_CLASS error_class, BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code);
BACNET_ERROR_CODE error_code);
// generic abort reply function // generic abort reply function
typedef void (*abort_function)( typedef void (*abort_function) (BACNET_ADDRESS * src,
BACNET_ADDRESS *src, uint8_t invoke_id, uint8_t abort_reason);
uint8_t invoke_id,
uint8_t abort_reason);
// generic reject reply function // generic reject reply function
typedef void (*reject_function)( typedef void (*reject_function) (BACNET_ADDRESS * src,
BACNET_ADDRESS *src, uint8_t invoke_id, uint8_t reject_reason);
uint8_t invoke_id,
uint8_t reject_reason);
void apdu_set_confirmed_ack_handler( void apdu_set_confirmed_ack_handler(BACNET_CONFIRMED_SERVICE
BACNET_CONFIRMED_SERVICE service_choice, service_choice, confirmed_ack_function pFunction);
confirmed_ack_function pFunction);
void apdu_set_confirmed_simple_ack_handler( void apdu_set_confirmed_simple_ack_handler(BACNET_CONFIRMED_SERVICE
BACNET_CONFIRMED_SERVICE service_choice, service_choice, confirmed_simple_ack_function pFunction);
confirmed_simple_ack_function pFunction);
// configure reject for confirmed services that are not supported // configure reject for confirmed services that are not supported
void apdu_set_unrecognized_service_handler_handler( void apdu_set_unrecognized_service_handler_handler(confirmed_function
confirmed_function pFunction); pFunction);
void apdu_set_confirmed_handler( void apdu_set_confirmed_handler(BACNET_CONFIRMED_SERVICE
BACNET_CONFIRMED_SERVICE service_choice, service_choice, confirmed_function pFunction);
confirmed_function pFunction);
/* returns true if the handler is set */ /* returns true if the handler is set */
bool apdu_confirmed_handler( bool apdu_confirmed_handler(BACNET_CONFIRMED_SERVICE service_choice);
BACNET_CONFIRMED_SERVICE service_choice);
void apdu_set_unconfirmed_handler( void apdu_set_unconfirmed_handler(BACNET_UNCONFIRMED_SERVICE
BACNET_UNCONFIRMED_SERVICE service_choice, service_choice, unconfirmed_function pFunction);
unconfirmed_function pFunction);
/* returns true if the handler is set */ /* returns true if the handler is set */
bool apdu_unconfirmed_handler( bool apdu_unconfirmed_handler(BACNET_UNCONFIRMED_SERVICE
BACNET_UNCONFIRMED_SERVICE service_choice); service_choice);
/* returns true if the service is supported by a handler */ /* returns true if the service is supported by a handler */
bool apdu_service_supported(BACNET_SERVICES_SUPPORTED service_supported); bool apdu_service_supported(BACNET_SERVICES_SUPPORTED
service_supported);
void apdu_set_error_handler( void apdu_set_error_handler(BACNET_CONFIRMED_SERVICE service_choice,
BACNET_CONFIRMED_SERVICE service_choice,
error_function pFunction); error_function pFunction);
void apdu_set_abort_handler( void apdu_set_abort_handler(abort_function pFunction);
abort_function pFunction);
void apdu_set_reject_handler( void apdu_set_reject_handler(reject_function pFunction);
reject_function pFunction);
uint16_t apdu_decode_confirmed_service_request( uint16_t apdu_decode_confirmed_service_request(uint8_t * apdu, // APDU data
uint8_t *apdu, // APDU data
uint16_t apdu_len, uint16_t apdu_len,
BACNET_CONFIRMED_SERVICE_DATA *service_data, BACNET_CONFIRMED_SERVICE_DATA * service_data,
uint8_t *service_choice, uint8_t * service_choice,
uint8_t **service_request, uint8_t ** service_request, uint16_t * service_request_len);
uint16_t *service_request_len);
void apdu_handler( void apdu_handler(BACNET_ADDRESS * src, // source address
BACNET_ADDRESS *src, // source address bool data_expecting_reply, uint8_t * apdu, // APDU data
bool data_expecting_reply,
uint8_t *apdu, // APDU data
uint16_t pdu_len); // for confirmed messages uint16_t pdu_len); // for confirmed messages
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+12 -17
View File
@@ -47,39 +47,34 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
bool arcnet_valid(void); bool arcnet_valid(void);
void arcnet_cleanup(void); void arcnet_cleanup(void);
bool arcnet_init(char *interface_name); bool arcnet_init(char *interface_name);
/* function to send a packet out the 802.2 socket */ /* function to send a packet out the 802.2 socket */
/* returns 0 on success, non-zero on failure */ /* returns 0 on success, non-zero on failure */
int arcnet_send( int arcnet_send(BACNET_ADDRESS * dest, // destination address
BACNET_ADDRESS *dest, // destination address BACNET_ADDRESS * src, // source address
BACNET_ADDRESS *src, // source address uint8_t * pdu, // any data to be sent - may be null
uint8_t *pdu, // any data to be sent - may be null
unsigned pdu_len); // number of bytes of data unsigned pdu_len); // number of bytes of data
/* function to send a packet out the 802.2 socket */ /* function to send a packet out the 802.2 socket */
/* returns zero on success, non-zero on failure */ /* returns zero on success, non-zero on failure */
int arcnet_send_pdu( int arcnet_send_pdu(BACNET_ADDRESS * dest, // destination address
BACNET_ADDRESS *dest, // destination address uint8_t * pdu, // any data to be sent - may be null
uint8_t *pdu, // any data to be sent - may be null
unsigned pdu_len); // number of bytes of data unsigned pdu_len); // number of bytes of data
// receives an framed packet // receives an framed packet
// returns the number of octets in the PDU, or zero on failure // returns the number of octets in the PDU, or zero on failure
uint16_t arcnet_receive( uint16_t arcnet_receive(BACNET_ADDRESS * src, // source address
BACNET_ADDRESS *src, // source address uint8_t * pdu, // PDU data
uint8_t *pdu, // PDU data
uint16_t max_pdu, // amount of space available in the PDU uint16_t max_pdu, // amount of space available in the PDU
unsigned timeout); // milliseconds to wait for a packet unsigned timeout); // milliseconds to wait for a packet
void arcnet_get_my_address(BACNET_ADDRESS *my_address); void arcnet_get_my_address(BACNET_ADDRESS * my_address);
void arcnet_get_broadcast_address( void arcnet_get_broadcast_address(BACNET_ADDRESS * dest); // destination address
BACNET_ADDRESS *dest); // destination address
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+69 -126
View File
@@ -41,24 +41,21 @@
// Atomic Read File // Atomic Read File
// encode service // encode service
int arf_encode_apdu( int arf_encode_apdu(uint8_t * apdu,
uint8_t *apdu, uint8_t invoke_id, BACNET_ATOMIC_READ_FILE_DATA * data)
uint8_t invoke_id,
BACNET_ATOMIC_READ_FILE_DATA *data)
{ {
int apdu_len = 0; // total length of the apdu, return value int apdu_len = 0; // total length of the apdu, return value
if (apdu) if (apdu) {
{
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST; apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
apdu[1] = encode_max_segs_max_apdu(0, Device_Max_APDU_Length_Accepted()); apdu[1] =
encode_max_segs_max_apdu(0, Device_Max_APDU_Length_Accepted());
apdu[2] = invoke_id; apdu[2] = invoke_id;
apdu[3] = SERVICE_CONFIRMED_ATOMIC_READ_FILE; // service choice apdu[3] = SERVICE_CONFIRMED_ATOMIC_READ_FILE; // service choice
apdu_len = 4; apdu_len = 4;
apdu_len += encode_tagged_object_id(&apdu[apdu_len], apdu_len += encode_tagged_object_id(&apdu[apdu_len],
data->object_type, data->object_instance); data->object_type, data->object_instance);
switch (data->access) switch (data->access) {
{
case FILE_STREAM_ACCESS: case FILE_STREAM_ACCESS:
apdu_len += encode_opening_tag(&apdu[apdu_len], 0); apdu_len += encode_opening_tag(&apdu[apdu_len], 0);
apdu_len += encode_tagged_signed(&apdu[apdu_len], apdu_len += encode_tagged_signed(&apdu[apdu_len],
@@ -84,10 +81,8 @@ int arf_encode_apdu(
} }
// decode the service request only // decode the service request only
int arf_decode_service_request( int arf_decode_service_request(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, BACNET_ATOMIC_READ_FILE_DATA * data)
unsigned apdu_len,
BACNET_ATOMIC_READ_FILE_DATA *data)
{ {
int len = 0; int len = 0;
int tag_len = 0; int tag_len = 0;
@@ -96,15 +91,15 @@ int arf_decode_service_request(
int type = 0; // for decoding int type = 0; // for decoding
// check for value pointers // check for value pointers
if (apdu_len && data) if (apdu_len && data) {
{ len =
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value_type); decode_tag_number_and_value(&apdu[0], &tag_number,
&len_value_type);
if (tag_number != BACNET_APPLICATION_TAG_OBJECT_ID) if (tag_number != BACNET_APPLICATION_TAG_OBJECT_ID)
return -1; return -1;
len += decode_object_id(&apdu[len], &type, &data->object_instance); len += decode_object_id(&apdu[len], &type, &data->object_instance);
data->object_type = type; data->object_type = type;
if (decode_is_opening_tag_number(&apdu[len], 0)) if (decode_is_opening_tag_number(&apdu[len], 0)) {
{
data->access = FILE_STREAM_ACCESS; data->access = FILE_STREAM_ACCESS;
// a tag number is not extended so only one octet // a tag number is not extended so only one octet
len++; len++;
@@ -115,8 +110,7 @@ int arf_decode_service_request(
if (tag_number != BACNET_APPLICATION_TAG_SIGNED_INT) if (tag_number != BACNET_APPLICATION_TAG_SIGNED_INT)
return -1; return -1;
len += decode_signed(&apdu[len], len += decode_signed(&apdu[len],
len_value_type, len_value_type, &data->type.stream.fileStartPosition);
&data->type.stream.fileStartPosition);
// requestedOctetCount // requestedOctetCount
tag_len = decode_tag_number_and_value(&apdu[len], tag_len = decode_tag_number_and_value(&apdu[len],
&tag_number, &len_value_type); &tag_number, &len_value_type);
@@ -124,15 +118,12 @@ int arf_decode_service_request(
if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT) if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT)
return -1; return -1;
len += decode_unsigned(&apdu[len], len += decode_unsigned(&apdu[len],
len_value_type, len_value_type, &data->type.stream.requestedOctetCount);
&data->type.stream.requestedOctetCount);
if (!decode_is_closing_tag_number(&apdu[len], 0)) if (!decode_is_closing_tag_number(&apdu[len], 0))
return -1; return -1;
// a tag number is not extended so only one octet // a tag number is not extended so only one octet
len++; len++;
} } else if (decode_is_opening_tag_number(&apdu[len], 1)) {
else if (decode_is_opening_tag_number(&apdu[len], 1))
{
data->access = FILE_RECORD_ACCESS; data->access = FILE_RECORD_ACCESS;
// a tag number is not extended so only one octet // a tag number is not extended so only one octet
len++; len++;
@@ -143,8 +134,7 @@ int arf_decode_service_request(
if (tag_number != BACNET_APPLICATION_TAG_SIGNED_INT) if (tag_number != BACNET_APPLICATION_TAG_SIGNED_INT)
return -1; return -1;
len += decode_signed(&apdu[len], len += decode_signed(&apdu[len],
len_value_type, len_value_type, &data->type.record.fileStartRecord);
&data->type.record.fileStartRecord);
// RecordCount // RecordCount
tag_len = decode_tag_number_and_value(&apdu[len], tag_len = decode_tag_number_and_value(&apdu[len],
&tag_number, &len_value_type); &tag_number, &len_value_type);
@@ -152,25 +142,21 @@ int arf_decode_service_request(
if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT) if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT)
return -1; return -1;
len += decode_unsigned(&apdu[len], len += decode_unsigned(&apdu[len],
len_value_type, len_value_type, &data->type.record.RecordCount);
&data->type.record.RecordCount);
if (!decode_is_closing_tag_number(&apdu[len], 1)) if (!decode_is_closing_tag_number(&apdu[len], 1))
return -1; return -1;
// a tag number is not extended so only one octet // a tag number is not extended so only one octet
len++; len++;
} } else
else
return -1; return -1;
} }
return len; return len;
} }
int arf_decode_apdu( int arf_decode_apdu(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
uint8_t *invoke_id, uint8_t * invoke_id, BACNET_ATOMIC_READ_FILE_DATA * data)
BACNET_ATOMIC_READ_FILE_DATA *data)
{ {
int len = 0; int len = 0;
unsigned offset = 0; unsigned offset = 0;
@@ -186,35 +172,29 @@ int arf_decode_apdu(
return -1; return -1;
offset = 4; offset = 4;
if (apdu_len > offset) if (apdu_len > offset) {
{ len = arf_decode_service_request(&apdu[offset],
len = arf_decode_service_request( apdu_len - offset, data);
&apdu[offset],
apdu_len - offset,
data);
} }
return len; return len;
} }
// encode service // encode service
int arf_ack_encode_apdu( int arf_ack_encode_apdu(uint8_t * apdu,
uint8_t *apdu, uint8_t invoke_id, BACNET_ATOMIC_READ_FILE_DATA * data)
uint8_t invoke_id,
BACNET_ATOMIC_READ_FILE_DATA *data)
{ {
int apdu_len = 0; // total length of the apdu, return value int apdu_len = 0; // total length of the apdu, return value
if (apdu) if (apdu) {
{
apdu[0] = PDU_TYPE_COMPLEX_ACK; apdu[0] = PDU_TYPE_COMPLEX_ACK;
apdu[1] = invoke_id; apdu[1] = invoke_id;
apdu[2] = SERVICE_CONFIRMED_ATOMIC_READ_FILE; // service choice apdu[2] = SERVICE_CONFIRMED_ATOMIC_READ_FILE; // service choice
apdu_len = 3; apdu_len = 3;
// endOfFile // endOfFile
apdu_len += encode_tagged_boolean(&apdu[apdu_len], data->endOfFile); apdu_len +=
switch (data->access) encode_tagged_boolean(&apdu[apdu_len], data->endOfFile);
{ switch (data->access) {
case FILE_STREAM_ACCESS: case FILE_STREAM_ACCESS:
apdu_len += encode_opening_tag(&apdu[apdu_len], 0); apdu_len += encode_opening_tag(&apdu[apdu_len], 0);
apdu_len += encode_tagged_signed(&apdu[apdu_len], apdu_len += encode_tagged_signed(&apdu[apdu_len],
@@ -242,10 +222,8 @@ int arf_ack_encode_apdu(
} }
// decode the service request only // decode the service request only
int arf_ack_decode_service_request( int arf_ack_decode_service_request(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, BACNET_ATOMIC_READ_FILE_DATA * data)
unsigned apdu_len,
BACNET_ATOMIC_READ_FILE_DATA *data)
{ {
int len = 0; int len = 0;
int tag_len = 0; int tag_len = 0;
@@ -253,14 +231,14 @@ int arf_ack_decode_service_request(
uint32_t len_value_type = 0; uint32_t len_value_type = 0;
// check for value pointers // check for value pointers
if (apdu_len && data) if (apdu_len && data) {
{ len =
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value_type); decode_tag_number_and_value(&apdu[0], &tag_number,
&len_value_type);
if (tag_number != BACNET_APPLICATION_TAG_BOOLEAN) if (tag_number != BACNET_APPLICATION_TAG_BOOLEAN)
return -1; return -1;
data->endOfFile = decode_boolean(len_value_type); data->endOfFile = decode_boolean(len_value_type);
if (decode_is_opening_tag_number(&apdu[len], 0)) if (decode_is_opening_tag_number(&apdu[len], 0)) {
{
data->access = FILE_STREAM_ACCESS; data->access = FILE_STREAM_ACCESS;
// a tag number is not extended so only one octet // a tag number is not extended so only one octet
len++; len++;
@@ -271,8 +249,7 @@ int arf_ack_decode_service_request(
if (tag_number != BACNET_APPLICATION_TAG_SIGNED_INT) if (tag_number != BACNET_APPLICATION_TAG_SIGNED_INT)
return -1; return -1;
len += decode_signed(&apdu[len], len += decode_signed(&apdu[len],
len_value_type, len_value_type, &data->type.stream.fileStartPosition);
&data->type.stream.fileStartPosition);
// fileData // fileData
tag_len = decode_tag_number_and_value(&apdu[len], tag_len = decode_tag_number_and_value(&apdu[len],
&tag_number, &len_value_type); &tag_number, &len_value_type);
@@ -280,15 +257,12 @@ int arf_ack_decode_service_request(
if (tag_number != BACNET_APPLICATION_TAG_OCTET_STRING) if (tag_number != BACNET_APPLICATION_TAG_OCTET_STRING)
return -1; return -1;
len += decode_octet_string(&apdu[len], len += decode_octet_string(&apdu[len],
len_value_type, len_value_type, &data->fileData);
&data->fileData);
if (!decode_is_closing_tag_number(&apdu[len], 0)) if (!decode_is_closing_tag_number(&apdu[len], 0))
return -1; return -1;
// a tag number is not extended so only one octet // a tag number is not extended so only one octet
len++; len++;
} } else if (decode_is_opening_tag_number(&apdu[len], 1)) {
else if (decode_is_opening_tag_number(&apdu[len], 1))
{
data->access = FILE_RECORD_ACCESS; data->access = FILE_RECORD_ACCESS;
// a tag number is not extended so only one octet // a tag number is not extended so only one octet
len++; len++;
@@ -299,8 +273,7 @@ int arf_ack_decode_service_request(
if (tag_number != BACNET_APPLICATION_TAG_SIGNED_INT) if (tag_number != BACNET_APPLICATION_TAG_SIGNED_INT)
return -1; return -1;
len += decode_signed(&apdu[len], len += decode_signed(&apdu[len],
len_value_type, len_value_type, &data->type.record.fileStartRecord);
&data->type.record.fileStartRecord);
// returnedRecordCount // returnedRecordCount
tag_len = decode_tag_number_and_value(&apdu[len], tag_len = decode_tag_number_and_value(&apdu[len],
&tag_number, &len_value_type); &tag_number, &len_value_type);
@@ -308,8 +281,7 @@ int arf_ack_decode_service_request(
if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT) if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT)
return -1; return -1;
len += decode_unsigned(&apdu[len], len += decode_unsigned(&apdu[len],
len_value_type, len_value_type, &data->type.record.RecordCount);
&data->type.record.RecordCount);
// fileData // fileData
tag_len = decode_tag_number_and_value(&apdu[len], tag_len = decode_tag_number_and_value(&apdu[len],
&tag_number, &len_value_type); &tag_number, &len_value_type);
@@ -317,25 +289,21 @@ int arf_ack_decode_service_request(
if (tag_number != BACNET_APPLICATION_TAG_OCTET_STRING) if (tag_number != BACNET_APPLICATION_TAG_OCTET_STRING)
return -1; return -1;
len += decode_octet_string(&apdu[len], len += decode_octet_string(&apdu[len],
len_value_type, len_value_type, &data->fileData);
&data->fileData);
if (!decode_is_closing_tag_number(&apdu[len], 1)) if (!decode_is_closing_tag_number(&apdu[len], 1))
return -1; return -1;
// a tag number is not extended so only one octet // a tag number is not extended so only one octet
len++; len++;
} } else
else
return -1; return -1;
} }
return len; return len;
} }
int arf_ack_decode_apdu( int arf_ack_decode_apdu(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
uint8_t *invoke_id, uint8_t * invoke_id, BACNET_ATOMIC_READ_FILE_DATA * data)
BACNET_ATOMIC_READ_FILE_DATA *data)
{ {
int len = 0; int len = 0;
unsigned offset = 0; unsigned offset = 0;
@@ -350,12 +318,9 @@ int arf_ack_decode_apdu(
return -1; return -1;
offset = 3; offset = 3;
if (apdu_len > offset) if (apdu_len > offset) {
{ len = arf_ack_decode_service_request(&apdu[offset],
len = arf_ack_decode_service_request( apdu_len - offset, data);
&apdu[offset],
apdu_len - offset,
data);
} }
return len; return len;
@@ -368,37 +333,28 @@ int arf_ack_decode_apdu(
#include "ctest.h" #include "ctest.h"
void testAtomicReadFileAckAccess(Test * pTest, void testAtomicReadFileAckAccess(Test * pTest,
BACNET_ATOMIC_READ_FILE_DATA *data) BACNET_ATOMIC_READ_FILE_DATA * data)
{ {
BACNET_ATOMIC_READ_FILE_DATA test_data = {0}; BACNET_ATOMIC_READ_FILE_DATA test_data = { 0 };
uint8_t apdu[480] = {0}; uint8_t apdu[480] = { 0 };
int len = 0; int len = 0;
int apdu_len = 0; int apdu_len = 0;
uint8_t invoke_id = 128; uint8_t invoke_id = 128;
uint8_t test_invoke_id = 0; uint8_t test_invoke_id = 0;
len = arf_ack_encode_apdu( len = arf_ack_encode_apdu(&apdu[0], invoke_id, data);
&apdu[0],
invoke_id,
data);
ct_test(pTest, len != 0); ct_test(pTest, len != 0);
apdu_len = len; apdu_len = len;
len = arf_ack_decode_apdu( len = arf_ack_decode_apdu(&apdu[0],
&apdu[0], apdu_len, &test_invoke_id, &test_data);
apdu_len,
&test_invoke_id,
&test_data);
ct_test(pTest, len != -1); ct_test(pTest, len != -1);
ct_test(pTest, test_data.endOfFile == data->endOfFile); ct_test(pTest, test_data.endOfFile == data->endOfFile);
ct_test(pTest, test_data.access == data->access); ct_test(pTest, test_data.access == data->access);
if (test_data.access == FILE_STREAM_ACCESS) if (test_data.access == FILE_STREAM_ACCESS) {
{
ct_test(pTest, test_data.type.stream.fileStartPosition == ct_test(pTest, test_data.type.stream.fileStartPosition ==
data->type.stream.fileStartPosition); data->type.stream.fileStartPosition);
} } else if (test_data.access == FILE_RECORD_ACCESS) {
else if (test_data.access == FILE_RECORD_ACCESS)
{
ct_test(pTest, test_data.type.record.fileStartRecord == ct_test(pTest, test_data.type.record.fileStartRecord ==
data->type.record.fileStartRecord); data->type.record.fileStartRecord);
ct_test(pTest, test_data.type.record.RecordCount == ct_test(pTest, test_data.type.record.RecordCount ==
@@ -406,15 +362,14 @@ void testAtomicReadFileAckAccess(Test * pTest,
} }
ct_test(pTest, octetstring_length(&test_data.fileData) == ct_test(pTest, octetstring_length(&test_data.fileData) ==
octetstring_length(&data->fileData)); octetstring_length(&data->fileData));
ct_test(pTest, memcmp( ct_test(pTest, memcmp(octetstring_value(&test_data.fileData),
octetstring_value(&test_data.fileData),
octetstring_value(&data->fileData), octetstring_value(&data->fileData),
octetstring_length(&test_data.fileData)) == 0); octetstring_length(&test_data.fileData)) == 0);
} }
void testAtomicReadFileAck(Test * pTest) void testAtomicReadFileAck(Test * pTest)
{ {
BACNET_ATOMIC_READ_FILE_DATA data = {0}; BACNET_ATOMIC_READ_FILE_DATA data = { 0 };
uint8_t test_octet_string[32] = "Joshua-Mary-Anna-Christopher"; uint8_t test_octet_string[32] = "Joshua-Mary-Anna-Christopher";
@@ -422,8 +377,7 @@ void testAtomicReadFileAck(Test * pTest)
data.access = FILE_STREAM_ACCESS; data.access = FILE_STREAM_ACCESS;
data.type.stream.fileStartPosition = 0; data.type.stream.fileStartPosition = 0;
octetstring_init(&data.fileData, octetstring_init(&data.fileData,
test_octet_string, test_octet_string, sizeof(test_octet_string));
sizeof(test_octet_string));
testAtomicReadFileAckAccess(pTest, &data); testAtomicReadFileAckAccess(pTest, &data);
data.endOfFile = false; data.endOfFile = false;
@@ -431,48 +385,37 @@ void testAtomicReadFileAck(Test * pTest)
data.type.record.fileStartRecord = 1; data.type.record.fileStartRecord = 1;
data.type.record.RecordCount = 2; data.type.record.RecordCount = 2;
octetstring_init(&data.fileData, octetstring_init(&data.fileData,
test_octet_string, test_octet_string, sizeof(test_octet_string));
sizeof(test_octet_string));
testAtomicReadFileAckAccess(pTest, &data); testAtomicReadFileAckAccess(pTest, &data);
return; return;
} }
void testAtomicReadFileAccess(Test * pTest, void testAtomicReadFileAccess(Test * pTest,
BACNET_ATOMIC_READ_FILE_DATA *data) BACNET_ATOMIC_READ_FILE_DATA * data)
{ {
BACNET_ATOMIC_READ_FILE_DATA test_data = {0}; BACNET_ATOMIC_READ_FILE_DATA test_data = { 0 };
uint8_t apdu[480] = {0}; uint8_t apdu[480] = { 0 };
int len = 0; int len = 0;
int apdu_len = 0; int apdu_len = 0;
uint8_t invoke_id = 128; uint8_t invoke_id = 128;
uint8_t test_invoke_id = 0; uint8_t test_invoke_id = 0;
len = arf_encode_apdu( len = arf_encode_apdu(&apdu[0], invoke_id, data);
&apdu[0],
invoke_id,
data);
ct_test(pTest, len != 0); ct_test(pTest, len != 0);
apdu_len = len; apdu_len = len;
len = arf_decode_apdu( len = arf_decode_apdu(&apdu[0], apdu_len, &test_invoke_id, &test_data);
&apdu[0],
apdu_len,
&test_invoke_id,
&test_data);
ct_test(pTest, len != -1); ct_test(pTest, len != -1);
ct_test(pTest, test_data.object_type == data->object_type); ct_test(pTest, test_data.object_type == data->object_type);
ct_test(pTest, test_data.object_instance == data->object_instance); ct_test(pTest, test_data.object_instance == data->object_instance);
ct_test(pTest, test_data.access == data->access); ct_test(pTest, test_data.access == data->access);
if (test_data.access == FILE_STREAM_ACCESS) if (test_data.access == FILE_STREAM_ACCESS) {
{
ct_test(pTest, test_data.type.stream.fileStartPosition == ct_test(pTest, test_data.type.stream.fileStartPosition ==
data->type.stream.fileStartPosition); data->type.stream.fileStartPosition);
ct_test(pTest, test_data.type.stream.requestedOctetCount == ct_test(pTest, test_data.type.stream.requestedOctetCount ==
data->type.stream.requestedOctetCount); data->type.stream.requestedOctetCount);
} } else if (test_data.access == FILE_RECORD_ACCESS) {
else if (test_data.access == FILE_RECORD_ACCESS)
{
ct_test(pTest, test_data.type.record.fileStartRecord == ct_test(pTest, test_data.type.record.fileStartRecord ==
data->type.record.fileStartRecord); data->type.record.fileStartRecord);
ct_test(pTest, test_data.type.record.RecordCount == ct_test(pTest, test_data.type.record.RecordCount ==
@@ -482,7 +425,7 @@ void testAtomicReadFileAccess(Test * pTest,
void testAtomicReadFile(Test * pTest) void testAtomicReadFile(Test * pTest)
{ {
BACNET_ATOMIC_READ_FILE_DATA data = {0}; BACNET_ATOMIC_READ_FILE_DATA data = { 0 };
data.object_type = OBJECT_FILE; data.object_type = OBJECT_FILE;
data.object_instance = 1; data.object_instance = 1;
+18 -36
View File
@@ -39,20 +39,16 @@
#include "bacdcode.h" #include "bacdcode.h"
#include "bacstr.h" #include "bacstr.h"
typedef struct BACnet_Atomic_Read_File_Data typedef struct BACnet_Atomic_Read_File_Data {
{
BACNET_OBJECT_TYPE object_type; BACNET_OBJECT_TYPE object_type;
uint32_t object_instance; uint32_t object_instance;
BACNET_FILE_ACCESS_METHOD access; BACNET_FILE_ACCESS_METHOD access;
union union {
{ struct {
struct
{
int32_t fileStartPosition; int32_t fileStartPosition;
uint32_t requestedOctetCount; uint32_t requestedOctetCount;
} stream; } stream;
struct struct {
{
int32_t fileStartRecord; int32_t fileStartRecord;
// requested or returned record count // requested or returned record count
uint32_t RecordCount; uint32_t RecordCount;
@@ -68,53 +64,39 @@ extern "C" {
// Atomic Read File // Atomic Read File
// encode service // encode service
int arf_encode_apdu( int arf_encode_apdu(uint8_t * apdu,
uint8_t *apdu, uint8_t invoke_id, BACNET_ATOMIC_READ_FILE_DATA * data);
uint8_t invoke_id,
BACNET_ATOMIC_READ_FILE_DATA *data);
// decode the service request only // decode the service request only
int arf_decode_service_request( int arf_decode_service_request(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, BACNET_ATOMIC_READ_FILE_DATA * data);
unsigned apdu_len,
BACNET_ATOMIC_READ_FILE_DATA *data);
int arf_decode_apdu( int arf_decode_apdu(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
uint8_t *invoke_id, uint8_t * invoke_id, BACNET_ATOMIC_READ_FILE_DATA * data);
BACNET_ATOMIC_READ_FILE_DATA *data);
// Atomic Read File Ack // Atomic Read File Ack
// encode service // encode service
int arf_ack_encode_apdu( int arf_ack_encode_apdu(uint8_t * apdu,
uint8_t *apdu, uint8_t invoke_id, BACNET_ATOMIC_READ_FILE_DATA * data);
uint8_t invoke_id,
BACNET_ATOMIC_READ_FILE_DATA *data);
// decode the service request only // decode the service request only
int arf_ack_decode_service_request( int arf_ack_decode_service_request(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, BACNET_ATOMIC_READ_FILE_DATA * data);
unsigned apdu_len,
BACNET_ATOMIC_READ_FILE_DATA *data);
int arf_ack_decode_apdu( int arf_ack_decode_apdu(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
uint8_t *invoke_id, uint8_t * invoke_id, BACNET_ATOMIC_READ_FILE_DATA * data);
BACNET_ATOMIC_READ_FILE_DATA *data);
#ifdef TEST #ifdef TEST
#include "ctest.h" #include "ctest.h"
void test_AtomicReadFile(Test * pTest); void test_AtomicReadFile(Test * pTest);
void test_AtomicReadFileAck(Test * pTest); void test_AtomicReadFileAck(Test * pTest);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+64 -121
View File
@@ -41,24 +41,21 @@
// Atomic Write File // Atomic Write File
// encode service // encode service
int awf_encode_apdu( int awf_encode_apdu(uint8_t * apdu,
uint8_t *apdu, uint8_t invoke_id, BACNET_ATOMIC_WRITE_FILE_DATA * data)
uint8_t invoke_id,
BACNET_ATOMIC_WRITE_FILE_DATA *data)
{ {
int apdu_len = 0; // total length of the apdu, return value int apdu_len = 0; // total length of the apdu, return value
if (apdu) if (apdu) {
{
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST; apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
apdu[1] = encode_max_segs_max_apdu(0, Device_Max_APDU_Length_Accepted()); apdu[1] =
encode_max_segs_max_apdu(0, Device_Max_APDU_Length_Accepted());
apdu[2] = invoke_id; apdu[2] = invoke_id;
apdu[3] = SERVICE_CONFIRMED_ATOMIC_WRITE_FILE; // service choice apdu[3] = SERVICE_CONFIRMED_ATOMIC_WRITE_FILE; // service choice
apdu_len = 4; apdu_len = 4;
apdu_len += encode_tagged_object_id(&apdu[apdu_len], apdu_len += encode_tagged_object_id(&apdu[apdu_len],
data->object_type, data->object_instance); data->object_type, data->object_instance);
switch (data->access) switch (data->access) {
{
case FILE_STREAM_ACCESS: case FILE_STREAM_ACCESS:
apdu_len += encode_opening_tag(&apdu[apdu_len], 0); apdu_len += encode_opening_tag(&apdu[apdu_len], 0);
apdu_len += encode_tagged_signed(&apdu[apdu_len], apdu_len += encode_tagged_signed(&apdu[apdu_len],
@@ -86,10 +83,8 @@ int awf_encode_apdu(
} }
// decode the service request only // decode the service request only
int awf_decode_service_request( int awf_decode_service_request(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, BACNET_ATOMIC_WRITE_FILE_DATA * data)
unsigned apdu_len,
BACNET_ATOMIC_WRITE_FILE_DATA *data)
{ {
int len = 0; int len = 0;
int tag_len = 0; int tag_len = 0;
@@ -98,15 +93,15 @@ int awf_decode_service_request(
int type = 0; // for decoding int type = 0; // for decoding
// check for value pointers // check for value pointers
if (apdu_len && data) if (apdu_len && data) {
{ len =
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value_type); decode_tag_number_and_value(&apdu[0], &tag_number,
&len_value_type);
if (tag_number != BACNET_APPLICATION_TAG_OBJECT_ID) if (tag_number != BACNET_APPLICATION_TAG_OBJECT_ID)
return -1; return -1;
len += decode_object_id(&apdu[len], &type, &data->object_instance); len += decode_object_id(&apdu[len], &type, &data->object_instance);
data->object_type = type; data->object_type = type;
if (decode_is_opening_tag_number(&apdu[len], 0)) if (decode_is_opening_tag_number(&apdu[len], 0)) {
{
data->access = FILE_STREAM_ACCESS; data->access = FILE_STREAM_ACCESS;
// a tag number of 2 is not extended so only one octet // a tag number of 2 is not extended so only one octet
len++; len++;
@@ -117,8 +112,7 @@ int awf_decode_service_request(
if (tag_number != BACNET_APPLICATION_TAG_SIGNED_INT) if (tag_number != BACNET_APPLICATION_TAG_SIGNED_INT)
return -1; return -1;
len += decode_signed(&apdu[len], len += decode_signed(&apdu[len],
len_value_type, len_value_type, &data->type.stream.fileStartPosition);
&data->type.stream.fileStartPosition);
// fileData // fileData
tag_len = decode_tag_number_and_value(&apdu[len], tag_len = decode_tag_number_and_value(&apdu[len],
&tag_number, &len_value_type); &tag_number, &len_value_type);
@@ -126,15 +120,12 @@ int awf_decode_service_request(
if (tag_number != BACNET_APPLICATION_TAG_OCTET_STRING) if (tag_number != BACNET_APPLICATION_TAG_OCTET_STRING)
return -1; return -1;
len += decode_octet_string(&apdu[len], len += decode_octet_string(&apdu[len],
len_value_type, len_value_type, &data->fileData);
&data->fileData);
if (!decode_is_closing_tag_number(&apdu[len], 0)) if (!decode_is_closing_tag_number(&apdu[len], 0))
return -1; return -1;
// a tag number is not extended so only one octet // a tag number is not extended so only one octet
len++; len++;
} } else if (decode_is_opening_tag_number(&apdu[len], 1)) {
else if (decode_is_opening_tag_number(&apdu[len], 1))
{
data->access = FILE_RECORD_ACCESS; data->access = FILE_RECORD_ACCESS;
// a tag number is not extended so only one octet // a tag number is not extended so only one octet
len++; len++;
@@ -145,8 +136,7 @@ int awf_decode_service_request(
if (tag_number != BACNET_APPLICATION_TAG_SIGNED_INT) if (tag_number != BACNET_APPLICATION_TAG_SIGNED_INT)
return -1; return -1;
len += decode_signed(&apdu[len], len += decode_signed(&apdu[len],
len_value_type, len_value_type, &data->type.record.fileStartRecord);
&data->type.record.fileStartRecord);
// returnedRecordCount // returnedRecordCount
tag_len = decode_tag_number_and_value(&apdu[len], tag_len = decode_tag_number_and_value(&apdu[len],
&tag_number, &len_value_type); &tag_number, &len_value_type);
@@ -154,8 +144,7 @@ int awf_decode_service_request(
if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT) if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT)
return -1; return -1;
len += decode_unsigned(&apdu[len], len += decode_unsigned(&apdu[len],
len_value_type, len_value_type, &data->type.record.returnedRecordCount);
&data->type.record.returnedRecordCount);
// fileData // fileData
tag_len = decode_tag_number_and_value(&apdu[len], tag_len = decode_tag_number_and_value(&apdu[len],
&tag_number, &len_value_type); &tag_number, &len_value_type);
@@ -163,25 +152,21 @@ int awf_decode_service_request(
if (tag_number != BACNET_APPLICATION_TAG_OCTET_STRING) if (tag_number != BACNET_APPLICATION_TAG_OCTET_STRING)
return -1; return -1;
len += decode_octet_string(&apdu[len], len += decode_octet_string(&apdu[len],
len_value_type, len_value_type, &data->fileData);
&data->fileData);
if (!decode_is_closing_tag_number(&apdu[len], 1)) if (!decode_is_closing_tag_number(&apdu[len], 1))
return -1; return -1;
// a tag number is not extended so only one octet // a tag number is not extended so only one octet
len++; len++;
} } else
else
return -1; return -1;
} }
return len; return len;
} }
int awf_decode_apdu( int awf_decode_apdu(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
uint8_t *invoke_id, uint8_t * invoke_id, BACNET_ATOMIC_WRITE_FILE_DATA * data)
BACNET_ATOMIC_WRITE_FILE_DATA *data)
{ {
int len = 0; int len = 0;
unsigned offset = 0; unsigned offset = 0;
@@ -197,32 +182,25 @@ int awf_decode_apdu(
return -1; return -1;
offset = 4; offset = 4;
if (apdu_len > offset) if (apdu_len > offset) {
{ len = awf_decode_service_request(&apdu[offset],
len = awf_decode_service_request( apdu_len - offset, data);
&apdu[offset],
apdu_len - offset,
data);
} }
return len; return len;
} }
int awf_ack_encode_apdu( int awf_ack_encode_apdu(uint8_t * apdu,
uint8_t *apdu, uint8_t invoke_id, BACNET_ATOMIC_WRITE_FILE_DATA * data)
uint8_t invoke_id,
BACNET_ATOMIC_WRITE_FILE_DATA *data)
{ {
int apdu_len = 0; // total length of the apdu, return value int apdu_len = 0; // total length of the apdu, return value
if (apdu) if (apdu) {
{
apdu[0] = PDU_TYPE_COMPLEX_ACK; apdu[0] = PDU_TYPE_COMPLEX_ACK;
apdu[1] = invoke_id; apdu[1] = invoke_id;
apdu[2] = SERVICE_CONFIRMED_ATOMIC_WRITE_FILE; // service choice apdu[2] = SERVICE_CONFIRMED_ATOMIC_WRITE_FILE; // service choice
apdu_len = 3; apdu_len = 3;
switch (data->access) switch (data->access) {
{
case FILE_STREAM_ACCESS: case FILE_STREAM_ACCESS:
apdu_len += encode_context_signed(&apdu[apdu_len], 0, apdu_len += encode_context_signed(&apdu[apdu_len], 0,
data->type.stream.fileStartPosition); data->type.stream.fileStartPosition);
@@ -240,45 +218,36 @@ int awf_ack_encode_apdu(
} }
// decode the service request only // decode the service request only
int awf_ack_decode_service_request( int awf_ack_decode_service_request(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, BACNET_ATOMIC_WRITE_FILE_DATA * data)
unsigned apdu_len,
BACNET_ATOMIC_WRITE_FILE_DATA *data)
{ {
int len = 0; int len = 0;
uint8_t tag_number = 0; uint8_t tag_number = 0;
uint32_t len_value_type = 0; uint32_t len_value_type = 0;
// check for value pointers // check for value pointers
if (apdu_len && data) if (apdu_len && data) {
{ len =
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value_type); decode_tag_number_and_value(&apdu[0], &tag_number,
if (tag_number == 0) &len_value_type);
{ if (tag_number == 0) {
data->access = FILE_STREAM_ACCESS; data->access = FILE_STREAM_ACCESS;
len += decode_signed(&apdu[len], len += decode_signed(&apdu[len],
len_value_type, len_value_type, &data->type.stream.fileStartPosition);
&data->type.stream.fileStartPosition); } else if (tag_number == 1) {
}
else if (tag_number == 1)
{
data->access = FILE_RECORD_ACCESS; data->access = FILE_RECORD_ACCESS;
len += decode_signed(&apdu[len], len += decode_signed(&apdu[len],
len_value_type, len_value_type, &data->type.record.fileStartRecord);
&data->type.record.fileStartRecord); } else
}
else
return -1; return -1;
} }
return len; return len;
} }
int awf_ack_decode_apdu( int awf_ack_decode_apdu(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
uint8_t *invoke_id, uint8_t * invoke_id, BACNET_ATOMIC_WRITE_FILE_DATA * data)
BACNET_ATOMIC_WRITE_FILE_DATA *data)
{ {
int len = 0; int len = 0;
unsigned offset = 0; unsigned offset = 0;
@@ -293,12 +262,9 @@ int awf_ack_decode_apdu(
return -1; return -1;
offset = 3; offset = 3;
if (apdu_len > offset) if (apdu_len > offset) {
{ len = awf_decode_service_request(&apdu[offset],
len = awf_decode_service_request( apdu_len - offset, data);
&apdu[offset],
apdu_len - offset,
data);
} }
return len; return len;
@@ -310,38 +276,28 @@ int awf_ack_decode_apdu(
#include "ctest.h" #include "ctest.h"
void testAtomicWriteFileAccess(Test * pTest, void testAtomicWriteFileAccess(Test * pTest,
BACNET_ATOMIC_WRITE_FILE_DATA *data) BACNET_ATOMIC_WRITE_FILE_DATA * data)
{ {
BACNET_ATOMIC_WRITE_FILE_DATA test_data = {0}; BACNET_ATOMIC_WRITE_FILE_DATA test_data = { 0 };
uint8_t apdu[480] = {0}; uint8_t apdu[480] = { 0 };
int len = 0; int len = 0;
int apdu_len = 0; int apdu_len = 0;
uint8_t invoke_id = 128; uint8_t invoke_id = 128;
uint8_t test_invoke_id = 0; uint8_t test_invoke_id = 0;
len = awf_encode_apdu( len = awf_encode_apdu(&apdu[0], invoke_id, data);
&apdu[0],
invoke_id,
data);
ct_test(pTest, len != 0); ct_test(pTest, len != 0);
apdu_len = len; apdu_len = len;
len = awf_decode_apdu( len = awf_decode_apdu(&apdu[0], apdu_len, &test_invoke_id, &test_data);
&apdu[0],
apdu_len,
&test_invoke_id,
&test_data);
ct_test(pTest, len != -1); ct_test(pTest, len != -1);
ct_test(pTest, test_data.object_type == data->object_type); ct_test(pTest, test_data.object_type == data->object_type);
ct_test(pTest, test_data.object_instance == data->object_instance); ct_test(pTest, test_data.object_instance == data->object_instance);
ct_test(pTest, test_data.access == data->access); ct_test(pTest, test_data.access == data->access);
if (test_data.access == FILE_STREAM_ACCESS) if (test_data.access == FILE_STREAM_ACCESS) {
{
ct_test(pTest, test_data.type.stream.fileStartPosition == ct_test(pTest, test_data.type.stream.fileStartPosition ==
data->type.stream.fileStartPosition); data->type.stream.fileStartPosition);
} } else if (test_data.access == FILE_RECORD_ACCESS) {
else if (test_data.access == FILE_RECORD_ACCESS)
{
ct_test(pTest, test_data.type.record.fileStartRecord == ct_test(pTest, test_data.type.record.fileStartRecord ==
data->type.record.fileStartRecord); data->type.record.fileStartRecord);
ct_test(pTest, test_data.type.record.returnedRecordCount == ct_test(pTest, test_data.type.record.returnedRecordCount ==
@@ -349,15 +305,14 @@ void testAtomicWriteFileAccess(Test * pTest,
} }
ct_test(pTest, octetstring_length(&test_data.fileData) == ct_test(pTest, octetstring_length(&test_data.fileData) ==
octetstring_length(&data->fileData)); octetstring_length(&data->fileData));
ct_test(pTest, memcmp( ct_test(pTest, memcmp(octetstring_value(&test_data.fileData),
octetstring_value(&test_data.fileData),
octetstring_value(&data->fileData), octetstring_value(&data->fileData),
octetstring_length(&test_data.fileData)) == 0); octetstring_length(&test_data.fileData)) == 0);
} }
void testAtomicWriteFile(Test * pTest) void testAtomicWriteFile(Test * pTest)
{ {
BACNET_ATOMIC_WRITE_FILE_DATA data = {0}; BACNET_ATOMIC_WRITE_FILE_DATA data = { 0 };
uint8_t test_octet_string[32] = "Joshua-Mary-Anna-Christopher"; uint8_t test_octet_string[32] = "Joshua-Mary-Anna-Christopher";
data.object_type = OBJECT_FILE; data.object_type = OBJECT_FILE;
@@ -365,8 +320,7 @@ void testAtomicWriteFile(Test * pTest)
data.access = FILE_STREAM_ACCESS; data.access = FILE_STREAM_ACCESS;
data.type.stream.fileStartPosition = 0; data.type.stream.fileStartPosition = 0;
octetstring_init(&data.fileData, octetstring_init(&data.fileData,
test_octet_string, test_octet_string, sizeof(test_octet_string));
sizeof(test_octet_string));
testAtomicWriteFileAccess(pTest, &data); testAtomicWriteFileAccess(pTest, &data);
data.object_type = OBJECT_FILE; data.object_type = OBJECT_FILE;
@@ -375,44 +329,33 @@ void testAtomicWriteFile(Test * pTest)
data.type.record.fileStartRecord = 1; data.type.record.fileStartRecord = 1;
data.type.record.returnedRecordCount = 2; data.type.record.returnedRecordCount = 2;
octetstring_init(&data.fileData, octetstring_init(&data.fileData,
test_octet_string, test_octet_string, sizeof(test_octet_string));
sizeof(test_octet_string));
testAtomicWriteFileAccess(pTest, &data); testAtomicWriteFileAccess(pTest, &data);
return; return;
} }
void testAtomicWriteFileAckAccess(Test * pTest, void testAtomicWriteFileAckAccess(Test * pTest,
BACNET_ATOMIC_WRITE_FILE_DATA *data) BACNET_ATOMIC_WRITE_FILE_DATA * data)
{ {
BACNET_ATOMIC_WRITE_FILE_DATA test_data = {0}; BACNET_ATOMIC_WRITE_FILE_DATA test_data = { 0 };
uint8_t apdu[480] = {0}; uint8_t apdu[480] = { 0 };
int len = 0; int len = 0;
int apdu_len = 0; int apdu_len = 0;
uint8_t invoke_id = 128; uint8_t invoke_id = 128;
uint8_t test_invoke_id = 0; uint8_t test_invoke_id = 0;
len = awf_encode_apdu( len = awf_encode_apdu(&apdu[0], invoke_id, data);
&apdu[0],
invoke_id,
data);
ct_test(pTest, len != 0); ct_test(pTest, len != 0);
apdu_len = len; apdu_len = len;
len = awf_decode_apdu( len = awf_decode_apdu(&apdu[0], apdu_len, &test_invoke_id, &test_data);
&apdu[0],
apdu_len,
&test_invoke_id,
&test_data);
ct_test(pTest, len != -1); ct_test(pTest, len != -1);
ct_test(pTest, test_data.access == data->access); ct_test(pTest, test_data.access == data->access);
if (test_data.access == FILE_STREAM_ACCESS) if (test_data.access == FILE_STREAM_ACCESS) {
{
ct_test(pTest, test_data.type.stream.fileStartPosition == ct_test(pTest, test_data.type.stream.fileStartPosition ==
data->type.stream.fileStartPosition); data->type.stream.fileStartPosition);
} } else if (test_data.access == FILE_RECORD_ACCESS) {
else if (test_data.access == FILE_RECORD_ACCESS)
{
ct_test(pTest, test_data.type.record.fileStartRecord == ct_test(pTest, test_data.type.record.fileStartRecord ==
data->type.record.fileStartRecord); data->type.record.fileStartRecord);
} }
@@ -420,7 +363,7 @@ void testAtomicWriteFileAckAccess(Test * pTest,
void testAtomicWriteFileAck(Test * pTest) void testAtomicWriteFileAck(Test * pTest)
{ {
BACNET_ATOMIC_WRITE_FILE_DATA data = {0}; BACNET_ATOMIC_WRITE_FILE_DATA data = { 0 };
data.access = FILE_STREAM_ACCESS; data.access = FILE_STREAM_ACCESS;
data.type.stream.fileStartPosition = 42; data.type.stream.fileStartPosition = 42;
+18 -36
View File
@@ -38,19 +38,15 @@
#include <stdbool.h> #include <stdbool.h>
#include "bacdcode.h" #include "bacdcode.h"
typedef struct BACnet_Atomic_Write_File_Data typedef struct BACnet_Atomic_Write_File_Data {
{
BACNET_OBJECT_TYPE object_type; BACNET_OBJECT_TYPE object_type;
uint32_t object_instance; uint32_t object_instance;
BACNET_FILE_ACCESS_METHOD access; BACNET_FILE_ACCESS_METHOD access;
union union {
{ struct {
struct
{
int32_t fileStartPosition; int32_t fileStartPosition;
} stream; } stream;
struct struct {
{
int32_t fileStartRecord; int32_t fileStartRecord;
uint32_t returnedRecordCount; uint32_t returnedRecordCount;
} record; } record;
@@ -64,52 +60,38 @@ extern "C" {
// Atomic Write File // Atomic Write File
// encode service // encode service
int awf_encode_apdu( int awf_encode_apdu(uint8_t * apdu,
uint8_t *apdu, uint8_t invoke_id, BACNET_ATOMIC_WRITE_FILE_DATA * data);
uint8_t invoke_id,
BACNET_ATOMIC_WRITE_FILE_DATA *data);
// decode the service request only // decode the service request only
int awf_decode_service_request( int awf_decode_service_request(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, BACNET_ATOMIC_WRITE_FILE_DATA * data);
unsigned apdu_len,
BACNET_ATOMIC_WRITE_FILE_DATA *data);
int awf_decode_apdu( int awf_decode_apdu(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
uint8_t *invoke_id, uint8_t * invoke_id, BACNET_ATOMIC_WRITE_FILE_DATA * data);
BACNET_ATOMIC_WRITE_FILE_DATA *data);
// Atomic Write File Ack // Atomic Write File Ack
// encode service // encode service
int awf_ack_encode_apdu( int awf_ack_encode_apdu(uint8_t * apdu,
uint8_t *apdu, uint8_t invoke_id, BACNET_ATOMIC_WRITE_FILE_DATA * data);
uint8_t invoke_id,
BACNET_ATOMIC_WRITE_FILE_DATA *data);
// decode the service request only // decode the service request only
int awf_ack_decode_service_request( int awf_ack_decode_service_request(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, BACNET_ATOMIC_WRITE_FILE_DATA * data);
unsigned apdu_len,
BACNET_ATOMIC_WRITE_FILE_DATA *data);
int awf_ack_decode_apdu( int awf_ack_decode_apdu(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
uint8_t *invoke_id, uint8_t * invoke_id, BACNET_ATOMIC_WRITE_FILE_DATA * data);
BACNET_ATOMIC_WRITE_FILE_DATA *data);
#ifdef TEST #ifdef TEST
#include "ctest.h" #include "ctest.h"
void test_AtomicWriteFile(Test * pTest); void test_AtomicWriteFile(Test * pTest);
void test_AtomicWriteFileAck(Test * pTest); void test_AtomicWriteFileAck(Test * pTest);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+272 -364
View File
@@ -43,14 +43,12 @@
#include "bacapp.h" #include "bacapp.h"
#include "bactext.h" #include "bactext.h"
int bacapp_encode_application_data( int bacapp_encode_application_data(uint8_t * apdu,
uint8_t *apdu, BACNET_APPLICATION_DATA_VALUE * value)
BACNET_APPLICATION_DATA_VALUE *value)
{ {
int apdu_len = 0; // total length of the apdu, return value int apdu_len = 0; // total length of the apdu, return value
if (apdu) if (apdu) {
{
if (value->tag == BACNET_APPLICATION_TAG_NULL) if (value->tag == BACNET_APPLICATION_TAG_NULL)
apdu[apdu_len++] = value->tag; apdu[apdu_len++] = value->tag;
else if (value->tag == BACNET_APPLICATION_TAG_BOOLEAN) else if (value->tag == BACNET_APPLICATION_TAG_BOOLEAN)
@@ -71,16 +69,13 @@ int bacapp_encode_application_data(
value->type.Double); value->type.Double);
#endif #endif
else if (value->tag == BACNET_APPLICATION_TAG_OCTET_STRING) else if (value->tag == BACNET_APPLICATION_TAG_OCTET_STRING)
apdu_len += encode_tagged_octet_string( apdu_len += encode_tagged_octet_string(&apdu[apdu_len],
&apdu[apdu_len],
&value->type.Octet_String); &value->type.Octet_String);
else if (value->tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) else if (value->tag == BACNET_APPLICATION_TAG_CHARACTER_STRING)
apdu_len += encode_tagged_character_string( apdu_len += encode_tagged_character_string(&apdu[apdu_len],
&apdu[apdu_len],
&value->type.Character_String); &value->type.Character_String);
else if (value->tag == BACNET_APPLICATION_TAG_BIT_STRING) else if (value->tag == BACNET_APPLICATION_TAG_BIT_STRING)
apdu_len += encode_tagged_bitstring( apdu_len += encode_tagged_bitstring(&apdu[apdu_len],
&apdu[apdu_len],
&value->type.Bit_String); &value->type.Bit_String);
else if (value->tag == BACNET_APPLICATION_TAG_ENUMERATED) else if (value->tag == BACNET_APPLICATION_TAG_ENUMERATED)
apdu_len += encode_tagged_enumerated(&apdu[apdu_len], apdu_len += encode_tagged_enumerated(&apdu[apdu_len],
@@ -89,26 +84,23 @@ int bacapp_encode_application_data(
apdu_len += encode_tagged_date(&apdu[apdu_len], apdu_len += encode_tagged_date(&apdu[apdu_len],
value->type.Date.year, value->type.Date.year,
value->type.Date.month, value->type.Date.month,
value->type.Date.day, value->type.Date.day, value->type.Date.wday);
value->type.Date.wday);
else if (value->tag == BACNET_APPLICATION_TAG_TIME) else if (value->tag == BACNET_APPLICATION_TAG_TIME)
apdu_len += encode_tagged_time(&apdu[apdu_len], apdu_len += encode_tagged_time(&apdu[apdu_len],
value->type.Time.hour, value->type.Time.hour,
value->type.Time.min, value->type.Time.min,
value->type.Time.sec, value->type.Time.sec, value->type.Time.hundredths);
value->type.Time.hundredths);
else if (value->tag == BACNET_APPLICATION_TAG_OBJECT_ID) else if (value->tag == BACNET_APPLICATION_TAG_OBJECT_ID)
apdu_len += encode_tagged_object_id(&apdu[apdu_len], apdu_len += encode_tagged_object_id(&apdu[apdu_len],
value->type.Object_Id.type,value->type.Object_Id.instance); value->type.Object_Id.type,
value->type.Object_Id.instance);
} }
return apdu_len; return apdu_len;
} }
int bacapp_decode_application_data( int bacapp_decode_application_data(uint8_t * apdu,
uint8_t *apdu, uint8_t apdu_len, BACNET_APPLICATION_DATA_VALUE * value)
uint8_t apdu_len,
BACNET_APPLICATION_DATA_VALUE *value)
{ {
int len = 0; int len = 0;
int tag_len = 0; int tag_len = 0;
@@ -120,72 +112,58 @@ int bacapp_decode_application_data(
uint32_t instance = 0; uint32_t instance = 0;
/* FIXME: use apdu_len! */ /* FIXME: use apdu_len! */
(void)apdu_len; (void) apdu_len;
if (apdu) if (apdu) {
{
tag_len = decode_tag_number_and_value(&apdu[0], tag_len = decode_tag_number_and_value(&apdu[0],
&tag_number, &len_value_type); &tag_number, &len_value_type);
if (tag_len) if (tag_len) {
{
len += tag_len; len += tag_len;
value->tag = tag_number; value->tag = tag_number;
if (tag_number == BACNET_APPLICATION_TAG_NULL) if (tag_number == BACNET_APPLICATION_TAG_NULL) {
{
/* nothing else to do */ /* nothing else to do */
} } else if (tag_number == BACNET_APPLICATION_TAG_BOOLEAN)
else if (tag_number == BACNET_APPLICATION_TAG_BOOLEAN)
value->type.Boolean = decode_boolean(len_value_type); value->type.Boolean = decode_boolean(len_value_type);
else if (tag_number == BACNET_APPLICATION_TAG_UNSIGNED_INT) else if (tag_number == BACNET_APPLICATION_TAG_UNSIGNED_INT)
len += decode_unsigned(&apdu[len], len += decode_unsigned(&apdu[len],
len_value_type, len_value_type, &value->type.Unsigned_Int);
&value->type.Unsigned_Int);
else if (tag_number == BACNET_APPLICATION_TAG_SIGNED_INT) else if (tag_number == BACNET_APPLICATION_TAG_SIGNED_INT)
len += decode_signed(&apdu[len], len += decode_signed(&apdu[len],
len_value_type, len_value_type, &value->type.Signed_Int);
&value->type.Signed_Int);
else if (tag_number == BACNET_APPLICATION_TAG_REAL) else if (tag_number == BACNET_APPLICATION_TAG_REAL)
len += decode_real(&apdu[len],&(value->type.Real)); len += decode_real(&apdu[len], &(value->type.Real));
#if 0 #if 0
else if (tag_number == BACNET_APPLICATION_TAG_DOUBLE) else if (tag_number == BACNET_APPLICATION_TAG_DOUBLE)
len += decode_double(&apdu[len],&(value->type.Double)); len += decode_double(&apdu[len], &(value->type.Double));
#endif #endif
else if (tag_number == BACNET_APPLICATION_TAG_OCTET_STRING) else if (tag_number == BACNET_APPLICATION_TAG_OCTET_STRING)
len += decode_octet_string(&apdu[len], len += decode_octet_string(&apdu[len],
len_value_type, len_value_type, &value->type.Octet_String);
&value->type.Octet_String);
else if (tag_number == BACNET_APPLICATION_TAG_CHARACTER_STRING) else if (tag_number == BACNET_APPLICATION_TAG_CHARACTER_STRING)
len += decode_character_string(&apdu[len], len += decode_character_string(&apdu[len],
len_value_type, len_value_type, &value->type.Character_String);
&value->type.Character_String);
else if (tag_number == BACNET_APPLICATION_TAG_BIT_STRING) else if (tag_number == BACNET_APPLICATION_TAG_BIT_STRING)
len += decode_bitstring(&apdu[len], len += decode_bitstring(&apdu[len],
len_value_type, len_value_type, &value->type.Bit_String);
&value->type.Bit_String);
else if (tag_number == BACNET_APPLICATION_TAG_ENUMERATED) else if (tag_number == BACNET_APPLICATION_TAG_ENUMERATED)
len += decode_enumerated(&apdu[len], len += decode_enumerated(&apdu[len],
len_value_type, len_value_type, &value->type.Enumerated);
&value->type.Enumerated); else if (tag_number == BACNET_APPLICATION_TAG_DATE) {
else if (tag_number == BACNET_APPLICATION_TAG_DATE)
{
len += decode_date(&apdu[len], &year, &month, &day, &wday); len += decode_date(&apdu[len], &year, &month, &day, &wday);
value->type.Date.year = year; value->type.Date.year = year;
value->type.Date.month = month; value->type.Date.month = month;
value->type.Date.day = day; value->type.Date.day = day;
value->type.Date.wday = wday; value->type.Date.wday = wday;
} } else if (tag_number == BACNET_APPLICATION_TAG_TIME) {
else if (tag_number == BACNET_APPLICATION_TAG_TIME) len +=
{ decode_bacnet_time(&apdu[len], &hour, &min, &sec,
len += decode_bacnet_time(&apdu[len], &hour, &min, &sec, &hundredths); &hundredths);
value->type.Time.hour = hour; value->type.Time.hour = hour;
value->type.Time.min = min; value->type.Time.min = min;
value->type.Time.sec = sec; value->type.Time.sec = sec;
value->type.Time.hundredths = hundredths; value->type.Time.hundredths = hundredths;
} } else if (tag_number == BACNET_APPLICATION_TAG_OBJECT_ID) {
else if (tag_number == BACNET_APPLICATION_TAG_OBJECT_ID)
{
len += decode_object_id(&apdu[len], len += decode_object_id(&apdu[len],
&object_type, &object_type, &instance);
&instance);
value->type.Object_Id.type = object_type; value->type.Object_Id.type = object_type;
value->type.Object_Id.instance = instance; value->type.Object_Id.instance = instance;
} }
@@ -195,17 +173,14 @@ int bacapp_decode_application_data(
return len; return len;
} }
bool bacapp_copy( bool bacapp_copy(BACNET_APPLICATION_DATA_VALUE * dest_value,
BACNET_APPLICATION_DATA_VALUE *dest_value, BACNET_APPLICATION_DATA_VALUE * src_value)
BACNET_APPLICATION_DATA_VALUE *src_value)
{ {
bool status = true; /*return value*/ bool status = true; /*return value */
if (dest_value && src_value) if (dest_value && src_value) {
{
dest_value->tag = src_value->tag; dest_value->tag = src_value->tag;
switch (src_value->tag) switch (src_value->tag) {
{
case BACNET_APPLICATION_TAG_NULL: case BACNET_APPLICATION_TAG_NULL:
break; break;
case BACNET_APPLICATION_TAG_BOOLEAN: case BACNET_APPLICATION_TAG_BOOLEAN:
@@ -236,20 +211,21 @@ bool bacapp_copy(
dest_value->type.Time.hour = src_value->type.Time.hour; dest_value->type.Time.hour = src_value->type.Time.hour;
dest_value->type.Time.min = src_value->type.Time.min; dest_value->type.Time.min = src_value->type.Time.min;
dest_value->type.Time.sec = src_value->type.Time.sec; dest_value->type.Time.sec = src_value->type.Time.sec;
dest_value->type.Time.hundredths = src_value->type.Time.hundredths; dest_value->type.Time.hundredths =
src_value->type.Time.hundredths;
break; break;
case BACNET_APPLICATION_TAG_OBJECT_ID: case BACNET_APPLICATION_TAG_OBJECT_ID:
dest_value->type.Object_Id.type = src_value->type.Object_Id.type; dest_value->type.Object_Id.type =
dest_value->type.Object_Id.instance = src_value->type.Object_Id.instance; src_value->type.Object_Id.type;
dest_value->type.Object_Id.instance =
src_value->type.Object_Id.instance;
break; break;
case BACNET_APPLICATION_TAG_OCTET_STRING: case BACNET_APPLICATION_TAG_OCTET_STRING:
octetstring_copy( octetstring_copy(&dest_value->type.Octet_String,
&dest_value->type.Octet_String,
&src_value->type.Octet_String); &src_value->type.Octet_String);
break; break;
case BACNET_APPLICATION_TAG_CHARACTER_STRING: case BACNET_APPLICATION_TAG_CHARACTER_STRING:
characterstring_copy( characterstring_copy(&dest_value->type.Character_String,
&dest_value->type.Character_String,
&src_value->type.Character_String); &src_value->type.Character_String);
break; break;
case BACNET_APPLICATION_TAG_BIT_STRING: case BACNET_APPLICATION_TAG_BIT_STRING:
@@ -261,21 +237,19 @@ bool bacapp_copy(
return status; return status;
} }
/* generic - can be used by other unit tests */ /* generic - can be used by other unit tests */
bool bacapp_compare( bool bacapp_compare(BACNET_APPLICATION_DATA_VALUE * value,
BACNET_APPLICATION_DATA_VALUE *value, BACNET_APPLICATION_DATA_VALUE * test_value)
BACNET_APPLICATION_DATA_VALUE *test_value)
{ {
bool status = true; /*return value*/ bool status = true; /*return value */
/* does the tag match? */ /* does the tag match? */
if (test_value->tag != value->tag) if (test_value->tag != value->tag)
status = false; status = false;
if (status) if (status) {
{
/* does the value match? */ /* does the value match? */
switch (test_value->tag) switch (test_value->tag) {
{
case BACNET_APPLICATION_TAG_NULL: case BACNET_APPLICATION_TAG_NULL:
break; break;
case BACNET_APPLICATION_TAG_BOOLEAN: case BACNET_APPLICATION_TAG_BOOLEAN:
@@ -309,7 +283,7 @@ bool bacapp_compare(
status = false; status = false;
if (test_value->type.Date.day != value->type.Date.day) if (test_value->type.Date.day != value->type.Date.day)
status = false; status = false;
if(test_value->type.Date.wday != value->type.Date.wday) if (test_value->type.Date.wday != value->type.Date.wday)
status = false; status = false;
break; break;
case BACNET_APPLICATION_TAG_TIME: case BACNET_APPLICATION_TAG_TIME:
@@ -319,18 +293,20 @@ bool bacapp_compare(
status = false; status = false;
if (test_value->type.Time.sec != value->type.Time.sec) if (test_value->type.Time.sec != value->type.Time.sec)
status = false; status = false;
if (test_value->type.Time.hundredths != value->type.Time.hundredths) if (test_value->type.Time.hundredths !=
value->type.Time.hundredths)
status = false; status = false;
break; break;
case BACNET_APPLICATION_TAG_OBJECT_ID: case BACNET_APPLICATION_TAG_OBJECT_ID:
if (test_value->type.Object_Id.type != value->type.Object_Id.type) if (test_value->type.Object_Id.type !=
value->type.Object_Id.type)
status = false; status = false;
if (test_value->type.Object_Id.instance != value->type.Object_Id.instance) if (test_value->type.Object_Id.instance !=
value->type.Object_Id.instance)
status = false; status = false;
break; break;
case BACNET_APPLICATION_TAG_CHARACTER_STRING: case BACNET_APPLICATION_TAG_CHARACTER_STRING:
status = !characterstring_same( status = !characterstring_same(&value->type.Character_String,
&value->type.Character_String,
&test_value->type.Character_String); &test_value->type.Character_String);
break; break;
case BACNET_APPLICATION_TAG_BIT_STRING: case BACNET_APPLICATION_TAG_BIT_STRING:
@@ -342,127 +318,122 @@ bool bacapp_compare(
return status; return status;
} }
bool bacapp_print_value( bool bacapp_print_value(FILE * stream,
FILE *stream, BACNET_APPLICATION_DATA_VALUE * value, BACNET_PROPERTY_ID property)
BACNET_APPLICATION_DATA_VALUE *value,
BACNET_PROPERTY_ID property)
{ {
bool status = true; /*return value*/ bool status = true; /*return value */
size_t len = 0, i = 0; size_t len = 0, i = 0;
char *char_str; char *char_str;
uint8_t *octet_str; uint8_t *octet_str;
if (value) if (value) {
{ switch (value->tag) {
switch (value->tag)
{
case BACNET_APPLICATION_TAG_NULL: case BACNET_APPLICATION_TAG_NULL:
fprintf(stream,"Null"); fprintf(stream, "Null");
break; break;
case BACNET_APPLICATION_TAG_BOOLEAN: case BACNET_APPLICATION_TAG_BOOLEAN:
fprintf(stream,"%s",value->type.Boolean?"TRUE":"FALSE"); fprintf(stream, "%s", value->type.Boolean ? "TRUE" : "FALSE");
break; break;
case BACNET_APPLICATION_TAG_UNSIGNED_INT: case BACNET_APPLICATION_TAG_UNSIGNED_INT:
fprintf(stream,"%u",value->type.Unsigned_Int); fprintf(stream, "%u", value->type.Unsigned_Int);
break; break;
case BACNET_APPLICATION_TAG_SIGNED_INT: case BACNET_APPLICATION_TAG_SIGNED_INT:
fprintf(stream,"%d",value->type.Signed_Int); fprintf(stream, "%d", value->type.Signed_Int);
break; break;
case BACNET_APPLICATION_TAG_REAL: case BACNET_APPLICATION_TAG_REAL:
fprintf(stream,"%f",(double)value->type.Real); fprintf(stream, "%f", (double) value->type.Real);
break; break;
case BACNET_APPLICATION_TAG_DOUBLE: case BACNET_APPLICATION_TAG_DOUBLE:
fprintf(stream,"%f",value->type.Double); fprintf(stream, "%f", value->type.Double);
break; break;
case BACNET_APPLICATION_TAG_ENUMERATED: case BACNET_APPLICATION_TAG_ENUMERATED:
switch (property) switch (property) {
{
case PROP_OBJECT_TYPE: case PROP_OBJECT_TYPE:
fprintf(stream,"%s", fprintf(stream, "%s",
bactext_object_type_name(value->type.Enumerated)); bactext_object_type_name(value->type.Enumerated));
break; break;
case PROP_EVENT_STATE: case PROP_EVENT_STATE:
fprintf(stream,"%s", fprintf(stream, "%s",
bactext_event_state_name(value->type.Enumerated)); bactext_event_state_name(value->type.Enumerated));
break; break;
case PROP_UNITS: case PROP_UNITS:
fprintf(stream,"%s", fprintf(stream, "%s",
bactext_engineering_unit_name(value->type.Enumerated)); bactext_engineering_unit_name(value->type.Enumerated));
break; break;
case PROP_PRESENT_VALUE: case PROP_PRESENT_VALUE:
fprintf(stream,"%s", fprintf(stream, "%s",
bactext_binary_present_value_name(value->type.Enumerated)); bactext_binary_present_value_name(value->type.
Enumerated));
break; break;
case PROP_RELIABILITY: case PROP_RELIABILITY:
fprintf(stream,"%s", fprintf(stream, "%s",
bactext_reliability_name(value->type.Enumerated)); bactext_reliability_name(value->type.Enumerated));
break; break;
case PROP_SYSTEM_STATUS: case PROP_SYSTEM_STATUS:
fprintf(stream,"%s", fprintf(stream, "%s",
bactext_device_status_name(value->type.Enumerated)); bactext_device_status_name(value->type.Enumerated));
break; break;
case PROP_SEGMENTATION_SUPPORTED: case PROP_SEGMENTATION_SUPPORTED:
fprintf(stream,"%s", fprintf(stream, "%s",
bactext_segmentation_name(value->type.Enumerated)); bactext_segmentation_name(value->type.Enumerated));
break; break;
default: default:
fprintf(stream,"%u",value->type.Enumerated); fprintf(stream, "%u", value->type.Enumerated);
break; break;
} }
break; break;
case BACNET_APPLICATION_TAG_DATE: case BACNET_APPLICATION_TAG_DATE:
fprintf(stream,"%s, %s %u, %u", fprintf(stream, "%s, %s %u, %u",
bactext_day_of_week_name(value->type.Date.wday), bactext_day_of_week_name(value->type.Date.wday),
bactext_month_name(value->type.Date.month), bactext_month_name(value->type.Date.month),
(unsigned)value->type.Date.day, (unsigned) value->type.Date.day,
(unsigned)value->type.Date.year); (unsigned) value->type.Date.year);
break; break;
case BACNET_APPLICATION_TAG_TIME: case BACNET_APPLICATION_TAG_TIME:
fprintf(stream,"%02u:%02u:%02u.%03u", fprintf(stream, "%02u:%02u:%02u.%03u",
(unsigned)value->type.Time.hour, (unsigned) value->type.Time.hour,
(unsigned)value->type.Time.min, (unsigned) value->type.Time.min,
(unsigned)value->type.Time.sec, (unsigned) value->type.Time.sec,
(unsigned)value->type.Time.hundredths); (unsigned) value->type.Time.hundredths);
break; break;
case BACNET_APPLICATION_TAG_OBJECT_ID: case BACNET_APPLICATION_TAG_OBJECT_ID:
fprintf(stream,"%s %u", fprintf(stream, "%s %u",
bactext_object_type_name(value->type.Object_Id.type), bactext_object_type_name(value->type.Object_Id.type),
value->type.Object_Id.instance); value->type.Object_Id.instance);
break; break;
case BACNET_APPLICATION_TAG_OCTET_STRING: case BACNET_APPLICATION_TAG_OCTET_STRING:
len = octetstring_length(&value->type.Octet_String); len = octetstring_length(&value->type.Octet_String);
octet_str = octetstring_value(&value->type.Octet_String); octet_str = octetstring_value(&value->type.Octet_String);
for (i = 0; i < len; i++) for (i = 0; i < len; i++) {
{ fprintf(stream, "%02X", *octet_str);
fprintf(stream,"%02X",*octet_str);
octet_str++; octet_str++;
} }
break; break;
case BACNET_APPLICATION_TAG_CHARACTER_STRING: case BACNET_APPLICATION_TAG_CHARACTER_STRING:
len = characterstring_length(&value->type.Character_String); len = characterstring_length(&value->type.Character_String);
char_str = characterstring_value(&value->type.Character_String); char_str =
fprintf(stream,"\""); characterstring_value(&value->type.Character_String);
for (i = 0; i < len; i++) fprintf(stream, "\"");
{ for (i = 0; i < len; i++) {
if (isprint(*char_str)) if (isprint(*char_str))
fprintf(stream,"%c",*char_str); fprintf(stream, "%c", *char_str);
else else
fprintf(stream,"."); fprintf(stream, ".");
char_str++; char_str++;
} }
fprintf(stream,"\""); fprintf(stream, "\"");
break; break;
case BACNET_APPLICATION_TAG_BIT_STRING: case BACNET_APPLICATION_TAG_BIT_STRING:
len = bitstring_bits_used(&value->type.Bit_String); len = bitstring_bits_used(&value->type.Bit_String);
fprintf(stream,"{"); fprintf(stream, "{");
for (i = 0; i < len; i++) for (i = 0; i < len; i++) {
{ fprintf(stream, "%s",
fprintf(stream,"%s", bitstring_bit(&value->type.Bit_String,
bitstring_bit(&value->type.Bit_String,i)?"true":"false"); i) ? "true" : "false");
if (i < len-1) if (i < len - 1)
fprintf(stream,","); fprintf(stream, ",");
} }
fprintf(stream,"}"); fprintf(stream, "}");
break; break;
default: default:
status = false; status = false;
@@ -475,10 +446,8 @@ bool bacapp_print_value(
/* used to load the app data struct with the proper data /* used to load the app data struct with the proper data
converted from a command line argument */ converted from a command line argument */
bool bacapp_parse_application_data( bool bacapp_parse_application_data(BACNET_APPLICATION_TAG tag_number,
BACNET_APPLICATION_TAG tag_number, const char *argv, BACNET_APPLICATION_DATA_VALUE * value)
const char *argv,
BACNET_APPLICATION_DATA_VALUE *value)
{ {
int hour, min, sec, hundredths; int hour, min, sec, hundredths;
int year, month, day, wday; int year, month, day, wday;
@@ -490,91 +459,64 @@ bool bacapp_parse_application_data(
double double_value = 0.0; double double_value = 0.0;
int count = 0; int count = 0;
if (value && (tag_number < MAX_BACNET_APPLICATION_TAG)) if (value && (tag_number < MAX_BACNET_APPLICATION_TAG)) {
{
status = true; status = true;
value->tag = tag_number; value->tag = tag_number;
if (tag_number == BACNET_APPLICATION_TAG_BOOLEAN) if (tag_number == BACNET_APPLICATION_TAG_BOOLEAN) {
{ long_value = strtol(argv, NULL, 0);
long_value = strtol(argv,NULL,0);
if (long_value) if (long_value)
value->type.Boolean = true; value->type.Boolean = true;
else else
value->type.Boolean = false; value->type.Boolean = false;
} } else if (tag_number == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
else if (tag_number == BACNET_APPLICATION_TAG_UNSIGNED_INT) unsigned_long_value = strtoul(argv, NULL, 0);
{
unsigned_long_value = strtoul(argv,NULL,0);
value->type.Unsigned_Int = unsigned_long_value; value->type.Unsigned_Int = unsigned_long_value;
} } else if (tag_number == BACNET_APPLICATION_TAG_SIGNED_INT) {
else if (tag_number == BACNET_APPLICATION_TAG_SIGNED_INT) long_value = strtol(argv, NULL, 0);
{
long_value = strtol(argv,NULL,0);
value->type.Signed_Int = long_value; value->type.Signed_Int = long_value;
} } else if (tag_number == BACNET_APPLICATION_TAG_REAL) {
else if (tag_number == BACNET_APPLICATION_TAG_REAL) double_value = strtod(argv, NULL);
{
double_value = strtod(argv,NULL);
value->type.Real = double_value; value->type.Real = double_value;
} } else if (tag_number == BACNET_APPLICATION_TAG_DOUBLE) {
else if (tag_number == BACNET_APPLICATION_TAG_DOUBLE) double_value = strtod(argv, NULL);
{
double_value = strtod(argv,NULL);
value->type.Double = double_value; value->type.Double = double_value;
} } else if (tag_number == BACNET_APPLICATION_TAG_CHARACTER_STRING) {
else if (tag_number == BACNET_APPLICATION_TAG_CHARACTER_STRING) status =
{ characterstring_init_ansi(&value->type.Character_String,
status = characterstring_init_ansi( (char *) argv);
&value->type.Character_String, } else if (tag_number == BACNET_APPLICATION_TAG_OCTET_STRING) {
(char *)argv); status = octetstring_init(&value->type.Octet_String,
} (uint8_t *) argv, strlen(argv));
else if (tag_number == BACNET_APPLICATION_TAG_OCTET_STRING) } else if (tag_number == BACNET_APPLICATION_TAG_ENUMERATED) {
{ unsigned_long_value = strtoul(argv, NULL, 0);
status = octetstring_init(
&value->type.Octet_String,
(uint8_t *)argv,
strlen(argv));
}
else if (tag_number == BACNET_APPLICATION_TAG_ENUMERATED)
{
unsigned_long_value = strtoul(argv,NULL,0);
value->type.Enumerated = unsigned_long_value; value->type.Enumerated = unsigned_long_value;
} } else if (tag_number == BACNET_APPLICATION_TAG_DATE) {
else if (tag_number == BACNET_APPLICATION_TAG_DATE) count =
{ sscanf(argv, "%d/%d/%d:%d", &year, &month, &day, &wday);
count = sscanf(argv,"%d/%d/%d:%d", &year, &month, &day, &wday); if (count == 4) {
if (count == 4)
{
value->type.Date.year = year; value->type.Date.year = year;
value->type.Date.month = month; value->type.Date.month = month;
value->type.Date.day = day; value->type.Date.day = day;
value->type.Date.wday = wday; value->type.Date.wday = wday;
} } else
else
status = false; status = false;
} } else if (tag_number == BACNET_APPLICATION_TAG_TIME) {
else if (tag_number == BACNET_APPLICATION_TAG_TIME) count =
{ sscanf(argv, "%d:%d:%d.%d", &hour, &min, &sec,
count = sscanf(argv,"%d:%d:%d.%d", &hour, &min, &sec, &hundredths); &hundredths);
if (count == 4) if (count == 4) {
{
value->type.Time.hour = hour; value->type.Time.hour = hour;
value->type.Time.min = min; value->type.Time.min = min;
value->type.Time.sec = sec; value->type.Time.sec = sec;
value->type.Time.hundredths = hundredths; value->type.Time.hundredths = hundredths;
} } else
else
status = false; status = false;
} } else if (tag_number == BACNET_APPLICATION_TAG_OBJECT_ID) {
else if (tag_number == BACNET_APPLICATION_TAG_OBJECT_ID) count = sscanf(argv, "%d:%d", &object_type, &instance);
{ if (count == 2) {
count = sscanf(argv,"%d:%d", &object_type, &instance);
if (count == 2)
{
value->type.Object_Id.type = object_type; value->type.Object_Id.type = object_type;
value->type.Object_Id.instance = instance; value->type.Object_Id.instance = instance;
} } else
else
status = false; status = false;
} }
} }
@@ -588,192 +530,158 @@ bool bacapp_parse_application_data(
#include <string.h> #include <string.h>
#include "ctest.h" #include "ctest.h"
static bool testBACnetApplicationDataValue(BACNET_APPLICATION_DATA_VALUE *value) static bool testBACnetApplicationDataValue(BACNET_APPLICATION_DATA_VALUE *
value)
{ {
uint8_t apdu[480] = {0}; uint8_t apdu[480] = { 0 };
int len = 0; int len = 0;
int apdu_len = 0; int apdu_len = 0;
BACNET_APPLICATION_DATA_VALUE test_value; BACNET_APPLICATION_DATA_VALUE test_value;
apdu_len = bacapp_encode_application_data(&apdu[0],value); apdu_len = bacapp_encode_application_data(&apdu[0], value);
len = bacapp_decode_application_data( len = bacapp_decode_application_data(&apdu[0], apdu_len, &test_value);
&apdu[0],
apdu_len,
&test_value);
return bacapp_compare(value, &test_value); return bacapp_compare(value, &test_value);
} }
void testBACnetApplicationData(Test * pTest) void testBACnetApplicationData(Test * pTest)
{ {
BACNET_APPLICATION_DATA_VALUE value = {0}; BACNET_APPLICATION_DATA_VALUE value = { 0 };
bool status = false; bool status = false;
status = bacapp_parse_application_data( status = bacapp_parse_application_data(BACNET_APPLICATION_TAG_NULL,
BACNET_APPLICATION_TAG_NULL, NULL, &value);
NULL, ct_test(pTest, status == true);
&value); ct_test(pTest, testBACnetApplicationDataValue(&value));
ct_test(pTest,status == true);
ct_test(pTest,testBACnetApplicationDataValue(&value));
status = bacapp_parse_application_data( status = bacapp_parse_application_data(BACNET_APPLICATION_TAG_BOOLEAN,
BACNET_APPLICATION_TAG_BOOLEAN, "1", &value);
"1", ct_test(pTest, status == true);
&value); ct_test(pTest, value.type.Boolean == true);
ct_test(pTest,status == true); ct_test(pTest, testBACnetApplicationDataValue(&value));
ct_test(pTest,value.type.Boolean == true);
ct_test(pTest,testBACnetApplicationDataValue(&value));
status = bacapp_parse_application_data( status = bacapp_parse_application_data(BACNET_APPLICATION_TAG_BOOLEAN,
BACNET_APPLICATION_TAG_BOOLEAN, "0", &value);
"0", ct_test(pTest, status == true);
&value); ct_test(pTest, value.type.Boolean == false);
ct_test(pTest,status == true); ct_test(pTest, testBACnetApplicationDataValue(&value));
ct_test(pTest,value.type.Boolean == false);
ct_test(pTest,testBACnetApplicationDataValue(&value));
status = bacapp_parse_application_data( status =
BACNET_APPLICATION_TAG_UNSIGNED_INT, bacapp_parse_application_data(BACNET_APPLICATION_TAG_UNSIGNED_INT,
"0", "0", &value);
&value); ct_test(pTest, status == true);
ct_test(pTest,status == true); ct_test(pTest, value.type.Unsigned_Int == 0);
ct_test(pTest,value.type.Unsigned_Int == 0); ct_test(pTest, testBACnetApplicationDataValue(&value));
ct_test(pTest,testBACnetApplicationDataValue(&value)); status =
status = bacapp_parse_application_data( bacapp_parse_application_data(BACNET_APPLICATION_TAG_UNSIGNED_INT,
BACNET_APPLICATION_TAG_UNSIGNED_INT, "0xFFFF", &value);
"0xFFFF", ct_test(pTest, status == true);
&value); ct_test(pTest, value.type.Unsigned_Int == 0xFFFF);
ct_test(pTest,status == true); ct_test(pTest, testBACnetApplicationDataValue(&value));
ct_test(pTest,value.type.Unsigned_Int == 0xFFFF); status =
ct_test(pTest,testBACnetApplicationDataValue(&value)); bacapp_parse_application_data(BACNET_APPLICATION_TAG_UNSIGNED_INT,
status = bacapp_parse_application_data( "0xFFFFFFFF", &value);
BACNET_APPLICATION_TAG_UNSIGNED_INT, ct_test(pTest, status == true);
"0xFFFFFFFF", ct_test(pTest, value.type.Unsigned_Int == 0xFFFFFFFF);
&value); ct_test(pTest, testBACnetApplicationDataValue(&value));
ct_test(pTest,status == true);
ct_test(pTest,value.type.Unsigned_Int == 0xFFFFFFFF);
ct_test(pTest,testBACnetApplicationDataValue(&value));
status = bacapp_parse_application_data( status =
BACNET_APPLICATION_TAG_SIGNED_INT, bacapp_parse_application_data(BACNET_APPLICATION_TAG_SIGNED_INT,
"0", "0", &value);
&value); ct_test(pTest, status == true);
ct_test(pTest,status == true); ct_test(pTest, value.type.Signed_Int == 0);
ct_test(pTest,value.type.Signed_Int == 0); ct_test(pTest, testBACnetApplicationDataValue(&value));
ct_test(pTest,testBACnetApplicationDataValue(&value)); status =
status = bacapp_parse_application_data( bacapp_parse_application_data(BACNET_APPLICATION_TAG_SIGNED_INT,
BACNET_APPLICATION_TAG_SIGNED_INT, "-1", &value);
"-1", ct_test(pTest, status == true);
&value); ct_test(pTest, value.type.Signed_Int == -1);
ct_test(pTest,status == true); ct_test(pTest, testBACnetApplicationDataValue(&value));
ct_test(pTest,value.type.Signed_Int == -1); status =
ct_test(pTest,testBACnetApplicationDataValue(&value)); bacapp_parse_application_data(BACNET_APPLICATION_TAG_SIGNED_INT,
status = bacapp_parse_application_data( "32768", &value);
BACNET_APPLICATION_TAG_SIGNED_INT, ct_test(pTest, status == true);
"32768", ct_test(pTest, value.type.Signed_Int == 32768);
&value); ct_test(pTest, testBACnetApplicationDataValue(&value));
ct_test(pTest,status == true); status =
ct_test(pTest,value.type.Signed_Int == 32768); bacapp_parse_application_data(BACNET_APPLICATION_TAG_SIGNED_INT,
ct_test(pTest,testBACnetApplicationDataValue(&value)); "-32768", &value);
status = bacapp_parse_application_data( ct_test(pTest, status == true);
BACNET_APPLICATION_TAG_SIGNED_INT, ct_test(pTest, value.type.Signed_Int == -32768);
"-32768", ct_test(pTest, testBACnetApplicationDataValue(&value));
&value);
ct_test(pTest,status == true);
ct_test(pTest,value.type.Signed_Int == -32768);
ct_test(pTest,testBACnetApplicationDataValue(&value));
status = bacapp_parse_application_data( status = bacapp_parse_application_data(BACNET_APPLICATION_TAG_REAL,
BACNET_APPLICATION_TAG_REAL, "0.0", &value);
"0.0", ct_test(pTest, status == true);
&value); ct_test(pTest, testBACnetApplicationDataValue(&value));
ct_test(pTest,status == true); status = bacapp_parse_application_data(BACNET_APPLICATION_TAG_REAL,
ct_test(pTest,testBACnetApplicationDataValue(&value)); "-1.0", &value);
status = bacapp_parse_application_data( ct_test(pTest, status == true);
BACNET_APPLICATION_TAG_REAL, ct_test(pTest, testBACnetApplicationDataValue(&value));
"-1.0", status = bacapp_parse_application_data(BACNET_APPLICATION_TAG_REAL,
&value); "1.0", &value);
ct_test(pTest,status == true); ct_test(pTest, status == true);
ct_test(pTest,testBACnetApplicationDataValue(&value)); ct_test(pTest, testBACnetApplicationDataValue(&value));
status = bacapp_parse_application_data( status = bacapp_parse_application_data(BACNET_APPLICATION_TAG_REAL,
BACNET_APPLICATION_TAG_REAL, "3.14159", &value);
"1.0", ct_test(pTest, status == true);
&value); ct_test(pTest, testBACnetApplicationDataValue(&value));
ct_test(pTest,status == true); status = bacapp_parse_application_data(BACNET_APPLICATION_TAG_REAL,
ct_test(pTest,testBACnetApplicationDataValue(&value)); "-3.14159", &value);
status = bacapp_parse_application_data( ct_test(pTest, status == true);
BACNET_APPLICATION_TAG_REAL, ct_test(pTest, testBACnetApplicationDataValue(&value));
"3.14159",
&value);
ct_test(pTest,status == true);
ct_test(pTest,testBACnetApplicationDataValue(&value));
status = bacapp_parse_application_data(
BACNET_APPLICATION_TAG_REAL,
"-3.14159",
&value);
ct_test(pTest,status == true);
ct_test(pTest,testBACnetApplicationDataValue(&value));
status = bacapp_parse_application_data( status =
BACNET_APPLICATION_TAG_ENUMERATED, bacapp_parse_application_data(BACNET_APPLICATION_TAG_ENUMERATED,
"0", "0", &value);
&value); ct_test(pTest, status == true);
ct_test(pTest,status == true); ct_test(pTest, value.type.Enumerated == 0);
ct_test(pTest,value.type.Enumerated == 0); ct_test(pTest, testBACnetApplicationDataValue(&value));
ct_test(pTest,testBACnetApplicationDataValue(&value)); status =
status = bacapp_parse_application_data( bacapp_parse_application_data(BACNET_APPLICATION_TAG_ENUMERATED,
BACNET_APPLICATION_TAG_ENUMERATED, "0xFFFF", &value);
"0xFFFF", ct_test(pTest, status == true);
&value); ct_test(pTest, value.type.Enumerated == 0xFFFF);
ct_test(pTest,status == true); ct_test(pTest, testBACnetApplicationDataValue(&value));
ct_test(pTest,value.type.Enumerated == 0xFFFF); status =
ct_test(pTest,testBACnetApplicationDataValue(&value)); bacapp_parse_application_data(BACNET_APPLICATION_TAG_ENUMERATED,
status = bacapp_parse_application_data( "0xFFFFFFFF", &value);
BACNET_APPLICATION_TAG_ENUMERATED, ct_test(pTest, status == true);
"0xFFFFFFFF", ct_test(pTest, value.type.Enumerated == 0xFFFFFFFF);
&value); ct_test(pTest, testBACnetApplicationDataValue(&value));
ct_test(pTest,status == true);
ct_test(pTest,value.type.Enumerated == 0xFFFFFFFF);
ct_test(pTest,testBACnetApplicationDataValue(&value));
status = bacapp_parse_application_data( status = bacapp_parse_application_data(BACNET_APPLICATION_TAG_DATE,
BACNET_APPLICATION_TAG_DATE, "2005/5/22:1", &value);
"2005/5/22:1", ct_test(pTest, status == true);
&value); ct_test(pTest, value.type.Date.year == 2005);
ct_test(pTest,status == true); ct_test(pTest, value.type.Date.month == 5);
ct_test(pTest,value.type.Date.year == 2005); ct_test(pTest, value.type.Date.day == 22);
ct_test(pTest,value.type.Date.month == 5); ct_test(pTest, value.type.Date.wday == 1);
ct_test(pTest,value.type.Date.day == 22); ct_test(pTest, testBACnetApplicationDataValue(&value));
ct_test(pTest,value.type.Date.wday == 1);
ct_test(pTest,testBACnetApplicationDataValue(&value));
status = bacapp_parse_application_data( status = bacapp_parse_application_data(BACNET_APPLICATION_TAG_TIME,
BACNET_APPLICATION_TAG_TIME, "23:59:59.12", &value);
"23:59:59.12", ct_test(pTest, status == true);
&value); ct_test(pTest, value.type.Time.hour == 23);
ct_test(pTest,status == true); ct_test(pTest, value.type.Time.min == 59);
ct_test(pTest,value.type.Time.hour == 23); ct_test(pTest, value.type.Time.sec == 59);
ct_test(pTest,value.type.Time.min == 59); ct_test(pTest, value.type.Time.hundredths == 12);
ct_test(pTest,value.type.Time.sec == 59); ct_test(pTest, testBACnetApplicationDataValue(&value));
ct_test(pTest,value.type.Time.hundredths == 12);
ct_test(pTest,testBACnetApplicationDataValue(&value));
status = bacapp_parse_application_data( status =
BACNET_APPLICATION_TAG_OBJECT_ID, bacapp_parse_application_data(BACNET_APPLICATION_TAG_OBJECT_ID,
"0:100", "0:100", &value);
&value); ct_test(pTest, status == true);
ct_test(pTest,status == true); ct_test(pTest, value.type.Object_Id.type == 0);
ct_test(pTest,value.type.Object_Id.type == 0); ct_test(pTest, value.type.Object_Id.instance == 100);
ct_test(pTest,value.type.Object_Id.instance == 100); ct_test(pTest, testBACnetApplicationDataValue(&value));
ct_test(pTest,testBACnetApplicationDataValue(&value));
status = bacapp_parse_application_data( status =
BACNET_APPLICATION_TAG_CHARACTER_STRING, bacapp_parse_application_data
"Karg!", (BACNET_APPLICATION_TAG_CHARACTER_STRING, "Karg!", &value);
&value); ct_test(pTest, status == true);
ct_test(pTest,status == true); ct_test(pTest, testBACnetApplicationDataValue(&value));
ct_test(pTest,testBACnetApplicationDataValue(&value));
return; return;
} }
+15 -27
View File
@@ -40,11 +40,9 @@
#include "bacdef.h" #include "bacdef.h"
#include "bacstr.h" #include "bacstr.h"
typedef struct BACnet_Application_Data_Value typedef struct BACnet_Application_Data_Value {
{
uint8_t tag; uint8_t tag;
union union {
{
/* NULL - not needed as it is encoded in the tag alone */ /* NULL - not needed as it is encoded in the tag alone */
bool Boolean; bool Boolean;
uint32_t Unsigned_Int; uint32_t Unsigned_Int;
@@ -65,41 +63,31 @@ typedef struct BACnet_Application_Data_Value
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
int bacapp_decode_application_data( int bacapp_decode_application_data(uint8_t * apdu,
uint8_t *apdu, uint8_t apdu_len, BACNET_APPLICATION_DATA_VALUE * value);
uint8_t apdu_len,
BACNET_APPLICATION_DATA_VALUE *value);
int bacapp_encode_application_data( int bacapp_encode_application_data(uint8_t * apdu,
uint8_t *apdu, BACNET_APPLICATION_DATA_VALUE * value);
BACNET_APPLICATION_DATA_VALUE *value);
bool bacapp_copy( bool bacapp_copy(BACNET_APPLICATION_DATA_VALUE * dest_value,
BACNET_APPLICATION_DATA_VALUE *dest_value, BACNET_APPLICATION_DATA_VALUE * src_value);
BACNET_APPLICATION_DATA_VALUE *src_value);
bool bacapp_compare( bool bacapp_compare(BACNET_APPLICATION_DATA_VALUE * value,
BACNET_APPLICATION_DATA_VALUE *value, BACNET_APPLICATION_DATA_VALUE * test_value);
BACNET_APPLICATION_DATA_VALUE *test_value);
bool bacapp_parse_application_data( bool bacapp_parse_application_data(BACNET_APPLICATION_TAG tag_number,
BACNET_APPLICATION_TAG tag_number, const char *argv, BACNET_APPLICATION_DATA_VALUE * value);
const char *argv,
BACNET_APPLICATION_DATA_VALUE *value);
bool bacapp_print_value( bool bacapp_print_value(FILE * stream,
FILE *stream, BACNET_APPLICATION_DATA_VALUE * value,
BACNET_APPLICATION_DATA_VALUE *value,
BACNET_PROPERTY_ID property); BACNET_PROPERTY_ID property);
#ifdef TEST #ifdef TEST
#include "ctest.h" #include "ctest.h"
void testBACnetApplicationData(Test * pTest); void testBACnetApplicationData(Test * pTest);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+178 -177
View File
@@ -124,8 +124,7 @@ int decode_max_segs(uint8_t octet)
{ {
int max_segs = 0; int max_segs = 0;
switch (octet & 0xF0) switch (octet & 0xF0) {
{
case 0: case 0:
max_segs = 0; max_segs = 0;
break; break;
@@ -161,8 +160,7 @@ int decode_max_apdu(uint8_t octet)
{ {
int max_apdu = 0; int max_apdu = 0;
switch (octet & 0x0F) switch (octet & 0x0F) {
{
case 0: case 0:
max_apdu = 50; max_apdu = 50;
break; break;
@@ -193,7 +191,8 @@ int encode_unsigned16(uint8_t * apdu, uint16_t value)
union { union {
uint8_t byte[2]; uint8_t byte[2];
uint16_t value; uint16_t value;
} short_data = {{0}}; } short_data = { {
0}};
short_data.value = value; short_data.value = value;
if (big_endian()) { if (big_endian()) {
@@ -207,12 +206,13 @@ int encode_unsigned16(uint8_t * apdu, uint16_t value)
return 2; return 2;
} }
int decode_unsigned16(uint8_t * apdu, uint16_t *value) int decode_unsigned16(uint8_t * apdu, uint16_t * value)
{ {
union { union {
uint8_t byte[2]; uint8_t byte[2];
uint16_t value; uint16_t value;
} short_data = {{0}}; } short_data = { {
0}};
if (big_endian()) { if (big_endian()) {
short_data.byte[0] = apdu[0]; short_data.byte[0] = apdu[0];
@@ -232,7 +232,8 @@ int encode_unsigned24(uint8_t * apdu, uint32_t value)
union { union {
uint8_t byte[4]; uint8_t byte[4];
uint32_t value; uint32_t value;
} long_data = {{0}}; } long_data = { {
0}};
long_data.value = value; long_data.value = value;
if (big_endian()) { if (big_endian()) {
@@ -248,12 +249,13 @@ int encode_unsigned24(uint8_t * apdu, uint32_t value)
return 3; return 3;
} }
int decode_unsigned24(uint8_t * apdu, uint32_t *value) int decode_unsigned24(uint8_t * apdu, uint32_t * value)
{ {
union { union {
uint8_t byte[4]; uint8_t byte[4];
uint32_t value; uint32_t value;
} long_data = {{0}}; } long_data = { {
0}};
if (big_endian()) { if (big_endian()) {
long_data.byte[1] = apdu[0]; long_data.byte[1] = apdu[0];
@@ -275,7 +277,8 @@ int encode_unsigned32(uint8_t * apdu, uint32_t value)
union { union {
uint8_t byte[4]; uint8_t byte[4];
uint32_t value; uint32_t value;
} long_data = {{0}}; } long_data = { {
0}};
long_data.value = value; long_data.value = value;
if (big_endian()) { if (big_endian()) {
@@ -293,12 +296,13 @@ int encode_unsigned32(uint8_t * apdu, uint32_t value)
return 4; return 4;
} }
int decode_unsigned32(uint8_t * apdu, uint32_t *value) int decode_unsigned32(uint8_t * apdu, uint32_t * value)
{ {
union { union {
uint8_t byte[4]; uint8_t byte[4];
uint32_t value; uint32_t value;
} long_data = {{0}}; } long_data = { {
0}};
if (big_endian()) { if (big_endian()) {
long_data.byte[0] = apdu[0]; long_data.byte[0] = apdu[0];
@@ -322,7 +326,8 @@ int encode_signed8(uint8_t * apdu, int8_t value)
union { union {
uint8_t byte; uint8_t byte;
int8_t value; int8_t value;
} byte_data = {0}; } byte_data = {
0};
byte_data.value = value; byte_data.value = value;
apdu[0] = byte_data.byte; apdu[0] = byte_data.byte;
@@ -330,12 +335,13 @@ int encode_signed8(uint8_t * apdu, int8_t value)
return 1; return 1;
} }
int decode_signed8(uint8_t * apdu, int8_t *value) int decode_signed8(uint8_t * apdu, int8_t * value)
{ {
union { union {
uint8_t byte; uint8_t byte;
int8_t value; int8_t value;
} byte_data = {0}; } byte_data = {
0};
byte_data.byte = apdu[0]; byte_data.byte = apdu[0];
if (value) if (value)
@@ -349,7 +355,8 @@ int encode_signed16(uint8_t * apdu, int16_t value)
union { union {
uint8_t byte[2]; uint8_t byte[2];
int16_t value; int16_t value;
} short_data = {{0}}; } short_data = { {
0}};
short_data.value = value; short_data.value = value;
if (big_endian()) { if (big_endian()) {
@@ -363,12 +370,13 @@ int encode_signed16(uint8_t * apdu, int16_t value)
return 2; return 2;
} }
int decode_signed16(uint8_t * apdu, int16_t *value) int decode_signed16(uint8_t * apdu, int16_t * value)
{ {
union { union {
uint8_t byte[2]; uint8_t byte[2];
int16_t value; int16_t value;
} short_data = {{0}}; } short_data = { {
0}};
if (big_endian()) { if (big_endian()) {
short_data.byte[0] = apdu[0]; short_data.byte[0] = apdu[0];
@@ -388,7 +396,8 @@ int encode_signed24(uint8_t * apdu, int32_t value)
union { union {
uint8_t byte[4]; uint8_t byte[4];
int32_t value; int32_t value;
} long_data = {{0}}; } long_data = { {
0}};
long_data.value = value; long_data.value = value;
if (big_endian()) { if (big_endian()) {
@@ -404,12 +413,13 @@ int encode_signed24(uint8_t * apdu, int32_t value)
return 3; return 3;
} }
int decode_signed24(uint8_t * apdu, int32_t *value) int decode_signed24(uint8_t * apdu, int32_t * value)
{ {
union { union {
uint8_t byte[4]; uint8_t byte[4];
int32_t value; int32_t value;
} long_data = {{0}}; } long_data = { {
0}};
if (big_endian()) { if (big_endian()) {
/* negative - bit 7 is set */ /* negative - bit 7 is set */
@@ -439,7 +449,8 @@ int encode_signed32(uint8_t * apdu, int32_t value)
union { union {
uint8_t byte[4]; uint8_t byte[4];
int32_t value; int32_t value;
} long_data = {{0}}; } long_data = { {
0}};
long_data.value = value; long_data.value = value;
if (big_endian()) { if (big_endian()) {
@@ -457,12 +468,13 @@ int encode_signed32(uint8_t * apdu, int32_t value)
return 4; return 4;
} }
int decode_signed32(uint8_t * apdu, int32_t *value) int decode_signed32(uint8_t * apdu, int32_t * value)
{ {
union { union {
uint8_t byte[4]; uint8_t byte[4];
int32_t value; int32_t value;
} long_data = {{0}}; } long_data = { {
0}};
if (big_endian()) { if (big_endian()) {
long_data.byte[0] = apdu[0]; long_data.byte[0] = apdu[0];
@@ -509,10 +521,11 @@ 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++] = (uint8_t)len_value_type; apdu[len++] = (uint8_t) len_value_type;
} else if (len_value_type <= 65535) { } else if (len_value_type <= 65535) {
apdu[len++] = 254; apdu[len++] = 254;
len += encode_unsigned16(&apdu[len], (uint16_t)len_value_type); len +=
encode_unsigned16(&apdu[len], (uint16_t) len_value_type);
} else { } else {
apdu[len++] = 255; apdu[len++] = 255;
len += encode_unsigned32(&apdu[len], len_value_type); len += encode_unsigned32(&apdu[len], len_value_type);
@@ -785,7 +798,7 @@ static uint8_t byte_reverse_bits(uint8_t in_byte)
// from clause 20.2.10 Encoding of a Bit String Value // from clause 20.2.10 Encoding of a Bit String Value
// returns the number of apdu bytes consumed // returns the number of apdu bytes consumed
int decode_bitstring(uint8_t * apdu, uint32_t len_value, int decode_bitstring(uint8_t * apdu, uint32_t len_value,
BACNET_BIT_STRING *bit_string) BACNET_BIT_STRING * bit_string)
{ {
int len = 0; int len = 0;
uint8_t unused_bits = 0; uint8_t unused_bits = 0;
@@ -794,20 +807,18 @@ int decode_bitstring(uint8_t * apdu, uint32_t len_value,
bitstring_init(bit_string); bitstring_init(bit_string);
if (len_value) if (len_value) {
{
// the first octet contains the unused bits // the first octet contains the unused bits
bytes_used = len_value - 1; bytes_used = len_value - 1;
if (bytes_used <= MAX_BITSTRING_BYTES) if (bytes_used <= MAX_BITSTRING_BYTES) {
{
len = 1; len = 1;
for (i = 0; i < bytes_used; i++) for (i = 0; i < bytes_used; i++) {
{ bitstring_set_octet(bit_string, (uint8_t) i,
bitstring_set_octet(bit_string, (uint8_t)i, byte_reverse_bits(apdu[len++])); byte_reverse_bits(apdu[len++]));
} }
unused_bits = apdu[0] & 0x07; unused_bits = apdu[0] & 0x07;
bitstring_set_bits_used(bit_string, bitstring_set_bits_used(bit_string,
(uint8_t)bytes_used, unused_bits); (uint8_t) bytes_used, unused_bits);
} }
} }
@@ -816,7 +827,7 @@ int decode_bitstring(uint8_t * apdu, uint32_t len_value,
// from clause 20.2.10 Encoding of a Bit String Value // from clause 20.2.10 Encoding of a Bit String Value
// returns the number of apdu bytes consumed // returns the number of apdu bytes consumed
int encode_bitstring(uint8_t * apdu, BACNET_BIT_STRING *bit_string) int encode_bitstring(uint8_t * apdu, BACNET_BIT_STRING * bit_string)
{ {
int len = 0; int len = 0;
uint8_t remaining_used_bits = 0; uint8_t remaining_used_bits = 0;
@@ -826,26 +837,25 @@ int encode_bitstring(uint8_t * apdu, BACNET_BIT_STRING *bit_string)
// if the bit string is empty, then the first octet shall be zero // if the bit string is empty, then the first octet shall be zero
if (bitstring_bits_used(bit_string) == 0) if (bitstring_bits_used(bit_string) == 0)
apdu[len++] = 0; apdu[len++] = 0;
else else {
{
used_bytes = bitstring_bytes_used(bit_string); used_bytes = bitstring_bytes_used(bit_string);
remaining_used_bits = bitstring_bits_used(bit_string) - remaining_used_bits = bitstring_bits_used(bit_string) -
((used_bytes - 1) * 8); ((used_bytes - 1) * 8);
// number of unused bits in the subsequent final octet // number of unused bits in the subsequent final octet
apdu[len++] = 8 - remaining_used_bits; apdu[len++] = 8 - remaining_used_bits;
for (i = 0; i < used_bytes; i++) for (i = 0; i < used_bytes; i++) {
{ apdu[len++] =
apdu[len++] = byte_reverse_bits(bitstring_octet(bit_string,i)); byte_reverse_bits(bitstring_octet(bit_string, i));
} }
} }
return len; return len;
} }
int encode_tagged_bitstring(uint8_t * apdu, BACNET_BIT_STRING *bit_string) int encode_tagged_bitstring(uint8_t * apdu, BACNET_BIT_STRING * bit_string)
{ {
int len = 0; int len = 0;
int bit_string_encoded_length = 1;// 1 for the bits remaining octet int bit_string_encoded_length = 1; // 1 for the bits remaining octet
// bit string may use more than 1 octet for the tag, so find out how many // bit string may use more than 1 octet for the tag, so find out how many
bit_string_encoded_length += bitstring_bytes_used(bit_string); bit_string_encoded_length += bitstring_bytes_used(bit_string);
@@ -924,15 +934,12 @@ 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( int decode_object_id(uint8_t * apdu, int *object_type, uint32_t * instance)
uint8_t *apdu,
int *object_type,
uint32_t *instance)
{ {
uint32_t value = 0; uint32_t value = 0;
int len = 0; int len = 0;
len = decode_unsigned32(apdu,&value); len = decode_unsigned32(apdu, &value);
*object_type = ((value >> BACNET_INSTANCE_BITS) & BACNET_MAX_OBJECT); *object_type = ((value >> BACNET_INSTANCE_BITS) & BACNET_MAX_OBJECT);
*instance = (value & BACNET_MAX_INSTANCE); *instance = (value & BACNET_MAX_INSTANCE);
@@ -941,10 +948,8 @@ int decode_object_id(
// 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( int encode_bacnet_object_id(uint8_t * apdu,
uint8_t * apdu, int object_type, uint32_t instance)
int object_type,
uint32_t instance)
{ {
uint32_t value = 0; uint32_t value = 0;
uint32_t type = 0; uint32_t type = 0;
@@ -953,7 +958,7 @@ int encode_bacnet_object_id(
type = object_type; type = object_type;
value = ((type & BACNET_MAX_OBJECT) << BACNET_INSTANCE_BITS) | value = ((type & BACNET_MAX_OBJECT) << BACNET_INSTANCE_BITS) |
(instance & BACNET_MAX_INSTANCE); (instance & BACNET_MAX_INSTANCE);
len = encode_unsigned32(apdu,value); len = encode_unsigned32(apdu, value);
return len; return len;
} }
@@ -961,17 +966,14 @@ int encode_bacnet_object_id(
// from clause 20.2.14 Encoding of an Object Identifier Value // from clause 20.2.14 Encoding of an Object Identifier 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
int encode_context_object_id( int encode_context_object_id(uint8_t * apdu,
uint8_t * apdu, int tag_number, int object_type, uint32_t instance)
int tag_number,
int object_type,
uint32_t instance)
{ {
int len = 0; int len = 0;
// assumes that the tag only consumes 1 octet // assumes that the tag only consumes 1 octet
len = encode_bacnet_object_id(&apdu[1], object_type, instance); len = encode_bacnet_object_id(&apdu[1], object_type, instance);
len += encode_tag(&apdu[0], (uint8_t)tag_number, true, len); len += encode_tag(&apdu[0], (uint8_t) tag_number, true, len);
return len; return len;
} }
@@ -979,10 +981,8 @@ int encode_context_object_id(
// from clause 20.2.14 Encoding of an Object Identifier Value // from clause 20.2.14 Encoding of an Object Identifier 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
int encode_tagged_object_id( int encode_tagged_object_id(uint8_t * apdu,
uint8_t * apdu, int object_type, uint32_t instance)
int object_type,
uint32_t instance)
{ {
int len = 0; int len = 0;
@@ -996,12 +996,11 @@ int encode_tagged_object_id(
// from clause 20.2.8 Encoding of an Octet String Value // from clause 20.2.8 Encoding of an Octet String Value
// returns the number of apdu bytes consumed // returns the number of apdu bytes consumed
int encode_octet_string(uint8_t * apdu, BACNET_OCTET_STRING *octet_string) int encode_octet_string(uint8_t * apdu, BACNET_OCTET_STRING * octet_string)
{ {
int len = 0; /* return value */ int len = 0; /* return value */
if (octet_string) if (octet_string) {
{
/* FIXME: might need to pass in the length of the APDU /* FIXME: might need to pass in the length of the APDU
to bounds check since it might not be the only data chunk */ to bounds check since it might not be the only data chunk */
len = octetstring_length(octet_string); len = octetstring_length(octet_string);
@@ -1015,13 +1014,13 @@ int encode_octet_string(uint8_t * apdu, BACNET_OCTET_STRING *octet_string)
// 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
int encode_tagged_octet_string(uint8_t * apdu, int encode_tagged_octet_string(uint8_t * apdu,
BACNET_OCTET_STRING *octet_string) BACNET_OCTET_STRING * octet_string)
{ {
int apdu_len = 0; int apdu_len = 0;
if (octet_string) if (octet_string) {
{ apdu_len =
apdu_len = encode_tag(&apdu[0], BACNET_APPLICATION_TAG_OCTET_STRING, encode_tag(&apdu[0], BACNET_APPLICATION_TAG_OCTET_STRING,
false, octetstring_length(octet_string)); false, octetstring_length(octet_string));
/* FIXME: probably need to pass in the length of the APDU /* FIXME: probably need to pass in the length of the APDU
to bounds check since it might not be the only data chunk */ to bounds check since it might not be the only data chunk */
@@ -1038,12 +1037,12 @@ int encode_tagged_octet_string(uint8_t * apdu,
// 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
int decode_octet_string(uint8_t * apdu, uint32_t len_value, int decode_octet_string(uint8_t * apdu, uint32_t len_value,
BACNET_OCTET_STRING *octet_string) BACNET_OCTET_STRING * octet_string)
{ {
int len = 0; // return value int len = 0; // return value
bool status = false; bool status = false;
status = octetstring_init(octet_string,&apdu[0],len_value); status = octetstring_init(octet_string, &apdu[0], len_value);
if (status) if (status)
len = len_value; len = len_value;
@@ -1053,7 +1052,7 @@ int decode_octet_string(uint8_t * apdu, uint32_t len_value,
// from clause 20.2.9 Encoding of a Character String Value // from clause 20.2.9 Encoding of a Character String Value
// returns the number of apdu bytes consumed // returns the number of apdu bytes consumed
int encode_bacnet_character_string(uint8_t * apdu, int encode_bacnet_character_string(uint8_t * apdu,
BACNET_CHARACTER_STRING *char_string) BACNET_CHARACTER_STRING * char_string)
{ {
int len; int len;
@@ -1061,20 +1060,22 @@ int encode_bacnet_character_string(uint8_t * apdu,
apdu[0] = characterstring_encoding(char_string); apdu[0] = characterstring_encoding(char_string);
memmove(&apdu[1], characterstring_value(char_string), len); memmove(&apdu[1], characterstring_value(char_string), len);
return len + 1 /* for encoding */; return len + 1 /* for encoding */ ;
} }
// from clause 20.2.9 Encoding of a Character String Value // from clause 20.2.9 Encoding of a Character String 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
int encode_tagged_character_string(uint8_t * apdu, int encode_tagged_character_string(uint8_t * apdu,
BACNET_CHARACTER_STRING *char_string) BACNET_CHARACTER_STRING * char_string)
{ {
int len = 0; int len = 0;
int string_len = 0; int string_len = 0;
string_len = characterstring_length(char_string) + 1 /* for encoding */; string_len =
len = encode_tag(&apdu[0], BACNET_APPLICATION_TAG_CHARACTER_STRING, characterstring_length(char_string) + 1 /* for encoding */ ;
len =
encode_tag(&apdu[0], BACNET_APPLICATION_TAG_CHARACTER_STRING,
false, string_len); false, string_len);
if ((len + string_len) < MAX_APDU) if ((len + string_len) < MAX_APDU)
len += encode_bacnet_character_string(&apdu[len], char_string); len += encode_bacnet_character_string(&apdu[len], char_string);
@@ -1085,13 +1086,14 @@ int encode_tagged_character_string(uint8_t * apdu,
} }
int encode_context_character_string(uint8_t * apdu, int tag_number, int encode_context_character_string(uint8_t * apdu, int tag_number,
BACNET_CHARACTER_STRING *char_string) BACNET_CHARACTER_STRING * char_string)
{ {
int len = 0; int len = 0;
int string_len = 0; int string_len = 0;
string_len = characterstring_length(char_string) + 1 /* for encoding */; string_len =
len += encode_tag(&apdu[0], (uint8_t)tag_number, true, string_len); characterstring_length(char_string) + 1 /* for encoding */ ;
len += encode_tag(&apdu[0], (uint8_t) tag_number, true, string_len);
if ((len + string_len) < MAX_APDU) if ((len + string_len) < MAX_APDU)
len += encode_bacnet_character_string(&apdu[len], char_string); len += encode_bacnet_character_string(&apdu[len], char_string);
else else
@@ -1104,13 +1106,13 @@ int encode_context_character_string(uint8_t * apdu, int tag_number,
// 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
int decode_character_string(uint8_t * apdu, uint32_t len_value, int decode_character_string(uint8_t * apdu, uint32_t len_value,
BACNET_CHARACTER_STRING *char_string) BACNET_CHARACTER_STRING * char_string)
{ {
int len = 0; // return value int len = 0; // return value
bool status = false; bool status = false;
status = characterstring_init(char_string, apdu[0], (char *)&apdu[1], status = characterstring_init(char_string, apdu[0], (char *) &apdu[1],
len_value-1); len_value - 1);
if (status) if (status)
len = len_value; len = len_value;
@@ -1126,14 +1128,14 @@ int encode_bacnet_unsigned(uint8_t * apdu, uint32_t value)
int len = 0; // return value int len = 0; // return value
if (value < 0x100) { if (value < 0x100) {
apdu[0] = (uint8_t)value; apdu[0] = (uint8_t) value;
len = 1; len = 1;
} else if (value < 0x10000) { } else if (value < 0x10000) {
len = encode_unsigned16(&apdu[0],(uint16_t)value); len = encode_unsigned16(&apdu[0], (uint16_t) value);
} else if (value < 0x1000000) { } else if (value < 0x1000000) {
len = encode_unsigned24(&apdu[0],value); len = encode_unsigned24(&apdu[0], value);
} else { } else {
len = encode_unsigned32(&apdu[0],value); len = encode_unsigned32(&apdu[0], value);
} }
return len; return len;
@@ -1147,7 +1149,7 @@ int encode_context_unsigned(uint8_t * apdu, int tag_number, uint32_t value)
int len = 0; int len = 0;
len = encode_bacnet_unsigned(&apdu[1], value); len = encode_bacnet_unsigned(&apdu[1], value);
len += encode_tag(&apdu[0], (uint8_t)tag_number, true, len); len += encode_tag(&apdu[0], (uint8_t) tag_number, true, len);
return len; return len;
} }
@@ -1170,7 +1172,7 @@ int encode_tagged_unsigned(uint8_t * apdu, uint32_t 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? // FIXME: What about endian?
int decode_unsigned(uint8_t * apdu, uint32_t len_value, uint32_t *value) int decode_unsigned(uint8_t * apdu, uint32_t len_value, uint32_t * value)
{ {
uint16_t unsigned16_value = 0; uint16_t unsigned16_value = 0;
@@ -1180,14 +1182,14 @@ int decode_unsigned(uint8_t * apdu, uint32_t len_value, uint32_t *value)
*value = apdu[0]; *value = apdu[0];
break; break;
case 2: case 2:
decode_unsigned16(&apdu[0],&unsigned16_value); decode_unsigned16(&apdu[0], &unsigned16_value);
*value = unsigned16_value; *value = unsigned16_value;
break; break;
case 3: case 3:
decode_unsigned24(&apdu[0],value); decode_unsigned24(&apdu[0], value);
break; break;
case 4: case 4:
decode_unsigned32(&apdu[0],value); decode_unsigned32(&apdu[0], value);
break; break;
default: default:
*value = 0; *value = 0;
@@ -1245,7 +1247,7 @@ int encode_context_enumerated(uint8_t * apdu, int tag_number, int value)
// assumes that the tag only consumes 1 octet // assumes that the tag only consumes 1 octet
len = encode_bacnet_enumerated(&apdu[1], value); len = encode_bacnet_enumerated(&apdu[1], value);
len += encode_tag(&apdu[0], (uint8_t)tag_number, true, len); len += encode_tag(&apdu[0], (uint8_t) tag_number, true, len);
return len; return len;
} }
@@ -1253,7 +1255,7 @@ int encode_context_enumerated(uint8_t * apdu, int tag_number, int value)
// from clause 20.2.5 Encoding of a Signed Integer Value // from clause 20.2.5 Encoding of a Signed 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
int decode_signed(uint8_t * apdu, uint32_t len_value, int32_t *value) int decode_signed(uint8_t * apdu, uint32_t len_value, int32_t * value)
{ {
int8_t signed8_value = 0; int8_t signed8_value = 0;
int16_t signed16_value = 0; int16_t signed16_value = 0;
@@ -1261,18 +1263,18 @@ int decode_signed(uint8_t * apdu, uint32_t len_value, int32_t *value)
if (value) { if (value) {
switch (len_value) { switch (len_value) {
case 1: case 1:
decode_signed8(&apdu[0],&signed8_value); decode_signed8(&apdu[0], &signed8_value);
*value = signed8_value; *value = signed8_value;
break; break;
case 2: case 2:
decode_signed16(&apdu[0],&signed16_value); decode_signed16(&apdu[0], &signed16_value);
*value = signed16_value; *value = signed16_value;
break; break;
case 3: case 3:
decode_signed24(&apdu[0],value); decode_signed24(&apdu[0], value);
break; break;
case 4: case 4:
decode_signed32(&apdu[0],value); decode_signed32(&apdu[0], value);
break; break;
default: default:
*value = 0; *value = 0;
@@ -1296,13 +1298,13 @@ int encode_bacnet_signed(uint8_t * apdu, int32_t value)
octet is 0, and the first octet shall not be X'FF' if the most octet is 0, and the first octet shall not be X'FF' if the most
significant bit of the second octet is 1. */ significant bit of the second octet is 1. */
if ((value >= -128) && (value < 128)) { if ((value >= -128) && (value < 128)) {
len = encode_signed8(&apdu[0],(int8_t)value); len = encode_signed8(&apdu[0], (int8_t) value);
} else if ((value >= -32768) && (value < 32768)) { } else if ((value >= -32768) && (value < 32768)) {
len = encode_signed16(&apdu[0],(int16_t)value); len = encode_signed16(&apdu[0], (int16_t) value);
} else if ((value > -8388608) && (value < 8388608)) { } else if ((value > -8388608) && (value < 8388608)) {
len = encode_signed24(&apdu[0],value); len = encode_signed24(&apdu[0], value);
} else { } else {
len = encode_signed32(&apdu[0],value); len = encode_signed32(&apdu[0], value);
} }
return len; return len;
@@ -1332,7 +1334,7 @@ int encode_context_signed(uint8_t * apdu, int tag_number, int32_t value)
// assumes that the tag only consumes 1 octet // assumes that the tag only consumes 1 octet
len = encode_bacnet_signed(&apdu[1], value); len = encode_bacnet_signed(&apdu[1], value);
len += encode_tag(&apdu[0], (uint8_t)tag_number, true, len); len += encode_tag(&apdu[0], (uint8_t) tag_number, true, len);
return len; return len;
} }
@@ -1394,8 +1396,7 @@ int encode_bacnet_date(uint8_t * apdu, int year, int month, int day,
int wday) int wday)
{ {
/* allow 2 digit years */ /* allow 2 digit years */
if (year < 1900) if (year < 1900) {
{
if (year <= 38) if (year <= 38)
year += 2000; year += 2000;
else else
@@ -1474,7 +1475,7 @@ static int get_apdu_len(bool extended_tag, uint32_t value)
return test_len; return test_len;
} }
static void print_apdu(uint8_t *pBlock, uint32_t num) static void print_apdu(uint8_t * pBlock, uint32_t num)
{ {
size_t lines = 0; /* number of lines to print */ size_t lines = 0; /* number of lines to print */
size_t line = 0; /* line of text counter */ size_t line = 0; /* line of text counter */
@@ -1621,8 +1622,10 @@ void testBACDCodeEnumerated(Test * pTest)
for (i = 0; i < 31; i++) { for (i = 0; i < 31; i++) {
apdu_len = encode_tagged_enumerated(&array[0], value); apdu_len = encode_tagged_enumerated(&array[0], value);
len = decode_tag_number_and_value(&array[0], &tag_number, &len_value); len =
len += decode_enumerated(&array[len],len_value, &decoded_value); decode_tag_number_and_value(&array[0], &tag_number,
&len_value);
len += decode_enumerated(&array[len], len_value, &decoded_value);
ct_test(pTest, decoded_value == value); ct_test(pTest, decoded_value == value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_ENUMERATED); ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_ENUMERATED);
ct_test(pTest, len == apdu_len); ct_test(pTest, len == apdu_len);
@@ -1664,10 +1667,9 @@ void testBACDCodeUnsignedValue(Test * pTest, uint32_t value)
len = decode_tag_number_and_value(&array[0], &tag_number, &len_value); len = decode_tag_number_and_value(&array[0], &tag_number, &len_value);
len = decode_unsigned(&array[len], len_value, &decoded_value); len = decode_unsigned(&array[len], len_value, &decoded_value);
ct_test(pTest, decoded_value == value); ct_test(pTest, decoded_value == value);
if (decoded_value != value) if (decoded_value != value) {
{
printf("value=%u decoded_value=%u\n", value, decoded_value); printf("value=%u decoded_value=%u\n", value, decoded_value);
print_apdu(&array[0],sizeof(array)); print_apdu(&array[0], sizeof(array));
} }
encode_tagged_unsigned(&encoded_array[0], decoded_value); encode_tagged_unsigned(&encoded_array[0], decoded_value);
ct_test(pTest, memcmp(&array[0], &encoded_array[0], ct_test(pTest, memcmp(&array[0], &encoded_array[0],
@@ -1689,9 +1691,9 @@ void testBACDCodeUnsigned(Test * pTest)
int i; int i;
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
testBACDCodeUnsignedValue(pTest, value-1); testBACDCodeUnsignedValue(pTest, value - 1);
testBACDCodeUnsignedValue(pTest, value); testBACDCodeUnsignedValue(pTest, value);
testBACDCodeUnsignedValue(pTest, value+1); testBACDCodeUnsignedValue(pTest, value + 1);
value = value << 1; value = value << 1;
} }
@@ -1714,19 +1716,17 @@ void testBACDCodeSignedValue(Test * pTest, int32_t value)
len = decode_signed(&array[len], len_value, &decoded_value); len = decode_signed(&array[len], len_value, &decoded_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_SIGNED_INT); ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_SIGNED_INT);
ct_test(pTest, decoded_value == value); ct_test(pTest, decoded_value == value);
if (decoded_value != value) if (decoded_value != value) {
{
printf("value=%d decoded_value=%d\n", value, decoded_value); printf("value=%d decoded_value=%d\n", value, decoded_value);
print_apdu(&array[0],sizeof(array)); print_apdu(&array[0], sizeof(array));
} }
encode_tagged_signed(&encoded_array[0], decoded_value); encode_tagged_signed(&encoded_array[0], decoded_value);
diff = memcmp(&array[0], &encoded_array[0], sizeof(array)); diff = memcmp(&array[0], &encoded_array[0], sizeof(array));
ct_test(pTest,diff == 0); ct_test(pTest, diff == 0);
if (diff) if (diff) {
{
printf("value=%d decoded_value=%d\n", value, decoded_value); printf("value=%d decoded_value=%d\n", value, decoded_value);
print_apdu(&array[0],sizeof(array)); print_apdu(&array[0], sizeof(array));
print_apdu(&encoded_array[0],sizeof(array)); print_apdu(&encoded_array[0], sizeof(array));
} }
// a signed int will take up to 4 octects // a signed int will take up to 4 octects
// plus a one octet for the tag // plus a one octet for the tag
@@ -1744,18 +1744,18 @@ void testBACDCodeSigned(Test * pTest)
int i = 0; int i = 0;
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
testBACDCodeSignedValue(pTest, value-1); testBACDCodeSignedValue(pTest, value - 1);
testBACDCodeSignedValue(pTest, value); testBACDCodeSignedValue(pTest, value);
testBACDCodeSignedValue(pTest, value+1); testBACDCodeSignedValue(pTest, value + 1);
value = value << 1; value = value << 1;
} }
testBACDCodeSignedValue(pTest,-1); testBACDCodeSignedValue(pTest, -1);
value = -2; value = -2;
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
testBACDCodeSignedValue(pTest, value-1); testBACDCodeSignedValue(pTest, value - 1);
testBACDCodeSignedValue(pTest, value); testBACDCodeSignedValue(pTest, value);
testBACDCodeSignedValue(pTest, value+1); testBACDCodeSignedValue(pTest, value + 1);
value = value << 1; value = value << 1;
} }
@@ -1777,11 +1777,8 @@ void testBACDCodeOctetString(Test * pTest)
bool status = false; bool status = false;
int diff = 0; /* for memcmp */ int diff = 0; /* for memcmp */
status = octetstring_init( status = octetstring_init(&octet_string, NULL, 0);
&octet_string, ct_test(pTest, status == true);
NULL,
0);
ct_test(pTest,status == true);
apdu_len = encode_tagged_octet_string(&array[0], &octet_string); apdu_len = encode_tagged_octet_string(&array[0], &octet_string);
len = decode_tag_number_and_value(&array[0], &tag_number, &len_value); len = decode_tag_number_and_value(&array[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OCTET_STRING); ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OCTET_STRING);
@@ -1789,18 +1786,17 @@ void testBACDCodeOctetString(Test * pTest)
ct_test(pTest, apdu_len == len); ct_test(pTest, apdu_len == len);
diff = memcmp(octetstring_value(&octet_string), &test_value[0], diff = memcmp(octetstring_value(&octet_string), &test_value[0],
octetstring_length(&octet_string)); octetstring_length(&octet_string));
ct_test(pTest,diff == 0); ct_test(pTest, diff == 0);
for (i = 0; i < (MAX_APDU - 6); i++) { for (i = 0; i < (MAX_APDU - 6); i++) {
test_value[i] = '0' + (i % 10); test_value[i] = '0' + (i % 10);
status = octetstring_init( status = octetstring_init(&octet_string, test_value, i);
&octet_string, ct_test(pTest, status == true);
test_value, apdu_len =
i); encode_tagged_octet_string(&encoded_array[0], &octet_string);
ct_test(pTest,status == true); len =
apdu_len = encode_tagged_octet_string(&encoded_array[0],&octet_string); decode_tag_number_and_value(&encoded_array[0], &tag_number,
len = decode_tag_number_and_value(&encoded_array[0], &len_value);
&tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OCTET_STRING); ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OCTET_STRING);
len += decode_octet_string(&encoded_array[len], len_value, len += decode_octet_string(&encoded_array[len], len_value,
&test_octet_string); &test_octet_string);
@@ -1813,7 +1809,7 @@ void testBACDCodeOctetString(Test * pTest)
if (diff) { if (diff) {
printf("test octet string=#%d\n", i); printf("test octet string=#%d\n", i);
} }
ct_test(pTest,diff == 0); ct_test(pTest, diff == 0);
} }
return; return;
@@ -1834,34 +1830,37 @@ void testBACDCodeCharacterString(Test * pTest)
int diff = 0; /* for comparison */ int diff = 0; /* for comparison */
bool status = false; bool status = false;
status = characterstring_init( status = characterstring_init(&char_string,
&char_string, CHARACTER_ANSI_X34, NULL, 0);
CHARACTER_ANSI_X34, ct_test(pTest, status == true);
NULL,
0);
ct_test(pTest,status == true);
apdu_len = encode_tagged_character_string(&array[0], &char_string); apdu_len = encode_tagged_character_string(&array[0], &char_string);
len = decode_tag_number_and_value(&array[0], &tag_number, &len_value); len = decode_tag_number_and_value(&array[0], &tag_number, &len_value);
ct_test(pTest,tag_number == BACNET_APPLICATION_TAG_CHARACTER_STRING); ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_CHARACTER_STRING);
len += decode_character_string(&array[len], len_value, &test_char_string); len +=
decode_character_string(&array[len], len_value, &test_char_string);
ct_test(pTest, apdu_len == len); ct_test(pTest, apdu_len == len);
diff = memcmp(characterstring_value(&char_string), &test_value[0], diff = memcmp(characterstring_value(&char_string), &test_value[0],
characterstring_length(&char_string)); characterstring_length(&char_string));
ct_test(pTest, diff == 0); ct_test(pTest, diff == 0);
for (i = 0; i < MAX_CHARACTER_STRING_BYTES-1; i++) { for (i = 0; i < MAX_CHARACTER_STRING_BYTES - 1; i++) {
test_value[i] = 'S'; test_value[i] = 'S';
test_value[i + 1] = '\0'; test_value[i + 1] = '\0';
status = characterstring_init_ansi(&char_string, test_value); status = characterstring_init_ansi(&char_string, test_value);
ct_test(pTest,status == true); ct_test(pTest, status == true);
apdu_len = apdu_len =
encode_tagged_character_string(&encoded_array[0], &char_string); encode_tagged_character_string(&encoded_array[0],
len = decode_tag_number_and_value(&encoded_array[0], &char_string);
&tag_number, &len_value); len =
ct_test(pTest,tag_number == BACNET_APPLICATION_TAG_CHARACTER_STRING); decode_tag_number_and_value(&encoded_array[0], &tag_number,
len += decode_character_string(&encoded_array[len], len_value, &len_value);
ct_test(pTest,
tag_number == BACNET_APPLICATION_TAG_CHARACTER_STRING);
len +=
decode_character_string(&encoded_array[len], len_value,
&test_char_string); &test_char_string);
if (apdu_len != len) { if (apdu_len != len) {
printf("test string=#%d apdu_len=%d len=%d\n", i,apdu_len,len); printf("test string=#%d apdu_len=%d len=%d\n", i, apdu_len,
len);
} }
ct_test(pTest, apdu_len == len); ct_test(pTest, apdu_len == len);
diff = memcmp(characterstring_value(&char_string), &test_value[0], diff = memcmp(characterstring_value(&char_string), &test_value[0],
@@ -1897,7 +1896,8 @@ void testBACDCodeObject(Test * pTest)
ct_test(pTest, memcmp(&object_array[0], &encoded_array[0], ct_test(pTest, memcmp(&object_array[0], &encoded_array[0],
sizeof(object_array)) == 0); sizeof(object_array)) == 0);
for (type = 0; type < 1024; type++) { for (type = 0; type < 1024; type++) {
for (instance = 0; instance <= BACNET_MAX_INSTANCE; instance += 1024) { for (instance = 0; instance <= BACNET_MAX_INSTANCE;
instance += 1024) {
encode_bacnet_object_id(&encoded_array[0], type, instance); encode_bacnet_object_id(&encoded_array[0], type, instance);
decode_object_id(&encoded_array[0], decode_object_id(&encoded_array[0],
(int *) &decoded_type, &decoded_instance); (int *) &decoded_type, &decoded_instance);
@@ -1914,17 +1914,15 @@ void testBACDCodeObject(Test * pTest)
void testBACDCodeMaxSegsApdu(Test * pTest) void testBACDCodeMaxSegsApdu(Test * pTest)
{ {
int max_segs[8] = {0,2,4,8,16,32,64,65}; int max_segs[8] = { 0, 2, 4, 8, 16, 32, 64, 65 };
int max_apdu[6] = {50,128,206,480,1024,1476}; int max_apdu[6] = { 50, 128, 206, 480, 1024, 1476 };
int i = 0; int i = 0;
int j = 0; int j = 0;
uint8_t octet = 0; uint8_t octet = 0;
// test // test
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++) {
{ for (j = 0; j < 6; j++) {
for (j = 0; j < 6; j++)
{
octet = encode_max_segs_max_apdu(max_segs[i], max_apdu[j]); octet = encode_max_segs_max_apdu(max_segs[i], max_apdu[j]);
ct_test(pTest, max_segs[i] == decode_max_segs(octet)); ct_test(pTest, max_segs[i] == decode_max_segs(octet));
ct_test(pTest, max_apdu[j] == decode_max_apdu(octet)); ct_test(pTest, max_apdu[j] == decode_max_apdu(octet));
@@ -1945,39 +1943,42 @@ void testBACDCodeBitString(Test * pTest)
bitstring_init(&bit_string); bitstring_init(&bit_string);
// verify initialization // verify initialization
ct_test(pTest, bitstring_bits_used(&bit_string) == 0); ct_test(pTest, bitstring_bits_used(&bit_string) == 0);
for (bit = 0; bit < (MAX_BITSTRING_BYTES*8); bit++) for (bit = 0; bit < (MAX_BITSTRING_BYTES * 8); bit++) {
{
ct_test(pTest, bitstring_bit(&bit_string, bit) == false); ct_test(pTest, bitstring_bit(&bit_string, bit) == false);
} }
// test encode/decode -- true // test encode/decode -- true
for (bit = 0; bit < (MAX_BITSTRING_BYTES*8); bit++) for (bit = 0; bit < (MAX_BITSTRING_BYTES * 8); bit++) {
{
bitstring_set_bit(&bit_string, bit, true); bitstring_set_bit(&bit_string, bit, true);
ct_test(pTest, bitstring_bits_used(&bit_string) == (bit + 1)); ct_test(pTest, bitstring_bits_used(&bit_string) == (bit + 1));
ct_test(pTest, bitstring_bit(&bit_string, bit) == true); ct_test(pTest, bitstring_bit(&bit_string, bit) == true);
// encode // encode
len = encode_tagged_bitstring(&apdu[0], &bit_string); len = encode_tagged_bitstring(&apdu[0], &bit_string);
// decode // decode
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value); len =
decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_BIT_STRING); ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_BIT_STRING);
len += decode_bitstring(&apdu[len], len_value,&decoded_bit_string); len +=
ct_test(pTest, bitstring_bits_used(&decoded_bit_string) == (bit + 1)); decode_bitstring(&apdu[len], len_value, &decoded_bit_string);
ct_test(pTest,
bitstring_bits_used(&decoded_bit_string) == (bit + 1));
ct_test(pTest, bitstring_bit(&decoded_bit_string, bit) == true); ct_test(pTest, bitstring_bit(&decoded_bit_string, bit) == true);
} }
// test encode/decode -- false // test encode/decode -- false
bitstring_init(&bit_string); bitstring_init(&bit_string);
for (bit = 0; bit < (MAX_BITSTRING_BYTES*8); bit++) for (bit = 0; bit < (MAX_BITSTRING_BYTES * 8); bit++) {
{
bitstring_set_bit(&bit_string, bit, false); bitstring_set_bit(&bit_string, bit, false);
ct_test(pTest, bitstring_bits_used(&bit_string) == (bit + 1)); ct_test(pTest, bitstring_bits_used(&bit_string) == (bit + 1));
ct_test(pTest, bitstring_bit(&bit_string, bit) == false); ct_test(pTest, bitstring_bit(&bit_string, bit) == false);
// encode // encode
len = encode_tagged_bitstring(&apdu[0], &bit_string); len = encode_tagged_bitstring(&apdu[0], &bit_string);
// decode // decode
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value); len =
decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_BIT_STRING); ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_BIT_STRING);
len += decode_bitstring(&apdu[len], len_value,&decoded_bit_string); len +=
ct_test(pTest, bitstring_bits_used(&decoded_bit_string) == (bit + 1)); decode_bitstring(&apdu[len], len_value, &decoded_bit_string);
ct_test(pTest,
bitstring_bits_used(&decoded_bit_string) == (bit + 1));
ct_test(pTest, bitstring_bit(&decoded_bit_string, bit) == false); ct_test(pTest, bitstring_bit(&decoded_bit_string, bit) == false);
} }
} }
+73 -66
View File
@@ -46,112 +46,120 @@ extern "C" {
// 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
int encode_tag(uint8_t * apdu, uint8_t tag_number, bool context_specific, int encode_tag(uint8_t * apdu, uint8_t tag_number,
uint32_t len_value_type); bool context_specific, uint32_t len_value_type);
// from clause 20.2.1.3.2 Constructed Data // from clause 20.2.1.3.2 Constructed Data
// returns the number of apdu bytes consumed // returns the number of apdu bytes consumed
int encode_opening_tag(uint8_t * apdu, uint8_t tag_number); int encode_opening_tag(uint8_t * apdu, uint8_t tag_number);
int encode_closing_tag(uint8_t * apdu, uint8_t tag_number); int encode_closing_tag(uint8_t * apdu, uint8_t tag_number);
int decode_tag_number_and_value(uint8_t * apdu, uint8_t * tag_number, int decode_tag_number_and_value(uint8_t * apdu, uint8_t * tag_number,
uint32_t * value); uint32_t * value);
// returns true if the tag is context specific // returns true if the tag is context specific
bool decode_is_context_specific(uint8_t * apdu); bool decode_is_context_specific(uint8_t * apdu);
// returns true if the tag is an opening tag and matches // returns true if the tag is an opening tag and matches
bool decode_is_opening_tag_number(uint8_t * apdu, uint8_t tag_number); bool decode_is_opening_tag_number(uint8_t * apdu, uint8_t tag_number);
// returns true if the tag is a closing tag and matches // returns true if the tag is a closing tag and matches
bool decode_is_closing_tag_number(uint8_t * apdu, uint8_t tag_number); bool decode_is_closing_tag_number(uint8_t * apdu, uint8_t tag_number);
// returns true if the tag is context specific and matches // returns true if the tag is context specific and matches
bool decode_is_context_tag(uint8_t * apdu, uint8_t tag_number); bool decode_is_context_tag(uint8_t * apdu, uint8_t tag_number);
// from clause 20.2.2 Encoding of a Null Value // from clause 20.2.2 Encoding of a Null Value
int encode_tagged_null(uint8_t * apdu); int encode_tagged_null(uint8_t * apdu);
// from clause 20.2.3 Encoding of a Boolean Value // from clause 20.2.3 Encoding of a Boolean Value
int encode_tagged_boolean(uint8_t * apdu, bool boolean_value); int encode_tagged_boolean(uint8_t * apdu, bool boolean_value);
bool decode_boolean(uint32_t len_value); bool decode_boolean(uint32_t len_value);
int encode_context_boolean(uint8_t * apdu, bool boolean_value); int encode_context_boolean(uint8_t * apdu, bool boolean_value);
bool decode_context_boolean(uint8_t * apdu); bool decode_context_boolean(uint8_t * apdu);
// from clause 20.2.10 Encoding of a Bit String Value // from clause 20.2.10 Encoding of a Bit String Value
// returns the number of apdu bytes consumed // returns the number of apdu bytes consumed
int decode_bitstring(uint8_t * apdu, uint32_t len_value, int decode_bitstring(uint8_t * apdu, uint32_t len_value,
BACNET_BIT_STRING *bit_string); BACNET_BIT_STRING * bit_string);
// returns the number of apdu bytes consumed // returns the number of apdu bytes consumed
int encode_bitstring(uint8_t * apdu, BACNET_BIT_STRING *bit_string); int encode_bitstring(uint8_t * apdu, BACNET_BIT_STRING * bit_string);
int encode_tagged_bitstring(uint8_t * apdu, BACNET_BIT_STRING *bit_string); int encode_tagged_bitstring(uint8_t * apdu,
BACNET_BIT_STRING * bit_string);
// from clause 20.2.6 Encoding of a Real Number Value // from clause 20.2.6 Encoding of a Real Number 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
int decode_real(uint8_t * apdu, float *real_value); int decode_real(uint8_t * apdu, float *real_value);
int encode_bacnet_real(float value, uint8_t * apdu); int encode_bacnet_real(float value, uint8_t * apdu);
int encode_tagged_real(uint8_t * apdu, float value); 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
// 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
int decode_object_id(uint8_t * apdu, int *object_type, uint32_t *instance); int decode_object_id(uint8_t * apdu, int *object_type,
int encode_bacnet_object_id(uint8_t * apdu, int object_type, uint32_t instance); uint32_t * instance);
int encode_context_object_id(uint8_t * apdu, int tag_number, int encode_bacnet_object_id(uint8_t * apdu, int object_type,
uint32_t instance);
int encode_context_object_id(uint8_t * apdu, int tag_number,
int object_type, uint32_t instance); int object_type, uint32_t instance);
int encode_tagged_object_id(uint8_t * apdu, int object_type, uint32_t instance); int encode_tagged_object_id(uint8_t * apdu, int object_type,
uint32_t instance);
// from clause 20.2.8 Encoding of an Octet String Value // from clause 20.2.8 Encoding of an Octet String 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
int encode_octet_string(uint8_t * apdu, int encode_octet_string(uint8_t * apdu,
BACNET_OCTET_STRING *octet_string); BACNET_OCTET_STRING * octet_string);
int encode_tagged_octet_string(uint8_t * apdu, int encode_tagged_octet_string(uint8_t * apdu,
BACNET_OCTET_STRING *octet_string); BACNET_OCTET_STRING * octet_string);
int decode_octet_string(uint8_t * apdu, uint32_t len_value, int decode_octet_string(uint8_t * apdu, uint32_t len_value,
BACNET_OCTET_STRING *octet_string); BACNET_OCTET_STRING * octet_string);
// from clause 20.2.9 Encoding of a Character String Value // from clause 20.2.9 Encoding of a Character String 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
int encode_bacnet_character_string(uint8_t * apdu, int encode_bacnet_character_string(uint8_t * apdu,
BACNET_CHARACTER_STRING *char_string); BACNET_CHARACTER_STRING * char_string);
int encode_tagged_character_string(uint8_t * apdu, int encode_tagged_character_string(uint8_t * apdu,
BACNET_CHARACTER_STRING *char_string); BACNET_CHARACTER_STRING * char_string);
int encode_context_character_string(uint8_t * apdu, int tag_number, int encode_context_character_string(uint8_t * apdu, int tag_number,
BACNET_CHARACTER_STRING *char_string); BACNET_CHARACTER_STRING * char_string);
int decode_character_string(uint8_t * apdu, uint32_t len_value, int decode_character_string(uint8_t * apdu, uint32_t len_value,
BACNET_CHARACTER_STRING *char_string); BACNET_CHARACTER_STRING * char_string);
// 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
int encode_bacnet_unsigned(uint8_t * apdu, uint32_t value); int encode_bacnet_unsigned(uint8_t * apdu, uint32_t value);
int encode_context_unsigned(uint8_t * apdu, int tag_number, uint32_t value); int encode_context_unsigned(uint8_t * apdu, int tag_number,
int encode_tagged_unsigned(uint8_t * apdu, uint32_t value); uint32_t value);
int decode_unsigned(uint8_t * apdu, uint32_t len_value, uint32_t *value); int encode_tagged_unsigned(uint8_t * apdu, uint32_t value);
int decode_unsigned(uint8_t * apdu, uint32_t len_value,
uint32_t * value);
// from clause 20.2.5 Encoding of a Signed Integer Value // from clause 20.2.5 Encoding of a Signed 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
int encode_bacnet_signed(uint8_t * apdu, int32_t value); int encode_bacnet_signed(uint8_t * apdu, int32_t value);
int encode_tagged_signed(uint8_t * apdu, int32_t value); int encode_tagged_signed(uint8_t * apdu, int32_t value);
int encode_context_signed(uint8_t * apdu, int tag_number, int32_t value); int encode_context_signed(uint8_t * apdu, int tag_number,
int decode_signed(uint8_t * apdu, uint32_t len_value, int32_t *value); int32_t value);
int decode_signed(uint8_t * apdu, uint32_t len_value, int32_t * value);
// from clause 20.2.11 Encoding of an Enumerated Value // from clause 20.2.11 Encoding of an Enumerated 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
int decode_enumerated(uint8_t * apdu, uint32_t len_value, int *value); int decode_enumerated(uint8_t * apdu, uint32_t len_value, int *value);
int encode_bacnet_enumerated(uint8_t * apdu, int value); int encode_bacnet_enumerated(uint8_t * apdu, int value);
int encode_tagged_enumerated(uint8_t * apdu, int value); int encode_tagged_enumerated(uint8_t * apdu, int value);
int encode_context_enumerated(uint8_t * apdu, int tag_number, int value); int encode_context_enumerated(uint8_t * apdu, int tag_number,
int value);
// from clause 20.2.13 Encoding of a Time Value // from clause 20.2.13 Encoding of a Time 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
int encode_bacnet_time(uint8_t * apdu, int hour, int min, int sec, int encode_bacnet_time(uint8_t * apdu, int hour, int min, int sec,
int hundredths); int hundredths);
int encode_tagged_time(uint8_t * apdu, int hour, int min, int sec, int encode_tagged_time(uint8_t * apdu, int hour, int min, int sec,
int hundredths); int hundredths);
int decode_bacnet_time(uint8_t * apdu, int *hour, int *min, int *sec, int decode_bacnet_time(uint8_t * apdu, int *hour, int *min, int *sec,
int *hundredths); int *hundredths);
// BACnet Date // BACnet Date
@@ -163,33 +171,32 @@ int decode_bacnet_time(uint8_t * apdu, int *hour, int *min, int *sec,
// from clause 20.2.12 Encoding of a Date Value // from clause 20.2.12 Encoding of a Date 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
int encode_bacnet_date(uint8_t * apdu, int year, int month, int day, int encode_bacnet_date(uint8_t * apdu, int year, int month, int day,
int wday); int wday);
int encode_tagged_date(uint8_t * apdu, int year, int month, int day, int encode_tagged_date(uint8_t * apdu, int year, int month, int day,
int wday); int wday);
int decode_date(uint8_t * apdu, int *year, int *month, int *day, int decode_date(uint8_t * apdu, int *year, int *month, int *day,
int *wday); int *wday);
// two octet unsigned16 // two octet unsigned16
int encode_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 // four octet unsigned32
int encode_unsigned32(uint8_t * apdu, uint32_t value); int encode_unsigned32(uint8_t * apdu, uint32_t value);
int decode_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
// returns the encoded octet // returns the encoded octet
uint8_t encode_max_segs_max_apdu(int max_segs, int max_apdu); uint8_t encode_max_segs_max_apdu(int max_segs, int max_apdu);
int decode_max_segs(uint8_t octet); int decode_max_segs(uint8_t octet);
int decode_max_apdu(uint8_t octet); int decode_max_apdu(uint8_t octet);
// returns the number of apdu bytes consumed // returns the number of apdu bytes consumed
int encode_simple_ack(uint8_t * apdu, uint8_t invoke_id, int encode_simple_ack(uint8_t * apdu, uint8_t invoke_id,
uint8_t service_choice); uint8_t service_choice);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+4 -8
View File
@@ -56,8 +56,7 @@
// embedded systems need fixed name sizes // embedded systems need fixed name sizes
#define MAX_OBJECT_NAME 10 #define MAX_OBJECT_NAME 10
// common object properties // common object properties
typedef struct BACnet_Object_Data typedef struct BACnet_Object_Data {
{
uint32_t Object_Identifier; uint32_t Object_Identifier;
char Object_Name[MAX_OBJECT_NAME]; char Object_Name[MAX_OBJECT_NAME];
BACNET_OBJECT_TYPE Object_Type; BACNET_OBJECT_TYPE Object_Type;
@@ -84,8 +83,7 @@ struct BACnet_Device_Address {
typedef struct BACnet_Device_Address BACNET_ADDRESS; typedef struct BACnet_Device_Address BACNET_ADDRESS;
/* date */ /* date */
typedef struct BACnet_Date typedef struct BACnet_Date {
{
uint16_t year; /* AD */ uint16_t year; /* AD */
uint8_t month; /* 1=Jan */ uint8_t month; /* 1=Jan */
uint8_t day; /* 1..31 */ uint8_t day; /* 1..31 */
@@ -93,8 +91,7 @@ typedef struct BACnet_Date
} BACNET_DATE; } BACNET_DATE;
/* time */ /* time */
typedef struct BACnet_Time typedef struct BACnet_Time {
{
uint8_t hour; uint8_t hour;
uint8_t min; uint8_t min;
uint8_t sec; uint8_t sec;
@@ -104,8 +101,7 @@ typedef struct BACnet_Time
/* note: with microprocessors having lots more code space than memory, /* note: with microprocessors having lots more code space than memory,
it might be better to have a packed encoding with a library to it might be better to have a packed encoding with a library to
easily access the data. */ easily access the data. */
typedef struct BACnet_Object_Id typedef struct BACnet_Object_Id {
{
uint16_t type; uint16_t type;
uint32_t instance; uint32_t instance;
} BACNET_OBJECT_ID; } BACNET_OBJECT_ID;
+28 -55
View File
@@ -34,8 +34,7 @@
#ifndef BACENUM_H #ifndef BACENUM_H
#define BACENUM_H #define BACENUM_H
typedef enum typedef enum {
{
PROP_ACKED_TRANSITIONS = 0, PROP_ACKED_TRANSITIONS = 0,
PROP_ACK_REQUIRED = 1, PROP_ACK_REQUIRED = 1,
PROP_ACTION = 2, PROP_ACTION = 2,
@@ -240,27 +239,23 @@ typedef enum
MAX_BACNET_PROPERTY_ID = 4194303 MAX_BACNET_PROPERTY_ID = 4194303
} BACNET_PROPERTY_ID; } BACNET_PROPERTY_ID;
typedef enum typedef enum {
{
ACTION_DIRECT = 0, ACTION_DIRECT = 0,
ACTION_REVERSE = 1 ACTION_REVERSE = 1
} BACNET_ACTION; } BACNET_ACTION;
typedef enum typedef enum {
{
BINARY_INACTIVE = 0, BINARY_INACTIVE = 0,
BINARY_ACTIVE = 1 BINARY_ACTIVE = 1
} BACNET_BINARY_PV; } BACNET_BINARY_PV;
typedef enum typedef enum {
{
ACTION_BINARY_PV, ACTION_BINARY_PV,
ACTION_UNSIGNED, ACTION_UNSIGNED,
ACTION_FLOAT ACTION_FLOAT
} BACNET_ACTION_VALUE_TYPE ; } BACNET_ACTION_VALUE_TYPE;
typedef enum typedef enum {
{
EVENT_STATE_NORMAL = 0, EVENT_STATE_NORMAL = 0,
EVENT_STATE_FAULT = 1, EVENT_STATE_FAULT = 1,
EVENT_STATE_OFFNORMAL = 2, EVENT_STATE_OFFNORMAL = 2,
@@ -268,8 +263,7 @@ typedef enum
EVENT_STATE_LOW_LIMIT = 4 EVENT_STATE_LOW_LIMIT = 4
} BACNET_EVENT_STATE; } BACNET_EVENT_STATE;
typedef enum typedef enum {
{
STATUS_OPERATIONAL = 0, STATUS_OPERATIONAL = 0,
STATUS_OPERATIONAL_READ_ONLY = 1, STATUS_OPERATIONAL_READ_ONLY = 1,
STATUS_DOWNLOAD_REQUIRED = 2, STATUS_DOWNLOAD_REQUIRED = 2,
@@ -277,8 +271,7 @@ typedef enum
STATUS_NON_OPERATIONAL = 4 STATUS_NON_OPERATIONAL = 4
} BACNET_DEVICE_STATUS; } BACNET_DEVICE_STATUS;
typedef enum typedef enum {
{
/* Acceleration */ /* Acceleration */
UNITS_METERS_PER_SECOND_PER_SECOND = 166, UNITS_METERS_PER_SECOND_PER_SECOND = 166,
/* Area */ /* Area */
@@ -498,14 +491,12 @@ typedef enum
The last enumeration used in this version is 189. */ The last enumeration used in this version is 189. */
} BACNET_ENGINEERING_UNITS; } BACNET_ENGINEERING_UNITS;
typedef enum typedef enum {
{
POLARITY_NORMAL = 0, POLARITY_NORMAL = 0,
POLARITY_REVERSE = 1 POLARITY_REVERSE = 1
} BACNET_POLARITY; } BACNET_POLARITY;
typedef enum typedef enum {
{
PROGRAM_REQUEST_READY = 0, PROGRAM_REQUEST_READY = 0,
PROGRAM_REQUEST_LOAD = 1, PROGRAM_REQUEST_LOAD = 1,
PROGRAM_REQUEST_RUN = 2, PROGRAM_REQUEST_RUN = 2,
@@ -514,8 +505,7 @@ typedef enum
PROGRAM_REQUEST_UNLOAD = 5 PROGRAM_REQUEST_UNLOAD = 5
} BACNET_PROGRAM_REQUEST; } BACNET_PROGRAM_REQUEST;
typedef enum typedef enum {
{
PROGRAM_STATE_IDLE = 0, PROGRAM_STATE_IDLE = 0,
PROGRAM_STATE_LOADING = 1, PROGRAM_STATE_LOADING = 1,
PROGRAM_STATE_RUNNING = 2, PROGRAM_STATE_RUNNING = 2,
@@ -524,8 +514,7 @@ typedef enum
PROGRAM_STATE_UNLOADING = 5 PROGRAM_STATE_UNLOADING = 5
} BACNET_PROGRAM_STATE; } BACNET_PROGRAM_STATE;
typedef enum typedef enum {
{
PROGRAM_ERROR_NORMAL = 0, PROGRAM_ERROR_NORMAL = 0,
PROGRAM_ERROR_LOAD_FAILED = 1, PROGRAM_ERROR_LOAD_FAILED = 1,
PROGRAM_ERROR_INTERNAL = 2, PROGRAM_ERROR_INTERNAL = 2,
@@ -536,8 +525,7 @@ typedef enum
// the procedures and constraints described in Clause 23. // the procedures and constraints described in Clause 23.
} BACNET_PROGRAM_ERROR; } BACNET_PROGRAM_ERROR;
typedef enum typedef enum {
{
RELIABILITY_NO_FAULT_DETECTED = 0, RELIABILITY_NO_FAULT_DETECTED = 0,
RELIABILITY_NO_SENSOR = 1, RELIABILITY_NO_SENSOR = 1,
RELIABILITY_OVER_RANGE = 2, RELIABILITY_OVER_RANGE = 2,
@@ -554,8 +542,7 @@ typedef enum
// the procedures and constraints described in Clause 23. // the procedures and constraints described in Clause 23.
} BACNET_RELIABILITY; } BACNET_RELIABILITY;
typedef enum typedef enum {
{
EVENT_CHANGE_OF_BITSTRING = 0, EVENT_CHANGE_OF_BITSTRING = 0,
EVENT_CHANGE_OF_STATE = 1, EVENT_CHANGE_OF_STATE = 1,
EVENT_CHANGE_OF_VALUE = 2, EVENT_CHANGE_OF_VALUE = 2,
@@ -577,15 +564,13 @@ typedef enum
// The last enumeration used in this version is 11. // The last enumeration used in this version is 11.
} BACNET_EVENT_TYPE; } BACNET_EVENT_TYPE;
typedef enum typedef enum {
{
FILE_RECORD_ACCESS = 0, FILE_RECORD_ACCESS = 0,
FILE_STREAM_ACCESS = 1, FILE_STREAM_ACCESS = 1,
FILE_RECORD_AND_STREAM_ACCESS = 2 FILE_RECORD_AND_STREAM_ACCESS = 2
} BACNET_FILE_ACCESS_METHOD; } BACNET_FILE_ACCESS_METHOD;
typedef enum typedef enum {
{
LIFE_SAFETY_MODE_OFF = 0, LIFE_SAFETY_MODE_OFF = 0,
LIFE_SAFETY_MODE_ON = 1, LIFE_SAFETY_MODE_ON = 1,
LIFE_SAFETY_MODE_TEST = 2, LIFE_SAFETY_MODE_TEST = 2,
@@ -606,8 +591,7 @@ typedef enum
// procedures and constraints described in Clause 23. // procedures and constraints described in Clause 23.
} BACNET_LIFE_SAFETY_MODE; } BACNET_LIFE_SAFETY_MODE;
typedef enum typedef enum {
{
LIFE_SAFETY_OPERATION_NONE = 0, LIFE_SAFETY_OPERATION_NONE = 0,
LIFE_SAFETY_OPERATION_SILENCE = 1, LIFE_SAFETY_OPERATION_SILENCE = 1,
LIFE_SAFETY_OPERATION_SILENCE_AUDIBLE = 2, LIFE_SAFETY_OPERATION_SILENCE_AUDIBLE = 2,
@@ -623,8 +607,7 @@ typedef enum
// procedures and constraints described in Clause 23. // procedures and constraints described in Clause 23.
} BACNET_LIFE_SAFETY_OPERATION; } BACNET_LIFE_SAFETY_OPERATION;
typedef enum typedef enum {
{
LIFE_SAFETY_STATE_QUIET = 0, LIFE_SAFETY_STATE_QUIET = 0,
LIFE_SAFETY_STATE_PRE_ALARM = 1, LIFE_SAFETY_STATE_PRE_ALARM = 1,
LIFE_SAFETY_STATE_ALARM = 2, LIFE_SAFETY_STATE_ALARM = 2,
@@ -654,8 +637,7 @@ typedef enum
// procedures and constraints described in Clause 23. // procedures and constraints described in Clause 23.
} BACNET_LIFE_SAFETY_STATE; } BACNET_LIFE_SAFETY_STATE;
typedef enum typedef enum {
{
MAINTENANCE_NONE = 0, MAINTENANCE_NONE = 0,
MAINTENANCE_PERIODIC_TEST = 1, MAINTENANCE_PERIODIC_TEST = 1,
AINTENANCE_NEED_SERVICE_OPERATIONAL = 2, AINTENANCE_NEED_SERVICE_OPERATIONAL = 2,
@@ -665,15 +647,13 @@ typedef enum
// procedures and constraints described in Clause 23. // procedures and constraints described in Clause 23.
} BACNET_MAINTENANCE; } BACNET_MAINTENANCE;
typedef enum typedef enum {
{
NOTIFY_ALARM = 0, NOTIFY_ALARM = 0,
NOTIFY_EVENT = 1, NOTIFY_EVENT = 1,
NOTIFY_ACK_NOTIFICATION = 2 NOTIFY_ACK_NOTIFICATION = 2
} BACNET_NOTIFY_TYPE; } BACNET_NOTIFY_TYPE;
typedef enum typedef enum {
{
OBJECT_ANALOG_INPUT = 0, OBJECT_ANALOG_INPUT = 0,
OBJECT_ANALOG_OUTPUT = 1, OBJECT_ANALOG_OUTPUT = 1,
OBJECT_ANALOG_VALUE = 2, OBJECT_ANALOG_VALUE = 2,
@@ -706,8 +686,7 @@ typedef enum
MAX_BACNET_OBJECT_TYPE = 1023 MAX_BACNET_OBJECT_TYPE = 1023
} BACNET_OBJECT_TYPE; } BACNET_OBJECT_TYPE;
typedef enum typedef enum {
{
SEGMENTATION_BOTH = 0, SEGMENTATION_BOTH = 0,
SEGMENTATION_TRANSMIT = 1, SEGMENTATION_TRANSMIT = 1,
SEGMENTATION_RECEIVE = 2, SEGMENTATION_RECEIVE = 2,
@@ -715,10 +694,9 @@ typedef enum
MAX_BACNET_SEGMENTATION = 4 MAX_BACNET_SEGMENTATION = 4
} BACNET_SEGMENTATION; } BACNET_SEGMENTATION;
typedef enum typedef enum {
{
VT_CLASS_DEFAULT = 0, VT_CLASS_DEFAULT = 0,
VT_CLASS_ANSI_X34 = 1, /* real name is ANSI X3.64*/ VT_CLASS_ANSI_X34 = 1, /* real name is ANSI X3.64 */
VT_CLASS_DEC_VT52 = 2, VT_CLASS_DEC_VT52 = 2,
VT_CLASS_DEC_VT100 = 3, VT_CLASS_DEC_VT100 = 3,
VT_CLASS_DEC_VT220 = 4, VT_CLASS_DEC_VT220 = 4,
@@ -729,8 +707,7 @@ typedef enum
// the procedures and constraints described in Clause 23. // the procedures and constraints described in Clause 23.
} BACNET_VT_CLASS; } BACNET_VT_CLASS;
typedef enum typedef enum {
{
CHARACTER_ANSI_X34 = 0, CHARACTER_ANSI_X34 = 0,
CHARACTER_MS_DBCS = 1, CHARACTER_MS_DBCS = 1,
CHARACTER_JISC_6226 = 2, CHARACTER_JISC_6226 = 2,
@@ -772,8 +749,7 @@ typedef enum {
PDU_TYPE_ABORT = 0x70 PDU_TYPE_ABORT = 0x70
} BACNET_PDU_TYPE; } BACNET_PDU_TYPE;
typedef enum typedef enum {
{
// Alarm and Event Services // Alarm and Event Services
SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM = 0, SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM = 0,
SERVICE_CONFIRMED_COV_NOTIFICATION = 1, SERVICE_CONFIRMED_COV_NOTIFICATION = 1,
@@ -838,8 +814,7 @@ typedef enum {
} BACNET_UNCONFIRMED_SERVICE; } BACNET_UNCONFIRMED_SERVICE;
// Bit String Enumerations // Bit String Enumerations
typedef enum typedef enum {
{
// Alarm and Event Services // Alarm and Event Services
SERVICE_SUPPORTED_ACKNOWLEDGE_ALARM = 0, SERVICE_SUPPORTED_ACKNOWLEDGE_ALARM = 0,
SERVICE_SUPPORTED_CONFIRMED_COV_NOTIFICATION = 1, SERVICE_SUPPORTED_CONFIRMED_COV_NOTIFICATION = 1,
@@ -1091,8 +1066,7 @@ typedef enum {
LAST_PROPRIETARY_ERROR_CODE = 65535 LAST_PROPRIETARY_ERROR_CODE = 65535
} BACNET_ERROR_CODE; } BACNET_ERROR_CODE;
typedef enum typedef enum {
{
BACNET_REINIT_COLDSTART = 0, BACNET_REINIT_COLDSTART = 0,
BACNET_REINIT_WARMSTART = 1, BACNET_REINIT_WARMSTART = 1,
BACNET_REINIT_STARTBACKUP = 2, BACNET_REINIT_STARTBACKUP = 2,
@@ -1104,4 +1078,3 @@ typedef enum
} BACNET_REINITIALIZED_STATE; } BACNET_REINITIALIZED_STATE;
#endif // end of BACENUM_H #endif // end of BACENUM_H
+51 -112
View File
@@ -37,51 +37,44 @@
#include "bacdef.h" #include "bacdef.h"
// encode service // encode service
int bacerror_encode_apdu( int bacerror_encode_apdu(uint8_t * apdu,
uint8_t *apdu,
uint8_t invoke_id, uint8_t invoke_id,
BACNET_CONFIRMED_SERVICE service, BACNET_CONFIRMED_SERVICE service,
BACNET_ERROR_CLASS error_class, BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code)
BACNET_ERROR_CODE error_code)
{ {
int apdu_len = 0; // total length of the apdu, return value int apdu_len = 0; // total length of the apdu, return value
if (apdu) if (apdu) {
{
apdu[0] = PDU_TYPE_ERROR; apdu[0] = PDU_TYPE_ERROR;
apdu[1] = invoke_id; apdu[1] = invoke_id;
apdu[2] = service; apdu[2] = service;
apdu_len = 3; apdu_len = 3;
// service parameters // service parameters
apdu_len += encode_tagged_enumerated(&apdu[apdu_len], apdu_len += encode_tagged_enumerated(&apdu[apdu_len], error_class);
error_class); apdu_len += encode_tagged_enumerated(&apdu[apdu_len], error_code);
apdu_len += encode_tagged_enumerated(&apdu[apdu_len],
error_code);
} }
return apdu_len; return apdu_len;
} }
// decode the application class and code // decode the application class and code
int bacerror_decode_error_class_and_code( int bacerror_decode_error_class_and_code(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
BACNET_ERROR_CLASS *error_class, BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
BACNET_ERROR_CODE *error_code)
{ {
int len = 0; int len = 0;
uint8_t tag_number = 0; uint8_t tag_number = 0;
uint32_t len_value_type = 0; uint32_t len_value_type = 0;
int decoded_value = 0; int decoded_value = 0;
if (apdu_len) if (apdu_len) {
{
// error class // error class
len += decode_tag_number_and_value(&apdu[len], len += decode_tag_number_and_value(&apdu[len],
&tag_number, &len_value_type); &tag_number, &len_value_type);
if (tag_number != BACNET_APPLICATION_TAG_ENUMERATED) if (tag_number != BACNET_APPLICATION_TAG_ENUMERATED)
return 0; return 0;
len += decode_enumerated(&apdu[len],len_value_type, &decoded_value); len +=
decode_enumerated(&apdu[len], len_value_type, &decoded_value);
if (error_class) if (error_class)
*error_class = decoded_value; *error_class = decoded_value;
// error code // error code
@@ -89,7 +82,8 @@ int bacerror_decode_error_class_and_code(
&tag_number, &len_value_type); &tag_number, &len_value_type);
if (tag_number != BACNET_APPLICATION_TAG_ENUMERATED) if (tag_number != BACNET_APPLICATION_TAG_ENUMERATED)
return 0; return 0;
len += decode_enumerated(&apdu[len],len_value_type, &decoded_value); len +=
decode_enumerated(&apdu[len], len_value_type, &decoded_value);
if (error_code) if (error_code)
*error_code = decoded_value; *error_code = decoded_value;
} }
@@ -98,60 +92,45 @@ int bacerror_decode_error_class_and_code(
} }
// decode the service request only // decode the service request only
int bacerror_decode_service_request( int bacerror_decode_service_request(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
uint8_t *invoke_id, uint8_t * invoke_id,
BACNET_CONFIRMED_SERVICE *service, BACNET_CONFIRMED_SERVICE * service,
BACNET_ERROR_CLASS *error_class, BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
BACNET_ERROR_CODE *error_code)
{ {
int len = 0; int len = 0;
if (apdu_len > 2) if (apdu_len > 2) {
{
if (invoke_id) if (invoke_id)
*invoke_id = apdu[0]; *invoke_id = apdu[0];
if (service) if (service)
*service = apdu[1]; *service = apdu[1];
// decode the application class and code // decode the application class and code
len = bacerror_decode_error_class_and_code( len = bacerror_decode_error_class_and_code(&apdu[2],
&apdu[2], apdu_len - 2, error_class, error_code);
apdu_len - 2,
error_class,
error_code);
} }
return len; return len;
} }
// decode the whole APDU - mainly used for unit testing // decode the whole APDU - mainly used for unit testing
int bacerror_decode_apdu( int bacerror_decode_apdu(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
uint8_t *invoke_id, uint8_t * invoke_id,
BACNET_CONFIRMED_SERVICE *service, BACNET_CONFIRMED_SERVICE * service,
BACNET_ERROR_CLASS *error_class, BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
BACNET_ERROR_CODE *error_code)
{ {
int len = 0; int len = 0;
if (!apdu) if (!apdu)
return -1; return -1;
// optional checking - most likely was already done prior to this call // optional checking - most likely was already done prior to this call
if (apdu_len) if (apdu_len) {
{
if (apdu[0] != PDU_TYPE_ERROR) if (apdu[0] != PDU_TYPE_ERROR)
return -1; return -1;
if (apdu_len > 1) if (apdu_len > 1) {
{ len = bacerror_decode_service_request(&apdu[1],
len = bacerror_decode_service_request( apdu_len - 1, invoke_id, service, error_class, error_code);
&apdu[1],
apdu_len - 1,
invoke_id,
service,
error_class,
error_code);
} }
} }
@@ -165,7 +144,7 @@ int bacerror_decode_apdu(
void testBACError(Test * pTest) void testBACError(Test * pTest)
{ {
uint8_t apdu[480] = {0}; uint8_t apdu[480] = { 0 };
int len = 0; int len = 0;
int apdu_len = 0; int apdu_len = 0;
uint8_t invoke_id = 0; uint8_t invoke_id = 0;
@@ -177,22 +156,15 @@ void testBACError(Test * pTest)
BACNET_ERROR_CLASS test_error_class = 0; BACNET_ERROR_CLASS test_error_class = 0;
BACNET_ERROR_CODE test_error_code = 0; BACNET_ERROR_CODE test_error_code = 0;
len = bacerror_encode_apdu( len = bacerror_encode_apdu(&apdu[0],
&apdu[0], invoke_id, service, error_class, error_code);
invoke_id,
service,
error_class,
error_code);
ct_test(pTest, len != 0); ct_test(pTest, len != 0);
apdu_len = len; apdu_len = len;
len = bacerror_decode_apdu( len = bacerror_decode_apdu(&apdu[0],
&apdu[0],
apdu_len, apdu_len,
&test_invoke_id, &test_invoke_id,
&test_service, &test_service, &test_error_class, &test_error_code);
&test_error_class,
&test_error_code);
ct_test(pTest, len != -1); ct_test(pTest, len != -1);
ct_test(pTest, test_invoke_id == invoke_id); ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest, test_service == service); ct_test(pTest, test_service == service);
@@ -201,67 +173,41 @@ void testBACError(Test * pTest)
// change type to get negative response // change type to get negative response
apdu[0] = PDU_TYPE_ABORT; apdu[0] = PDU_TYPE_ABORT;
len = bacerror_decode_apdu( len = bacerror_decode_apdu(&apdu[0],
&apdu[0],
apdu_len, apdu_len,
&test_invoke_id, &test_invoke_id,
&test_service, &test_service, &test_error_class, &test_error_code);
&test_error_class,
&test_error_code);
ct_test(pTest, len == -1); ct_test(pTest, len == -1);
// test NULL APDU // test NULL APDU
len = bacerror_decode_apdu( len = bacerror_decode_apdu(NULL,
NULL,
apdu_len, apdu_len,
&test_invoke_id, &test_invoke_id,
&test_service, &test_service, &test_error_class, &test_error_code);
&test_error_class,
&test_error_code);
ct_test(pTest, len == -1); ct_test(pTest, len == -1);
// force a zero length // force a zero length
len = bacerror_decode_apdu( len = bacerror_decode_apdu(&apdu[0],
&apdu[0],
0, 0,
&test_invoke_id, &test_invoke_id,
&test_service, &test_service, &test_error_class, &test_error_code);
&test_error_class,
&test_error_code);
ct_test(pTest, len == 0); ct_test(pTest, len == 0);
// check them all... // check them all...
for ( for (service = 0; service < MAX_BACNET_CONFIRMED_SERVICE; service++) {
service = 0; for (error_class = 0;
service < MAX_BACNET_CONFIRMED_SERVICE; error_class < MAX_BACNET_ERROR_CLASS; error_class++) {
service++) for (error_code = 0;
{ error_code < MAX_BACNET_ERROR_CODE; error_code++) {
for ( len = bacerror_encode_apdu(&apdu[0],
error_class = 0; invoke_id, service, error_class, error_code);
error_class < MAX_BACNET_ERROR_CLASS;
error_class++)
{
for (
error_code = 0;
error_code < MAX_BACNET_ERROR_CODE;
error_code++)
{
len = bacerror_encode_apdu(
&apdu[0],
invoke_id,
service,
error_class,
error_code);
apdu_len = len; apdu_len = len;
ct_test(pTest, len != 0); ct_test(pTest, len != 0);
len = bacerror_decode_apdu( len = bacerror_decode_apdu(&apdu[0],
&apdu[0],
apdu_len, apdu_len,
&test_invoke_id, &test_invoke_id,
&test_service, &test_service, &test_error_class, &test_error_code);
&test_error_class,
&test_error_code);
ct_test(pTest, len != -1); ct_test(pTest, len != -1);
ct_test(pTest, test_invoke_id == invoke_id); ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest, test_service == service); ct_test(pTest, test_service == service);
@@ -275,21 +221,14 @@ void testBACError(Test * pTest)
service = 255; service = 255;
error_class = LAST_PROPRIETARY_ERROR_CLASS; error_class = LAST_PROPRIETARY_ERROR_CLASS;
error_code = LAST_PROPRIETARY_ERROR_CODE; error_code = LAST_PROPRIETARY_ERROR_CODE;
len = bacerror_encode_apdu( len = bacerror_encode_apdu(&apdu[0],
&apdu[0], invoke_id, service, error_class, error_code);
invoke_id,
service,
error_class,
error_code);
apdu_len = len; apdu_len = len;
ct_test(pTest, len != 0); ct_test(pTest, len != 0);
len = bacerror_decode_apdu( len = bacerror_decode_apdu(&apdu[0],
&apdu[0],
apdu_len, apdu_len,
&test_invoke_id, &test_invoke_id,
&test_service, &test_service, &test_error_class, &test_error_code);
&test_error_class,
&test_error_code);
ct_test(pTest, len != -1); ct_test(pTest, len != -1);
ct_test(pTest, test_invoke_id == invoke_id); ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest, test_service == service); ct_test(pTest, test_service == service);
+13 -23
View File
@@ -42,43 +42,33 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
int bacerror_encode_apdu( int bacerror_encode_apdu(uint8_t * apdu,
uint8_t *apdu,
uint8_t invoke_id, uint8_t invoke_id,
BACNET_CONFIRMED_SERVICE service, BACNET_CONFIRMED_SERVICE service,
BACNET_ERROR_CLASS error_class, BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code);
BACNET_ERROR_CODE error_code);
int bacerror_decode_service_request( int bacerror_decode_service_request(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
uint8_t *invoke_id, uint8_t * invoke_id,
BACNET_CONFIRMED_SERVICE *service, BACNET_CONFIRMED_SERVICE * service,
BACNET_ERROR_CLASS *error_class, BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
BACNET_ERROR_CODE *error_code);
int bacerror_decode_apdu( int bacerror_decode_apdu(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
uint8_t *invoke_id, uint8_t * invoke_id,
BACNET_CONFIRMED_SERVICE *service, BACNET_CONFIRMED_SERVICE * service,
BACNET_ERROR_CLASS *error_class, BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
BACNET_ERROR_CODE *error_code);
int bacerror_decode_error_class_and_code( int bacerror_decode_error_class_and_code(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
BACNET_ERROR_CLASS *error_class, BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
BACNET_ERROR_CODE *error_code);
#ifdef TEST #ifdef TEST
#include "ctest.h" #include "ctest.h"
void testBACError(Test * pTest); void testBACError(Test * pTest);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+47 -35
View File
@@ -37,39 +37,53 @@
#include "bacprop.h" #include "bacprop.h"
PROP_TAG_DATA bacnet_object_device_property_tag_map[] = { PROP_TAG_DATA bacnet_object_device_property_tag_map[] = {
{PROP_OBJECT_IDENTIFIER, BACNET_APPLICATION_TAG_OBJECT_ID}, {PROP_OBJECT_IDENTIFIER, BACNET_APPLICATION_TAG_OBJECT_ID}
{PROP_OBJECT_NAME, BACNET_APPLICATION_TAG_CHARACTER_STRING}, ,
{PROP_OBJECT_TYPE, BACNET_APPLICATION_TAG_ENUMERATED}, {PROP_OBJECT_NAME, BACNET_APPLICATION_TAG_CHARACTER_STRING}
{PROP_SYSTEM_STATUS, BACNET_APPLICATION_TAG_ENUMERATED}, ,
{PROP_VENDOR_NAME, BACNET_APPLICATION_TAG_CHARACTER_STRING}, {PROP_OBJECT_TYPE, BACNET_APPLICATION_TAG_ENUMERATED}
{PROP_VENDOR_IDENTIFIER, BACNET_APPLICATION_TAG_UNSIGNED_INT}, ,
{PROP_MODEL_NAME, BACNET_APPLICATION_TAG_CHARACTER_STRING}, {PROP_SYSTEM_STATUS, BACNET_APPLICATION_TAG_ENUMERATED}
{PROP_FIRMWARE_REVISION, BACNET_APPLICATION_TAG_CHARACTER_STRING}, ,
{PROP_APPLICATION_SOFTWARE_VERSION, BACNET_APPLICATION_TAG_CHARACTER_STRING}, {PROP_VENDOR_NAME, BACNET_APPLICATION_TAG_CHARACTER_STRING}
{PROP_PROTOCOL_VERSION, BACNET_APPLICATION_TAG_UNSIGNED_INT}, ,
{PROP_PROTOCOL_CONFORMANCE_CLASS, BACNET_APPLICATION_TAG_UNSIGNED_INT}, {PROP_VENDOR_IDENTIFIER, BACNET_APPLICATION_TAG_UNSIGNED_INT}
{PROP_PROTOCOL_SERVICES_SUPPORTED, BACNET_APPLICATION_TAG_BIT_STRING}, ,
{PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED, BACNET_APPLICATION_TAG_BIT_STRING}, {PROP_MODEL_NAME, BACNET_APPLICATION_TAG_CHARACTER_STRING}
{PROP_MAX_APDU_LENGTH_ACCEPTED, BACNET_APPLICATION_TAG_UNSIGNED_INT}, ,
{PROP_SEGMENTATION_SUPPORTED, BACNET_APPLICATION_TAG_ENUMERATED}, {PROP_FIRMWARE_REVISION, BACNET_APPLICATION_TAG_CHARACTER_STRING}
{PROP_APDU_TIMEOUT, BACNET_APPLICATION_TAG_UNSIGNED_INT}, ,
{PROP_NUMBER_OF_APDU_RETRIES, BACNET_APPLICATION_TAG_UNSIGNED_INT}, {PROP_APPLICATION_SOFTWARE_VERSION,
{ -1, -1 } BACNET_APPLICATION_TAG_CHARACTER_STRING}
,
{PROP_PROTOCOL_VERSION, BACNET_APPLICATION_TAG_UNSIGNED_INT}
,
{PROP_PROTOCOL_CONFORMANCE_CLASS, BACNET_APPLICATION_TAG_UNSIGNED_INT}
,
{PROP_PROTOCOL_SERVICES_SUPPORTED, BACNET_APPLICATION_TAG_BIT_STRING}
,
{PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED,
BACNET_APPLICATION_TAG_BIT_STRING}
,
{PROP_MAX_APDU_LENGTH_ACCEPTED, BACNET_APPLICATION_TAG_UNSIGNED_INT}
,
{PROP_SEGMENTATION_SUPPORTED, BACNET_APPLICATION_TAG_ENUMERATED}
,
{PROP_APDU_TIMEOUT, BACNET_APPLICATION_TAG_UNSIGNED_INT}
,
{PROP_NUMBER_OF_APDU_RETRIES, BACNET_APPLICATION_TAG_UNSIGNED_INT}
,
{-1, -1}
}; };
signed bacprop_tag_by_index_default( signed bacprop_tag_by_index_default(PROP_TAG_DATA * data_list,
PROP_TAG_DATA *data_list, signed index, signed default_ret)
signed index,
signed default_ret)
{ {
signed pUnsigned = 0; signed pUnsigned = 0;
if (data_list) if (data_list) {
{ while (data_list->prop_id != -1) {
while (data_list->prop_id != -1) if (data_list->prop_id == index) {
{
if (data_list->prop_id == index)
{
pUnsigned = data_list->tag_id; pUnsigned = data_list->tag_id;
break; break;
} }
@@ -77,19 +91,17 @@ signed bacprop_tag_by_index_default(
} }
} }
return pUnsigned?pUnsigned:default_ret; return pUnsigned ? pUnsigned : default_ret;
} }
signed bacprop_property_tag(BACNET_OBJECT_TYPE type, signed prop) signed bacprop_property_tag(BACNET_OBJECT_TYPE type, signed prop)
{ {
switch (type) switch (type) {
{
case OBJECT_DEVICE: case OBJECT_DEVICE:
return bacprop_tag_by_index_default( return
bacnet_object_device_property_tag_map, bacprop_tag_by_index_default
prop, (bacnet_object_device_property_tag_map, prop, -1);
-1);
default: default:
fprintf(stderr, "Unsupported object type"); fprintf(stderr, "Unsupported object type");
break; break;
+4 -8
View File
@@ -38,8 +38,7 @@
#include <stdint.h> #include <stdint.h>
#include "bacenum.h" #include "bacenum.h"
typedef struct typedef struct {
{
signed prop_id; /* index number that matches the text */ signed prop_id; /* index number that matches the text */
signed tag_id; /* text pair - use NULL to end the list */ signed tag_id; /* text pair - use NULL to end the list */
} PROP_TAG_DATA; } PROP_TAG_DATA;
@@ -48,15 +47,12 @@ typedef struct
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
signed bacprop_tag_by_index_default( signed bacprop_tag_by_index_default(PROP_TAG_DATA * data_list,
PROP_TAG_DATA *data_list, signed index, signed default_ret);
signed index,
signed default_ret);
signed bacprop_property_tag(BACNET_OBJECT_TYPE type, signed prop); signed bacprop_property_tag(BACNET_OBJECT_TYPE type, signed prop);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+141 -233
View File
@@ -38,24 +38,23 @@
#include "bacstr.h" #include "bacstr.h"
#include "bits.h" #include "bits.h"
void bitstring_init(BACNET_BIT_STRING *bit_string) void bitstring_init(BACNET_BIT_STRING * bit_string)
{ {
int i; int i;
bit_string->bits_used = 0; bit_string->bits_used = 0;
for (i = 0; i < MAX_BITSTRING_BYTES; i++) for (i = 0; i < MAX_BITSTRING_BYTES; i++) {
{
bit_string->value[i] = 0; bit_string->value[i] = 0;
} }
} }
void bitstring_set_bit(BACNET_BIT_STRING *bit_string, uint8_t bit, bool value) void bitstring_set_bit(BACNET_BIT_STRING * bit_string, uint8_t bit,
bool value)
{ {
uint8_t byte_number = bit/8; uint8_t byte_number = bit / 8;
uint8_t bit_mask = 1; uint8_t bit_mask = 1;
if (byte_number < MAX_BITSTRING_BYTES) if (byte_number < MAX_BITSTRING_BYTES) {
{
// set max bits used // set max bits used
if (bit_string->bits_used < (bit + 1)) if (bit_string->bits_used < (bit + 1))
bit_string->bits_used = bit + 1; bit_string->bits_used = bit + 1;
@@ -67,14 +66,13 @@ void bitstring_set_bit(BACNET_BIT_STRING *bit_string, uint8_t bit, bool value)
} }
} }
bool bitstring_bit(BACNET_BIT_STRING *bit_string, uint8_t bit) bool bitstring_bit(BACNET_BIT_STRING * bit_string, uint8_t bit)
{ {
bool value = false; bool value = false;
uint8_t byte_number = bit/8; uint8_t byte_number = bit / 8;
uint8_t bit_mask = 1; uint8_t bit_mask = 1;
if (bit < (MAX_BITSTRING_BYTES * 8)) if (bit < (MAX_BITSTRING_BYTES * 8)) {
{
bit_mask = bit_mask << (bit - (byte_number * 8)); bit_mask = bit_mask << (bit - (byte_number * 8));
if (bit_string->value[byte_number] & bit_mask) if (bit_string->value[byte_number] & bit_mask)
value = true; value = true;
@@ -83,20 +81,19 @@ bool bitstring_bit(BACNET_BIT_STRING *bit_string, uint8_t bit)
return value; return value;
} }
uint8_t bitstring_bits_used(BACNET_BIT_STRING *bit_string) uint8_t bitstring_bits_used(BACNET_BIT_STRING * bit_string)
{ {
return bit_string->bits_used; return bit_string->bits_used;
} }
// returns the number of bytes that a bit string is using // returns the number of bytes that a bit string is using
int bitstring_bytes_used(BACNET_BIT_STRING *bit_string) int bitstring_bytes_used(BACNET_BIT_STRING * bit_string)
{ {
int len = 0; // return value int len = 0; // return value
uint8_t used_bytes = 0; uint8_t used_bytes = 0;
uint8_t last_bit = 0; uint8_t last_bit = 0;
if (bit_string->bits_used) if (bit_string->bits_used) {
{
last_bit = bit_string->bits_used - 1; last_bit = bit_string->bits_used - 1;
used_bytes = last_bit / 8; used_bytes = last_bit / 8;
// add one for the first byte // add one for the first byte
@@ -107,14 +104,12 @@ int bitstring_bytes_used(BACNET_BIT_STRING *bit_string)
return len; return len;
} }
uint8_t bitstring_octet(BACNET_BIT_STRING *bit_string, uint8_t index) uint8_t bitstring_octet(BACNET_BIT_STRING * bit_string, uint8_t index)
{ {
uint8_t octet = 0; uint8_t octet = 0;
if (bit_string) if (bit_string) {
{ if (index < MAX_BITSTRING_BYTES) {
if (index < MAX_BITSTRING_BYTES)
{
octet = bit_string->value[index]; octet = bit_string->value[index];
} }
} }
@@ -122,17 +117,13 @@ uint8_t bitstring_octet(BACNET_BIT_STRING *bit_string, uint8_t index)
return octet; return octet;
} }
bool bitstring_set_octet( bool bitstring_set_octet(BACNET_BIT_STRING * bit_string,
BACNET_BIT_STRING *bit_string, uint8_t index, uint8_t octet)
uint8_t index,
uint8_t octet)
{ {
bool status = false; bool status = false;
if (bit_string) if (bit_string) {
{ if (index < MAX_BITSTRING_BYTES) {
if (index < MAX_BITSTRING_BYTES)
{
bit_string->value[index] = octet; bit_string->value[index] = octet;
status = true; status = true;
} }
@@ -141,15 +132,12 @@ bool bitstring_set_octet(
return status; return status;
} }
bool bitstring_set_bits_used( bool bitstring_set_bits_used(BACNET_BIT_STRING * bit_string,
BACNET_BIT_STRING *bit_string, uint8_t bytes_used, uint8_t unused_bits)
uint8_t bytes_used,
uint8_t unused_bits)
{ {
bool status = false; bool status = false;
if (bit_string) if (bit_string) {
{
/* FIXME: check that bytes_used is at least one? */ /* FIXME: check that bytes_used is at least one? */
bit_string->bits_used = bytes_used * 8; bit_string->bits_used = bytes_used * 8;
bit_string->bits_used -= unused_bits; bit_string->bits_used -= unused_bits;
@@ -159,7 +147,7 @@ bool bitstring_set_bits_used(
return status; return status;
} }
uint8_t bitstring_bits_capacity(BACNET_BIT_STRING *bit_string) uint8_t bitstring_bits_capacity(BACNET_BIT_STRING * bit_string)
{ {
if (bit_string) if (bit_string)
return (sizeof(bit_string->value) * 8); return (sizeof(bit_string->value) * 8);
@@ -170,40 +158,28 @@ uint8_t bitstring_bits_capacity(BACNET_BIT_STRING *bit_string)
#define CHARACTER_STRING_CAPACITY (MAX_CHARACTER_STRING_BYTES - 1) #define CHARACTER_STRING_CAPACITY (MAX_CHARACTER_STRING_BYTES - 1)
/* returns false if the string exceeds capacity /* returns false if the string exceeds capacity
initialize by using length=0 */ initialize by using length=0 */
bool characterstring_init( bool characterstring_init(BACNET_CHARACTER_STRING * char_string,
BACNET_CHARACTER_STRING *char_string, uint8_t encoding, char *value, size_t length)
uint8_t encoding,
char *value,
size_t length)
{ {
bool status = false; /* return value */ bool status = false; /* return value */
size_t i; /* counter */ size_t i; /* counter */
if (char_string) if (char_string) {
{
char_string->length = 0; char_string->length = 0;
char_string->encoding = encoding; char_string->encoding = encoding;
/* save a byte at the end for NULL - /* save a byte at the end for NULL -
note: assumes printable characters */ note: assumes printable characters */
if (length <= CHARACTER_STRING_CAPACITY) if (length <= CHARACTER_STRING_CAPACITY) {
{ if (value) {
if (value) for (i = 0; i < MAX_CHARACTER_STRING_BYTES; i++) {
{ if (i < length) {
for (i = 0; i < MAX_CHARACTER_STRING_BYTES; i++)
{
if (i < length)
{
char_string->value[char_string->length] = value[i]; char_string->value[char_string->length] = value[i];
char_string->length++; char_string->length++;
} } else
else
char_string->value[i] = 0; char_string->value[i] = 0;
} }
} } else {
else for (i = 0; i < MAX_CHARACTER_STRING_BYTES; i++) {
{
for (i = 0; i < MAX_CHARACTER_STRING_BYTES; i++)
{
char_string->value[i] = 0; char_string->value[i] = 0;
} }
} }
@@ -214,56 +190,42 @@ bool characterstring_init(
return status; return status;
} }
bool characterstring_init_ansi( bool characterstring_init_ansi(BACNET_CHARACTER_STRING * char_string,
BACNET_CHARACTER_STRING *char_string,
char *value) char *value)
{ {
return characterstring_init( return characterstring_init(char_string,
char_string, CHARACTER_ANSI_X34, value, value ? strlen(value) : 0);
CHARACTER_ANSI_X34,
value, value?strlen(value):0);
} }
bool characterstring_copy( bool characterstring_copy(BACNET_CHARACTER_STRING * dest,
BACNET_CHARACTER_STRING *dest, BACNET_CHARACTER_STRING * src)
BACNET_CHARACTER_STRING *src)
{ {
return characterstring_init(dest, return characterstring_init(dest,
characterstring_encoding(src), characterstring_encoding(src),
characterstring_value(src), characterstring_value(src), characterstring_length(src));
characterstring_length(src));
} }
bool characterstring_same( bool characterstring_same(BACNET_CHARACTER_STRING * dest,
BACNET_CHARACTER_STRING *dest, BACNET_CHARACTER_STRING * src)
BACNET_CHARACTER_STRING *src)
{ {
size_t i; /* counter */ size_t i; /* counter */
bool same_status = false; bool same_status = false;
if (src && dest) if (src && dest) {
{
if ((src->length == dest->length) && if ((src->length == dest->length) &&
(src->encoding == dest->encoding)) (src->encoding == dest->encoding)) {
{
same_status = true; same_status = true;
for (i = 0; i < src->length; i++) for (i = 0; i < src->length; i++) {
{ if (src->value[i] != dest->value[i]) {
if (src->value[i] != dest->value[i])
{
same_status = false; same_status = false;
break; break;
} }
} }
} }
} } else if (src) {
else if (src)
{
if (src->length == 0) if (src->length == 0)
same_status = true; same_status = true;
} } else if (dest) {
else if (dest)
{
if (dest->length == 0) if (dest->length == 0)
same_status = true; same_status = true;
} }
@@ -271,23 +233,18 @@ bool characterstring_same(
return same_status; return same_status;
} }
bool characterstring_ansi_same( bool characterstring_ansi_same(BACNET_CHARACTER_STRING * dest,
BACNET_CHARACTER_STRING *dest,
const char *src) const char *src)
{ {
size_t i; /* counter */ size_t i; /* counter */
bool same_status = false; bool same_status = false;
if (src && dest) if (src && dest) {
{
if ((dest->length == strlen(src)) && if ((dest->length == strlen(src)) &&
(dest->encoding == CHARACTER_ANSI_X34)) (dest->encoding == CHARACTER_ANSI_X34)) {
{
same_status = true; same_status = true;
for (i = 0; i < dest->length; i++) for (i = 0; i < dest->length; i++) {
{ if (src[i] != dest->value[i]) {
if (src[i] != dest->value[i])
{
same_status = false; same_status = false;
break; break;
} }
@@ -295,13 +252,10 @@ bool characterstring_ansi_same(
} }
} }
/* NULL matches an empty string in our world */ /* NULL matches an empty string in our world */
else if (src) else if (src) {
{
if (strlen(src) == 0) if (strlen(src) == 0)
same_status = true; same_status = true;
} } else if (dest) {
else if (dest)
{
if (dest->length == 0) if (dest->length == 0)
same_status = true; same_status = true;
} }
@@ -310,20 +264,15 @@ bool characterstring_ansi_same(
} }
/* returns false if the string exceeds capacity */ /* returns false if the string exceeds capacity */
bool characterstring_append( bool characterstring_append(BACNET_CHARACTER_STRING * char_string,
BACNET_CHARACTER_STRING *char_string, char *value, size_t length)
char *value,
size_t length)
{ {
size_t i; /* counter */ size_t i; /* counter */
bool status = false; /* return value */ bool status = false; /* return value */
if (char_string) if (char_string) {
{ if ((length + char_string->length) <= CHARACTER_STRING_CAPACITY) {
if ((length + char_string->length) <= CHARACTER_STRING_CAPACITY) for (i = 0; i < length; i++) {
{
for (i = 0; i < length; i++)
{
char_string->value[char_string->length] = value[i]; char_string->value[char_string->length] = value[i];
char_string->length++; char_string->length++;
} }
@@ -337,16 +286,13 @@ bool characterstring_append(
/* This function sets a new length without changing the value. /* This function sets a new length without changing the value.
If length exceeds capacity, no modification happens and If length exceeds capacity, no modification happens and
function returns false. */ function returns false. */
bool characterstring_truncate( bool characterstring_truncate(BACNET_CHARACTER_STRING * char_string,
BACNET_CHARACTER_STRING *char_string,
size_t length) size_t length)
{ {
bool status = false; /* return value */ bool status = false; /* return value */
if (char_string) if (char_string) {
{ if (length <= CHARACTER_STRING_CAPACITY) {
if (length <= CHARACTER_STRING_CAPACITY)
{
char_string->length = length; char_string->length = length;
status = true; status = true;
} }
@@ -356,12 +302,11 @@ bool characterstring_truncate(
} }
/* Returns the value. */ /* Returns the value. */
char *characterstring_value(BACNET_CHARACTER_STRING *char_string) char *characterstring_value(BACNET_CHARACTER_STRING * char_string)
{ {
char *value = NULL; char *value = NULL;
if (char_string) if (char_string) {
{
value = char_string->value; value = char_string->value;
} }
@@ -369,12 +314,11 @@ char *characterstring_value(BACNET_CHARACTER_STRING *char_string)
} }
/* returns the length. */ /* returns the length. */
size_t characterstring_length(BACNET_CHARACTER_STRING *char_string) size_t characterstring_length(BACNET_CHARACTER_STRING * char_string)
{ {
size_t length = 0; size_t length = 0;
if (char_string) if (char_string) {
{
/* FIXME: validate length is within bounds? */ /* FIXME: validate length is within bounds? */
length = char_string->length; length = char_string->length;
} }
@@ -382,12 +326,11 @@ size_t characterstring_length(BACNET_CHARACTER_STRING *char_string)
return length; return length;
} }
size_t characterstring_capacity(BACNET_CHARACTER_STRING *char_string) size_t characterstring_capacity(BACNET_CHARACTER_STRING * char_string)
{ {
size_t length = 0; size_t length = 0;
if (char_string) if (char_string) {
{
length = CHARACTER_STRING_CAPACITY; length = CHARACTER_STRING_CAPACITY;
} }
@@ -395,12 +338,11 @@ size_t characterstring_capacity(BACNET_CHARACTER_STRING *char_string)
} }
/* returns the encoding. */ /* returns the encoding. */
uint8_t characterstring_encoding(BACNET_CHARACTER_STRING *char_string) uint8_t characterstring_encoding(BACNET_CHARACTER_STRING * char_string)
{ {
uint8_t encoding = 0; uint8_t encoding = 0;
if (char_string) if (char_string) {
{
encoding = char_string->encoding; encoding = char_string->encoding;
} }
@@ -409,31 +351,22 @@ uint8_t characterstring_encoding(BACNET_CHARACTER_STRING *char_string)
/* returns false if the string exceeds capacity /* returns false if the string exceeds capacity
initialize by using length=0 */ initialize by using length=0 */
bool octetstring_init( bool octetstring_init(BACNET_OCTET_STRING * octet_string,
BACNET_OCTET_STRING *octet_string, uint8_t * value, size_t length)
uint8_t *value,
size_t length)
{ {
bool status = false; /* return value */ bool status = false; /* return value */
size_t i; /* counter */ size_t i; /* counter */
if (octet_string) if (octet_string) {
{
octet_string->length = 0; octet_string->length = 0;
if (length <= sizeof(octet_string->value)) if (length <= sizeof(octet_string->value)) {
{ if (value) {
if (value) for (i = 0; i < length; i++) {
{
for (i = 0; i < length; i++)
{
octet_string->value[octet_string->length] = value[i]; octet_string->value[octet_string->length] = value[i];
octet_string->length++; octet_string->length++;
} }
} } else {
else for (i = 0; i < sizeof(octet_string->value); i++) {
{
for (i = 0; i < sizeof(octet_string->value); i++)
{
octet_string->value[i] = 0; octet_string->value[i] = 0;
} }
} }
@@ -444,30 +377,23 @@ bool octetstring_init(
return status; return status;
} }
bool octetstring_copy( bool octetstring_copy(BACNET_OCTET_STRING * dest,
BACNET_OCTET_STRING *dest, BACNET_OCTET_STRING * src)
BACNET_OCTET_STRING *src)
{ {
return octetstring_init(dest, return octetstring_init(dest,
octetstring_value(src), octetstring_value(src), octetstring_length(src));
octetstring_length(src));
} }
/* returns false if the string exceeds capacity */ /* returns false if the string exceeds capacity */
bool octetstring_append( bool octetstring_append(BACNET_OCTET_STRING * octet_string,
BACNET_OCTET_STRING *octet_string, uint8_t * value, size_t length)
uint8_t *value,
size_t length)
{ {
size_t i; /* counter */ size_t i; /* counter */
bool status = false; /* return value */ bool status = false; /* return value */
if (octet_string) if (octet_string) {
{ if ((length + octet_string->length) <= sizeof(octet_string->value)) {
if ((length + octet_string->length) <= sizeof(octet_string->value)) for (i = 0; i < length; i++) {
{
for (i = 0; i < length; i++)
{
octet_string->value[octet_string->length] = value[i]; octet_string->value[octet_string->length] = value[i];
octet_string->length++; octet_string->length++;
} }
@@ -481,16 +407,13 @@ bool octetstring_append(
/* This function sets a new length without changing the value. /* This function sets a new length without changing the value.
If length exceeds capacity, no modification happens and If length exceeds capacity, no modification happens and
function returns false. */ function returns false. */
bool octetstring_truncate( bool octetstring_truncate(BACNET_OCTET_STRING * octet_string,
BACNET_OCTET_STRING *octet_string,
size_t length) size_t length)
{ {
bool status = false; /* return value */ bool status = false; /* return value */
if (octet_string) if (octet_string) {
{ if (length <= sizeof(octet_string->value)) {
if (length <= sizeof(octet_string->value))
{
octet_string->length = length; octet_string->length = length;
status = true; status = true;
} }
@@ -500,12 +423,11 @@ bool octetstring_truncate(
} }
/* returns the length. Returns the value in parameter. */ /* returns the length. Returns the value in parameter. */
uint8_t *octetstring_value(BACNET_OCTET_STRING *octet_string) uint8_t *octetstring_value(BACNET_OCTET_STRING * octet_string)
{ {
uint8_t *value = NULL; uint8_t *value = NULL;
if (octet_string) if (octet_string) {
{
value = octet_string->value; value = octet_string->value;
} }
@@ -513,12 +435,11 @@ uint8_t *octetstring_value(BACNET_OCTET_STRING *octet_string)
} }
/* returns the length. */ /* returns the length. */
size_t octetstring_length(BACNET_OCTET_STRING *octet_string) size_t octetstring_length(BACNET_OCTET_STRING * octet_string)
{ {
size_t length = 0; size_t length = 0;
if (octet_string) if (octet_string) {
{
/* FIXME: validate length is within bounds? */ /* FIXME: validate length is within bounds? */
length = octet_string->length; length = octet_string->length;
} }
@@ -527,12 +448,11 @@ size_t octetstring_length(BACNET_OCTET_STRING *octet_string)
} }
/* returns the length. */ /* returns the length. */
size_t octetstring_capacity(BACNET_OCTET_STRING *octet_string) size_t octetstring_capacity(BACNET_OCTET_STRING * octet_string)
{ {
size_t length = 0; size_t length = 0;
if (octet_string) if (octet_string) {
{
/* FIXME: validate length is within bounds? */ /* FIXME: validate length is within bounds? */
length = sizeof(octet_string->value); length = sizeof(octet_string->value);
} }
@@ -553,22 +473,19 @@ void testBitString(Test * pTest)
bitstring_init(&bit_string); bitstring_init(&bit_string);
// verify initialization // verify initialization
ct_test(pTest, bitstring_bits_used(&bit_string) == 0); ct_test(pTest, bitstring_bits_used(&bit_string) == 0);
for (bit = 0; bit < (MAX_BITSTRING_BYTES*8); bit++) for (bit = 0; bit < (MAX_BITSTRING_BYTES * 8); bit++) {
{
ct_test(pTest, bitstring_bit(&bit_string, bit) == false); ct_test(pTest, bitstring_bit(&bit_string, bit) == false);
} }
// test for true // test for true
for (bit = 0; bit < (MAX_BITSTRING_BYTES*8); bit++) for (bit = 0; bit < (MAX_BITSTRING_BYTES * 8); bit++) {
{
bitstring_set_bit(&bit_string, bit, true); bitstring_set_bit(&bit_string, bit, true);
ct_test(pTest, bitstring_bits_used(&bit_string) == (bit + 1)); ct_test(pTest, bitstring_bits_used(&bit_string) == (bit + 1));
ct_test(pTest, bitstring_bit(&bit_string, bit) == true); ct_test(pTest, bitstring_bit(&bit_string, bit) == true);
} }
// test for false // test for false
bitstring_init(&bit_string); bitstring_init(&bit_string);
for (bit = 0; bit < (MAX_BITSTRING_BYTES*8); bit++) for (bit = 0; bit < (MAX_BITSTRING_BYTES * 8); bit++) {
{
bitstring_set_bit(&bit_string, bit, false); bitstring_set_bit(&bit_string, bit, false);
ct_test(pTest, bitstring_bits_used(&bit_string) == (bit + 1)); ct_test(pTest, bitstring_bits_used(&bit_string) == (bit + 1));
ct_test(pTest, bitstring_bit(&bit_string, bit) == false); ct_test(pTest, bitstring_bit(&bit_string, bit) == false);
@@ -588,52 +505,47 @@ void testCharacterString(Test * pTest)
size_t i = 0; size_t i = 0;
// verify initialization // verify initialization
status = characterstring_init(&bacnet_string,CHARACTER_ANSI_X34,NULL,0); status =
characterstring_init(&bacnet_string, CHARACTER_ANSI_X34, NULL, 0);
ct_test(pTest, status == true); ct_test(pTest, status == true);
ct_test(pTest,characterstring_length(&bacnet_string) == 0); ct_test(pTest, characterstring_length(&bacnet_string) == 0);
ct_test(pTest,characterstring_encoding(&bacnet_string) == CHARACTER_ANSI_X34); ct_test(pTest,
characterstring_encoding(&bacnet_string) == CHARACTER_ANSI_X34);
/* bounds check */ /* bounds check */
status = characterstring_init( status = characterstring_init(&bacnet_string,
&bacnet_string,
CHARACTER_ANSI_X34, CHARACTER_ANSI_X34,
NULL, NULL, characterstring_capacity(&bacnet_string) + 1);
characterstring_capacity(&bacnet_string)+1);
ct_test(pTest, status == false); ct_test(pTest, status == false);
status = characterstring_truncate( status =
&bacnet_string,characterstring_capacity(&bacnet_string)+1); characterstring_truncate(&bacnet_string,
characterstring_capacity(&bacnet_string) + 1);
ct_test(pTest, status == false); ct_test(pTest, status == false);
status = characterstring_truncate( status =
&bacnet_string,characterstring_capacity(&bacnet_string)); characterstring_truncate(&bacnet_string,
characterstring_capacity(&bacnet_string));
ct_test(pTest, status == true); ct_test(pTest, status == true);
test_length = strlen(test_value); test_length = strlen(test_value);
status = characterstring_init( status = characterstring_init(&bacnet_string,
&bacnet_string, CHARACTER_ANSI_X34, &test_value[0], test_length);
CHARACTER_ANSI_X34,
&test_value[0],
test_length);
ct_test(pTest, status == true); ct_test(pTest, status == true);
value = characterstring_value(&bacnet_string); value = characterstring_value(&bacnet_string);
length = characterstring_length(&bacnet_string); length = characterstring_length(&bacnet_string);
ct_test(pTest, length == test_length); ct_test(pTest, length == test_length);
for (i = 0; i < test_length; i++) for (i = 0; i < test_length; i++) {
{
ct_test(pTest, value[i] == test_value[i]); ct_test(pTest, value[i] == test_value[i]);
} }
test_length = strlen(test_append_value); test_length = strlen(test_append_value);
status = characterstring_append( status = characterstring_append(&bacnet_string,
&bacnet_string, &test_append_value[0], test_length);
&test_append_value[0], strcat(test_append_string, test_value);
test_length); strcat(test_append_string, test_append_value);
strcat(test_append_string,test_value);
strcat(test_append_string,test_append_value);
test_length = strlen(test_append_string); test_length = strlen(test_append_string);
ct_test(pTest, status == true); ct_test(pTest, status == true);
length = characterstring_length(&bacnet_string); length = characterstring_length(&bacnet_string);
value = characterstring_value(&bacnet_string); value = characterstring_value(&bacnet_string);
ct_test(pTest, length == test_length); ct_test(pTest, length == test_length);
for (i = 0; i < test_length; i++) for (i = 0; i < test_length; i++) {
{
ct_test(pTest, value[i] == test_append_string[i]); ct_test(pTest, value[i] == test_append_string[i]);
} }
} }
@@ -651,54 +563,50 @@ void testOctetString(Test * pTest)
size_t i = 0; size_t i = 0;
// verify initialization // verify initialization
status = octetstring_init(&bacnet_string,NULL,0); status = octetstring_init(&bacnet_string, NULL, 0);
ct_test(pTest, status == true); ct_test(pTest, status == true);
ct_test(pTest,octetstring_length(&bacnet_string) == 0); ct_test(pTest, octetstring_length(&bacnet_string) == 0);
value = octetstring_value(&bacnet_string); value = octetstring_value(&bacnet_string);
for (i = 0; i < octetstring_capacity(&bacnet_string); i++) for (i = 0; i < octetstring_capacity(&bacnet_string); i++) {
{
ct_test(pTest, value[i] == 0); ct_test(pTest, value[i] == 0);
} }
/* bounds check */ /* bounds check */
status = octetstring_init(&bacnet_string,NULL, status = octetstring_init(&bacnet_string, NULL,
octetstring_capacity(&bacnet_string)+1); octetstring_capacity(&bacnet_string) + 1);
ct_test(pTest, status == false); ct_test(pTest, status == false);
status = octetstring_init(&bacnet_string,NULL, status = octetstring_init(&bacnet_string, NULL,
octetstring_capacity(&bacnet_string)); octetstring_capacity(&bacnet_string));
ct_test(pTest, status == true); ct_test(pTest, status == true);
status = octetstring_truncate(&bacnet_string,octetstring_capacity(&bacnet_string)+1); status =
octetstring_truncate(&bacnet_string,
octetstring_capacity(&bacnet_string) + 1);
ct_test(pTest, status == false); ct_test(pTest, status == false);
status = octetstring_truncate(&bacnet_string,octetstring_capacity(&bacnet_string)); status =
octetstring_truncate(&bacnet_string,
octetstring_capacity(&bacnet_string));
ct_test(pTest, status == true); ct_test(pTest, status == true);
test_length = strlen((char *)test_value); test_length = strlen((char *) test_value);
status = octetstring_init( status = octetstring_init(&bacnet_string, &test_value[0], test_length);
&bacnet_string,
&test_value[0],
test_length);
ct_test(pTest, status == true); ct_test(pTest, status == true);
length = octetstring_length(&bacnet_string); length = octetstring_length(&bacnet_string);
value = octetstring_value(&bacnet_string); value = octetstring_value(&bacnet_string);
ct_test(pTest, length == test_length); ct_test(pTest, length == test_length);
for (i = 0; i < test_length; i++) for (i = 0; i < test_length; i++) {
{
ct_test(pTest, value[i] == test_value[i]); ct_test(pTest, value[i] == test_value[i]);
} }
test_length = strlen((char *)test_append_value); test_length = strlen((char *) test_append_value);
status = octetstring_append( status = octetstring_append(&bacnet_string,
&bacnet_string, &test_append_value[0], test_length);
&test_append_value[0], strcat((char *) test_append_string, (char *) test_value);
test_length); strcat((char *) test_append_string, (char *) test_append_value);
strcat((char *)test_append_string,(char *)test_value); test_length = strlen((char *) test_append_string);
strcat((char *)test_append_string,(char *)test_append_value);
test_length = strlen((char *)test_append_string);
ct_test(pTest, status == true); ct_test(pTest, status == true);
length = octetstring_length(&bacnet_string); length = octetstring_length(&bacnet_string);
value = octetstring_value(&bacnet_string); value = octetstring_value(&bacnet_string);
ct_test(pTest, length == test_length); ct_test(pTest, length == test_length);
for (i = 0; i < test_length; i++) for (i = 0; i < test_length; i++) {
{
ct_test(pTest, value[i] == test_append_string[i]); ct_test(pTest, value[i] == test_append_string[i]);
} }
} }
+44 -66
View File
@@ -42,15 +42,13 @@
/* bit strings /* bit strings
They could be as large as 256/8=32 octets */ They could be as large as 256/8=32 octets */
#define MAX_BITSTRING_BYTES 15 #define MAX_BITSTRING_BYTES 15
typedef struct BACnet_Bit_String typedef struct BACnet_Bit_String {
{
uint8_t bits_used; uint8_t bits_used;
uint8_t value[MAX_BITSTRING_BYTES]; uint8_t value[MAX_BITSTRING_BYTES];
} BACNET_BIT_STRING; } BACNET_BIT_STRING;
#define MAX_CHARACTER_STRING_BYTES (MAX_APDU-6) #define MAX_CHARACTER_STRING_BYTES (MAX_APDU-6)
typedef struct BACnet_Character_String typedef struct BACnet_Character_String {
{
size_t length; size_t length;
uint8_t encoding; uint8_t encoding;
/* limit - 6 octets is the most our tag and type could be */ /* limit - 6 octets is the most our tag and type could be */
@@ -59,105 +57,85 @@ typedef struct BACnet_Character_String
/* FIXME: convert the bacdcode library to use BACNET_OCTET_STRING /* FIXME: convert the bacdcode library to use BACNET_OCTET_STRING
for APDU buffer to prevent buffer overflows */ for APDU buffer to prevent buffer overflows */
typedef struct BACnet_Octet_String typedef struct BACnet_Octet_String {
{
size_t length; size_t length;
/* limit - 6 octets is the most our tag and type could be */ /* limit - 6 octets is the most our tag and type could be */
uint8_t value[MAX_APDU-6]; uint8_t value[MAX_APDU - 6];
} BACNET_OCTET_STRING; } BACNET_OCTET_STRING;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
void bitstring_init(BACNET_BIT_STRING *bit_string); void bitstring_init(BACNET_BIT_STRING * bit_string);
void bitstring_set_bit(BACNET_BIT_STRING *bit_string, uint8_t bit, bool value); void bitstring_set_bit(BACNET_BIT_STRING * bit_string, uint8_t bit,
bool bitstring_bit(BACNET_BIT_STRING *bit_string, uint8_t bit); bool value);
uint8_t bitstring_bits_used(BACNET_BIT_STRING *bit_string); bool bitstring_bit(BACNET_BIT_STRING * bit_string, uint8_t bit);
uint8_t bitstring_bits_used(BACNET_BIT_STRING * bit_string);
// returns the number of bytes that a bit string is using // returns the number of bytes that a bit string is using
int bitstring_bytes_used(BACNET_BIT_STRING *bit_string); int bitstring_bytes_used(BACNET_BIT_STRING * bit_string);
uint8_t bitstring_bits_capacity(BACNET_BIT_STRING *bit_string); uint8_t bitstring_bits_capacity(BACNET_BIT_STRING * bit_string);
/* used for encoding and decoding from the APDU */ /* used for encoding and decoding from the APDU */
uint8_t bitstring_octet(BACNET_BIT_STRING *bit_string, uint8_t octet_index); uint8_t bitstring_octet(BACNET_BIT_STRING * bit_string,
bool bitstring_set_octet( uint8_t octet_index);
BACNET_BIT_STRING *bit_string, bool bitstring_set_octet(BACNET_BIT_STRING * bit_string, uint8_t index,
uint8_t index,
uint8_t octet); uint8_t octet);
bool bitstring_set_bits_used( bool bitstring_set_bits_used(BACNET_BIT_STRING * bit_string,
BACNET_BIT_STRING *bit_string, uint8_t bytes_used, uint8_t unused_bits);
uint8_t bytes_used,
uint8_t unused_bits);
/* returns false if the string exceeds capacity /* returns false if the string exceeds capacity
initialize by using length=0 */ initialize by using length=0 */
bool characterstring_init( bool characterstring_init(BACNET_CHARACTER_STRING * char_string,
BACNET_CHARACTER_STRING *char_string, uint8_t encoding, char *value, size_t length);
uint8_t encoding,
char *value,
size_t length);
/* used for ANSI C-Strings */ /* used for ANSI C-Strings */
bool characterstring_init_ansi( bool characterstring_init_ansi(BACNET_CHARACTER_STRING * char_string,
BACNET_CHARACTER_STRING *char_string,
char *value); char *value);
bool characterstring_copy( bool characterstring_copy(BACNET_CHARACTER_STRING * dest,
BACNET_CHARACTER_STRING *dest, BACNET_CHARACTER_STRING * src);
BACNET_CHARACTER_STRING *src);
/* returns true if the strings are the same length, encoding, value */ /* returns true if the strings are the same length, encoding, value */
bool characterstring_same( bool characterstring_same(BACNET_CHARACTER_STRING * dest,
BACNET_CHARACTER_STRING *dest, BACNET_CHARACTER_STRING * src);
BACNET_CHARACTER_STRING *src); bool characterstring_ansi_same(BACNET_CHARACTER_STRING * dest,
bool characterstring_ansi_same(
BACNET_CHARACTER_STRING *dest,
const char *src); const char *src);
/* returns false if the string exceeds capacity */ /* returns false if the string exceeds capacity */
bool characterstring_append( bool characterstring_append(BACNET_CHARACTER_STRING * char_string,
BACNET_CHARACTER_STRING *char_string, char *value, size_t length);
char *value,
size_t length);
/* This function sets a new length without changing the value. /* This function sets a new length without changing the value.
If length exceeds capacity, no modification happens and If length exceeds capacity, no modification happens and
function returns false. */ function returns false. */
bool characterstring_truncate( bool characterstring_truncate(BACNET_CHARACTER_STRING * char_string,
BACNET_CHARACTER_STRING *char_string,
size_t length); size_t length);
bool characterstring_set_encoding( bool characterstring_set_encoding(BACNET_CHARACTER_STRING *
BACNET_CHARACTER_STRING *char_string, char_string, uint8_t encoding);
uint8_t encoding);
/* Returns the value */ /* Returns the value */
char *characterstring_value(BACNET_CHARACTER_STRING *char_string); char *characterstring_value(BACNET_CHARACTER_STRING * char_string);
/* returns the length */ /* returns the length */
size_t characterstring_length(BACNET_CHARACTER_STRING *char_string); size_t characterstring_length(BACNET_CHARACTER_STRING * char_string);
uint8_t characterstring_encoding(BACNET_CHARACTER_STRING *char_string); uint8_t characterstring_encoding(BACNET_CHARACTER_STRING *
size_t characterstring_capacity(BACNET_CHARACTER_STRING *char_string); char_string);
size_t characterstring_capacity(BACNET_CHARACTER_STRING * char_string);
/* returns false if the string exceeds capacity /* returns false if the string exceeds capacity
initialize by using length=0 */ initialize by using length=0 */
bool octetstring_init( bool octetstring_init(BACNET_OCTET_STRING * octet_string,
BACNET_OCTET_STRING *octet_string, uint8_t * value, size_t length);
uint8_t *value, bool octetstring_copy(BACNET_OCTET_STRING * dest,
size_t length); BACNET_OCTET_STRING * src);
bool octetstring_copy(
BACNET_OCTET_STRING *dest,
BACNET_OCTET_STRING *src);
/* returns false if the string exceeds capacity */ /* returns false if the string exceeds capacity */
bool octetstring_append( bool octetstring_append(BACNET_OCTET_STRING * octet_string,
BACNET_OCTET_STRING *octet_string, uint8_t * value, size_t length);
uint8_t *value,
size_t length);
/* This function sets a new length without changing the value. /* This function sets a new length without changing the value.
If length exceeds capacity, no modification happens and If length exceeds capacity, no modification happens and
function returns false. */ function returns false. */
bool octetstring_truncate( bool octetstring_truncate(BACNET_OCTET_STRING * octet_string,
BACNET_OCTET_STRING *octet_string,
size_t length); size_t length);
/* Returns the value */ /* Returns the value */
uint8_t *octetstring_value(BACNET_OCTET_STRING *octet_string); uint8_t *octetstring_value(BACNET_OCTET_STRING * octet_string);
/* Returns the length.*/ /* Returns the length.*/
size_t octetstring_length(BACNET_OCTET_STRING *octet_string); size_t octetstring_length(BACNET_OCTET_STRING * octet_string);
size_t octetstring_capacity(BACNET_OCTET_STRING *octet_string); size_t octetstring_capacity(BACNET_OCTET_STRING * octet_string);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+1188 -667
View File
File diff suppressed because it is too large Load Diff
+19 -20
View File
@@ -42,29 +42,28 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
const char *bactext_confirmed_service_name(int index); const char *bactext_confirmed_service_name(int index);
const char *bactext_unconfirmed_service_name(int index); const char *bactext_unconfirmed_service_name(int index);
const char *bactext_application_tag_name(int index); const char *bactext_application_tag_name(int index);
const char *bactext_object_type_name(int index); const char *bactext_object_type_name(int index);
const char *bactext_property_name(int index); const char *bactext_property_name(int index);
const char *bactext_engineering_unit_name(int index); const char *bactext_engineering_unit_name(int index);
const char *bactext_reject_reason_name(int index); const char *bactext_reject_reason_name(int index);
const char *bactext_abort_reason_name(int index); const char *bactext_abort_reason_name(int index);
const char *bactext_error_class_name(int index); const char *bactext_error_class_name(int index);
const char *bactext_error_code_name(int index); const char *bactext_error_code_name(int index);
unsigned bactext_property_id(const char* name); unsigned bactext_property_id(const char *name);
const char *bactext_month_name(int index); const char *bactext_month_name(int index);
const char *bactext_week_of_month_name(int index); const char *bactext_week_of_month_name(int index);
const char *bactext_day_of_week_name(int index); const char *bactext_day_of_week_name(int index);
const char *bactext_event_state_name(int index); const char *bactext_event_state_name(int index);
const char *bactext_binary_present_value_name(int index); const char *bactext_binary_present_value_name(int index);
const char *bactext_reliability_name(int index); const char *bactext_reliability_name(int index);
const char *bactext_device_status_name(int index); const char *bactext_device_status_name(int index);
const char *bactext_segmentation_name(int index); const char *bactext_segmentation_name(int index);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+1 -2
View File
@@ -21,10 +21,9 @@ extern "C" {
// x[2] = 0x03 // x[2] = 0x03
// x[3] = 0x04 // x[3] = 0x04
int big_endian(void); int big_endian(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+46 -68
View File
@@ -71,7 +71,8 @@ static void set_network_address(struct in_addr *net_address,
union { union {
uint8_t byte[4]; uint8_t byte[4];
uint32_t value; uint32_t value;
} long_data = {{0}}; } long_data = { {
0}};
long_data.byte[0] = octet1; long_data.byte[0] = octet1;
long_data.byte[1] = octet2; long_data.byte[1] = octet2;
@@ -81,22 +82,17 @@ static void set_network_address(struct in_addr *net_address,
net_address->s_addr = long_data.value; net_address->s_addr = long_data.value;
} }
void bip_set_address( void bip_set_address(uint8_t octet1,
uint8_t octet1, uint8_t octet2, uint8_t octet3, uint8_t octet4)
uint8_t octet2,
uint8_t octet3,
uint8_t octet4)
{ {
set_network_address(&BIP_Address, octet1, octet2, octet3, octet4); set_network_address(&BIP_Address, octet1, octet2, octet3, octet4);
} }
void bip_set_broadcast_address( void bip_set_broadcast_address(uint8_t octet1,
uint8_t octet1, uint8_t octet2, uint8_t octet3, uint8_t octet4)
uint8_t octet2,
uint8_t octet3,
uint8_t octet4)
{ {
set_network_address(&BIP_Broadcast_Address, octet1, octet2, octet3, octet4); set_network_address(&BIP_Broadcast_Address, octet1, octet2, octet3,
octet4);
} }
// set using network byte order // set using network byte order
@@ -137,9 +133,7 @@ uint16_t bip_get_port(void)
/* function to send a packet out the BACnet/IP socket (Annex J) */ /* function to send a packet out the BACnet/IP socket (Annex J) */
/* returns number of bytes sent on success, negative number on failure */ /* returns number of bytes sent on success, negative number on failure */
static int bip_send( static int bip_send(struct sockaddr_in *bip_dest, uint8_t * pdu, // any data to be sent - may be null
struct sockaddr_in *bip_dest,
uint8_t *pdu, // any data to be sent - may be null
unsigned pdu_len) // number of bytes of data unsigned pdu_len) // number of bytes of data
{ {
uint8_t mtu[MAX_MPDU] = { 0 }; uint8_t mtu[MAX_MPDU] = { 0 };
@@ -156,43 +150,41 @@ static int bip_send(
else else
mtu[1] = 0x0A; /* Original-Unicast-NPDU */ mtu[1] = 0x0A; /* Original-Unicast-NPDU */
mtu_len = 2; mtu_len = 2;
mtu_len += encode_unsigned16(&mtu[mtu_len], (uint16_t)(pdu_len + 4/*inclusive*/) ); mtu_len +=
encode_unsigned16(&mtu[mtu_len],
(uint16_t) (pdu_len + 4 /*inclusive */ ));
memcpy(&mtu[mtu_len], pdu, pdu_len); memcpy(&mtu[mtu_len], pdu, pdu_len);
mtu_len += pdu_len; mtu_len += pdu_len;
/* Send the packet */ /* Send the packet */
bytes_sent = sendto(BIP_Socket, (char *)mtu, mtu_len, 0, bytes_sent = sendto(BIP_Socket, (char *) mtu, mtu_len, 0,
(struct sockaddr *)bip_dest, (struct sockaddr *) bip_dest, sizeof(struct sockaddr));
sizeof(struct sockaddr));
return bytes_sent; return bytes_sent;
} }
/* function to send a packet out the BACnet/IP socket (Annex J) */ /* function to send a packet out the BACnet/IP socket (Annex J) */
/* returns number of bytes sent on success, negative number on failure */ /* returns number of bytes sent on success, negative number on failure */
int bip_send_pdu( int bip_send_pdu(BACNET_ADDRESS * dest, // destination address
BACNET_ADDRESS *dest, // destination address uint8_t * pdu, // any data to be sent - may be null
uint8_t *pdu, // any data to be sent - may be null
unsigned pdu_len) // number of bytes of data unsigned pdu_len) // number of bytes of data
{ {
struct sockaddr_in bip_dest; struct sockaddr_in bip_dest;
/* load destination IP address */ /* load destination IP address */
bip_dest.sin_family = AF_INET; bip_dest.sin_family = AF_INET;
if (dest->mac_len == 6) if (dest->mac_len == 6) {
{ (void) decode_unsigned32(&dest->mac[0],
(void)decode_unsigned32(&dest->mac[0], &(bip_dest.sin_addr.s_addr)); &(bip_dest.sin_addr.s_addr));
(void)decode_unsigned16(&dest->mac[4], &(bip_dest.sin_port)); (void) decode_unsigned16(&dest->mac[4], &(bip_dest.sin_port));
memset(&(bip_dest.sin_zero), '\0', 8); memset(&(bip_dest.sin_zero), '\0', 8);
} }
/* broadcast */ /* broadcast */
else if (dest->mac_len == 0) else if (dest->mac_len == 0) {
{
bip_dest.sin_addr.s_addr = htonl(BIP_Broadcast_Address.s_addr); bip_dest.sin_addr.s_addr = htonl(BIP_Broadcast_Address.s_addr);
bip_dest.sin_port = htons(BIP_Port); bip_dest.sin_port = htons(BIP_Port);
memset(&(bip_dest.sin_zero), '\0', 8); memset(&(bip_dest.sin_zero), '\0', 8);
} } else
else
return -1; return -1;
/* function to send a packet out the BACnet/IP socket */ /* function to send a packet out the BACnet/IP socket */
@@ -204,19 +196,18 @@ int bip_send_pdu(
// receives a BACnet/IP packet // receives a BACnet/IP packet
// returns the number of octets in the PDU, or zero on failure // returns the number of octets in the PDU, or zero on failure
uint16_t bip_receive( uint16_t bip_receive(BACNET_ADDRESS * src, // source address
BACNET_ADDRESS *src, // source address uint8_t * pdu, // PDU data
uint8_t *pdu, // PDU data
uint16_t max_pdu, // amount of space available in the PDU uint16_t max_pdu, // amount of space available in the PDU
unsigned timeout) // number of milliseconds to wait for a packet unsigned timeout) // number of milliseconds to wait for a packet
{ {
int received_bytes; int received_bytes;
uint8_t buf[MAX_MPDU] = {0}; // data uint8_t buf[MAX_MPDU] = { 0 }; // data
uint16_t pdu_len = 0; // return value uint16_t pdu_len = 0; // return value
fd_set read_fds; fd_set read_fds;
int max; int max;
struct timeval select_timeout; struct timeval select_timeout;
struct sockaddr_in sin = {-1}; struct sockaddr_in sin = { -1 };
socklen_t sin_len = sizeof(sin); socklen_t sin_len = sizeof(sin);
/* Make sure the socket is open */ /* Make sure the socket is open */
@@ -226,25 +217,22 @@ uint16_t bip_receive(
/* we could just use a non-blocking socket, but that consumes all /* we could just use a non-blocking socket, but that consumes all
the CPU time. We can use a timeout; it is only supported as the CPU time. We can use a timeout; it is only supported as
a select. */ a select. */
if (timeout >= 1000) if (timeout >= 1000) {
{
select_timeout.tv_sec = timeout / 1000; select_timeout.tv_sec = timeout / 1000;
select_timeout.tv_usec = select_timeout.tv_usec =
1000 * (timeout - select_timeout.tv_sec * 1000); 1000 * (timeout - select_timeout.tv_sec * 1000);
} } else {
else
{
select_timeout.tv_sec = 0; select_timeout.tv_sec = 0;
select_timeout.tv_usec = 1000 * timeout; select_timeout.tv_usec = 1000 * timeout;
} }
FD_ZERO(&read_fds); FD_ZERO(&read_fds);
FD_SET((unsigned int)BIP_Socket, &read_fds); FD_SET((unsigned int) BIP_Socket, &read_fds);
max = BIP_Socket; max = BIP_Socket;
/* see if there is a packet for us */ /* see if there is a packet for us */
if (select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0) if (select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0)
received_bytes = recvfrom(BIP_Socket, received_bytes = recvfrom(BIP_Socket,
(char *)&buf[0], MAX_MPDU, 0, (char *) &buf[0], MAX_MPDU, 0,
(struct sockaddr *)&sin, &sin_len); (struct sockaddr *) &sin, &sin_len);
else else
return 0; return 0;
@@ -261,28 +249,24 @@ uint16_t bip_receive(
if (buf[0] != 0x81) if (buf[0] != 0x81)
return 0; return 0;
/* Original-Broadcast-NPDU or Original-Unicast-NPDU */ /* Original-Broadcast-NPDU or Original-Unicast-NPDU */
if ((buf[1] == 0x0B) || (buf[1] == 0x0A)) if ((buf[1] == 0x0B) || (buf[1] == 0x0A)) {
{
/* ignore messages from me */ /* ignore messages from me */
if (sin.sin_addr.s_addr == BIP_Address.s_addr) if (sin.sin_addr.s_addr == BIP_Address.s_addr)
pdu_len = 0; pdu_len = 0;
else else {
{
/* copy the source address /* copy the source address
FIXME: IPv6? */ FIXME: IPv6? */
src->mac_len = 6; src->mac_len = 6;
(void)encode_unsigned32(&src->mac[0], (void) encode_unsigned32(&src->mac[0], sin.sin_addr.s_addr);
sin.sin_addr.s_addr); (void) encode_unsigned16(&src->mac[4], sin.sin_port);
(void)encode_unsigned16(&src->mac[4],
sin.sin_port);
// FIXME: check destination address // FIXME: check destination address
// see if it is broadcast or for us // see if it is broadcast or for us
/* decode the length of the PDU - length is inclusive of BVLC */ /* decode the length of the PDU - length is inclusive of BVLC */
(void)decode_unsigned16(&buf[2],&pdu_len); (void) decode_unsigned16(&buf[2], &pdu_len);
/* copy the buffer into the PDU */ /* copy the buffer into the PDU */
pdu_len -= 4; /* BVLC header */ pdu_len -= 4; /* BVLC header */
if (pdu_len < max_pdu) if (pdu_len < max_pdu)
memmove(&pdu[0],&buf[4],pdu_len); memmove(&pdu[0], &buf[4], pdu_len);
// ignore packets that are too large // ignore packets that are too large
// clients should check my max-apdu first // clients should check my max-apdu first
else else
@@ -293,19 +277,17 @@ uint16_t bip_receive(
return pdu_len; return pdu_len;
} }
void bip_get_my_address(BACNET_ADDRESS *my_address) void bip_get_my_address(BACNET_ADDRESS * my_address)
{ {
int i = 0; int i = 0;
my_address->mac_len = 6; my_address->mac_len = 6;
(void)encode_unsigned32(&my_address->mac[0], (void) encode_unsigned32(&my_address->mac[0],
htonl(BIP_Address.s_addr)); htonl(BIP_Address.s_addr));
(void)encode_unsigned16(&my_address->mac[4], (void) encode_unsigned16(&my_address->mac[4], htons(BIP_Port));
htons(BIP_Port));
my_address->net = 0; /* local only, no routing */ my_address->net = 0; /* local only, no routing */
my_address->len = 0; /* no SLEN */ my_address->len = 0; /* no SLEN */
for (i = 0; i < MAX_MAC_LEN; i++) for (i = 0; i < MAX_MAC_LEN; i++) {
{
/* no SADR */ /* no SADR */
my_address->adr[i] = 0; my_address->adr[i] = 0;
} }
@@ -313,22 +295,18 @@ void bip_get_my_address(BACNET_ADDRESS *my_address)
return; return;
} }
void bip_get_broadcast_address( void bip_get_broadcast_address(BACNET_ADDRESS * dest) // destination address
BACNET_ADDRESS *dest) // destination address
{ {
int i = 0; // counter int i = 0; // counter
if (dest) if (dest) {
{
dest->mac_len = 6; dest->mac_len = 6;
(void)encode_unsigned32(&dest->mac[0], (void) encode_unsigned32(&dest->mac[0],
htonl(BIP_Broadcast_Address.s_addr)); htonl(BIP_Broadcast_Address.s_addr));
(void)encode_unsigned16(&dest->mac[4], (void) encode_unsigned16(&dest->mac[4], htons(BIP_Port));
htons(BIP_Port));
dest->net = BACNET_BROADCAST_NETWORK; dest->net = BACNET_BROADCAST_NETWORK;
dest->len = 0; /* no SLEN */ dest->len = 0; /* no SLEN */
for (i = 0; i < MAX_MAC_LEN; i++) for (i = 0; i < MAX_MAC_LEN; i++) {
{
/* no SADR */ /* no SADR */
dest->adr[i] = 0; dest->adr[i] = 0;
} }
+19 -23
View File
@@ -49,55 +49,51 @@ extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
// note: define init and cleanup in your ports section // note: define init and cleanup in your ports section
bool bip_init(void); bool bip_init(void);
// normal functions... // normal functions...
void bip_cleanup(void); void bip_cleanup(void);
void bip_set_socket(int sock_fd); void bip_set_socket(int sock_fd);
bool bip_valid(void); bool bip_valid(void);
void bip_get_broadcast_address( void bip_get_broadcast_address(BACNET_ADDRESS * dest); // destination address
BACNET_ADDRESS *dest); // destination address void bip_get_my_address(BACNET_ADDRESS * my_address);
void bip_get_my_address(BACNET_ADDRESS *my_address);
/* function to send a packet out the BACnet/IP socket */ /* function to send a packet out the BACnet/IP socket */
/* returns zero on success, non-zero on failure */ /* returns zero on success, non-zero on failure */
int bip_send_pdu( int bip_send_pdu(BACNET_ADDRESS * dest, // destination address
BACNET_ADDRESS *dest, // destination address uint8_t * pdu, // any data to be sent - may be null
uint8_t *pdu, // any data to be sent - may be null
unsigned pdu_len); // number of bytes of data unsigned pdu_len); // number of bytes of data
// receives a BACnet/IP packet // receives a BACnet/IP packet
// returns the number of octets in the PDU, or zero on failure // returns the number of octets in the PDU, or zero on failure
uint16_t bip_receive( uint16_t bip_receive(BACNET_ADDRESS * src, // source address
BACNET_ADDRESS *src, // source address uint8_t * pdu, // PDU data
uint8_t *pdu, // PDU data
uint16_t max_pdu, // amount of space available in the PDU uint16_t max_pdu, // amount of space available in the PDU
unsigned timeout); // milliseconds to wait for a packet unsigned timeout); // milliseconds to wait for a packet
void bip_set_address(uint8_t octet1, uint8_t octet2, void bip_set_address(uint8_t octet1, uint8_t octet2,
uint8_t octet3, uint8_t octet4); uint8_t octet3, uint8_t octet4);
void bip_set_broadcast_address(uint8_t octet1, uint8_t octet2, void bip_set_broadcast_address(uint8_t octet1, uint8_t octet2,
uint8_t octet3, uint8_t octet4); uint8_t octet3, uint8_t octet4);
// use host byte order for setting // use host byte order for setting
void bip_set_port(uint16_t port); void bip_set_port(uint16_t port);
// returns host byte order // returns host byte order
uint16_t bip_get_port(void); uint16_t bip_get_port(void);
// use network byte order for setting // use network byte order for setting
void bip_set_addr(uint32_t net_address); void bip_set_addr(uint32_t net_address);
// returns host byte order // returns host byte order
uint32_t bip_get_addr(void); uint32_t bip_get_addr(void);
// use network byte order for setting // use network byte order for setting
void bip_set_broadcast_addr(uint32_t net_address); void bip_set_broadcast_addr(uint32_t net_address);
// returns host byte order // returns host byte order
uint32_t bip_get_broadcast_addr(void); uint32_t bip_get_broadcast_addr(void);
void bip_set_interface(char *ifname); void bip_set_interface(char *ifname);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+8 -9
View File
@@ -7,11 +7,11 @@
#include <stdint.h> #include <stdint.h>
#ifndef LO_NIB #ifndef LO_NIB
#define LO_NIB(b) ((b) & 0xF) #define LO_NIB(b) ((b) & 0xF)
#endif #endif
#ifndef HI_NIB #ifndef HI_NIB
#define HI_NIB(b) ((b) >> 4) #define HI_NIB(b) ((b) >> 4)
#endif #endif
@@ -19,7 +19,7 @@
#ifndef LO_BYTE #ifndef LO_BYTE
#define LO_BYTE(w) ((uint8_t)(w)) #define LO_BYTE(w) ((uint8_t)(w))
#endif #endif
@@ -27,7 +27,7 @@
#ifndef HI_BYTE #ifndef HI_BYTE
#define HI_BYTE(w) ((uint8_t)((uint16_t)(w) >> 8)) #define HI_BYTE(w) ((uint8_t)((uint16_t)(w) >> 8))
#endif #endif
@@ -35,7 +35,7 @@
#ifndef LO_WORD #ifndef LO_WORD
#define LO_WORD(x) ((uint16_t)(x)) #define LO_WORD(x) ((uint16_t)(x))
#endif #endif
@@ -43,7 +43,7 @@
#ifndef HI_WORD #ifndef HI_WORD
#define HI_WORD(x) ((uint16_t)((uint32_t)(x) >> 16)) #define HI_WORD(x) ((uint16_t)((uint32_t)(x) >> 16))
#endif #endif
@@ -51,7 +51,7 @@
#ifndef MAKE_WORD #ifndef MAKE_WORD
#define MAKE_WORD(lo,hi) \ #define MAKE_WORD(lo,hi) \
((uint16_t)(((uint8_t)(lo))|(((uint16_t)((uint8_t)(hi)))<<8))) ((uint16_t)(((uint8_t)(lo))|(((uint16_t)((uint8_t)(hi)))<<8)))
#endif #endif
@@ -60,7 +60,7 @@
#ifndef MAKE_LONG #ifndef MAKE_LONG
#define MAKE_LONG(lo,hi) \ #define MAKE_LONG(lo,hi) \
((uint32_t)(((uint16_t)(lo))|(((uint32_t)((uint16_t)(hi)))<<16))) ((uint32_t)(((uint16_t)(lo))|(((uint32_t)((uint16_t)(hi)))<<16)))
#endif #endif
@@ -68,4 +68,3 @@
#endif // end of header file #endif // end of header file
+29 -29
View File
@@ -68,8 +68,8 @@ uint16_t CRC_Calc_Data(uint8_t dataValue, uint16_t crcValue)
crcLow = (crcValue & 0xff) ^ dataValue; /* XOR C7..C0 with D7..D0 */ crcLow = (crcValue & 0xff) ^ dataValue; /* XOR C7..C0 with D7..D0 */
/* Exclusive OR the terms in the table (top down) */ /* Exclusive OR the terms in the table (top down) */
return (crcValue >>8) ^ (crcLow << 8) ^ (crcLow <<3) return (crcValue >> 8) ^ (crcLow << 8) ^ (crcLow << 3)
^ (crcLow <<12) ^ (crcLow >> 4) ^ (crcLow << 12) ^ (crcLow >> 4)
^ (crcLow & 0x0f) ^ ((crcLow & 0x0f) << 7); ^ (crcLow & 0x0f) ^ ((crcLow & 0x0f) << 7);
} }
@@ -80,50 +80,50 @@ uint16_t CRC_Calc_Data(uint8_t dataValue, uint16_t crcValue)
#include "bytes.h" #include "bytes.h"
// test from Annex G 1.0 of BACnet Standard // test from Annex G 1.0 of BACnet Standard
void testCRC8(Test* pTest) void testCRC8(Test * pTest)
{ {
uint8_t crc = 0xff; // accumulates the crc value uint8_t crc = 0xff; // accumulates the crc value
uint8_t frame_crc; // appended to the end of the frame uint8_t frame_crc; // appended to the end of the frame
crc = CRC_Calc_Header(0x00,crc); crc = CRC_Calc_Header(0x00, crc);
ct_test(pTest,crc == 0x55); ct_test(pTest, crc == 0x55);
crc = CRC_Calc_Header(0x10,crc); crc = CRC_Calc_Header(0x10, crc);
ct_test(pTest,crc == 0xC2); ct_test(pTest, crc == 0xC2);
crc = CRC_Calc_Header(0x05,crc); crc = CRC_Calc_Header(0x05, crc);
ct_test(pTest,crc == 0xBC); ct_test(pTest, crc == 0xBC);
crc = CRC_Calc_Header(0x00,crc); crc = CRC_Calc_Header(0x00, crc);
ct_test(pTest,crc == 0x95); ct_test(pTest, crc == 0x95);
crc = CRC_Calc_Header(0x00,crc); crc = CRC_Calc_Header(0x00, crc);
ct_test(pTest,crc == 0x73); ct_test(pTest, crc == 0x73);
// send the ones complement of the CRC in place of // send the ones complement of the CRC in place of
// the CRC, and the resulting CRC will always equal 0x55. // the CRC, and the resulting CRC will always equal 0x55.
frame_crc = ~crc; frame_crc = ~crc;
ct_test(pTest,frame_crc == 0x8C); ct_test(pTest, frame_crc == 0x8C);
// use the ones complement value and the next to last CRC value // use the ones complement value and the next to last CRC value
crc = CRC_Calc_Header(frame_crc,crc); crc = CRC_Calc_Header(frame_crc, crc);
ct_test(pTest,crc == 0x55); ct_test(pTest, crc == 0x55);
} }
// test from Annex G 2.0 of BACnet Standard // test from Annex G 2.0 of BACnet Standard
void testCRC16(Test* pTest) void testCRC16(Test * pTest)
{ {
uint16_t crc = 0xffff; uint16_t crc = 0xffff;
uint16_t data_crc; uint16_t data_crc;
crc = CRC_Calc_Data(0x01,crc); crc = CRC_Calc_Data(0x01, crc);
ct_test(pTest,crc == 0x1E0E); ct_test(pTest, crc == 0x1E0E);
crc = CRC_Calc_Data(0x22,crc); crc = CRC_Calc_Data(0x22, crc);
ct_test(pTest,crc == 0xEB70); ct_test(pTest, crc == 0xEB70);
crc = CRC_Calc_Data(0x30,crc); crc = CRC_Calc_Data(0x30, crc);
ct_test(pTest,crc == 0x42EF); ct_test(pTest, crc == 0x42EF);
// send the ones complement of the CRC in place of // send the ones complement of the CRC in place of
// the CRC, and the resulting CRC will always equal 0xF0B8. // the CRC, and the resulting CRC will always equal 0xF0B8.
data_crc = ~crc; data_crc = ~crc;
ct_test(pTest,data_crc == 0xBD10); ct_test(pTest, data_crc == 0xBD10);
crc = CRC_Calc_Data(LO_BYTE(data_crc),crc); crc = CRC_Calc_Data(LO_BYTE(data_crc), crc);
ct_test(pTest,crc == 0x0F3A); ct_test(pTest, crc == 0x0F3A);
crc = CRC_Calc_Data(HI_BYTE(data_crc),crc); crc = CRC_Calc_Data(HI_BYTE(data_crc), crc);
ct_test(pTest,crc == 0xF0B8); ct_test(pTest, crc == 0xF0B8);
} }
#endif #endif
@@ -144,7 +144,7 @@ int main(void)
ct_setStream(pTest, stdout); ct_setStream(pTest, stdout);
ct_run(pTest); ct_run(pTest);
(void)ct_report(pTest); (void) ct_report(pTest);
ct_destroy(pTest); ct_destroy(pTest);
+2 -3
View File
@@ -42,11 +42,10 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
uint8_t CRC_Calc_Header(uint8_t dataValue, uint8_t crcValue); uint8_t CRC_Calc_Header(uint8_t dataValue, uint8_t crcValue);
uint16_t CRC_Calc_Data(uint8_t dataValue, uint16_t crcValue); uint16_t CRC_Calc_Data(uint8_t dataValue, uint16_t crcValue);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+22 -55
View File
@@ -41,72 +41,42 @@
// as part of the calls. // as part of the calls.
/* returns number of bytes sent on success, negative on failure */ /* returns number of bytes sent on success, negative on failure */
int datalink_send_pdu( int datalink_send_pdu(BACNET_ADDRESS * dest, // destination address
BACNET_ADDRESS *dest, // destination address uint8_t * pdu, // any data to be sent - may be null
uint8_t *pdu, // any data to be sent - may be null
unsigned pdu_len) // number of bytes of data unsigned pdu_len) // number of bytes of data
{ {
#ifdef BACDL_ARCNET #ifdef BACDL_ARCNET
return arcnet_send_pdu( return arcnet_send_pdu(dest, pdu, pdu_len);
dest,
pdu,
pdu_len);
#endif #endif
#ifdef BACDL_MSTP #ifdef BACDL_MSTP
return dlmstp_send_pdu( return dlmstp_send_pdu(dest, pdu, pdu_len);
dest,
pdu,
pdu_len);
#endif #endif
#ifdef BACDL_ETHERNET #ifdef BACDL_ETHERNET
return ethernet_send_pdu( return ethernet_send_pdu(dest, pdu, pdu_len);
dest,
pdu,
pdu_len);
#endif #endif
#ifdef BACDL_BIP #ifdef BACDL_BIP
return bip_send_pdu( return bip_send_pdu(dest, pdu, pdu_len);
dest,
pdu,
pdu_len);
#endif #endif
} }
// returns the number of octets in the PDU, or zero on failure // returns the number of octets in the PDU, or zero on failure
uint16_t datalink_receive( uint16_t datalink_receive(BACNET_ADDRESS * src, // source address
BACNET_ADDRESS *src, // source address uint8_t * pdu, // PDU data
uint8_t *pdu, // PDU data
uint16_t max_pdu, // amount of space available in the PDU uint16_t max_pdu, // amount of space available in the PDU
unsigned timeout) // number of milliseconds to wait for a packet unsigned timeout) // number of milliseconds to wait for a packet
{ {
#ifdef BACDL_ARCNET #ifdef BACDL_ARCNET
return arcnet_receive( return arcnet_receive(src, pdu, max_pdu, timeout);
src, #endif
pdu, #ifdef BACDL_MSTP
max_pdu, return dlmstp_receive(src, pdu, max_pdu, timeout);
timeout); #endif
#endif #ifdef BACDL_ETHERNET
#ifdef BACDL_MSTP return ethernet_receive(src, pdu, max_pdu, timeout);
return dlmstp_receive( #endif
src, #ifdef BACDL_BIP
pdu, return bip_receive(src, pdu, max_pdu, timeout);
max_pdu, #endif
timeout);
#endif
#ifdef BACDL_ETHERNET
return ethernet_receive(
src,
pdu,
max_pdu,
timeout);
#endif
#ifdef BACDL_BIP
return bip_receive(
src,
pdu,
max_pdu,
timeout);
#endif
} }
void datalink_cleanup(void) void datalink_cleanup(void)
@@ -125,8 +95,7 @@ void datalink_cleanup(void)
#endif #endif
} }
void datalink_get_broadcast_address( void datalink_get_broadcast_address(BACNET_ADDRESS * dest) // destination address
BACNET_ADDRESS *dest) // destination address
{ {
#ifdef BACDL_ARCNET #ifdef BACDL_ARCNET
arcnet_get_broadcast_address(dest); arcnet_get_broadcast_address(dest);
@@ -142,8 +111,7 @@ void datalink_get_broadcast_address(
#endif #endif
} }
void datalink_get_my_address( void datalink_get_my_address(BACNET_ADDRESS * my_address)
BACNET_ADDRESS *my_address)
{ {
#ifdef BACDL_ARCNET #ifdef BACDL_ARCNET
arcnet_get_my_address(my_address); arcnet_get_my_address(my_address);
@@ -158,4 +126,3 @@ void datalink_get_my_address(
bip_get_my_address(my_address); bip_get_my_address(my_address);
#endif #endif
} }
+7 -12
View File
@@ -60,28 +60,23 @@ extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
/* returns number of bytes sent on success, negative on failure */ /* returns number of bytes sent on success, negative on failure */
int datalink_send_pdu( int datalink_send_pdu(BACNET_ADDRESS * dest, // destination address
BACNET_ADDRESS *dest, // destination address uint8_t * pdu, // any data to be sent - may be null
uint8_t *pdu, // any data to be sent - may be null
unsigned pdu_len); // number of bytes of data unsigned pdu_len); // number of bytes of data
// returns the number of octets in the PDU, or zero on failure // returns the number of octets in the PDU, or zero on failure
uint16_t datalink_receive( uint16_t datalink_receive(BACNET_ADDRESS * src, // source address
BACNET_ADDRESS *src, // source address uint8_t * pdu, // PDU data
uint8_t *pdu, // PDU data
uint16_t max_pdu, // amount of space available in the PDU uint16_t max_pdu, // amount of space available in the PDU
unsigned timeout); // number of milliseconds to wait for a packet unsigned timeout); // number of milliseconds to wait for a packet
void datalink_cleanup(void); void datalink_cleanup(void);
void datalink_get_broadcast_address( void datalink_get_broadcast_address(BACNET_ADDRESS * dest); // destination address
BACNET_ADDRESS *dest); // destination address
void datalink_get_my_address( void datalink_get_my_address(BACNET_ADDRESS * my_address);
BACNET_ADDRESS *my_address);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+51 -82
View File
@@ -87,8 +87,7 @@ uint32_t dcc_duration_seconds(void)
then seconds should be the number of seconds to tick away */ then seconds should be the number of seconds to tick away */
void dcc_timer_seconds(uint32_t seconds) void dcc_timer_seconds(uint32_t seconds)
{ {
if (DCC_Time_Duration_Seconds) if (DCC_Time_Duration_Seconds) {
{
if (DCC_Time_Duration_Seconds > seconds) if (DCC_Time_Duration_Seconds > seconds)
DCC_Time_Duration_Seconds -= seconds; DCC_Time_Duration_Seconds -= seconds;
else else
@@ -99,15 +98,13 @@ void dcc_timer_seconds(uint32_t seconds)
} }
} }
bool dcc_set_status_duration( bool dcc_set_status_duration(BACNET_COMMUNICATION_ENABLE_DISABLE status,
BACNET_COMMUNICATION_ENABLE_DISABLE status,
uint16_t minutes) uint16_t minutes)
{ {
bool valid = false; bool valid = false;
/* valid? */ /* valid? */
if (status < MAX_BACNET_COMMUNICATION_ENABLE_DISABLE) if (status < MAX_BACNET_COMMUNICATION_ENABLE_DISABLE) {
{
DCC_Enable_Disable = status; DCC_Enable_Disable = status;
if (status == COMMUNICATION_ENABLE) if (status == COMMUNICATION_ENABLE)
DCC_Time_Duration_Seconds = 0; DCC_Time_Duration_Seconds = 0;
@@ -120,37 +117,35 @@ bool dcc_set_status_duration(
} }
/* encode service */ /* encode service */
int dcc_encode_apdu( int dcc_encode_apdu(uint8_t * apdu, uint8_t invoke_id, uint16_t timeDuration, /* 0=optional */
uint8_t *apdu,
uint8_t invoke_id,
uint16_t timeDuration, /* 0=optional */
BACNET_COMMUNICATION_ENABLE_DISABLE enable_disable, BACNET_COMMUNICATION_ENABLE_DISABLE enable_disable,
BACNET_CHARACTER_STRING *password) /* NULL=optional */ BACNET_CHARACTER_STRING * password)
{ { /* NULL=optional */
int len = 0; /* length of each encoding */ int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */ int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) if (apdu) {
{
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST; apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU); apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU);
apdu[2] = invoke_id; apdu[2] = invoke_id;
apdu[3] = SERVICE_CONFIRMED_REINITIALIZE_DEVICE; apdu[3] = SERVICE_CONFIRMED_REINITIALIZE_DEVICE;
apdu_len = 4; apdu_len = 4;
/* optional timeDuration */ /* optional timeDuration */
if (timeDuration) if (timeDuration) {
{ len =
len = encode_context_unsigned(&apdu[apdu_len], 0, timeDuration); encode_context_unsigned(&apdu[apdu_len], 0, timeDuration);
apdu_len += len; apdu_len += len;
} }
/* enable disable */ /* enable disable */
len = encode_context_enumerated(&apdu[apdu_len], 1, enable_disable); len =
encode_context_enumerated(&apdu[apdu_len], 1, enable_disable);
apdu_len += len; apdu_len += len;
/* optional password */ /* optional password */
if (password) if (password) {
{
/* FIXME: must be at least 1 character, limited to 20 characters */ /* FIXME: must be at least 1 character, limited to 20 characters */
len = encode_context_character_string(&apdu[apdu_len], 2, password); len =
encode_context_character_string(&apdu[apdu_len], 2,
password);
apdu_len += len; apdu_len += len;
} }
} }
@@ -159,12 +154,11 @@ int dcc_encode_apdu(
} }
/* decode the service request only */ /* decode the service request only */
int dcc_decode_service_request( int dcc_decode_service_request(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
uint16_t *timeDuration, uint16_t * timeDuration,
BACNET_COMMUNICATION_ENABLE_DISABLE *enable_disable, BACNET_COMMUNICATION_ENABLE_DISABLE * enable_disable,
BACNET_CHARACTER_STRING *password) BACNET_CHARACTER_STRING * password)
{ {
unsigned len = 0; unsigned len = 0;
uint8_t tag_number = 0; uint8_t tag_number = 0;
@@ -173,18 +167,15 @@ int dcc_decode_service_request(
uint32_t value32 = 0; uint32_t value32 = 0;
/* check for value pointers */ /* check for value pointers */
if (apdu_len) if (apdu_len) {
{
/* Tag 0: timeDuration --optional-- */ /* Tag 0: timeDuration --optional-- */
if (decode_is_context_tag(&apdu[len], 0)) if (decode_is_context_tag(&apdu[len], 0)) {
{
len += decode_tag_number_and_value(&apdu[len], &tag_number, len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type); &len_value_type);
len += decode_unsigned(&apdu[len], len_value_type, &value32); len += decode_unsigned(&apdu[len], len_value_type, &value32);
if (timeDuration) if (timeDuration)
*timeDuration = value32; *timeDuration = value32;
} } else if (timeDuration)
else if (timeDuration)
*timeDuration = 0; *timeDuration = 0;
/* Tag 1: enable_disable */ /* Tag 1: enable_disable */
if (!decode_is_context_tag(&apdu[len], 1)) if (!decode_is_context_tag(&apdu[len], 1))
@@ -195,28 +186,27 @@ int dcc_decode_service_request(
if (enable_disable) if (enable_disable)
*enable_disable = value; *enable_disable = value;
/* Tag 2: password --optional-- */ /* Tag 2: password --optional-- */
if (len < apdu_len) if (len < apdu_len) {
{
if (!decode_is_context_tag(&apdu[len], 2)) if (!decode_is_context_tag(&apdu[len], 2))
return -1; return -1;
len += decode_tag_number_and_value(&apdu[len], len += decode_tag_number_and_value(&apdu[len],
&tag_number, &len_value_type); &tag_number, &len_value_type);
len += decode_character_string(&apdu[len], len_value_type, password); len +=
} decode_character_string(&apdu[len], len_value_type,
else if (password) password);
characterstring_init_ansi(password,NULL); } else if (password)
characterstring_init_ansi(password, NULL);
} }
return (int)len; return (int) len;
} }
int dcc_decode_apdu( int dcc_decode_apdu(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
uint8_t *invoke_id, uint8_t * invoke_id,
uint16_t *timeDuration, uint16_t * timeDuration,
BACNET_COMMUNICATION_ENABLE_DISABLE *enable_disable, BACNET_COMMUNICATION_ENABLE_DISABLE * enable_disable,
BACNET_CHARACTER_STRING *password) BACNET_CHARACTER_STRING * password)
{ {
int len = 0; int len = 0;
unsigned offset = 0; unsigned offset = 0;
@@ -232,14 +222,9 @@ int dcc_decode_apdu(
return -1; return -1;
offset = 4; offset = 4;
if (apdu_len > offset) if (apdu_len > offset) {
{ len = dcc_decode_service_request(&apdu[offset],
len = dcc_decode_service_request( apdu_len - offset, timeDuration, enable_disable, password);
&apdu[offset],
apdu_len - offset,
timeDuration,
enable_disable,
password);
} }
return len; return len;
@@ -250,14 +235,13 @@ int dcc_decode_apdu(
#include <string.h> #include <string.h>
#include "ctest.h" #include "ctest.h"
void test_DeviceCommunicationControlData( void test_DeviceCommunicationControlData(Test * pTest,
Test * pTest,
uint8_t invoke_id, uint8_t invoke_id,
uint16_t timeDuration, uint16_t timeDuration,
BACNET_COMMUNICATION_ENABLE_DISABLE enable_disable, BACNET_COMMUNICATION_ENABLE_DISABLE enable_disable,
BACNET_CHARACTER_STRING *password) BACNET_CHARACTER_STRING * password)
{ {
uint8_t apdu[480] = {0}; uint8_t apdu[480] = { 0 };
int len = 0; int len = 0;
int apdu_len = 0; int apdu_len = 0;
uint8_t test_invoke_id = 0; uint8_t test_invoke_id = 0;
@@ -265,27 +249,20 @@ void test_DeviceCommunicationControlData(
BACNET_COMMUNICATION_ENABLE_DISABLE test_enable_disable; BACNET_COMMUNICATION_ENABLE_DISABLE test_enable_disable;
BACNET_CHARACTER_STRING test_password; BACNET_CHARACTER_STRING test_password;
len = dcc_encode_apdu( len = dcc_encode_apdu(&apdu[0],
&apdu[0], invoke_id, timeDuration, enable_disable, password);
invoke_id,
timeDuration,
enable_disable,
password);
ct_test(pTest, len != 0); ct_test(pTest, len != 0);
apdu_len = len; apdu_len = len;
len = dcc_decode_apdu( len = dcc_decode_apdu(&apdu[0],
&apdu[0],
apdu_len, apdu_len,
&test_invoke_id, &test_invoke_id,
&test_timeDuration, &test_timeDuration, &test_enable_disable, &test_password);
&test_enable_disable,
&test_password);
ct_test(pTest, len != -1); ct_test(pTest, len != -1);
ct_test(pTest, test_invoke_id == invoke_id); ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest, test_timeDuration == timeDuration); ct_test(pTest, test_timeDuration == timeDuration);
ct_test(pTest, test_enable_disable == enable_disable); ct_test(pTest, test_enable_disable == enable_disable);
ct_test(pTest, characterstring_same(&test_password,password)); ct_test(pTest, characterstring_same(&test_password, password));
} }
void test_DeviceCommunicationControl(Test * pTest) void test_DeviceCommunicationControl(Test * pTest)
@@ -297,22 +274,14 @@ void test_DeviceCommunicationControl(Test * pTest)
timeDuration = 0; timeDuration = 0;
enable_disable = COMMUNICATION_DISABLE_INITIATION; enable_disable = COMMUNICATION_DISABLE_INITIATION;
characterstring_init_ansi(&password,"John 3:16"); characterstring_init_ansi(&password, "John 3:16");
test_DeviceCommunicationControlData( test_DeviceCommunicationControlData(pTest,
pTest, invoke_id, timeDuration, enable_disable, &password);
invoke_id,
timeDuration,
enable_disable,
&password);
timeDuration = 12345; timeDuration = 12345;
enable_disable = COMMUNICATION_DISABLE; enable_disable = COMMUNICATION_DISABLE;
test_DeviceCommunicationControlData( test_DeviceCommunicationControlData(pTest,
pTest, invoke_id, timeDuration, enable_disable, NULL);
invoke_id,
timeDuration,
enable_disable,
NULL);
return; return;
} }
+20 -29
View File
@@ -44,52 +44,43 @@ extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
/* return the status */ /* return the status */
BACNET_COMMUNICATION_ENABLE_DISABLE dcc_enable_status(void); BACNET_COMMUNICATION_ENABLE_DISABLE dcc_enable_status(void);
bool dcc_communication_enabled(void); bool dcc_communication_enabled(void);
bool dcc_communication_disabled(void); bool dcc_communication_disabled(void);
bool dcc_communication_initiation_disabled(void); bool dcc_communication_initiation_disabled(void);
/* return the time */ /* return the time */
uint32_t dcc_duration_seconds(void); uint32_t dcc_duration_seconds(void);
/* called every second or so. If more than one second, /* called every second or so. If more than one second,
then seconds should be the number of seconds to tick away */ then seconds should be the number of seconds to tick away */
void dcc_timer_seconds(uint32_t seconds); void dcc_timer_seconds(uint32_t seconds);
/* setup the communication values */ /* setup the communication values */
bool dcc_set_status_duration( bool dcc_set_status_duration(BACNET_COMMUNICATION_ENABLE_DISABLE
BACNET_COMMUNICATION_ENABLE_DISABLE status, status, uint16_t minutes);
uint16_t minutes);
// encode service // encode service
int dcc_encode_apdu( int dcc_encode_apdu(uint8_t * apdu, uint8_t invoke_id, uint16_t timeDuration, /* 0=optional */
uint8_t *apdu, BACNET_COMMUNICATION_ENABLE_DISABLE enable_disable, BACNET_CHARACTER_STRING * password); /* NULL=optional */
uint8_t invoke_id,
uint16_t timeDuration, /* 0=optional */
BACNET_COMMUNICATION_ENABLE_DISABLE enable_disable,
BACNET_CHARACTER_STRING *password); /* NULL=optional */
// decode the service request only // decode the service request only
int dcc_decode_service_request( int dcc_decode_service_request(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
uint16_t *timeDuration, uint16_t * timeDuration,
BACNET_COMMUNICATION_ENABLE_DISABLE *enable_disable, BACNET_COMMUNICATION_ENABLE_DISABLE * enable_disable,
BACNET_CHARACTER_STRING *password); BACNET_CHARACTER_STRING * password);
int dcc_decode_apdu( int dcc_decode_apdu(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
uint8_t *invoke_id, uint8_t * invoke_id,
uint16_t *timeDuration, uint16_t * timeDuration,
BACNET_COMMUNICATION_ENABLE_DISABLE *enable_disable, BACNET_COMMUNICATION_ENABLE_DISABLE * enable_disable,
BACNET_CHARACTER_STRING *password); BACNET_CHARACTER_STRING * password);
#ifdef TEST #ifdef TEST
#include "ctest.h" #include "ctest.h"
void test_DeviceCommunicationControl(Test * pTest); void test_DeviceCommunicationControl(Test * pTest);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+14 -17
View File
@@ -50,46 +50,43 @@ void dlmstp_cleanup(void)
} }
/* returns number of bytes sent on success, negative on failure */ /* returns number of bytes sent on success, negative on failure */
int dlmstp_send_pdu( int dlmstp_send_pdu(BACNET_ADDRESS * dest, // destination address
BACNET_ADDRESS *dest, // destination address uint8_t * pdu, // any data to be sent - may be null
uint8_t *pdu, // any data to be sent - may be null
unsigned pdu_len) // number of bytes of data unsigned pdu_len) // number of bytes of data
{ {
(void)dest; (void) dest;
(void)pdu; (void) pdu;
(void)pdu_len; (void) pdu_len;
return 0; return 0;
} }
// returns the number of octets in the PDU, or zero on failure // returns the number of octets in the PDU, or zero on failure
uint16_t dlmstp_receive( uint16_t dlmstp_receive(BACNET_ADDRESS * src, // source address
BACNET_ADDRESS *src, // source address uint8_t * pdu, // PDU data
uint8_t *pdu, // PDU data
uint16_t max_pdu, // amount of space available in the PDU uint16_t max_pdu, // amount of space available in the PDU
unsigned timeout) // milliseconds to wait for a packet unsigned timeout) // milliseconds to wait for a packet
{ {
(void)src; (void) src;
(void)pdu; (void) pdu;
(void)max_pdu; (void) max_pdu;
(void)timeout; (void) timeout;
return 0; return 0;
} }
void dlmstp_set_my_address(BACNET_ADDRESS *my_address) void dlmstp_set_my_address(BACNET_ADDRESS * my_address)
{ {
return; return;
} }
void dlmstp_get_my_address(BACNET_ADDRESS *my_address) void dlmstp_get_my_address(BACNET_ADDRESS * my_address)
{ {
return; return;
} }
void dlmstp_get_broadcast_address( void dlmstp_get_broadcast_address(BACNET_ADDRESS * dest) // destination address
BACNET_ADDRESS *dest) // destination address
{ {
return; return;
} }
+9 -13
View File
@@ -48,29 +48,25 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
void dlmstp_init(void); void dlmstp_init(void);
void dlmstp_cleanup(void); void dlmstp_cleanup(void);
/* returns number of bytes sent on success, negative on failure */ /* returns number of bytes sent on success, negative on failure */
int dlmstp_send_pdu( int dlmstp_send_pdu(BACNET_ADDRESS * dest, // destination address
BACNET_ADDRESS *dest, // destination address uint8_t * pdu, // any data to be sent - may be null
uint8_t *pdu, // any data to be sent - may be null
unsigned pdu_len); // number of bytes of data unsigned pdu_len); // number of bytes of data
// returns the number of octets in the PDU, or zero on failure // returns the number of octets in the PDU, or zero on failure
uint16_t dlmstp_receive( uint16_t dlmstp_receive(BACNET_ADDRESS * src, // source address
BACNET_ADDRESS *src, // source address uint8_t * pdu, // PDU data
uint8_t *pdu, // PDU data
uint16_t max_pdu, // amount of space available in the PDU uint16_t max_pdu, // amount of space available in the PDU
unsigned timeout); // milliseconds to wait for a packet unsigned timeout); // milliseconds to wait for a packet
void dlmstp_set_my_address(BACNET_ADDRESS *my_address); void dlmstp_set_my_address(BACNET_ADDRESS * my_address);
void dlmstp_get_my_address(BACNET_ADDRESS *my_address); void dlmstp_get_my_address(BACNET_ADDRESS * my_address);
void dlmstp_get_broadcast_address( void dlmstp_get_broadcast_address(BACNET_ADDRESS * dest); // destination address
BACNET_ADDRESS *dest); // destination address
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+13 -18
View File
@@ -47,40 +47,35 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
bool ethernet_valid(void); bool ethernet_valid(void);
void ethernet_cleanup(void); void ethernet_cleanup(void);
bool ethernet_init(char *interface_name); bool ethernet_init(char *interface_name);
/* function to send a packet out the 802.2 socket */ /* function to send a packet out the 802.2 socket */
/* returns number of bytes sent on success, negative on failure */ /* returns number of bytes sent on success, negative on failure */
int ethernet_send( int ethernet_send(BACNET_ADDRESS * dest, // destination address
BACNET_ADDRESS *dest, // destination address BACNET_ADDRESS * src, // source address
BACNET_ADDRESS *src, // source address uint8_t * pdu, // any data to be sent - may be null
uint8_t *pdu, // any data to be sent - may be null
unsigned pdu_len); // number of bytes of data unsigned pdu_len); // number of bytes of data
/* function to send a packet out the 802.2 socket */ /* function to send a packet out the 802.2 socket */
/* returns number of bytes sent on success, negative on failure */ /* returns number of bytes sent on success, negative on failure */
int ethernet_send_pdu( int ethernet_send_pdu(BACNET_ADDRESS * dest, // destination address
BACNET_ADDRESS *dest, // destination address uint8_t * pdu, // any data to be sent - may be null
uint8_t *pdu, // any data to be sent - may be null
unsigned pdu_len); // number of bytes of data unsigned pdu_len); // number of bytes of data
// receives an 802.2 framed packet // receives an 802.2 framed packet
// returns the number of octets in the PDU, or zero on failure // returns the number of octets in the PDU, or zero on failure
uint16_t ethernet_receive( uint16_t ethernet_receive(BACNET_ADDRESS * src, // source address
BACNET_ADDRESS *src, // source address uint8_t * pdu, // PDU data
uint8_t *pdu, // PDU data
uint16_t max_pdu, // amount of space available in the PDU uint16_t max_pdu, // amount of space available in the PDU
unsigned timeout); // milliseconds to wait for a packet unsigned timeout); // milliseconds to wait for a packet
void ethernet_set_my_address(BACNET_ADDRESS *my_address); void ethernet_set_my_address(BACNET_ADDRESS * my_address);
void ethernet_get_my_address(BACNET_ADDRESS *my_address); void ethernet_get_my_address(BACNET_ADDRESS * my_address);
void ethernet_get_broadcast_address( void ethernet_get_broadcast_address(BACNET_ADDRESS * dest); // destination address
BACNET_ADDRESS *dest); // destination address
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+9 -11
View File
@@ -39,11 +39,10 @@ char *filename_remove_path(const char *filename_in)
char *filename_out = NULL; char *filename_out = NULL;
/* allow the device ID to be set */ /* allow the device ID to be set */
if (filename_in) if (filename_in) {
{ filename_out = strrchr(filename_in, '\\');
filename_out = strrchr(filename_in,'\\');
if (!filename_out) if (!filename_out)
filename_out = strrchr(filename_in,'/'); filename_out = strrchr(filename_in, '/');
/* go beyond the slash */ /* go beyond the slash */
if (filename_out) if (filename_out)
filename_out++; filename_out++;
@@ -58,7 +57,7 @@ char *filename_remove_path(const char *filename_in)
#include "ctest.h" #include "ctest.h"
void testFilename(Test* pTest) void testFilename(Test * pTest)
{ {
char *data1 = "c:\\Joshua\\run"; char *data1 = "c:\\Joshua\\run";
char *data2 = "/home/Anna/run"; char *data2 = "/home/Anna/run";
@@ -67,13 +66,13 @@ void testFilename(Test* pTest)
char *filename = NULL; char *filename = NULL;
filename = filename_remove_path(data1); filename = filename_remove_path(data1);
ct_test(pTest,strcmp("run",filename) == 0); ct_test(pTest, strcmp("run", filename) == 0);
filename = filename_remove_path(data2); filename = filename_remove_path(data2);
ct_test(pTest,strcmp("run",filename) == 0); ct_test(pTest, strcmp("run", filename) == 0);
filename = filename_remove_path(data3); filename = filename_remove_path(data3);
ct_test(pTest,strcmp("run.exe",filename) == 0); ct_test(pTest, strcmp("run.exe", filename) == 0);
filename = filename_remove_path(data4); filename = filename_remove_path(data4);
ct_test(pTest,strcmp("run",filename) == 0); ct_test(pTest, strcmp("run", filename) == 0);
return; return;
} }
@@ -92,7 +91,7 @@ int main(void)
ct_setStream(pTest, stdout); ct_setStream(pTest, stdout);
ct_run(pTest); ct_run(pTest);
(void)ct_report(pTest); (void) ct_report(pTest);
ct_destroy(pTest); ct_destroy(pTest);
@@ -100,4 +99,3 @@ int main(void)
} }
#endif /* TEST_FILENAME */ #endif /* TEST_FILENAME */
#endif /* TEST */ #endif /* TEST */
+1 -2
View File
@@ -38,10 +38,9 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
char *filename_remove_path(const char *filename_in); char *filename_remove_path(const char *filename_in);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+54 -86
View File
@@ -41,12 +41,9 @@
#include "address.h" #include "address.h"
// encode I-Am service // encode I-Am service
int iam_encode_apdu( int iam_encode_apdu(uint8_t * apdu,
uint8_t *apdu,
uint32_t device_id, uint32_t device_id,
unsigned max_apdu, unsigned max_apdu, int segmentation, uint16_t vendor_id)
int segmentation,
uint16_t vendor_id)
{ {
int len = 0; // length of each encoding int len = 0; // length of each encoding
int apdu_len = 0; // total length of the apdu, return value int apdu_len = 0; // total length of the apdu, return value
@@ -55,34 +52,23 @@ int iam_encode_apdu(
apdu[0] = PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST; apdu[0] = PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST;
apdu[1] = SERVICE_UNCONFIRMED_I_AM; // service choice apdu[1] = SERVICE_UNCONFIRMED_I_AM; // service choice
apdu_len = 2; apdu_len = 2;
len = encode_tagged_object_id( len = encode_tagged_object_id(&apdu[apdu_len],
&apdu[apdu_len], OBJECT_DEVICE, device_id);
OBJECT_DEVICE,
device_id);
apdu_len += len; apdu_len += len;
len = encode_tagged_unsigned( len = encode_tagged_unsigned(&apdu[apdu_len], max_apdu);
&apdu[apdu_len],
max_apdu);
apdu_len += len; apdu_len += len;
len = encode_tagged_enumerated( len = encode_tagged_enumerated(&apdu[apdu_len], segmentation);
&apdu[apdu_len],
segmentation);
apdu_len += len; apdu_len += len;
len = encode_tagged_unsigned( len = encode_tagged_unsigned(&apdu[apdu_len], vendor_id);
&apdu[apdu_len],
vendor_id);
apdu_len += len; apdu_len += len;
} }
return apdu_len; return apdu_len;
} }
int iam_decode_service_request( int iam_decode_service_request(uint8_t * apdu,
uint8_t *apdu, uint32_t * pDevice_id,
uint32_t *pDevice_id, unsigned *pMax_apdu, int *pSegmentation, uint16_t * pVendor_id)
unsigned *pMax_apdu,
int *pSegmentation,
uint16_t *pVendor_id)
{ {
int len = 0; int len = 0;
int apdu_len = 0; // total length of the apdu, return value int apdu_len = 0; // total length of the apdu, return value
@@ -94,18 +80,23 @@ int iam_decode_service_request(
int decoded_integer = 0; int decoded_integer = 0;
// OBJECT ID - object id // OBJECT ID - object id
len = decode_tag_number_and_value(&apdu[apdu_len], &tag_number, &len_value); len =
decode_tag_number_and_value(&apdu[apdu_len], &tag_number,
&len_value);
apdu_len += len; apdu_len += len;
if (tag_number != BACNET_APPLICATION_TAG_OBJECT_ID) if (tag_number != BACNET_APPLICATION_TAG_OBJECT_ID)
return -1; return -1;
len = decode_object_id(&apdu[apdu_len], &object_type, &object_instance); len =
decode_object_id(&apdu[apdu_len], &object_type, &object_instance);
apdu_len += len; apdu_len += len;
if (object_type != OBJECT_DEVICE) if (object_type != OBJECT_DEVICE)
return -1; return -1;
if (pDevice_id) if (pDevice_id)
*pDevice_id = object_instance; *pDevice_id = object_instance;
// MAX APDU - unsigned // MAX APDU - unsigned
len = decode_tag_number_and_value(&apdu[apdu_len], &tag_number, &len_value); len =
decode_tag_number_and_value(&apdu[apdu_len], &tag_number,
&len_value);
apdu_len += len; apdu_len += len;
if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT) if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT)
return -1; return -1;
@@ -114,18 +105,22 @@ int iam_decode_service_request(
if (pMax_apdu) if (pMax_apdu)
*pMax_apdu = decoded_value; *pMax_apdu = decoded_value;
// Segmentation - enumerated // Segmentation - enumerated
len = decode_tag_number_and_value(&apdu[apdu_len], &tag_number, &len_value); len =
decode_tag_number_and_value(&apdu[apdu_len], &tag_number,
&len_value);
apdu_len += len; apdu_len += len;
if (tag_number != BACNET_APPLICATION_TAG_ENUMERATED) if (tag_number != BACNET_APPLICATION_TAG_ENUMERATED)
return -1; return -1;
len = decode_enumerated(&apdu[apdu_len],len_value, &decoded_integer); len = decode_enumerated(&apdu[apdu_len], len_value, &decoded_integer);
apdu_len += len; apdu_len += len;
if (decoded_integer >= MAX_BACNET_SEGMENTATION) if (decoded_integer >= MAX_BACNET_SEGMENTATION)
return -1; return -1;
if (pSegmentation) if (pSegmentation)
*pSegmentation = decoded_integer; *pSegmentation = decoded_integer;
// Vendor ID - unsigned16 // Vendor ID - unsigned16
len = decode_tag_number_and_value(&apdu[apdu_len], &tag_number, &len_value); len =
decode_tag_number_and_value(&apdu[apdu_len], &tag_number,
&len_value);
apdu_len += len; apdu_len += len;
if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT) if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT)
return -1; return -1;
@@ -134,17 +129,14 @@ int iam_decode_service_request(
if (decoded_value > 0xFFFF) if (decoded_value > 0xFFFF)
return -1; return -1;
if (pVendor_id) if (pVendor_id)
*pVendor_id = (uint16_t)decoded_value; *pVendor_id = (uint16_t) decoded_value;
return apdu_len; return apdu_len;
} }
int iam_decode_apdu( int iam_decode_apdu(uint8_t * apdu,
uint8_t *apdu, uint32_t * pDevice_id,
uint32_t *pDevice_id, unsigned *pMax_apdu, int *pSegmentation, uint16_t * pVendor_id)
unsigned *pMax_apdu,
int *pSegmentation,
uint16_t *pVendor_id)
{ {
int apdu_len = 0; // total length of the apdu, return value int apdu_len = 0; // total length of the apdu, return value
@@ -156,17 +148,13 @@ int iam_decode_apdu(
return -1; return -1;
if (apdu[1] != SERVICE_UNCONFIRMED_I_AM) if (apdu[1] != SERVICE_UNCONFIRMED_I_AM)
return -1; return -1;
apdu_len = iam_decode_service_request( apdu_len = iam_decode_service_request(&apdu[2],
&apdu[2], pDevice_id, pMax_apdu, pSegmentation, pVendor_id);
pDevice_id,
pMax_apdu,
pSegmentation,
pVendor_id);
return apdu_len; return apdu_len;
} }
int iam_send(uint8_t *buffer) int iam_send(uint8_t * buffer)
{ {
int pdu_len = 0; int pdu_len = 0;
BACNET_ADDRESS dest; BACNET_ADDRESS dest;
@@ -176,25 +164,16 @@ int iam_send(uint8_t *buffer)
datalink_get_broadcast_address(&dest); datalink_get_broadcast_address(&dest);
// encode the NPDU portion of the packet // encode the NPDU portion of the packet
pdu_len = npdu_encode_apdu( pdu_len = npdu_encode_apdu(&buffer[0], &dest, NULL, false, // true for confirmed messages
&buffer[0],
&dest,
NULL,
false, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL); MESSAGE_PRIORITY_NORMAL);
// encode the APDU portion of the packet // encode the APDU portion of the packet
pdu_len += iam_encode_apdu( pdu_len += iam_encode_apdu(&buffer[pdu_len],
&buffer[pdu_len],
Device_Object_Instance_Number(), Device_Object_Instance_Number(),
MAX_APDU, MAX_APDU, SEGMENTATION_NONE, Device_Vendor_Identifier());
SEGMENTATION_NONE,
Device_Vendor_Identifier());
bytes_sent = datalink_send_pdu( bytes_sent = datalink_send_pdu(&dest, // destination address
&dest, // destination address &buffer[0], pdu_len); // number of bytes of data
&buffer[0],
pdu_len); // number of bytes of data
return bytes_sent; return bytes_sent;
} }
@@ -206,7 +185,7 @@ int iam_send(uint8_t *buffer)
void testIAm(Test * pTest) void testIAm(Test * pTest)
{ {
uint8_t apdu[480] = {0}; uint8_t apdu[480] = { 0 };
int len = 0; int len = 0;
uint32_t device_id = 42; uint32_t device_id = 42;
unsigned max_apdu = 480; unsigned max_apdu = 480;
@@ -217,20 +196,13 @@ void testIAm(Test * pTest)
int test_segmentation = 0; int test_segmentation = 0;
uint16_t test_vendor_id = 0; uint16_t test_vendor_id = 0;
len = iam_encode_apdu( len = iam_encode_apdu(&apdu[0],
&apdu[0], device_id, max_apdu, segmentation, vendor_id);
device_id,
max_apdu,
segmentation,
vendor_id);
ct_test(pTest, len != 0); ct_test(pTest, len != 0);
len = iam_decode_apdu( len = iam_decode_apdu(&apdu[0],
&apdu[0],
&test_device_id, &test_device_id,
&test_max_apdu, &test_max_apdu, &test_segmentation, &test_vendor_id);
&test_segmentation,
&test_vendor_id);
ct_test(pTest, len != -1); ct_test(pTest, len != -1);
ct_test(pTest, test_device_id == device_id); ct_test(pTest, test_device_id == device_id);
@@ -241,19 +213,17 @@ void testIAm(Test * pTest)
#ifdef TEST_IAM #ifdef TEST_IAM
// Dummy stubs to eliminate depencies // Dummy stubs to eliminate depencies
void datalink_get_broadcast_address( void datalink_get_broadcast_address(BACNET_ADDRESS * dest) // destination address
BACNET_ADDRESS *dest) // destination address
{ {
(void)dest; (void) dest;
} }
int datalink_send_pdu( int datalink_send_pdu(BACNET_ADDRESS * dest, // destination address
BACNET_ADDRESS *dest, // destination address uint8_t * pdu, // any data to be sent - may be null
uint8_t *pdu, // any data to be sent - may be null
unsigned pdu_len) // number of bytes of data unsigned pdu_len) // number of bytes of data
{ {
(void)dest; (void) dest;
(void)pdu; (void) pdu;
return pdu_len; return pdu_len;
} }
@@ -268,21 +238,19 @@ uint32_t Device_Object_Instance_Number(void)
return 0; return 0;
} }
void address_add_binding( void address_add_binding(uint32_t device_id,
uint32_t device_id, unsigned max_apdu, BACNET_ADDRESS * src)
unsigned max_apdu,
BACNET_ADDRESS *src)
{ {
(void)device_id; (void) device_id;
(void)max_apdu; (void) max_apdu;
(void)src; (void) src;
} }
// dummy for apdu dependency // dummy for apdu dependency
void tsm_free_invoke_id(uint8_t invokeID) void tsm_free_invoke_id(uint8_t invokeID)
{ {
// dummy stub for testing // dummy stub for testing
(void)invokeID; (void) invokeID;
} }
+10 -20
View File
@@ -42,36 +42,26 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
int iam_encode_apdu( int iam_encode_apdu(uint8_t * apdu,
uint8_t *apdu,
uint32_t device_id, uint32_t device_id,
unsigned max_apdu, unsigned max_apdu, int segmentation, uint16_t vendor_id);
int segmentation,
uint16_t vendor_id);
int iam_decode_service_request( int iam_decode_service_request(uint8_t * apdu,
uint8_t *apdu, uint32_t * pDevice_id,
uint32_t *pDevice_id, unsigned *pMax_apdu, int *pSegmentation, uint16_t * pVendor_id);
unsigned *pMax_apdu,
int *pSegmentation,
uint16_t *pVendor_id);
int iam_decode_apdu( int iam_decode_apdu(uint8_t * apdu,
uint8_t *apdu, uint32_t * pDevice_id,
uint32_t *pDevice_id, unsigned *pMax_apdu, int *pSegmentation, uint16_t * pVendor_id);
unsigned *pMax_apdu,
int *pSegmentation,
uint16_t *pVendor_id);
int iam_send(uint8_t *buffer); int iam_send(uint8_t * buffer);
#ifdef TEST #ifdef TEST
#include "ctest.h" #include "ctest.h"
void testIAm(Test * pTest); void testIAm(Test * pTest);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+44 -74
View File
@@ -37,9 +37,7 @@
#include "bacdef.h" #include "bacdef.h"
#include "ihave.h" #include "ihave.h"
int ihave_encode_apdu( int ihave_encode_apdu(uint8_t * apdu, BACNET_I_HAVE_DATA * data)
uint8_t *apdu,
BACNET_I_HAVE_DATA *data)
{ {
int len = 0; /* length of each encoding */ int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */ int apdu_len = 0; /* total length of the apdu, return value */
@@ -49,20 +47,15 @@ int ihave_encode_apdu(
apdu[1] = SERVICE_UNCONFIRMED_I_HAVE; apdu[1] = SERVICE_UNCONFIRMED_I_HAVE;
apdu_len = 2; apdu_len = 2;
/* deviceIdentifier */ /* deviceIdentifier */
len = encode_tagged_object_id( len = encode_tagged_object_id(&apdu[apdu_len],
&apdu[apdu_len], data->device_id.type, data->device_id.instance);
data->device_id.type,
data->device_id.instance);
apdu_len += len; apdu_len += len;
/* objectIdentifier */ /* objectIdentifier */
len = encode_tagged_object_id( len = encode_tagged_object_id(&apdu[apdu_len],
&apdu[apdu_len], data->object_id.type, data->object_id.instance);
data->object_id.type,
data->object_id.instance);
apdu_len += len; apdu_len += len;
/* objectName */ /* objectName */
len = encode_tagged_character_string( len = encode_tagged_character_string(&apdu[apdu_len],
&apdu[apdu_len],
&data->object_name); &data->object_name);
apdu_len += len; apdu_len += len;
} }
@@ -71,58 +64,52 @@ int ihave_encode_apdu(
} }
/* decode the service request only */ /* decode the service request only */
int ihave_decode_service_request( int ihave_decode_service_request(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, BACNET_I_HAVE_DATA * data)
unsigned apdu_len,
BACNET_I_HAVE_DATA *data)
{ {
int len = 0; int len = 0;
uint8_t tag_number = 0; uint8_t tag_number = 0;
uint32_t len_value = 0; uint32_t len_value = 0;
int decoded_type = 0; /* for decoding */ int decoded_type = 0; /* for decoding */
if (apdu_len && data) if (apdu_len && data) {
{
/* deviceIdentifier */ /* deviceIdentifier */
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); len +=
if (tag_number == BACNET_APPLICATION_TAG_OBJECT_ID) decode_tag_number_and_value(&apdu[len], &tag_number,
{ &len_value);
if (tag_number == BACNET_APPLICATION_TAG_OBJECT_ID) {
len += decode_object_id(&apdu[len], &decoded_type, len += decode_object_id(&apdu[len], &decoded_type,
&data->device_id.instance); &data->device_id.instance);
data->device_id.type = decoded_type; data->device_id.type = decoded_type;
} } else
else
return -1; return -1;
/* objectIdentifier */ /* objectIdentifier */
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); len +=
if (tag_number == BACNET_APPLICATION_TAG_OBJECT_ID) decode_tag_number_and_value(&apdu[len], &tag_number,
{ &len_value);
if (tag_number == BACNET_APPLICATION_TAG_OBJECT_ID) {
len += decode_object_id(&apdu[len], &decoded_type, len += decode_object_id(&apdu[len], &decoded_type,
&data->object_id.instance); &data->object_id.instance);
data->object_id.type = decoded_type; data->object_id.type = decoded_type;
} } else
else
return -1; return -1;
/* objectName */ /* objectName */
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); len +=
if (tag_number == BACNET_APPLICATION_TAG_CHARACTER_STRING) decode_tag_number_and_value(&apdu[len], &tag_number,
{ &len_value);
if (tag_number == BACNET_APPLICATION_TAG_CHARACTER_STRING) {
len += decode_character_string(&apdu[len], len_value, len += decode_character_string(&apdu[len], len_value,
&data->object_name); &data->object_name);
} } else
else
return -1; return -1;
} } else
else
return -1; return -1;
return len; return len;
} }
int ihave_decode_apdu( int ihave_decode_apdu(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, BACNET_I_HAVE_DATA * data)
unsigned apdu_len,
BACNET_I_HAVE_DATA *data)
{ {
int len = 0; int len = 0;
@@ -133,10 +120,7 @@ int ihave_decode_apdu(
return -1; return -1;
if (apdu[1] != SERVICE_UNCONFIRMED_I_HAVE) if (apdu[1] != SERVICE_UNCONFIRMED_I_HAVE)
return -1; return -1;
len = ihave_decode_service_request( len = ihave_decode_service_request(&apdu[2], apdu_len - 2, data);
&apdu[2],
apdu_len - 2,
data);
return len; return len;
} }
@@ -146,59 +130,45 @@ int ihave_decode_apdu(
#include <string.h> #include <string.h>
#include "ctest.h" #include "ctest.h"
void testIHaveData(Test * pTest, BACNET_I_HAVE_DATA *data) void testIHaveData(Test * pTest, BACNET_I_HAVE_DATA * data)
{ {
uint8_t apdu[480] = {0}; uint8_t apdu[480] = { 0 };
int len = 0; int len = 0;
int apdu_len = 0; int apdu_len = 0;
BACNET_I_HAVE_DATA test_data; BACNET_I_HAVE_DATA test_data;
len = ihave_encode_apdu( len = ihave_encode_apdu(&apdu[0], data);
&apdu[0],
data);
ct_test(pTest, len != 0); ct_test(pTest, len != 0);
apdu_len = len; apdu_len = len;
len = ihave_decode_apdu( len = ihave_decode_apdu(&apdu[0], apdu_len, &test_data);
&apdu[0],
apdu_len,
&test_data);
ct_test(pTest, len != -1); ct_test(pTest, len != -1);
ct_test(pTest, test_data.device_id.type == ct_test(pTest, test_data.device_id.type == data->device_id.type);
data->device_id.type);
ct_test(pTest, test_data.device_id.instance == ct_test(pTest, test_data.device_id.instance ==
data->device_id.instance); data->device_id.instance);
ct_test(pTest, test_data.object_id.type == ct_test(pTest, test_data.object_id.type == data->object_id.type);
data->object_id.type);
ct_test(pTest, test_data.object_id.instance == ct_test(pTest, test_data.object_id.instance ==
data->object_id.instance); data->object_id.instance);
ct_test(pTest, characterstring_same( ct_test(pTest, characterstring_same(&test_data.object_name,
&test_data.object_name,&data->object_name)); &data->object_name));
} }
void testIHave(Test * pTest) void testIHave(Test * pTest)
{ {
BACNET_I_HAVE_DATA data; BACNET_I_HAVE_DATA data;
characterstring_init_ansi( characterstring_init_ansi(&data.object_name, "patricia");
&data.object_name,"patricia");
data.device_id.type = OBJECT_DEVICE; data.device_id.type = OBJECT_DEVICE;
for ( for (data.device_id.instance = 1;
data.device_id.instance = 1;
data.device_id.instance <= BACNET_MAX_INSTANCE; data.device_id.instance <= BACNET_MAX_INSTANCE;
data.device_id.instance <<= 1) data.device_id.instance <<= 1) {
{ for (data.object_id.type = OBJECT_ANALOG_INPUT;
for (
data.object_id.type = OBJECT_ANALOG_INPUT;
data.object_id.type <= MAX_BACNET_OBJECT_TYPE; data.object_id.type <= MAX_BACNET_OBJECT_TYPE;
data.object_id.type++) data.object_id.type++) {
{ for (data.object_id.instance = 1;
for (
data.object_id.instance = 1;
data.object_id.instance <= BACNET_MAX_INSTANCE; data.object_id.instance <= BACNET_MAX_INSTANCE;
data.object_id.instance <<= 1) data.object_id.instance <<= 1) {
{ testIHaveData(pTest, &data);
testIHaveData(pTest,&data);
} }
} }
} }
+7 -16
View File
@@ -38,8 +38,7 @@
#include <stdbool.h> #include <stdbool.h>
#include "bacstr.h" #include "bacstr.h"
typedef struct BACnet_I_Have_Data typedef struct BACnet_I_Have_Data {
{
BACNET_OBJECT_ID device_id; BACNET_OBJECT_ID device_id;
BACNET_OBJECT_ID object_id; BACNET_OBJECT_ID object_id;
BACNET_CHARACTER_STRING object_name; BACNET_CHARACTER_STRING object_name;
@@ -49,28 +48,20 @@ typedef struct BACnet_I_Have_Data
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
int ihave_encode_apdu( int ihave_encode_apdu(uint8_t * apdu, BACNET_I_HAVE_DATA * data);
uint8_t *apdu,
BACNET_I_HAVE_DATA *data);
int ihave_decode_service_request( int ihave_decode_service_request(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, BACNET_I_HAVE_DATA * data);
unsigned apdu_len,
BACNET_I_HAVE_DATA *data);
int ihave_decode_apdu( int ihave_decode_apdu(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, BACNET_I_HAVE_DATA * data);
unsigned apdu_len,
BACNET_I_HAVE_DATA *data);
#ifdef TEST #ifdef TEST
#include "ctest.h" #include "ctest.h"
void testIHave(Test * pTest); void testIHave(Test * pTest);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+54 -83
View File
@@ -39,20 +39,15 @@
#define strcasecmp stricmp #define strcasecmp stricmp
#endif #endif
bool indtext_by_string( bool indtext_by_string(INDTEXT_DATA * data_list,
INDTEXT_DATA *data_list, const char *search_name, unsigned *found_index)
const char *search_name,
unsigned *found_index)
{ {
bool found = false; bool found = false;
unsigned index = 0; unsigned index = 0;
if (data_list && search_name) if (data_list && search_name) {
{ while (data_list->pString) {
while (data_list->pString) if (strcmp(data_list->pString, search_name) == 0) {
{
if (strcmp(data_list->pString,search_name) == 0)
{
index = data_list->index; index = data_list->index;
found = true; found = true;
break; break;
@@ -68,20 +63,15 @@ bool indtext_by_string(
} }
/* case insensitive version */ /* case insensitive version */
bool indtext_by_istring( bool indtext_by_istring(INDTEXT_DATA * data_list,
INDTEXT_DATA *data_list, const char *search_name, unsigned *found_index)
const char *search_name,
unsigned *found_index)
{ {
bool found = false; bool found = false;
unsigned index = 0; unsigned index = 0;
if (data_list && search_name) if (data_list && search_name) {
{ while (data_list->pString) {
while (data_list->pString) if (strcasecmp(data_list->pString, search_name) == 0) {
{
if (strcasecmp(data_list->pString,search_name) == 0)
{
index = data_list->index; index = data_list->index;
found = true; found = true;
break; break;
@@ -96,45 +86,36 @@ bool indtext_by_istring(
return found; return found;
} }
unsigned indtext_by_string_default( unsigned indtext_by_string_default(INDTEXT_DATA * data_list,
INDTEXT_DATA *data_list, const char *search_name, unsigned default_index)
const char *search_name,
unsigned default_index)
{ {
unsigned index = 0; unsigned index = 0;
if (!indtext_by_string(data_list,search_name,&index)) if (!indtext_by_string(data_list, search_name, &index))
index = default_index; index = default_index;
return index; return index;
} }
unsigned indtext_by_istring_default( unsigned indtext_by_istring_default(INDTEXT_DATA * data_list,
INDTEXT_DATA *data_list, const char *search_name, unsigned default_index)
const char *search_name,
unsigned default_index)
{ {
unsigned index = 0; unsigned index = 0;
if (!indtext_by_istring(data_list,search_name,&index)) if (!indtext_by_istring(data_list, search_name, &index))
index = default_index; index = default_index;
return index; return index;
} }
const char *indtext_by_index_default( const char *indtext_by_index_default(INDTEXT_DATA * data_list,
INDTEXT_DATA *data_list, unsigned index, const char *default_string)
unsigned index,
const char *default_string)
{ {
const char *pString = NULL; const char *pString = NULL;
if (data_list) if (data_list) {
{ while (data_list->pString) {
while (data_list->pString) if (data_list->index == index) {
{
if (data_list->index == index)
{
pString = data_list->pString; pString = data_list->pString;
break; break;
} }
@@ -142,42 +123,33 @@ const char *indtext_by_index_default(
} }
} }
return pString?pString:default_string; return pString ? pString : default_string;
} }
const char *indtext_by_index_split_default( const char *indtext_by_index_split_default(INDTEXT_DATA * data_list,
INDTEXT_DATA *data_list,
int index, int index,
int split_index, int split_index,
const char *before_split_default_name, const char *before_split_default_name, const char *default_name)
const char *default_name)
{ {
if (index < split_index) if (index < split_index)
return indtext_by_index_default(data_list, index, before_split_default_name); return indtext_by_index_default(data_list, index,
before_split_default_name);
else else
return indtext_by_index_default(data_list, index, default_name); return indtext_by_index_default(data_list, index, default_name);
}; };
const char *indtext_by_index( const char *indtext_by_index(INDTEXT_DATA * data_list, unsigned index)
INDTEXT_DATA *data_list,
unsigned index)
{ {
return indtext_by_index_default( return indtext_by_index_default(data_list, index, NULL);
data_list,
index,
NULL);
} }
unsigned indtext_count( unsigned indtext_count(INDTEXT_DATA * data_list)
INDTEXT_DATA *data_list)
{ {
unsigned count = 0; /* return value */ unsigned count = 0; /* return value */
if (data_list) if (data_list) {
{ while (data_list->pString) {
while (data_list->pString)
{
count++; count++;
data_list++; data_list++;
} }
@@ -189,8 +161,7 @@ unsigned indtext_count(
#include <assert.h> #include <assert.h>
#include "ctest.h" #include "ctest.h"
static INDTEXT_DATA data_list[] = static INDTEXT_DATA data_list[] = {
{
{1, "Joshua"}, {1, "Joshua"},
{2, "Mary"}, {2, "Mary"},
{3, "Anna"}, {3, "Anna"},
@@ -199,7 +170,7 @@ static INDTEXT_DATA data_list[] =
{0, NULL} {0, NULL}
}; };
void testIndexText(Test* pTest) void testIndexText(Test * pTest)
{ {
unsigned i; /*counter */ unsigned i; /*counter */
const char *pString; const char *pString;
@@ -207,30 +178,30 @@ void testIndexText(Test* pTest)
bool valid; bool valid;
unsigned count = 0; unsigned count = 0;
for (i = 0; i < 10; i++) for (i = 0; i < 10; i++) {
{ pString = indtext_by_index(data_list, i);
pString = indtext_by_index(data_list,i); if (pString) {
if (pString)
{
count++; count++;
valid = indtext_by_string(data_list,pString,&index); valid = indtext_by_string(data_list, pString, &index);
ct_test(pTest,valid == true); ct_test(pTest, valid == true);
ct_test(pTest,index == i); ct_test(pTest, index == i);
ct_test(pTest,index == indtext_by_string_default(data_list,pString,index)); ct_test(pTest, index == indtext_by_string_default(data_list,
pString, index));
} }
} }
ct_test(pTest,indtext_count(data_list) == count); ct_test(pTest, indtext_count(data_list) == count);
ct_test(pTest,indtext_by_string(data_list,"Harry",NULL) == false); ct_test(pTest, indtext_by_string(data_list, "Harry", NULL) == false);
ct_test(pTest,indtext_by_string(data_list,NULL,NULL) == false); ct_test(pTest, indtext_by_string(data_list, NULL, NULL) == false);
ct_test(pTest,indtext_by_string(NULL,NULL,NULL) == false); ct_test(pTest, indtext_by_string(NULL, NULL, NULL) == false);
ct_test(pTest,indtext_by_index(data_list,0) == NULL); ct_test(pTest, indtext_by_index(data_list, 0) == NULL);
ct_test(pTest,indtext_by_index(data_list,10) == NULL); ct_test(pTest, indtext_by_index(data_list, 10) == NULL);
ct_test(pTest,indtext_by_index(NULL,10) == NULL); ct_test(pTest, indtext_by_index(NULL, 10) == NULL);
/* case insensitive versions */ /* case insensitive versions */
ct_test(pTest,indtext_by_istring(data_list,"JOSHUA",NULL) == true); ct_test(pTest, indtext_by_istring(data_list, "JOSHUA", NULL) == true);
ct_test(pTest,indtext_by_istring(data_list,"joshua",NULL) == true); ct_test(pTest, indtext_by_istring(data_list, "joshua", NULL) == true);
valid = indtext_by_istring(data_list,"ANNA",&index); valid = indtext_by_istring(data_list, "ANNA", &index);
ct_test(pTest,index == indtext_by_istring_default(data_list,"ANNA",index)); ct_test(pTest, index == indtext_by_istring_default(data_list, "ANNA",
index));
} }
#endif #endif
@@ -248,7 +219,7 @@ int main(void)
ct_setStream(pTest, stdout); ct_setStream(pTest, stdout);
ct_run(pTest); ct_run(pTest);
(void)ct_report(pTest); (void) ct_report(pTest);
ct_destroy(pTest); ct_destroy(pTest);
+17 -34
View File
@@ -39,8 +39,7 @@
#include <string.h> #include <string.h>
/* index and text pairs */ /* index and text pairs */
typedef struct typedef struct {
{
unsigned index; /* index number that matches the text */ unsigned index; /* index number that matches the text */
const char *pString; /* text pair - use NULL to end the list */ const char *pString; /* text pair - use NULL to end the list */
} INDTEXT_DATA; } INDTEXT_DATA;
@@ -54,59 +53,43 @@ extern "C" {
If the string is not found, false is returned If the string is not found, false is returned
If the string is found, true is returned and the found_index contains If the string is found, true is returned and the found_index contains
the first index where the string was found. */ the first index where the string was found. */
bool indtext_by_string( bool indtext_by_string(INDTEXT_DATA * data_list,
INDTEXT_DATA *data_list, const char *search_name, unsigned *found_index);
const char *search_name,
unsigned *found_index);
/* case insensitive version */ /* case insensitive version */
bool indtext_by_istring( bool indtext_by_istring(INDTEXT_DATA * data_list,
INDTEXT_DATA *data_list, const char *search_name, unsigned *found_index);
const char *search_name,
unsigned *found_index);
/* Searches for a matching string and returns the index to the string /* Searches for a matching string and returns the index to the string
or the default_index if the string is not found. */ or the default_index if the string is not found. */
unsigned indtext_by_string_default( unsigned indtext_by_string_default(INDTEXT_DATA * data_list,
INDTEXT_DATA *data_list, const char *search_name, unsigned default_index);
const char *search_name,
unsigned default_index);
/* case insensitive version */ /* case insensitive version */
unsigned indtext_by_istring_default( unsigned indtext_by_istring_default(INDTEXT_DATA * data_list,
INDTEXT_DATA *data_list, const char *search_name, unsigned default_index);
const char *search_name,
unsigned default_index);
/* for a given index, return the matching string, /* for a given index, return the matching string,
or NULL if not found */ or NULL if not found */
const char *indtext_by_index( const char *indtext_by_index(INDTEXT_DATA * data_list, unsigned index);
INDTEXT_DATA *data_list,
unsigned index);
/* for a given index, return the matching string, /* for a given index, return the matching string,
or default_name if not found */ or default_name if not found */
const char *indtext_by_index_default( const char *indtext_by_index_default(INDTEXT_DATA * data_list,
INDTEXT_DATA *data_list, unsigned index, const char *default_name);
unsigned index,
const char *default_name);
/* for a given index, return the matching string, /* for a given index, return the matching string,
or default_name if not found. or default_name if not found.
if the index is before the split, if the index is before the split,
the before_split_default_name is used */ the before_split_default_name is used */
const char *indtext_by_index_split_default( const char *indtext_by_index_split_default(INDTEXT_DATA * data_list,
INDTEXT_DATA *data_list,
int index, int index,
int split_index, int split_index,
const char *before_split_default_name, const char *before_split_default_name, const char *default_name);
const char *default_name);
/* returns the number of elements in the list */ /* returns the number of elements in the list */
unsigned indtext_count( unsigned indtext_count(INDTEXT_DATA * data_list);
INDTEXT_DATA *data_list);
#ifdef TEST #ifdef TEST
#include "ctest.h" #include "ctest.h"
void testIndexText(Test* pTest); void testIndexText(Test * pTest);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+2 -3
View File
@@ -46,11 +46,10 @@ int main(void)
struct mstp_port_struct_t mstp_port; // port data struct mstp_port_struct_t mstp_port; // port data
uint8_t my_mac = 0x05; // local MAC address uint8_t my_mac = 0x05; // local MAC address
MSTP_Init(&mstp_port,my_mac); MSTP_Init(&mstp_port, my_mac);
// loop forever // loop forever
for (;;) for (;;) {
{
// input // input
RS485_Check_UART_Data(&mstp_port); RS485_Check_UART_Data(&mstp_port);
MSTP_Receive_Frame_FSM(&mstp_port); MSTP_Receive_Frame_FSM(&mstp_port);
+399 -517
View File
File diff suppressed because it is too large Load Diff
+10 -12
View File
@@ -66,8 +66,7 @@
#define FRAME_TYPE_PROPRIETARY_MAX 255 #define FRAME_TYPE_PROPRIETARY_MAX 255
// receive FSM states // receive FSM states
typedef enum typedef enum {
{
MSTP_RECEIVE_STATE_IDLE, MSTP_RECEIVE_STATE_IDLE,
MSTP_RECEIVE_STATE_PREAMBLE, MSTP_RECEIVE_STATE_PREAMBLE,
MSTP_RECEIVE_STATE_HEADER, MSTP_RECEIVE_STATE_HEADER,
@@ -77,8 +76,7 @@ typedef enum
} MSTP_RECEIVE_STATE; } MSTP_RECEIVE_STATE;
// master node FSM states // master node FSM states
typedef enum typedef enum {
{
MSTP_MASTER_STATE_INITIALIZE, MSTP_MASTER_STATE_INITIALIZE,
MSTP_MASTER_STATE_IDLE, MSTP_MASTER_STATE_IDLE,
MSTP_MASTER_STATE_USE_TOKEN, MSTP_MASTER_STATE_USE_TOKEN,
@@ -90,8 +88,7 @@ typedef enum
MSTP_MASTER_STATE_ANSWER_DATA_REQUEST MSTP_MASTER_STATE_ANSWER_DATA_REQUEST
} MSTP_MASTER_STATE; } MSTP_MASTER_STATE;
struct mstp_port_struct_t struct mstp_port_struct_t {
{
MSTP_RECEIVE_STATE receive_state; MSTP_RECEIVE_STATE receive_state;
// When a master node is powered up or reset, // When a master node is powered up or reset,
// it shall unconditionally enter the INITIALIZE state. // it shall unconditionally enter the INITIALIZE state.
@@ -208,15 +205,16 @@ struct mstp_port_struct_t
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
void MSTP_Init( void MSTP_Init(volatile struct mstp_port_struct_t *mstp_port,
volatile struct mstp_port_struct_t *mstp_port,
uint8_t this_station_mac); uint8_t this_station_mac);
void MSTP_Millisecond_Timer(volatile struct mstp_port_struct_t *mstp_port); void MSTP_Millisecond_Timer(volatile struct mstp_port_struct_t
void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port); *mstp_port);
void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port); void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t
*mstp_port);
void MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t
*mstp_port);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+84 -153
View File
@@ -40,17 +40,14 @@
#include "npdu.h" #include "npdu.h"
#include "apdu.h" #include "apdu.h"
int npdu_encode_raw( int npdu_encode_raw(uint8_t * npdu,
uint8_t *npdu, BACNET_ADDRESS * dest,
BACNET_ADDRESS *dest, BACNET_ADDRESS * src, BACNET_NPDU_DATA * npdu_data)
BACNET_ADDRESS *src,
BACNET_NPDU_DATA *npdu_data)
{ {
int len = 0; // return value - number of octets loaded in this function int len = 0; // return value - number of octets loaded in this function
int i = 0; // counter int i = 0; // counter
if (npdu && npdu_data) if (npdu && npdu_data) {
{
// Protocol Version // Protocol Version
npdu[0] = 1; npdu[0] = 1;
// control octet // control octet
@@ -94,30 +91,24 @@ int npdu_encode_raw(
// B'00' = Normal message // B'00' = Normal message
npdu[1] |= (npdu_data->priority & 0x03); npdu[1] |= (npdu_data->priority & 0x03);
len = 2; len = 2;
if (dest && dest->net) if (dest && dest->net) {
{
len += encode_unsigned16(&npdu[len], dest->net); len += encode_unsigned16(&npdu[len], dest->net);
npdu[len++] = dest->len; npdu[len++] = dest->len;
// DLEN = 0 denotes broadcast MAC DADR and DADR field is absent // DLEN = 0 denotes broadcast MAC DADR and DADR field is absent
// DLEN > 0 specifies length of DADR field // DLEN > 0 specifies length of DADR field
if (dest->len) if (dest->len) {
{ for (i = 0; i < dest->len; i++) {
for (i = 0; i < dest->len; i++)
{
npdu[len++] = dest->adr[i]; npdu[len++] = dest->adr[i];
} }
} }
} }
if (src && src->net) if (src && src->net) {
{
len += encode_unsigned16(&npdu[len], src->net); len += encode_unsigned16(&npdu[len], src->net);
npdu[len++] = src->len; npdu[len++] = src->len;
// SLEN = 0 denotes broadcast MAC SADR and SADR field is absent // SLEN = 0 denotes broadcast MAC SADR and SADR field is absent
// SLEN > 0 specifies length of SADR field // SLEN > 0 specifies length of SADR field
if (src->len) if (src->len) {
{ for (i = 0; i < src->len; i++) {
for (i = 0; i < src->len; i++)
{
npdu[len++] = src->adr[i]; npdu[len++] = src->adr[i];
} }
} }
@@ -125,13 +116,11 @@ int npdu_encode_raw(
// The Hop Count field shall be present only if the message is // The Hop Count field shall be present only if the message is
// destined for a remote network, i.e., if DNET is present. // destined for a remote network, i.e., if DNET is present.
// This is a one-octet field that is initialized to a value of 0xff. // This is a one-octet field that is initialized to a value of 0xff.
if (dest && dest->net) if (dest && dest->net) {
{
npdu[len] = 0xFF; npdu[len] = 0xFF;
len++; len++;
} }
if (npdu_data->network_layer_message) if (npdu_data->network_layer_message) {
{
npdu[len] = npdu_data->network_message_type; npdu[len] = npdu_data->network_message_type;
len++; len++;
// Message Type field contains a value in the range 0x80 - 0xFF, // Message Type field contains a value in the range 0x80 - 0xFF,
@@ -146,14 +135,10 @@ int npdu_encode_raw(
// encode the NPDU portion of the packet for an APDU // encode the NPDU portion of the packet for an APDU
// This function does not handle the network messages, just APDUs. // This function does not handle the network messages, just APDUs.
int npdu_encode_apdu( int npdu_encode_apdu(uint8_t * npdu, BACNET_ADDRESS * dest, BACNET_ADDRESS * src, bool data_expecting_reply, // true for confirmed messages
uint8_t *npdu,
BACNET_ADDRESS *dest,
BACNET_ADDRESS *src,
bool data_expecting_reply, // true for confirmed messages
BACNET_MESSAGE_PRIORITY priority) BACNET_MESSAGE_PRIORITY priority)
{ {
BACNET_NPDU_DATA npdu_data = {0}; BACNET_NPDU_DATA npdu_data = { 0 };
npdu_data.data_expecting_reply = data_expecting_reply; npdu_data.data_expecting_reply = data_expecting_reply;
npdu_data.network_layer_message = false; // false if APDU npdu_data.network_layer_message = false; // false if APDU
@@ -161,18 +146,12 @@ int npdu_encode_apdu(
npdu_data.vendor_id = 0; // optional, if net message type is > 0x80 npdu_data.vendor_id = 0; // optional, if net message type is > 0x80
npdu_data.priority = priority; npdu_data.priority = priority;
// call the real function... // call the real function...
return npdu_encode_raw( return npdu_encode_raw(npdu, dest, src, &npdu_data);
npdu,
dest,
src,
&npdu_data);
} }
int npdu_decode( int npdu_decode(uint8_t * npdu,
uint8_t *npdu, BACNET_ADDRESS * dest,
BACNET_ADDRESS *dest, BACNET_ADDRESS * src, BACNET_NPDU_DATA * npdu_data)
BACNET_ADDRESS *src,
BACNET_NPDU_DATA *npdu_data)
{ {
int len = 0; // return value - number of octets loaded in this function int len = 0; // return value - number of octets loaded in this function
int i = 0; // counter int i = 0; // counter
@@ -181,8 +160,7 @@ int npdu_decode(
uint8_t address_len = 0; uint8_t address_len = 0;
uint8_t mac_octet = 0; uint8_t mac_octet = 0;
if (npdu && npdu_data) if (npdu && npdu_data) {
{
// Protocol Version // Protocol Version
npdu_data->protocol_version = npdu[0]; npdu_data->protocol_version = npdu[0];
// control octet // control octet
@@ -215,21 +193,17 @@ int npdu_decode(
// 1 = DNET, DLEN, and Hop Count present // 1 = DNET, DLEN, and Hop Count present
// DLEN = 0 denotes broadcast MAC DADR and DADR field is absent // DLEN = 0 denotes broadcast MAC DADR and DADR field is absent
// DLEN > 0 specifies length of DADR field // DLEN > 0 specifies length of DADR field
if (npdu[1] & BIT5) if (npdu[1] & BIT5) {
{
len += decode_unsigned16(&npdu[len], &dest_net); len += decode_unsigned16(&npdu[len], &dest_net);
// DLEN = 0 denotes broadcast MAC DADR and DADR field is absent // DLEN = 0 denotes broadcast MAC DADR and DADR field is absent
// DLEN > 0 specifies length of DADR field // DLEN > 0 specifies length of DADR field
address_len = npdu[len++]; address_len = npdu[len++];
if (dest) if (dest) {
{
dest->net = dest_net; dest->net = dest_net;
dest->len = address_len; dest->len = address_len;
} }
if (address_len) if (address_len) {
{ for (i = 0; i < address_len; i++) {
for (i = 0; i < address_len; i++)
{
mac_octet = npdu[len++]; mac_octet = npdu[len++];
if (dest) if (dest)
dest->adr[i] = mac_octet; dest->adr[i] = mac_octet;
@@ -237,12 +211,10 @@ int npdu_decode(
} }
} }
// zero out the destination address // zero out the destination address
else if (dest) else if (dest) {
{
dest->net = 0; dest->net = 0;
dest->len = 0; dest->len = 0;
for (i = 0; i < MAX_MAC_LEN; i++) for (i = 0; i < MAX_MAC_LEN; i++) {
{
dest->adr[i] = 0; dest->adr[i] = 0;
} }
} }
@@ -251,33 +223,26 @@ int npdu_decode(
// 1 = SNET, SLEN, and SADR present // 1 = SNET, SLEN, and SADR present
// SLEN = 0 Invalid // SLEN = 0 Invalid
// SLEN > 0 specifies length of SADR field // SLEN > 0 specifies length of SADR field
if (npdu[1] & BIT3) if (npdu[1] & BIT3) {
{
len += decode_unsigned16(&npdu[len], &src_net); len += decode_unsigned16(&npdu[len], &src_net);
// SLEN = 0 denotes broadcast MAC SADR and SADR field is absent // SLEN = 0 denotes broadcast MAC SADR and SADR field is absent
// SLEN > 0 specifies length of SADR field // SLEN > 0 specifies length of SADR field
address_len = npdu[len++]; address_len = npdu[len++];
if (src) if (src) {
{
src->net = src_net; src->net = src_net;
src->len = address_len; src->len = address_len;
} }
if (address_len) if (address_len) {
{ for (i = 0; i < address_len; i++) {
for (i = 0; i < address_len; i++)
{
mac_octet = npdu[len++]; mac_octet = npdu[len++];
if (src) if (src)
src->adr[i] = mac_octet; src->adr[i] = mac_octet;
} }
} }
} } else if (src) {
else if (src)
{
src->net = 0; src->net = 0;
src->len = 0; src->len = 0;
for (i = 0; i < MAX_MAC_LEN; i++) for (i = 0; i < MAX_MAC_LEN; i++) {
{
src->adr[i] = 0; src->adr[i] = 0;
} }
} }
@@ -290,46 +255,38 @@ int npdu_decode(
npdu_data->hop_count = 0; npdu_data->hop_count = 0;
// Indicates that the NSDU conveys a network layer message. // Indicates that the NSDU conveys a network layer message.
// Message Type field is present. // Message Type field is present.
if (npdu_data->network_layer_message) if (npdu_data->network_layer_message) {
{
npdu_data->network_message_type = npdu[len++]; npdu_data->network_message_type = npdu[len++];
// Message Type field contains a value in the range 0x80 - 0xFF, // Message Type field contains a value in the range 0x80 - 0xFF,
// then a Vendor ID field shall be present // then a Vendor ID field shall be present
if (npdu_data->network_message_type >= 0x80) if (npdu_data->network_message_type >= 0x80)
len += decode_unsigned16(&npdu[len], &npdu_data->vendor_id); len +=
} decode_unsigned16(&npdu[len], &npdu_data->vendor_id);
else } else
npdu_data->network_message_type = 0; npdu_data->network_message_type = 0;
} }
return len; return len;
} }
void npdu_handler( void npdu_handler(BACNET_ADDRESS * src, // source address
BACNET_ADDRESS *src, // source address uint8_t * pdu, // PDU data
uint8_t *pdu, // PDU data
uint16_t pdu_len) // length PDU uint16_t pdu_len) // length PDU
{ {
int apdu_offset = 0; int apdu_offset = 0;
BACNET_ADDRESS dest = {0}; BACNET_ADDRESS dest = { 0 };
BACNET_NPDU_DATA npdu_data = {0}; BACNET_NPDU_DATA npdu_data = { 0 };
apdu_offset = npdu_decode( apdu_offset = npdu_decode(&pdu[0], // data to decode
&pdu[0], // data to decode
&dest, // destination address - get the DNET/DLEN/DADR if in there &dest, // destination address - get the DNET/DLEN/DADR if in there
src, // source address - get the SNET/SLEN/SADR if in there src, // source address - get the SNET/SLEN/SADR if in there
&npdu_data); // amount of data to decode &npdu_data); // amount of data to decode
if (npdu_data.network_layer_message) if (npdu_data.network_layer_message) {
{
//FIXME: network layer message received! Handle it! //FIXME: network layer message received! Handle it!
} } else {
else apdu_handler(src,
{
apdu_handler(
src,
npdu_data.data_expecting_reply, npdu_data.data_expecting_reply,
&pdu[apdu_offset], &pdu[apdu_offset], pdu_len - apdu_offset);
pdu_len - apdu_offset);
} }
return; return;
@@ -343,139 +300,115 @@ void npdu_handler(
void testNPDU2(Test * pTest) void testNPDU2(Test * pTest)
{ {
uint8_t pdu[480] = {0}; uint8_t pdu[480] = { 0 };
BACNET_ADDRESS dest = {0}; BACNET_ADDRESS dest = { 0 };
BACNET_ADDRESS src = {0}; BACNET_ADDRESS src = { 0 };
BACNET_ADDRESS npdu_dest = {0}; BACNET_ADDRESS npdu_dest = { 0 };
BACNET_ADDRESS npdu_src = {0}; BACNET_ADDRESS npdu_src = { 0 };
int len = 0; int len = 0;
bool data_expecting_reply = false; // true for confirmed messages bool data_expecting_reply = false; // true for confirmed messages
BACNET_MESSAGE_PRIORITY priority = MESSAGE_PRIORITY_NORMAL; BACNET_MESSAGE_PRIORITY priority = MESSAGE_PRIORITY_NORMAL;
BACNET_NPDU_DATA npdu_data = {0}; BACNET_NPDU_DATA npdu_data = { 0 };
int i = 0; // counter int i = 0; // counter
int npdu_len = 0; int npdu_len = 0;
bool network_layer_message = false; // false if APDU bool network_layer_message = false; // false if APDU
BACNET_NETWORK_MESSAGE_TYPE network_message_type = 0;// optional BACNET_NETWORK_MESSAGE_TYPE network_message_type = 0; // optional
uint16_t vendor_id = 0; // optional, if net message type is > 0x80 uint16_t vendor_id = 0; // optional, if net message type is > 0x80
// mac_len = 0 if global address // mac_len = 0 if global address
dest.mac_len = 6; dest.mac_len = 6;
for (i = 0; i < dest.mac_len; i++) for (i = 0; i < dest.mac_len; i++) {
{
dest.mac[i] = i; dest.mac[i] = i;
} }
// DNET,DLEN,DADR // DNET,DLEN,DADR
dest.net = 1; dest.net = 1;
dest.len = 6; dest.len = 6;
for (i = 0; i < dest.len; i++) for (i = 0; i < dest.len; i++) {
{
dest.adr[i] = i * 10; dest.adr[i] = i * 10;
} }
src.mac_len = 1; src.mac_len = 1;
for (i = 0; i < src.mac_len; i++) for (i = 0; i < src.mac_len; i++) {
{
src.mac[i] = 0x80; src.mac[i] = 0x80;
} }
// SNET,SLEN,SADR // SNET,SLEN,SADR
src.net = 2; src.net = 2;
src.len = 1; src.len = 1;
for (i = 0; i < src.len; i++) for (i = 0; i < src.len; i++) {
{
src.adr[i] = 0x40; src.adr[i] = 0x40;
} }
len = npdu_encode_apdu( len = npdu_encode_apdu(&pdu[0],
&pdu[0], &dest, &src, data_expecting_reply, priority);
&dest,
&src,
data_expecting_reply,
priority);
ct_test(pTest, len != 0); ct_test(pTest, len != 0);
// can we get the info back? // can we get the info back?
npdu_len = npdu_decode( npdu_len = npdu_decode(&pdu[0], &npdu_dest, &npdu_src, &npdu_data);
&pdu[0],
&npdu_dest,
&npdu_src,
&npdu_data);
ct_test(pTest, npdu_len != 0); ct_test(pTest, npdu_len != 0);
ct_test(pTest, npdu_data.data_expecting_reply == data_expecting_reply); ct_test(pTest, npdu_data.data_expecting_reply == data_expecting_reply);
ct_test(pTest, npdu_data.network_layer_message == network_layer_message); ct_test(pTest,
npdu_data.network_layer_message == network_layer_message);
ct_test(pTest, npdu_data.network_message_type == network_message_type); ct_test(pTest, npdu_data.network_message_type == network_message_type);
ct_test(pTest, npdu_data.vendor_id == vendor_id); ct_test(pTest, npdu_data.vendor_id == vendor_id);
ct_test(pTest, npdu_data.priority == priority); ct_test(pTest, npdu_data.priority == priority);
// DNET,DLEN,DADR // DNET,DLEN,DADR
ct_test(pTest, npdu_dest.net == dest.net); ct_test(pTest, npdu_dest.net == dest.net);
ct_test(pTest, npdu_dest.len == dest.len); ct_test(pTest, npdu_dest.len == dest.len);
for (i = 0; i < dest.len; i++) for (i = 0; i < dest.len; i++) {
{
ct_test(pTest, npdu_dest.adr[i] == dest.adr[i]); ct_test(pTest, npdu_dest.adr[i] == dest.adr[i]);
} }
// SNET,SLEN,SADR // SNET,SLEN,SADR
ct_test(pTest, npdu_src.net == src.net); ct_test(pTest, npdu_src.net == src.net);
ct_test(pTest, npdu_src.len == src.len); ct_test(pTest, npdu_src.len == src.len);
for (i = 0; i < src.len; i++) for (i = 0; i < src.len; i++) {
{
ct_test(pTest, npdu_src.adr[i] == src.adr[i]); ct_test(pTest, npdu_src.adr[i] == src.adr[i]);
} }
} }
void testNPDU1(Test * pTest) void testNPDU1(Test * pTest)
{ {
uint8_t pdu[480] = {0}; uint8_t pdu[480] = { 0 };
BACNET_ADDRESS dest = {0}; BACNET_ADDRESS dest = { 0 };
BACNET_ADDRESS src = {0}; BACNET_ADDRESS src = { 0 };
BACNET_ADDRESS npdu_dest = {0}; BACNET_ADDRESS npdu_dest = { 0 };
BACNET_ADDRESS npdu_src = {0}; BACNET_ADDRESS npdu_src = { 0 };
int len = 0; int len = 0;
bool data_expecting_reply = false; // true for confirmed messages bool data_expecting_reply = false; // true for confirmed messages
BACNET_MESSAGE_PRIORITY priority = MESSAGE_PRIORITY_NORMAL; BACNET_MESSAGE_PRIORITY priority = MESSAGE_PRIORITY_NORMAL;
BACNET_NPDU_DATA npdu_data = {0}; BACNET_NPDU_DATA npdu_data = { 0 };
int i = 0; // counter int i = 0; // counter
int npdu_len = 0; int npdu_len = 0;
bool network_layer_message = false; // false if APDU bool network_layer_message = false; // false if APDU
BACNET_NETWORK_MESSAGE_TYPE network_message_type = 0;// optional BACNET_NETWORK_MESSAGE_TYPE network_message_type = 0; // optional
uint16_t vendor_id = 0; // optional, if net message type is > 0x80 uint16_t vendor_id = 0; // optional, if net message type is > 0x80
// mac_len = 0 if global address // mac_len = 0 if global address
dest.mac_len = 0; dest.mac_len = 0;
for (i = 0; i < MAX_MAC_LEN; i++) for (i = 0; i < MAX_MAC_LEN; i++) {
{
dest.mac[i] = 0; dest.mac[i] = 0;
} }
// DNET,DLEN,DADR // DNET,DLEN,DADR
dest.net = 0; dest.net = 0;
dest.len = 0; dest.len = 0;
for (i = 0; i < MAX_MAC_LEN; i++) for (i = 0; i < MAX_MAC_LEN; i++) {
{
dest.adr[i] = 0; dest.adr[i] = 0;
} }
src.mac_len = 0; src.mac_len = 0;
for (i = 0; i < MAX_MAC_LEN; i++) for (i = 0; i < MAX_MAC_LEN; i++) {
{
src.mac[i] = 0; src.mac[i] = 0;
} }
// SNET,SLEN,SADR // SNET,SLEN,SADR
src.net = 0; src.net = 0;
src.len = 0; src.len = 0;
for (i = 0; i < MAX_MAC_LEN; i++) for (i = 0; i < MAX_MAC_LEN; i++) {
{
src.adr[i] = 0; src.adr[i] = 0;
} }
len = npdu_encode_apdu( len = npdu_encode_apdu(&pdu[0],
&pdu[0], &dest, &src, data_expecting_reply, priority);
&dest,
&src,
data_expecting_reply,
priority);
ct_test(pTest, len != 0); ct_test(pTest, len != 0);
// can we get the info back? // can we get the info back?
npdu_len = npdu_decode( npdu_len = npdu_decode(&pdu[0], &npdu_dest, &npdu_src, &npdu_data);
&pdu[0],
&npdu_dest,
&npdu_src,
&npdu_data);
ct_test(pTest, npdu_len != 0); ct_test(pTest, npdu_len != 0);
ct_test(pTest, npdu_data.data_expecting_reply == data_expecting_reply); ct_test(pTest, npdu_data.data_expecting_reply == data_expecting_reply);
ct_test(pTest, npdu_data.network_layer_message == network_layer_message); ct_test(pTest,
npdu_data.network_layer_message == network_layer_message);
ct_test(pTest, npdu_data.network_message_type == network_message_type); ct_test(pTest, npdu_data.network_message_type == network_message_type);
ct_test(pTest, npdu_data.vendor_id == vendor_id); ct_test(pTest, npdu_data.vendor_id == vendor_id);
ct_test(pTest, npdu_data.priority == priority); ct_test(pTest, npdu_data.priority == priority);
@@ -487,17 +420,15 @@ void testNPDU1(Test * pTest)
// dummy stub for testing // dummy stub for testing
void tsm_free_invoke_id(uint8_t invokeID) void tsm_free_invoke_id(uint8_t invokeID)
{ {
(void)invokeID; (void) invokeID;
} }
void iam_handler( void iam_handler(uint8_t * service_request,
uint8_t *service_request, uint16_t service_len, BACNET_ADDRESS * src)
uint16_t service_len,
BACNET_ADDRESS *src)
{ {
(void)service_request; (void) service_request;
(void)service_len; (void) service_len;
(void)src; (void) src;
} }
int main(void) int main(void)
+11 -22
View File
@@ -40,8 +40,7 @@
#include "bacenum.h" #include "bacenum.h"
// an NPDU structure keeps the parameter stack to a minimum // an NPDU structure keeps the parameter stack to a minimum
typedef struct bacnet_npdu_data_t typedef struct bacnet_npdu_data_t {
{
uint8_t protocol_version; uint8_t protocol_version;
// parts of the control octet: // parts of the control octet:
bool data_expecting_reply; // true for confirmed messages bool data_expecting_reply; // true for confirmed messages
@@ -57,33 +56,23 @@ typedef struct bacnet_npdu_data_t
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
uint8_t npdu_encode_max_seg_max_apdu(int max_segs, int max_apdu); uint8_t npdu_encode_max_seg_max_apdu(int max_segs, int max_apdu);
int npdu_encode_raw( int npdu_encode_raw(uint8_t * npdu,
uint8_t *npdu, BACNET_ADDRESS * dest,
BACNET_ADDRESS *dest, BACNET_ADDRESS * src, BACNET_NPDU_DATA * npdu_data);
BACNET_ADDRESS *src,
BACNET_NPDU_DATA *npdu_data);
// encode the NPDU portion of the packet for an APDU // encode the NPDU portion of the packet for an APDU
int npdu_encode_apdu( int npdu_encode_apdu(uint8_t * npdu, BACNET_ADDRESS * dest, BACNET_ADDRESS * src, bool data_expecting_reply, // true for confirmed messages
uint8_t *npdu,
BACNET_ADDRESS *dest,
BACNET_ADDRESS *src,
bool data_expecting_reply, // true for confirmed messages
BACNET_MESSAGE_PRIORITY priority); BACNET_MESSAGE_PRIORITY priority);
int npdu_decode( int npdu_decode(uint8_t * npdu,
uint8_t *npdu, BACNET_ADDRESS * dest,
BACNET_ADDRESS *dest, BACNET_ADDRESS * src, BACNET_NPDU_DATA * npdu_data);
BACNET_ADDRESS *src,
BACNET_NPDU_DATA *npdu_data);
void npdu_handler( void npdu_handler(BACNET_ADDRESS * src, // source address
BACNET_ADDRESS *src, // source address uint8_t * pdu, // PDU data
uint8_t *pdu, // PDU data
uint16_t pdu_len); // length PDU uint16_t pdu_len); // length PDU
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+25 -46
View File
@@ -38,28 +38,23 @@
#include "rd.h" #include "rd.h"
/* encode service */ /* encode service */
int rd_encode_apdu( int rd_encode_apdu(uint8_t * apdu,
uint8_t *apdu,
uint8_t invoke_id, uint8_t invoke_id,
BACNET_REINITIALIZED_STATE state, BACNET_REINITIALIZED_STATE state, BACNET_CHARACTER_STRING * password)
BACNET_CHARACTER_STRING *password)
{ {
int len = 0; /* length of each encoding */ int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */ int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) if (apdu) {
{
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST; apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU); apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU);
apdu[2] = invoke_id; apdu[2] = invoke_id;
apdu[3] = SERVICE_CONFIRMED_REINITIALIZE_DEVICE; apdu[3] = SERVICE_CONFIRMED_REINITIALIZE_DEVICE;
apdu_len = 4; apdu_len = 4;
len = encode_context_enumerated(&apdu[apdu_len], 0, len = encode_context_enumerated(&apdu[apdu_len], 0, state);
state);
apdu_len += len; apdu_len += len;
/* optional password */ /* optional password */
if (password) if (password) {
{
/* FIXME: must be at least 1 character, limited to 20 characters */ /* FIXME: must be at least 1 character, limited to 20 characters */
len = encode_context_character_string(&apdu[apdu_len], 1, len = encode_context_character_string(&apdu[apdu_len], 1,
password); password);
@@ -71,11 +66,9 @@ int rd_encode_apdu(
} }
/* decode the service request only */ /* decode the service request only */
int rd_decode_service_request( int rd_decode_service_request(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
BACNET_REINITIALIZED_STATE *state, BACNET_REINITIALIZED_STATE * state, BACNET_CHARACTER_STRING * password)
BACNET_CHARACTER_STRING *password)
{ {
unsigned len = 0; unsigned len = 0;
uint8_t tag_number = 0; uint8_t tag_number = 0;
@@ -83,8 +76,7 @@ int rd_decode_service_request(
int value = 0; int value = 0;
/* check for value pointers */ /* check for value pointers */
if (apdu_len) if (apdu_len) {
{
/* Tag 0: reinitializedStateOfDevice */ /* Tag 0: reinitializedStateOfDevice */
if (!decode_is_context_tag(&apdu[len], 0)) if (!decode_is_context_tag(&apdu[len], 0))
return -1; return -1;
@@ -94,25 +86,24 @@ int rd_decode_service_request(
if (state) if (state)
*state = value; *state = value;
/* Tag 1: password - optional */ /* Tag 1: password - optional */
if (len < apdu_len) if (len < apdu_len) {
{
if (!decode_is_context_tag(&apdu[len], 1)) if (!decode_is_context_tag(&apdu[len], 1))
return -1; return -1;
len += decode_tag_number_and_value(&apdu[len], len += decode_tag_number_and_value(&apdu[len],
&tag_number, &len_value_type); &tag_number, &len_value_type);
len += decode_character_string(&apdu[len], len_value_type, password); len +=
decode_character_string(&apdu[len], len_value_type,
password);
} }
} }
return (int)len; return (int) len;
} }
int rd_decode_apdu( int rd_decode_apdu(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
uint8_t *invoke_id, uint8_t * invoke_id,
BACNET_REINITIALIZED_STATE *state, BACNET_REINITIALIZED_STATE * state, BACNET_CHARACTER_STRING * password)
BACNET_CHARACTER_STRING *password)
{ {
int len = 0; int len = 0;
unsigned offset = 0; unsigned offset = 0;
@@ -128,13 +119,9 @@ int rd_decode_apdu(
return -1; return -1;
offset = 4; offset = 4;
if (apdu_len > offset) if (apdu_len > offset) {
{ len = rd_decode_service_request(&apdu[offset],
len = rd_decode_service_request( apdu_len - offset, state, password);
&apdu[offset],
apdu_len - offset,
state,
password);
} }
return len; return len;
@@ -147,7 +134,7 @@ int rd_decode_apdu(
void test_ReinitializeDevice(Test * pTest) void test_ReinitializeDevice(Test * pTest)
{ {
uint8_t apdu[480] = {0}; uint8_t apdu[480] = { 0 };
int len = 0; int len = 0;
int apdu_len = 0; int apdu_len = 0;
uint8_t invoke_id = 128; uint8_t invoke_id = 128;
@@ -158,25 +145,17 @@ void test_ReinitializeDevice(Test * pTest)
BACNET_CHARACTER_STRING test_password; BACNET_CHARACTER_STRING test_password;
state = BACNET_REINIT_WARMSTART; state = BACNET_REINIT_WARMSTART;
characterstring_init_ansi(&password,"John 3:16"); characterstring_init_ansi(&password, "John 3:16");
len = rd_encode_apdu( len = rd_encode_apdu(&apdu[0], invoke_id, state, &password);
&apdu[0],
invoke_id,
state,
&password);
ct_test(pTest, len != 0); ct_test(pTest, len != 0);
apdu_len = len; apdu_len = len;
len = rd_decode_apdu( len = rd_decode_apdu(&apdu[0],
&apdu[0], apdu_len, &test_invoke_id, &test_state, &test_password);
apdu_len,
&test_invoke_id,
&test_state,
&test_password);
ct_test(pTest, len != -1); ct_test(pTest, len != -1);
ct_test(pTest, test_invoke_id == invoke_id); ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest, test_state == state); ct_test(pTest, test_state == state);
ct_test(pTest, characterstring_same(&test_password,&password)); ct_test(pTest, characterstring_same(&test_password, &password));
return; return;
} }
+10 -15
View File
@@ -42,34 +42,29 @@ extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
// encode service // encode service
int rd_encode_apdu( int rd_encode_apdu(uint8_t * apdu,
uint8_t *apdu,
uint8_t invoke_id, uint8_t invoke_id,
BACNET_REINITIALIZED_STATE state, BACNET_REINITIALIZED_STATE state,
BACNET_CHARACTER_STRING *password); BACNET_CHARACTER_STRING * password);
// decode the service request only // decode the service request only
int rd_decode_service_request( int rd_decode_service_request(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
BACNET_REINITIALIZED_STATE *state, BACNET_REINITIALIZED_STATE * state,
BACNET_CHARACTER_STRING *password); BACNET_CHARACTER_STRING * password);
int rd_decode_apdu( int rd_decode_apdu(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
uint8_t *invoke_id, uint8_t * invoke_id,
BACNET_REINITIALIZED_STATE *state, BACNET_REINITIALIZED_STATE * state,
BACNET_CHARACTER_STRING *password); BACNET_CHARACTER_STRING * password);
#ifdef TEST #ifdef TEST
#include "ctest.h" #include "ctest.h"
void test_ReinitializeDevice(Test * pTest); void test_ReinitializeDevice(Test * pTest);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+27 -71
View File
@@ -37,15 +37,12 @@
#include "bacdef.h" #include "bacdef.h"
// encode service // encode service
int reject_encode_apdu( int reject_encode_apdu(uint8_t * apdu,
uint8_t *apdu, uint8_t invoke_id, uint8_t reject_reason)
uint8_t invoke_id,
uint8_t reject_reason)
{ {
int apdu_len = 0; // total length of the apdu, return value int apdu_len = 0; // total length of the apdu, return value
if (apdu) if (apdu) {
{
apdu[0] = PDU_TYPE_REJECT; apdu[0] = PDU_TYPE_REJECT;
apdu[1] = invoke_id; apdu[1] = invoke_id;
apdu[2] = reject_reason; apdu[2] = reject_reason;
@@ -56,16 +53,12 @@ int reject_encode_apdu(
} }
// decode the service request only // decode the service request only
int reject_decode_service_request( int reject_decode_service_request(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, uint8_t * invoke_id, uint8_t * reject_reason)
unsigned apdu_len,
uint8_t *invoke_id,
uint8_t *reject_reason)
{ {
int len = 0; int len = 0;
if (apdu_len) if (apdu_len) {
{
if (invoke_id) if (invoke_id)
*invoke_id = apdu[0]; *invoke_id = apdu[0];
if (reject_reason) if (reject_reason)
@@ -76,28 +69,20 @@ int reject_decode_service_request(
} }
// decode the whole APDU - mainly used for unit testing // decode the whole APDU - mainly used for unit testing
int reject_decode_apdu( int reject_decode_apdu(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, uint8_t * invoke_id, uint8_t * reject_reason)
unsigned apdu_len,
uint8_t *invoke_id,
uint8_t *reject_reason)
{ {
int len = 0; int len = 0;
if (!apdu) if (!apdu)
return -1; return -1;
// optional checking - most likely was already done prior to this call // optional checking - most likely was already done prior to this call
if (apdu_len) if (apdu_len) {
{
if (apdu[0] != PDU_TYPE_REJECT) if (apdu[0] != PDU_TYPE_REJECT)
return -1; return -1;
if (apdu_len > 1) if (apdu_len > 1) {
{ len = reject_decode_service_request(&apdu[1],
len = reject_decode_service_request( apdu_len - 1, invoke_id, reject_reason);
&apdu[1],
apdu_len - 1,
invoke_id,
reject_reason);
} }
} }
@@ -111,7 +96,7 @@ int reject_decode_apdu(
void testReject(Test * pTest) void testReject(Test * pTest)
{ {
uint8_t apdu[480] = {0}; uint8_t apdu[480] = { 0 };
int len = 0; int len = 0;
int apdu_len = 0; int apdu_len = 0;
uint8_t invoke_id = 0; uint8_t invoke_id = 0;
@@ -119,70 +104,41 @@ void testReject(Test * pTest)
uint8_t test_invoke_id = 0; uint8_t test_invoke_id = 0;
uint8_t test_reject_reason = 0; uint8_t test_reject_reason = 0;
len = reject_encode_apdu( len = reject_encode_apdu(&apdu[0], invoke_id, reject_reason);
&apdu[0],
invoke_id,
reject_reason);
ct_test(pTest, len != 0); ct_test(pTest, len != 0);
apdu_len = len; apdu_len = len;
len = reject_decode_apdu( len = reject_decode_apdu(&apdu[0],
&apdu[0], apdu_len, &test_invoke_id, &test_reject_reason);
apdu_len,
&test_invoke_id,
&test_reject_reason);
ct_test(pTest, len != -1); ct_test(pTest, len != -1);
ct_test(pTest, test_invoke_id == invoke_id); ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest, test_reject_reason == reject_reason); ct_test(pTest, test_reject_reason == reject_reason);
// change type to get negative response // change type to get negative response
apdu[0] = PDU_TYPE_ABORT; apdu[0] = PDU_TYPE_ABORT;
len = reject_decode_apdu( len = reject_decode_apdu(&apdu[0],
&apdu[0], apdu_len, &test_invoke_id, &test_reject_reason);
apdu_len,
&test_invoke_id,
&test_reject_reason);
ct_test(pTest, len == -1); ct_test(pTest, len == -1);
// test NULL APDU // test NULL APDU
len = reject_decode_apdu( len = reject_decode_apdu(NULL,
NULL, apdu_len, &test_invoke_id, &test_reject_reason);
apdu_len,
&test_invoke_id,
&test_reject_reason);
ct_test(pTest, len == -1); ct_test(pTest, len == -1);
// force a zero length // force a zero length
len = reject_decode_apdu( len = reject_decode_apdu(&apdu[0],
&apdu[0], 0, &test_invoke_id, &test_reject_reason);
0,
&test_invoke_id,
&test_reject_reason);
ct_test(pTest, len == 0); ct_test(pTest, len == 0);
// check them all... // check them all...
for ( for (invoke_id = 0; invoke_id < 255; invoke_id++) {
invoke_id = 0; for (reject_reason = 0; reject_reason < 255; reject_reason++) {
invoke_id < 255; len = reject_encode_apdu(&apdu[0], invoke_id, reject_reason);
invoke_id++)
{
for (
reject_reason = 0;
reject_reason < 255;
reject_reason++)
{
len = reject_encode_apdu(
&apdu[0],
invoke_id,
reject_reason);
apdu_len = len; apdu_len = len;
ct_test(pTest, len != 0); ct_test(pTest, len != 0);
len = reject_decode_apdu( len = reject_decode_apdu(&apdu[0],
&apdu[0], apdu_len, &test_invoke_id, &test_reject_reason);
apdu_len,
&test_invoke_id,
&test_reject_reason);
ct_test(pTest, len != -1); ct_test(pTest, len != -1);
ct_test(pTest, test_invoke_id == invoke_id); ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest, test_reject_reason == reject_reason); ct_test(pTest, test_reject_reason == reject_reason);
+7 -17
View File
@@ -41,30 +41,20 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
int reject_encode_apdu( int reject_encode_apdu(uint8_t * apdu,
uint8_t *apdu, uint8_t invoke_id, uint8_t reject_reason);
uint8_t invoke_id,
uint8_t reject_reason);
int reject_decode_service_request( int reject_decode_service_request(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, uint8_t * invoke_id, uint8_t * reject_reason);
unsigned apdu_len,
uint8_t *invoke_id,
uint8_t *reject_reason);
int reject_decode_apdu( int reject_decode_apdu(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, uint8_t * invoke_id, uint8_t * reject_reason);
unsigned apdu_len,
uint8_t *invoke_id,
uint8_t *reject_reason);
#ifdef TEST #ifdef TEST
void testReject(Test * pTest); void testReject(Test * pTest);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+52 -67
View File
@@ -68,12 +68,11 @@ char *Ringbuf_Get_Front(RING_BUFFER const *b)
* ALGORITHM: none * ALGORITHM: none
* NOTES: none * NOTES: none
*****************************************************************************/ *****************************************************************************/
char *Ringbuf_Pop_Front(RING_BUFFER *b) char *Ringbuf_Pop_Front(RING_BUFFER * b)
{ {
char *data = NULL; // return value char *data = NULL; // return value
if (b->count) if (b->count) {
{
data = &(b->data[b->head * b->element_size]); data = &(b->data[b->head * b->element_size]);
b->head++; b->head++;
if (b->head >= b->element_count) if (b->head >= b->element_count)
@@ -90,8 +89,7 @@ char *Ringbuf_Pop_Front(RING_BUFFER *b)
* ALGORITHM: none * ALGORITHM: none
* NOTES: none * NOTES: none
*****************************************************************************/ *****************************************************************************/
bool Ringbuf_Put( bool Ringbuf_Put(RING_BUFFER * b, // ring buffer structure
RING_BUFFER *b, // ring buffer structure
char *data_element) // one element to add to the ring char *data_element) // one element to add to the ring
{ {
bool status = false; // return value bool status = false; // return value
@@ -99,17 +97,14 @@ bool Ringbuf_Put(
char *ring_data = NULL; // used to help point ring data char *ring_data = NULL; // used to help point ring data
unsigned i; // loop counter unsigned i; // loop counter
if (b && data_element) if (b && data_element) {
{
// limit the amount of data that we accept // limit the amount of data that we accept
if (b->count < b->element_count) if (b->count < b->element_count) {
{
offset = b->head + b->count; offset = b->head + b->count;
if (offset >= b->element_count) if (offset >= b->element_count)
offset -= b->element_count; offset -= b->element_count;
ring_data = b->data + offset * b->element_size; ring_data = b->data + offset * b->element_size;
for(i = 0; i < b->element_size; i++) for (i = 0; i < b->element_size; i++) {
{
ring_data[i] = data_element[i]; ring_data[i] = data_element[i];
} }
b->count++; b->count++;
@@ -126,8 +121,7 @@ bool Ringbuf_Put(
* ALGORITHM: none * ALGORITHM: none
* NOTES: none * NOTES: none
*****************************************************************************/ *****************************************************************************/
void Ringbuf_Init( void Ringbuf_Init(RING_BUFFER * b, // ring buffer structure
RING_BUFFER *b, // ring buffer structure
char *data, // data block or array of data char *data, // data block or array of data
unsigned element_size, // size of one element in the data block unsigned element_size, // size of one element in the data block
unsigned element_count) // number of elements in the data block unsigned element_count) // number of elements in the data block
@@ -150,7 +144,7 @@ void Ringbuf_Init(
// test the FIFO // test the FIFO
#define RING_BUFFER_DATA_SIZE 5 #define RING_BUFFER_DATA_SIZE 5
#define RING_BUFFER_SIZE 16 #define RING_BUFFER_SIZE 16
void testRingBuf(Test* pTest) void testRingBuf(Test * pTest)
{ {
RING_BUFFER test_buffer; RING_BUFFER test_buffer;
char data_store[RING_BUFFER_DATA_SIZE * RING_BUFFER_SIZE]; char data_store[RING_BUFFER_DATA_SIZE * RING_BUFFER_SIZE];
@@ -162,102 +156,94 @@ void testRingBuf(Test* pTest)
unsigned dummy; unsigned dummy;
bool status; bool status;
Ringbuf_Init(&test_buffer,data_store,RING_BUFFER_DATA_SIZE,RING_BUFFER_SIZE); Ringbuf_Init(&test_buffer, data_store, RING_BUFFER_DATA_SIZE,
ct_test(pTest,Ringbuf_Empty(&test_buffer)); RING_BUFFER_SIZE);
ct_test(pTest, Ringbuf_Empty(&test_buffer));
for (data_index = 0; data_index < RING_BUFFER_DATA_SIZE; data_index++) for (data_index = 0; data_index < RING_BUFFER_DATA_SIZE; data_index++) {
{
data[data_index] = data_index; data[data_index] = data_index;
} }
status = Ringbuf_Put(&test_buffer, data); status = Ringbuf_Put(&test_buffer, data);
ct_test(pTest,status == true); ct_test(pTest, status == true);
ct_test(pTest,!Ringbuf_Empty(&test_buffer)); ct_test(pTest, !Ringbuf_Empty(&test_buffer));
test_data = Ringbuf_Get_Front(&test_buffer); test_data = Ringbuf_Get_Front(&test_buffer);
for (data_index = 0; data_index < RING_BUFFER_DATA_SIZE; data_index++) for (data_index = 0; data_index < RING_BUFFER_DATA_SIZE; data_index++) {
{ ct_test(pTest, test_data[data_index] == data[data_index]);
ct_test(pTest,test_data[data_index] == data[data_index]);
} }
ct_test(pTest,!Ringbuf_Empty(&test_buffer)); ct_test(pTest, !Ringbuf_Empty(&test_buffer));
test_data = Ringbuf_Pop_Front(&test_buffer); test_data = Ringbuf_Pop_Front(&test_buffer);
for (data_index = 0; data_index < RING_BUFFER_DATA_SIZE; data_index++) for (data_index = 0; data_index < RING_BUFFER_DATA_SIZE; data_index++) {
{ ct_test(pTest, test_data[data_index] == data[data_index]);
ct_test(pTest,test_data[data_index] == data[data_index]);
} }
ct_test(pTest,Ringbuf_Empty(&test_buffer)); ct_test(pTest, Ringbuf_Empty(&test_buffer));
// fill to max // fill to max
for (index = 0; index < RING_BUFFER_SIZE; index++) for (index = 0; index < RING_BUFFER_SIZE; index++) {
{ for (data_index = 0; data_index < RING_BUFFER_DATA_SIZE;
for (data_index = 0; data_index < RING_BUFFER_DATA_SIZE; data_index++) data_index++) {
{
data[data_index] = index; data[data_index] = index;
} }
status = Ringbuf_Put(&test_buffer, data); status = Ringbuf_Put(&test_buffer, data);
ct_test(pTest,status == true); ct_test(pTest, status == true);
ct_test(pTest,!Ringbuf_Empty(&test_buffer)); ct_test(pTest, !Ringbuf_Empty(&test_buffer));
} }
// verify actions on full buffer // verify actions on full buffer
for (index = 0; index < RING_BUFFER_SIZE; index++) for (index = 0; index < RING_BUFFER_SIZE; index++) {
{ for (data_index = 0; data_index < RING_BUFFER_DATA_SIZE;
for (data_index = 0; data_index < RING_BUFFER_DATA_SIZE; data_index++) data_index++) {
{
data[data_index] = index; data[data_index] = index;
} }
status = Ringbuf_Put(&test_buffer, data); status = Ringbuf_Put(&test_buffer, data);
ct_test(pTest,status == false); ct_test(pTest, status == false);
ct_test(pTest,!Ringbuf_Empty(&test_buffer)); ct_test(pTest, !Ringbuf_Empty(&test_buffer));
} }
// check buffer full // check buffer full
for (index = 0; index < RING_BUFFER_SIZE; index++) for (index = 0; index < RING_BUFFER_SIZE; index++) {
{
test_data = Ringbuf_Get_Front(&test_buffer); test_data = Ringbuf_Get_Front(&test_buffer);
for (data_index = 0; data_index < RING_BUFFER_DATA_SIZE; data_index++) for (data_index = 0; data_index < RING_BUFFER_DATA_SIZE;
{ data_index++) {
ct_test(pTest,test_data[data_index] == index); ct_test(pTest, test_data[data_index] == index);
} }
test_data = Ringbuf_Pop_Front(&test_buffer); test_data = Ringbuf_Pop_Front(&test_buffer);
for (data_index = 0; data_index < RING_BUFFER_DATA_SIZE; data_index++) for (data_index = 0; data_index < RING_BUFFER_DATA_SIZE;
{ data_index++) {
ct_test(pTest,test_data[data_index] == index); ct_test(pTest, test_data[data_index] == index);
} }
} }
ct_test(pTest,Ringbuf_Empty(&test_buffer)); ct_test(pTest, Ringbuf_Empty(&test_buffer));
// test the ring around the buffer // test the ring around the buffer
for (index = 0; index < RING_BUFFER_SIZE; index++) for (index = 0; index < RING_BUFFER_SIZE; index++) {
{ for (count = 1; count < 4; count++) {
for (count = 1; count < 4; count++)
{
dummy = index * count; dummy = index * count;
for (data_index = 0; data_index < RING_BUFFER_DATA_SIZE; data_index++) for (data_index = 0; data_index < RING_BUFFER_DATA_SIZE;
{ data_index++) {
data[data_index] = dummy; data[data_index] = dummy;
} }
status = Ringbuf_Put(&test_buffer, data); status = Ringbuf_Put(&test_buffer, data);
ct_test(pTest,status == true); ct_test(pTest, status == true);
} }
for (count = 1; count < 4; count++) for (count = 1; count < 4; count++) {
{
dummy = index * count; dummy = index * count;
test_data = Ringbuf_Get_Front(&test_buffer); test_data = Ringbuf_Get_Front(&test_buffer);
for (data_index = 0; data_index < RING_BUFFER_DATA_SIZE; data_index++) for (data_index = 0; data_index < RING_BUFFER_DATA_SIZE;
{ data_index++) {
ct_test(pTest,test_data[data_index] == dummy); ct_test(pTest, test_data[data_index] == dummy);
} }
test_data = Ringbuf_Pop_Front(&test_buffer); test_data = Ringbuf_Pop_Front(&test_buffer);
for (data_index = 0; data_index < RING_BUFFER_DATA_SIZE; data_index++) for (data_index = 0; data_index < RING_BUFFER_DATA_SIZE;
{ data_index++) {
ct_test(pTest,test_data[data_index] == dummy); ct_test(pTest, test_data[data_index] == dummy);
} }
} }
} }
ct_test(pTest,Ringbuf_Empty(&test_buffer)); ct_test(pTest, Ringbuf_Empty(&test_buffer));
return; return;
@@ -277,7 +263,7 @@ int main(void)
ct_setStream(pTest, stdout); ct_setStream(pTest, stdout);
ct_run(pTest); ct_run(pTest);
(void)ct_report(pTest); (void) ct_report(pTest);
ct_destroy(pTest); ct_destroy(pTest);
@@ -285,4 +271,3 @@ int main(void)
} }
#endif #endif
#endif #endif
+6 -10
View File
@@ -42,8 +42,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
struct ring_buffer_t struct ring_buffer_t {
{
char *data; // block of memory or array of data char *data; // block of memory or array of data
unsigned element_size; // how many bytes for each chunk unsigned element_size; // how many bytes for each chunk
unsigned element_count; // number of chunks of data unsigned element_count; // number of chunks of data
@@ -56,14 +55,12 @@ typedef struct ring_buffer_t RING_BUFFER;
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
bool Ringbuf_Empty(RING_BUFFER const *b); bool Ringbuf_Empty(RING_BUFFER const *b);
char *Ringbuf_Get_Front(RING_BUFFER const *b); char *Ringbuf_Get_Front(RING_BUFFER const *b);
char *Ringbuf_Pop_Front(RING_BUFFER *b); char *Ringbuf_Pop_Front(RING_BUFFER * b);
bool Ringbuf_Put( bool Ringbuf_Put(RING_BUFFER * b, // ring buffer structure
RING_BUFFER *b, // ring buffer structure
char *data_element); // one element to add to the ring char *data_element); // one element to add to the ring
void Ringbuf_Init( void Ringbuf_Init(RING_BUFFER * b, // ring buffer structure
RING_BUFFER *b, // ring buffer structure
char *data, // data block or array of data char *data, // data block or array of data
unsigned element_size, // size of one element in the data block unsigned element_size, // size of one element in the data block
unsigned element_count); // number of elements in the data block unsigned element_count); // number of elements in the data block
@@ -71,5 +68,4 @@ void Ringbuf_Init(
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+51 -103
View File
@@ -38,16 +38,13 @@
#include "rp.h" #include "rp.h"
// encode service // encode service
int rp_encode_apdu( int rp_encode_apdu(uint8_t * apdu,
uint8_t *apdu, uint8_t invoke_id, BACNET_READ_PROPERTY_DATA * data)
uint8_t invoke_id,
BACNET_READ_PROPERTY_DATA *data)
{ {
int len = 0; // length of each encoding int len = 0; // length of each encoding
int apdu_len = 0; // total length of the apdu, return value int apdu_len = 0; // total length of the apdu, return value
if (apdu) if (apdu) {
{
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST; apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU); apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU);
apdu[2] = invoke_id; apdu[2] = invoke_id;
@@ -60,8 +57,7 @@ int rp_encode_apdu(
data->object_property); data->object_property);
apdu_len += len; apdu_len += len;
/* optional array index */ /* optional array index */
if (data->array_index != BACNET_ARRAY_ALL) if (data->array_index != BACNET_ARRAY_ALL) {
{
len = encode_context_unsigned(&apdu[apdu_len], 2, len = encode_context_unsigned(&apdu[apdu_len], 2,
data->array_index); data->array_index);
apdu_len += len; apdu_len += len;
@@ -72,10 +68,8 @@ int rp_encode_apdu(
} }
// decode the service request only // decode the service request only
int rp_decode_service_request( int rp_decode_service_request(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, BACNET_READ_PROPERTY_DATA * data)
unsigned apdu_len,
BACNET_READ_PROPERTY_DATA *data)
{ {
unsigned len = 0; unsigned len = 0;
uint8_t tag_number = 0; uint8_t tag_number = 0;
@@ -85,8 +79,7 @@ int rp_decode_service_request(
uint32_t array_value = 0; // for decoding uint32_t array_value = 0; // for decoding
// check for value pointers // check for value pointers
if (apdu_len && data) if (apdu_len && data) {
{
// Tag 0: Object ID // Tag 0: Object ID
if (!decode_is_context_tag(&apdu[len++], 0)) if (!decode_is_context_tag(&apdu[len++], 0))
return -1; return -1;
@@ -100,31 +93,25 @@ int rp_decode_service_request(
len += decode_enumerated(&apdu[len], len_value_type, &property); len += decode_enumerated(&apdu[len], len_value_type, &property);
data->object_property = property; data->object_property = property;
// Tag 2: Optional Array Index // Tag 2: Optional Array Index
if (len < apdu_len) if (len < apdu_len) {
{ len += decode_tag_number_and_value(&apdu[len], &tag_number,
len += decode_tag_number_and_value(&apdu[len],&tag_number,
&len_value_type); &len_value_type);
if (tag_number == 2) if (tag_number == 2) {
{
len += decode_unsigned(&apdu[len], len_value_type, len += decode_unsigned(&apdu[len], len_value_type,
&array_value); &array_value);
data->array_index = array_value; data->array_index = array_value;
} } else
else
data->array_index = BACNET_ARRAY_ALL; data->array_index = BACNET_ARRAY_ALL;
} } else
else
data->array_index = BACNET_ARRAY_ALL; data->array_index = BACNET_ARRAY_ALL;
} }
return (int)len; return (int) len;
} }
int rp_decode_apdu( int rp_decode_apdu(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
uint8_t *invoke_id, uint8_t * invoke_id, BACNET_READ_PROPERTY_DATA * data)
BACNET_READ_PROPERTY_DATA *data)
{ {
int len = 0; int len = 0;
unsigned offset = 0; unsigned offset = 0;
@@ -140,27 +127,21 @@ int rp_decode_apdu(
return -1; return -1;
offset = 4; offset = 4;
if (apdu_len > offset) if (apdu_len > offset) {
{ len = rp_decode_service_request(&apdu[offset],
len = rp_decode_service_request( apdu_len - offset, data);
&apdu[offset],
apdu_len - offset,
data);
} }
return len; return len;
} }
int rp_ack_encode_apdu( int rp_ack_encode_apdu(uint8_t * apdu,
uint8_t *apdu, uint8_t invoke_id, BACNET_READ_PROPERTY_DATA * data)
uint8_t invoke_id,
BACNET_READ_PROPERTY_DATA *data)
{ {
int len = 0; // length of each encoding int len = 0; // length of each encoding
int apdu_len = 0; // total length of the apdu, return value int apdu_len = 0; // total length of the apdu, return value
if (apdu) if (apdu) {
{
apdu[0] = PDU_TYPE_COMPLEX_ACK; /* complex ACK service */ apdu[0] = PDU_TYPE_COMPLEX_ACK; /* complex ACK service */
apdu[1] = invoke_id; /* original invoke id from request */ apdu[1] = invoke_id; /* original invoke id from request */
apdu[2] = SERVICE_CONFIRMED_READ_PROPERTY; // service choice apdu[2] = SERVICE_CONFIRMED_READ_PROPERTY; // service choice
@@ -171,15 +152,13 @@ int rp_ack_encode_apdu(
apdu_len += encode_context_enumerated(&apdu[apdu_len], 1, apdu_len += encode_context_enumerated(&apdu[apdu_len], 1,
data->object_property); data->object_property);
// context 2 array index is optional // context 2 array index is optional
if (data->array_index != BACNET_ARRAY_ALL) if (data->array_index != BACNET_ARRAY_ALL) {
{
apdu_len += encode_context_unsigned(&apdu[apdu_len], 2, apdu_len += encode_context_unsigned(&apdu[apdu_len], 2,
data->array_index); data->array_index);
} }
// propertyValue // propertyValue
apdu_len += encode_opening_tag(&apdu[apdu_len], 3); apdu_len += encode_opening_tag(&apdu[apdu_len], 3);
for (len = 0; len < data->application_data_len; len++) for (len = 0; len < data->application_data_len; len++) {
{
apdu[apdu_len++] = data->application_data[len]; apdu[apdu_len++] = data->application_data[len];
} }
apdu_len += encode_closing_tag(&apdu[apdu_len], 3); apdu_len += encode_closing_tag(&apdu[apdu_len], 3);
@@ -188,10 +167,8 @@ int rp_ack_encode_apdu(
return apdu_len; return apdu_len;
} }
int rp_ack_decode_service_request( int rp_ack_decode_service_request(uint8_t * apdu, int apdu_len, // total length of the apdu
uint8_t *apdu, BACNET_READ_PROPERTY_DATA * data)
int apdu_len, // total length of the apdu
BACNET_READ_PROPERTY_DATA *data)
{ {
uint8_t tag_number = 0; uint8_t tag_number = 0;
uint32_t len_value_type = 0; uint32_t len_value_type = 0;
@@ -205,51 +182,40 @@ int rp_ack_decode_service_request(
if (!decode_is_context_tag(&apdu[0], 0)) if (!decode_is_context_tag(&apdu[0], 0))
return -1; return -1;
len = 1; len = 1;
len += decode_object_id(&apdu[len], len += decode_object_id(&apdu[len], &object, &data->object_instance);
&object, &data->object_instance);
data->object_type = object; data->object_type = object;
// Tag 1: Property ID // Tag 1: Property ID
len += decode_tag_number_and_value(&apdu[len], len += decode_tag_number_and_value(&apdu[len],
&tag_number, &len_value_type); &tag_number, &len_value_type);
if (tag_number != 1) if (tag_number != 1)
return -1; return -1;
len += decode_enumerated(&apdu[len], len += decode_enumerated(&apdu[len], len_value_type, &property);
len_value_type,
&property);
data->object_property = property; data->object_property = property;
// Tag 2: Optional Array Index // Tag 2: Optional Array Index
tag_len = decode_tag_number_and_value(&apdu[len], tag_len = decode_tag_number_and_value(&apdu[len],
&tag_number, &len_value_type); &tag_number, &len_value_type);
if (tag_number == 2) if (tag_number == 2) {
{
len += tag_len; len += tag_len;
len += decode_unsigned(&apdu[len], len += decode_unsigned(&apdu[len], len_value_type, &array_value);
len_value_type, &array_value);
data->array_index = array_value; data->array_index = array_value;
} } else
else
data->array_index = BACNET_ARRAY_ALL; data->array_index = BACNET_ARRAY_ALL;
// Tag 3: opening context tag */ // Tag 3: opening context tag */
if (decode_is_opening_tag_number(&apdu[len], 3)) if (decode_is_opening_tag_number(&apdu[len], 3)) {
{
// a tag number of 3 is not extended so only one octet // a tag number of 3 is not extended so only one octet
len++; len++;
// don't decode the application tag number or its data here // don't decode the application tag number or its data here
data->application_data = &apdu[len]; data->application_data = &apdu[len];
data->application_data_len = apdu_len - len - 1 /*closing tag*/; data->application_data_len = apdu_len - len - 1 /*closing tag */ ;
} } else
else
return -1; return -1;
return len; return len;
} }
int rp_ack_decode_apdu( int rp_ack_decode_apdu(uint8_t * apdu, int apdu_len, // total length of the apdu
uint8_t *apdu, uint8_t * invoke_id, BACNET_READ_PROPERTY_DATA * data)
int apdu_len, // total length of the apdu
uint8_t *invoke_id,
BACNET_READ_PROPERTY_DATA *data)
{ {
int len = 0; int len = 0;
int offset = 0; int offset = 0;
@@ -263,12 +229,9 @@ int rp_ack_decode_apdu(
if (apdu[2] != SERVICE_CONFIRMED_READ_PROPERTY) if (apdu[2] != SERVICE_CONFIRMED_READ_PROPERTY)
return -1; return -1;
offset = 3; offset = 3;
if (apdu_len > offset) if (apdu_len > offset) {
{ len = rp_ack_decode_service_request(&apdu[offset],
len = rp_ack_decode_service_request( apdu_len - offset, data);
&apdu[offset],
apdu_len - offset,
data);
} }
return len; return len;
@@ -281,8 +244,8 @@ int rp_ack_decode_apdu(
void testReadPropertyAck(Test * pTest) void testReadPropertyAck(Test * pTest)
{ {
uint8_t apdu[480] = {0}; uint8_t apdu[480] = { 0 };
uint8_t apdu2[480] = {0}; uint8_t apdu2[480] = { 0 };
int len = 0; int len = 0;
int apdu_len = 0; int apdu_len = 0;
uint8_t invoke_id = 1; uint8_t invoke_id = 1;
@@ -299,22 +262,15 @@ void testReadPropertyAck(Test * pTest)
data.array_index = BACNET_ARRAY_ALL; data.array_index = BACNET_ARRAY_ALL;
data.application_data_len = encode_bacnet_object_id(&apdu2[0], data.application_data_len = encode_bacnet_object_id(&apdu2[0],
data.object_type, data.object_type, data.object_instance);
data.object_instance);
data.application_data = &apdu2[0]; data.application_data = &apdu2[0];
len = rp_ack_encode_apdu( len = rp_ack_encode_apdu(&apdu[0], invoke_id, &data);
&apdu[0],
invoke_id,
&data);
ct_test(pTest, len != 0); ct_test(pTest, len != 0);
ct_test(pTest, len != -1); ct_test(pTest, len != -1);
apdu_len = len; apdu_len = len;
len = rp_ack_decode_apdu( len = rp_ack_decode_apdu(&apdu[0], apdu_len, // total length of the apdu
&apdu[0], &test_invoke_id, &test_data);
apdu_len, // total length of the apdu
&test_invoke_id,
&test_data);
ct_test(pTest, len != -1); ct_test(pTest, len != -1);
ct_test(pTest, test_invoke_id == invoke_id); ct_test(pTest, test_invoke_id == invoke_id);
@@ -322,14 +278,13 @@ void testReadPropertyAck(Test * pTest)
ct_test(pTest, test_data.object_instance == data.object_instance); ct_test(pTest, test_data.object_instance == data.object_instance);
ct_test(pTest, test_data.object_property == data.object_property); ct_test(pTest, test_data.object_property == data.object_property);
ct_test(pTest, test_data.array_index == data.array_index); ct_test(pTest, test_data.array_index == data.array_index);
ct_test(pTest, test_data.application_data_len == data.application_data_len); ct_test(pTest,
test_data.application_data_len == data.application_data_len);
/* since object property == object_id, decode the application data using /* since object property == object_id, decode the application data using
the appropriate decode function */ the appropriate decode function */
len = decode_object_id( len = decode_object_id(test_data.application_data,
test_data.application_data, &object, &object_instance);
&object,
&object_instance);
object_type = object; object_type = object;
ct_test(pTest, object_type == data.object_type); ct_test(pTest, object_type == data.object_type);
ct_test(pTest, object_instance == data.object_instance); ct_test(pTest, object_instance == data.object_instance);
@@ -337,7 +292,7 @@ void testReadPropertyAck(Test * pTest)
void testReadProperty(Test * pTest) void testReadProperty(Test * pTest)
{ {
uint8_t apdu[480] = {0}; uint8_t apdu[480] = { 0 };
int len = 0; int len = 0;
int apdu_len = 0; int apdu_len = 0;
uint8_t invoke_id = 128; uint8_t invoke_id = 128;
@@ -349,18 +304,11 @@ void testReadProperty(Test * pTest)
data.object_instance = 1; data.object_instance = 1;
data.object_property = PROP_OBJECT_IDENTIFIER; data.object_property = PROP_OBJECT_IDENTIFIER;
data.array_index = BACNET_ARRAY_ALL; data.array_index = BACNET_ARRAY_ALL;
len = rp_encode_apdu( len = rp_encode_apdu(&apdu[0], invoke_id, &data);
&apdu[0],
invoke_id,
&data);
ct_test(pTest, len != 0); ct_test(pTest, len != 0);
apdu_len = len; apdu_len = len;
len = rp_decode_apdu( len = rp_decode_apdu(&apdu[0], apdu_len, &test_invoke_id, &test_data);
&apdu[0],
apdu_len,
&test_invoke_id,
&test_data);
ct_test(pTest, len != -1); ct_test(pTest, len != -1);
ct_test(pTest, test_data.object_type == data.object_type); ct_test(pTest, test_data.object_type == data.object_type);
ct_test(pTest, test_data.object_instance == data.object_instance); ct_test(pTest, test_data.object_instance == data.object_instance);
+16 -32
View File
@@ -37,8 +37,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
typedef struct BACnet_Read_Property_Data typedef struct BACnet_Read_Property_Data {
{
BACNET_OBJECT_TYPE object_type; BACNET_OBJECT_TYPE object_type;
uint32_t object_instance; uint32_t object_instance;
BACNET_PROPERTY_ID object_property; BACNET_PROPERTY_ID object_property;
@@ -52,50 +51,35 @@ extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
// encode service // encode service
int rp_encode_apdu( int rp_encode_apdu(uint8_t * apdu,
uint8_t *apdu, uint8_t invoke_id, BACNET_READ_PROPERTY_DATA * data);
uint8_t invoke_id,
BACNET_READ_PROPERTY_DATA *data);
// decode the service request only // decode the service request only
int rp_decode_service_request( int rp_decode_service_request(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, BACNET_READ_PROPERTY_DATA * data);
int rp_decode_apdu(uint8_t * apdu,
unsigned apdu_len, unsigned apdu_len,
BACNET_READ_PROPERTY_DATA *data); uint8_t * invoke_id, BACNET_READ_PROPERTY_DATA * data);
int rp_decode_apdu( int rp_ack_encode_apdu(uint8_t * apdu,
uint8_t *apdu, uint8_t invoke_id, BACNET_READ_PROPERTY_DATA * data);
unsigned apdu_len,
uint8_t *invoke_id,
BACNET_READ_PROPERTY_DATA *data);
int rp_ack_encode_apdu( int rp_ack_decode_service_request(uint8_t * apdu, int apdu_len, // total length of the apdu
uint8_t *apdu, BACNET_READ_PROPERTY_DATA * data);
uint8_t invoke_id,
BACNET_READ_PROPERTY_DATA *data);
int rp_ack_decode_service_request( int rp_ack_decode_apdu(uint8_t * apdu, int apdu_len, // total length of the apdu
uint8_t *apdu, uint8_t * invoke_id, BACNET_READ_PROPERTY_DATA * data);
int apdu_len, // total length of the apdu
BACNET_READ_PROPERTY_DATA *data);
int rp_ack_decode_apdu(
uint8_t *apdu,
int apdu_len, // total length of the apdu
uint8_t *invoke_id,
BACNET_READ_PROPERTY_DATA *data);
#ifdef TEST #ifdef TEST
#include "ctest.h" #include "ctest.h"
void test_ReadProperty(Test * pTest); void test_ReadProperty(Test * pTest);
void test_ReadPropertyAck(Test * pTest); void test_ReadPropertyAck(Test * pTest);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+154 -285
View File
@@ -40,14 +40,11 @@
#include "rpm.h" #include "rpm.h"
/* encode the initial portion of the service */ /* encode the initial portion of the service */
int rpm_encode_apdu_init( int rpm_encode_apdu_init(uint8_t * apdu, uint8_t invoke_id)
uint8_t *apdu,
uint8_t invoke_id)
{ {
int apdu_len = 0; /* total length of the apdu, return value */ int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) if (apdu) {
{
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST; apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU); apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU);
apdu[2] = invoke_id; apdu[2] = invoke_id;
@@ -58,15 +55,12 @@ int rpm_encode_apdu_init(
return apdu_len; return apdu_len;
} }
int rpm_encode_apdu_object_begin( int rpm_encode_apdu_object_begin(uint8_t * apdu,
uint8_t *apdu, BACNET_OBJECT_TYPE object_type, uint32_t object_instance)
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance)
{ {
int apdu_len = 0; /* total length of the apdu, return value */ int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) if (apdu) {
{
apdu_len = encode_context_object_id(&apdu[0], 0, apdu_len = encode_context_object_id(&apdu[0], 0,
object_type, object_instance); object_type, object_instance);
/* Tag 1: sequence of ReadAccessSpecification */ /* Tag 1: sequence of ReadAccessSpecification */
@@ -76,17 +70,13 @@ int rpm_encode_apdu_object_begin(
return apdu_len; return apdu_len;
} }
int rpm_encode_apdu_object_property( int rpm_encode_apdu_object_property(uint8_t * apdu,
uint8_t *apdu, BACNET_PROPERTY_ID object_property, int32_t array_index)
BACNET_PROPERTY_ID object_property,
int32_t array_index)
{ {
int apdu_len = 0; /* total length of the apdu, return value */ int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) if (apdu) {
{ apdu_len = encode_context_enumerated(&apdu[0], 0, object_property);
apdu_len = encode_context_enumerated(&apdu[0], 0,
object_property);
/* optional array index */ /* optional array index */
if (array_index != BACNET_ARRAY_ALL) if (array_index != BACNET_ARRAY_ALL)
apdu_len += encode_context_unsigned(&apdu[apdu_len], 1, apdu_len += encode_context_unsigned(&apdu[apdu_len], 1,
@@ -96,13 +86,11 @@ int rpm_encode_apdu_object_property(
return apdu_len; return apdu_len;
} }
int rpm_encode_apdu_object_end( int rpm_encode_apdu_object_end(uint8_t * apdu)
uint8_t *apdu)
{ {
int apdu_len = 0; /* total length of the apdu, return value */ int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) if (apdu) {
{
apdu_len = encode_closing_tag(&apdu[0], 1); apdu_len = encode_closing_tag(&apdu[0], 1);
} }
@@ -110,18 +98,15 @@ int rpm_encode_apdu_object_end(
} }
/* decode the object portion of the service request only */ /* decode the object portion of the service request only */
int rpm_decode_object_id( int rpm_decode_object_id(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
BACNET_OBJECT_TYPE *object_type, BACNET_OBJECT_TYPE * object_type, uint32_t * object_instance)
uint32_t *object_instance)
{ {
unsigned len = 0; unsigned len = 0;
int type = 0; /* for decoding */ int type = 0; /* for decoding */
/* check for value pointers */ /* check for value pointers */
if (apdu && apdu_len && object_type && object_instance) if (apdu && apdu_len && object_type && object_instance) {
{
/* Tag 0: Object ID */ /* Tag 0: Object ID */
if (!decode_is_context_tag(&apdu[len++], 0)) if (!decode_is_context_tag(&apdu[len++], 0))
return -1; return -1;
@@ -134,18 +119,15 @@ int rpm_decode_object_id(
len++; /* opening tag is only one octet */ len++; /* opening tag is only one octet */
} }
return (int)len; return (int) len;
} }
int rpm_decode_object_end( int rpm_decode_object_end(uint8_t * apdu, unsigned apdu_len)
uint8_t *apdu,
unsigned apdu_len)
{ {
int len = 0; /* total length of the apdu, return value */ int len = 0; /* total length of the apdu, return value */
if (apdu && apdu_len) if (apdu && apdu_len) {
{ if (decode_is_closing_tag_number(apdu, 1))
if (decode_is_closing_tag_number(apdu,1))
len = 1; len = 1;
} }
@@ -153,11 +135,9 @@ int rpm_decode_object_end(
} }
/* decode the object property portion of the service request only */ /* decode the object property portion of the service request only */
int rpm_decode_object_property( int rpm_decode_object_property(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
BACNET_PROPERTY_ID *object_property, BACNET_PROPERTY_ID * object_property, int32_t * array_index)
int32_t *array_index)
{ {
unsigned len = 0; unsigned len = 0;
unsigned option_len = 0; unsigned option_len = 0;
@@ -167,8 +147,7 @@ int rpm_decode_object_property(
uint32_t array_value = 0; /* for decoding */ uint32_t array_value = 0; /* for decoding */
/* check for valid pointers */ /* check for valid pointers */
if (apdu && apdu_len && object_property && array_index) if (apdu && apdu_len && object_property && array_index) {
{
/* Tag 0: propertyIdentifier */ /* Tag 0: propertyIdentifier */
len += decode_tag_number_and_value(&apdu[len], len += decode_tag_number_and_value(&apdu[len],
&tag_number, &len_value_type); &tag_number, &len_value_type);
@@ -178,33 +157,28 @@ int rpm_decode_object_property(
if (object_property) if (object_property)
*object_property = property; *object_property = property;
/* Tag 1: Optional propertyArrayIndex */ /* Tag 1: Optional propertyArrayIndex */
if (len < apdu_len) if (len < apdu_len) {
{ option_len =
option_len = decode_tag_number_and_value(&apdu[len],&tag_number, decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type); &len_value_type);
if (tag_number == 2) if (tag_number == 2) {
{
len += option_len; len += option_len;
len += decode_unsigned(&apdu[len], len_value_type, len += decode_unsigned(&apdu[len], len_value_type,
&array_value); &array_value);
*array_index = array_value; *array_index = array_value;
} } else
else
*array_index = BACNET_ARRAY_ALL; *array_index = BACNET_ARRAY_ALL;
} } else
else
*array_index = BACNET_ARRAY_ALL; *array_index = BACNET_ARRAY_ALL;
} }
return (int)len; return (int) len;
} }
int rpm_decode_apdu( int rpm_decode_apdu(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
uint8_t *invoke_id, uint8_t * invoke_id,
uint8_t **service_request, uint8_t ** service_request, unsigned *service_request_len)
unsigned *service_request_len)
{ {
unsigned offset = 0; unsigned offset = 0;
@@ -219,8 +193,7 @@ int rpm_decode_apdu(
return -1; return -1;
offset = 4; offset = 4;
if (apdu_len > offset) if (apdu_len > offset) {
{
if (service_request) if (service_request)
*service_request = &apdu[offset]; *service_request = &apdu[offset];
if (service_request_len) if (service_request_len)
@@ -230,14 +203,11 @@ int rpm_decode_apdu(
return offset; return offset;
} }
int rpm_ack_encode_apdu_init( int rpm_ack_encode_apdu_init(uint8_t * apdu, uint8_t invoke_id)
uint8_t *apdu,
uint8_t invoke_id)
{ {
int apdu_len = 0; /* total length of the apdu, return value */ int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) if (apdu) {
{
apdu[0] = PDU_TYPE_COMPLEX_ACK; /* complex ACK service */ apdu[0] = PDU_TYPE_COMPLEX_ACK; /* complex ACK service */
apdu[1] = invoke_id; /* original invoke id from request */ apdu[1] = invoke_id; /* original invoke id from request */
apdu[2] = SERVICE_CONFIRMED_READ_PROPERTY_MULTIPLE; /* service choice */ apdu[2] = SERVICE_CONFIRMED_READ_PROPERTY_MULTIPLE; /* service choice */
@@ -247,15 +217,12 @@ int rpm_ack_encode_apdu_init(
return apdu_len; return apdu_len;
} }
int rpm_ack_encode_apdu_object_begin( int rpm_ack_encode_apdu_object_begin(uint8_t * apdu,
uint8_t *apdu, BACNET_OBJECT_TYPE object_type, uint32_t object_instance)
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance)
{ {
int apdu_len = 0; /* total length of the apdu, return value */ int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) if (apdu) {
{
/* Tag 0: objectIdentifier */ /* Tag 0: objectIdentifier */
apdu_len = encode_context_object_id(&apdu[0], 0, apdu_len = encode_context_object_id(&apdu[0], 0,
object_type, object_instance); object_type, object_instance);
@@ -266,18 +233,14 @@ int rpm_ack_encode_apdu_object_begin(
return apdu_len; return apdu_len;
} }
int rpm_ack_encode_apdu_object_property( int rpm_ack_encode_apdu_object_property(uint8_t * apdu,
uint8_t *apdu, BACNET_PROPERTY_ID object_property, int32_t array_index)
BACNET_PROPERTY_ID object_property,
int32_t array_index)
{ {
int apdu_len = 0; /* total length of the apdu, return value */ int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) if (apdu) {
{
/* Tag 2: propertyIdentifier */ /* Tag 2: propertyIdentifier */
apdu_len = encode_context_enumerated(&apdu[0], 2, apdu_len = encode_context_enumerated(&apdu[0], 2, object_property);
object_property);
/* Tag 3: optional propertyArrayIndex */ /* Tag 3: optional propertyArrayIndex */
if (array_index != BACNET_ARRAY_ALL) if (array_index != BACNET_ARRAY_ALL)
apdu_len += encode_context_unsigned(&apdu[apdu_len], 3, apdu_len += encode_context_unsigned(&apdu[apdu_len], 3,
@@ -287,20 +250,16 @@ int rpm_ack_encode_apdu_object_property(
return apdu_len; return apdu_len;
} }
int rpm_ack_encode_apdu_object_property_value( int rpm_ack_encode_apdu_object_property_value(uint8_t * apdu,
uint8_t *apdu, uint8_t * application_data, unsigned application_data_len)
uint8_t *application_data,
unsigned application_data_len)
{ {
int apdu_len = 0; /* total length of the apdu, return value */ int apdu_len = 0; /* total length of the apdu, return value */
unsigned len = 0; unsigned len = 0;
if (apdu) if (apdu) {
{
/* Tag 4: propertyValue */ /* Tag 4: propertyValue */
apdu_len += encode_opening_tag(&apdu[apdu_len], 4); apdu_len += encode_opening_tag(&apdu[apdu_len], 4);
for (len = 0; len < application_data_len; len++) for (len = 0; len < application_data_len; len++) {
{
apdu[apdu_len++] = application_data[len]; apdu[apdu_len++] = application_data[len];
} }
apdu_len += encode_closing_tag(&apdu[apdu_len], 4); apdu_len += encode_closing_tag(&apdu[apdu_len], 4);
@@ -309,15 +268,12 @@ int rpm_ack_encode_apdu_object_property_value(
return apdu_len; return apdu_len;
} }
int rpm_ack_encode_apdu_object_property_error( int rpm_ack_encode_apdu_object_property_error(uint8_t * apdu,
uint8_t *apdu, BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code)
BACNET_ERROR_CLASS error_class,
BACNET_ERROR_CODE error_code)
{ {
int apdu_len = 0; /* total length of the apdu, return value */ int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) if (apdu) {
{
/* Tag 5: propertyAccessError */ /* Tag 5: propertyAccessError */
apdu_len += encode_opening_tag(&apdu[apdu_len], 5); apdu_len += encode_opening_tag(&apdu[apdu_len], 5);
apdu_len += encode_tagged_enumerated(&apdu[apdu_len], error_class); apdu_len += encode_tagged_enumerated(&apdu[apdu_len], error_class);
@@ -328,13 +284,11 @@ int rpm_ack_encode_apdu_object_property_error(
return apdu_len; return apdu_len;
} }
int rpm_ack_encode_apdu_object_end( int rpm_ack_encode_apdu_object_end(uint8_t * apdu)
uint8_t *apdu)
{ {
int apdu_len = 0; /* total length of the apdu, return value */ int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) if (apdu) {
{
apdu_len = encode_closing_tag(&apdu[0], 1); apdu_len = encode_closing_tag(&apdu[0], 1);
} }
@@ -342,18 +296,15 @@ int rpm_ack_encode_apdu_object_end(
} }
/* decode the object portion of the service request only */ /* decode the object portion of the service request only */
int rpm_ack_decode_object_id( int rpm_ack_decode_object_id(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
BACNET_OBJECT_TYPE *object_type, BACNET_OBJECT_TYPE * object_type, uint32_t * object_instance)
uint32_t *object_instance)
{ {
unsigned len = 0; unsigned len = 0;
int type = 0; /* for decoding */ int type = 0; /* for decoding */
/* check for value pointers */ /* check for value pointers */
if (apdu && apdu_len && object_type && object_instance) if (apdu && apdu_len && object_type && object_instance) {
{
/* Tag 0: objectIdentifier */ /* Tag 0: objectIdentifier */
if (!decode_is_context_tag(&apdu[len++], 0)) if (!decode_is_context_tag(&apdu[len++], 0))
return -1; return -1;
@@ -366,30 +317,25 @@ int rpm_ack_decode_object_id(
len++; /* opening tag is only one octet */ len++; /* opening tag is only one octet */
} }
return (int)len; return (int) len;
} }
/* is this the end of the list of this objects properties values? */ /* is this the end of the list of this objects properties values? */
int rpm_ack_decode_object_end( int rpm_ack_decode_object_end(uint8_t * apdu, unsigned apdu_len)
uint8_t *apdu,
unsigned apdu_len)
{ {
int len = 0; /* total length of the apdu, return value */ int len = 0; /* total length of the apdu, return value */
if (apdu && apdu_len) if (apdu && apdu_len) {
{ if (decode_is_closing_tag_number(apdu, 1))
if (decode_is_closing_tag_number(apdu,1))
len = 1; len = 1;
} }
return len; return len;
} }
int rpm_ack_decode_object_property( int rpm_ack_decode_object_property(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
BACNET_PROPERTY_ID *object_property, BACNET_PROPERTY_ID * object_property, int32_t * array_index)
int32_t *array_index)
{ {
unsigned len = 0; unsigned len = 0;
unsigned tag_len = 0; unsigned tag_len = 0;
@@ -399,8 +345,7 @@ int rpm_ack_decode_object_property(
uint32_t array_value = 0; /* for decoding */ uint32_t array_value = 0; /* for decoding */
/* check for valid pointers */ /* check for valid pointers */
if (apdu && apdu_len && object_property && array_index) if (apdu && apdu_len && object_property && array_index) {
{
/* Tag 2: propertyIdentifier */ /* Tag 2: propertyIdentifier */
len += decode_tag_number_and_value(&apdu[len], len += decode_tag_number_and_value(&apdu[len],
&tag_number, &len_value_type); &tag_number, &len_value_type);
@@ -410,28 +355,23 @@ int rpm_ack_decode_object_property(
if (object_property) if (object_property)
*object_property = property; *object_property = property;
/* Tag 3: Optional propertyArrayIndex */ /* Tag 3: Optional propertyArrayIndex */
tag_len = decode_tag_number_and_value(&apdu[len],&tag_number, tag_len = decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type); &len_value_type);
if (tag_number == 3) if (tag_number == 3) {
{
len += tag_len; len += tag_len;
len += decode_unsigned(&apdu[len], len_value_type, len += decode_unsigned(&apdu[len], len_value_type,
&array_value); &array_value);
*array_index = array_value; *array_index = array_value;
} } else
else
*array_index = BACNET_ARRAY_ALL; *array_index = BACNET_ARRAY_ALL;
} }
return (int)len; return (int) len;
} }
int rpm_ack_decode_apdu( int rpm_ack_decode_apdu(uint8_t * apdu, int apdu_len, /* total length of the apdu */
uint8_t *apdu, uint8_t * invoke_id,
int apdu_len, /* total length of the apdu */ uint8_t ** service_request, unsigned *service_request_len)
uint8_t *invoke_id,
uint8_t **service_request,
unsigned *service_request_len)
{ {
int offset = 0; int offset = 0;
@@ -444,8 +384,7 @@ int rpm_ack_decode_apdu(
if (apdu[2] != SERVICE_CONFIRMED_READ_PROPERTY_MULTIPLE) if (apdu[2] != SERVICE_CONFIRMED_READ_PROPERTY_MULTIPLE)
return -1; return -1;
offset = 3; offset = 3;
if (apdu_len > offset) if (apdu_len > offset) {
{
if (service_request) if (service_request)
*service_request = &apdu[offset]; *service_request = &apdu[offset];
if (service_request_len) if (service_request_len)
@@ -462,7 +401,7 @@ int rpm_ack_decode_apdu(
void testReadPropertyMultiple(Test * pTest) void testReadPropertyMultiple(Test * pTest)
{ {
uint8_t apdu[480] = {0}; uint8_t apdu[480] = { 0 };
int len = 0; int len = 0;
int test_len = 0; int test_len = 0;
int apdu_len = 0; int apdu_len = 0;
@@ -502,96 +441,66 @@ void testReadPropertyMultiple(Test * pTest)
ct_test(pTest, apdu_len != 0); ct_test(pTest, apdu_len != 0);
test_len = rpm_decode_apdu( test_len = rpm_decode_apdu(&apdu[0], apdu_len, &test_invoke_id, &service_request, /* will point to the service request in the apdu */
&apdu[0],
apdu_len,
&test_invoke_id,
&service_request, /* will point to the service request in the apdu */
&service_request_len); &service_request_len);
ct_test(pTest, test_len != -1); ct_test(pTest, test_len != -1);
ct_test(pTest, test_invoke_id == invoke_id); ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest, service_request != NULL); ct_test(pTest, service_request != NULL);
ct_test(pTest, service_request_len > 0); ct_test(pTest, service_request_len > 0);
test_len = rpm_decode_object_id( test_len = rpm_decode_object_id(service_request,
service_request, service_request_len, &object_type, &object_instance);
service_request_len,
&object_type,
&object_instance);
ct_test(pTest, test_len != -1); ct_test(pTest, test_len != -1);
ct_test(pTest, object_type == OBJECT_DEVICE); ct_test(pTest, object_type == OBJECT_DEVICE);
ct_test(pTest, object_instance == 123); ct_test(pTest, object_instance == 123);
len = test_len; len = test_len;
/* decode the object property portion of the service request */ /* decode the object property portion of the service request */
test_len = rpm_decode_object_property( test_len = rpm_decode_object_property(&service_request[len],
&service_request[len], service_request_len - len, &object_property, &array_index);
service_request_len - len,
&object_property,
&array_index);
ct_test(pTest, test_len != -1); ct_test(pTest, test_len != -1);
ct_test(pTest, object_property == PROP_OBJECT_IDENTIFIER); ct_test(pTest, object_property == PROP_OBJECT_IDENTIFIER);
ct_test(pTest, array_index == BACNET_ARRAY_ALL); ct_test(pTest, array_index == BACNET_ARRAY_ALL);
len += test_len; len += test_len;
test_len = rpm_decode_object_property( test_len = rpm_decode_object_property(&service_request[len],
&service_request[len], service_request_len - len, &object_property, &array_index);
service_request_len - len,
&object_property,
&array_index);
ct_test(pTest, test_len != -1); ct_test(pTest, test_len != -1);
ct_test(pTest, object_property == PROP_OBJECT_NAME); ct_test(pTest, object_property == PROP_OBJECT_NAME);
ct_test(pTest, array_index == BACNET_ARRAY_ALL); ct_test(pTest, array_index == BACNET_ARRAY_ALL);
len += test_len; len += test_len;
/* try again - we should fail */ /* try again - we should fail */
test_len = rpm_decode_object_property( test_len = rpm_decode_object_property(&service_request[len],
&service_request[len], service_request_len - len, &object_property, &array_index);
service_request_len - len,
&object_property,
&array_index);
ct_test(pTest, test_len == -1); ct_test(pTest, test_len == -1);
/* is it the end of this object? */ /* is it the end of this object? */
test_len = rpm_decode_object_end( test_len = rpm_decode_object_end(&service_request[len],
&service_request[len],
service_request_len - len); service_request_len - len);
ct_test(pTest, test_len == 1); ct_test(pTest, test_len == 1);
len += test_len; len += test_len;
/* try to decode an object id */ /* try to decode an object id */
test_len = rpm_decode_object_id( test_len = rpm_decode_object_id(&service_request[len],
&service_request[len], service_request_len - len, &object_type, &object_instance);
service_request_len - len,
&object_type,
&object_instance);
ct_test(pTest, test_len != -1); ct_test(pTest, test_len != -1);
ct_test(pTest, object_type == OBJECT_ANALOG_INPUT); ct_test(pTest, object_type == OBJECT_ANALOG_INPUT);
ct_test(pTest, object_instance == 33); ct_test(pTest, object_instance == 33);
len += test_len; len += test_len;
/* decode the object property portion of the service request only */ /* decode the object property portion of the service request only */
test_len = rpm_decode_object_property( test_len = rpm_decode_object_property(&service_request[len],
&service_request[len], service_request_len - len, &object_property, &array_index);
service_request_len - len,
&object_property,
&array_index);
ct_test(pTest, test_len != -1); ct_test(pTest, test_len != -1);
ct_test(pTest, object_property == PROP_OBJECT_IDENTIFIER); ct_test(pTest, object_property == PROP_OBJECT_IDENTIFIER);
ct_test(pTest, array_index == BACNET_ARRAY_ALL); ct_test(pTest, array_index == BACNET_ARRAY_ALL);
len += test_len; len += test_len;
test_len = rpm_decode_object_property( test_len = rpm_decode_object_property(&service_request[len],
&service_request[len], service_request_len - len, &object_property, &array_index);
service_request_len - len,
&object_property,
&array_index);
ct_test(pTest, test_len != -1); ct_test(pTest, test_len != -1);
ct_test(pTest, object_property == PROP_ALL); ct_test(pTest, object_property == PROP_ALL);
ct_test(pTest, array_index == BACNET_ARRAY_ALL); ct_test(pTest, array_index == BACNET_ARRAY_ALL);
len += test_len; len += test_len;
test_len = rpm_decode_object_property( test_len = rpm_decode_object_property(&service_request[len],
&service_request[len], service_request_len - len, &object_property, &array_index);
service_request_len - len,
&object_property,
&array_index);
ct_test(pTest, test_len == -1); ct_test(pTest, test_len == -1);
/* got an error -1, is it the end of this object? */ /* got an error -1, is it the end of this object? */
test_len = rpm_decode_object_end( test_len = rpm_decode_object_end(&service_request[len],
&service_request[len],
service_request_len - len); service_request_len - len);
ct_test(pTest, test_len == 1); ct_test(pTest, test_len == 1);
len += test_len; len += test_len;
@@ -600,7 +509,7 @@ void testReadPropertyMultiple(Test * pTest)
void testReadPropertyMultipleAck(Test * pTest) void testReadPropertyMultipleAck(Test * pTest)
{ {
uint8_t apdu[480] = {0}; uint8_t apdu[480] = { 0 };
int len = 0; int len = 0;
int test_len = 0; int test_len = 0;
int apdu_len = 0; int apdu_len = 0;
@@ -612,9 +521,9 @@ void testReadPropertyMultipleAck(Test * pTest)
uint32_t object_instance = 0; uint32_t object_instance = 0;
BACNET_PROPERTY_ID object_property = PROP_OBJECT_IDENTIFIER; BACNET_PROPERTY_ID object_property = PROP_OBJECT_IDENTIFIER;
int32_t array_index = 0; int32_t array_index = 0;
BACNET_APPLICATION_DATA_VALUE application_data[4] = {{0}}; BACNET_APPLICATION_DATA_VALUE application_data[4] = { {0} };
BACNET_APPLICATION_DATA_VALUE test_application_data = {0}; BACNET_APPLICATION_DATA_VALUE test_application_data = { 0 };
uint8_t application_data_buffer[MAX_APDU] = {0}; uint8_t application_data_buffer[MAX_APDU] = { 0 };
int application_data_buffer_len = 0; int application_data_buffer_len = 0;
BACNET_ERROR_CLASS error_class; BACNET_ERROR_CLASS error_class;
BACNET_ERROR_CODE error_code; BACNET_ERROR_CODE error_code;
@@ -640,24 +549,24 @@ void testReadPropertyMultipleAck(Test * pTest)
application_data[0].tag = BACNET_APPLICATION_TAG_OBJECT_ID; application_data[0].tag = BACNET_APPLICATION_TAG_OBJECT_ID;
application_data[0].type.Object_Id.type = OBJECT_DEVICE; application_data[0].type.Object_Id.type = OBJECT_DEVICE;
application_data[0].type.Object_Id.instance = 123; application_data[0].type.Object_Id.instance = 123;
application_data_buffer_len = bacapp_encode_application_data( application_data_buffer_len =
&application_data_buffer[0], bacapp_encode_application_data(&application_data_buffer[0],
&application_data[0]); &application_data[0]);
apdu_len += rpm_ack_encode_apdu_object_property_value(&apdu[apdu_len], apdu_len +=
&application_data_buffer[0], rpm_ack_encode_apdu_object_property_value(&apdu[apdu_len],
application_data_buffer_len); &application_data_buffer[0], application_data_buffer_len);
/* reply property */ /* reply property */
apdu_len += rpm_ack_encode_apdu_object_property(&apdu[apdu_len], apdu_len += rpm_ack_encode_apdu_object_property(&apdu[apdu_len],
PROP_OBJECT_TYPE, BACNET_ARRAY_ALL); PROP_OBJECT_TYPE, BACNET_ARRAY_ALL);
/* reply value */ /* reply value */
application_data[1].tag = BACNET_APPLICATION_TAG_ENUMERATED; application_data[1].tag = BACNET_APPLICATION_TAG_ENUMERATED;
application_data[1].type.Enumerated = OBJECT_DEVICE; application_data[1].type.Enumerated = OBJECT_DEVICE;
application_data_buffer_len = bacapp_encode_application_data( application_data_buffer_len =
&application_data_buffer[0], bacapp_encode_application_data(&application_data_buffer[0],
&application_data[1]); &application_data[1]);
apdu_len += rpm_ack_encode_apdu_object_property_value(&apdu[apdu_len], apdu_len +=
&application_data_buffer[0], rpm_ack_encode_apdu_object_property_value(&apdu[apdu_len],
application_data_buffer_len); &application_data_buffer[0], application_data_buffer_len);
/* object end */ /* object end */
apdu_len += rpm_ack_encode_apdu_object_end(&apdu[apdu_len]); apdu_len += rpm_ack_encode_apdu_object_end(&apdu[apdu_len]);
@@ -670,12 +579,12 @@ void testReadPropertyMultipleAck(Test * pTest)
/* reply value */ /* reply value */
application_data[2].tag = BACNET_APPLICATION_TAG_REAL; application_data[2].tag = BACNET_APPLICATION_TAG_REAL;
application_data[2].type.Real = 0.0; application_data[2].type.Real = 0.0;
application_data_buffer_len = bacapp_encode_application_data( application_data_buffer_len =
&application_data_buffer[0], bacapp_encode_application_data(&application_data_buffer[0],
&application_data[2]); &application_data[2]);
apdu_len += rpm_ack_encode_apdu_object_property_value(&apdu[apdu_len], apdu_len +=
&application_data_buffer[0], rpm_ack_encode_apdu_object_property_value(&apdu[apdu_len],
application_data_buffer_len); &application_data_buffer[0], application_data_buffer_len);
/* reply property */ /* reply property */
apdu_len += rpm_ack_encode_apdu_object_property(&apdu[apdu_len], apdu_len += rpm_ack_encode_apdu_object_property(&apdu[apdu_len],
PROP_DEADBAND, BACNET_ARRAY_ALL); PROP_DEADBAND, BACNET_ARRAY_ALL);
@@ -687,164 +596,125 @@ void testReadPropertyMultipleAck(Test * pTest)
ct_test(pTest, apdu_len != 0); ct_test(pTest, apdu_len != 0);
/****** decode the packet ******/ /****** decode the packet ******/
test_len = rpm_ack_decode_apdu( test_len = rpm_ack_decode_apdu(&apdu[0], apdu_len, &test_invoke_id, &service_request, /* will point to the service request in the apdu */
&apdu[0],
apdu_len,
&test_invoke_id,
&service_request, /* will point to the service request in the apdu */
&service_request_len); &service_request_len);
ct_test(pTest, test_len != -1); ct_test(pTest, test_len != -1);
ct_test(pTest, test_invoke_id == invoke_id); ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest, service_request != NULL); ct_test(pTest, service_request != NULL);
ct_test(pTest, service_request_len > 0); ct_test(pTest, service_request_len > 0);
/* the first part should be the first object id */ /* the first part should be the first object id */
test_len = rpm_ack_decode_object_id( test_len = rpm_ack_decode_object_id(service_request,
service_request, service_request_len, &object_type, &object_instance);
service_request_len,
&object_type,
&object_instance);
ct_test(pTest, test_len != -1); ct_test(pTest, test_len != -1);
ct_test(pTest, object_type == OBJECT_DEVICE); ct_test(pTest, object_type == OBJECT_DEVICE);
ct_test(pTest, object_instance == 123); ct_test(pTest, object_instance == 123);
len = test_len; len = test_len;
/* extract the property */ /* extract the property */
test_len = rpm_ack_decode_object_property( test_len = rpm_ack_decode_object_property(&service_request[len],
&service_request[len], service_request_len - len, &object_property, &array_index);
service_request_len - len,
&object_property,
&array_index);
ct_test(pTest, object_property == PROP_OBJECT_IDENTIFIER); ct_test(pTest, object_property == PROP_OBJECT_IDENTIFIER);
ct_test(pTest, array_index == BACNET_ARRAY_ALL); ct_test(pTest, array_index == BACNET_ARRAY_ALL);
len += test_len; len += test_len;
/* what is the result? An error or a value? */ /* what is the result? An error or a value? */
ct_test(pTest,decode_is_opening_tag_number(&service_request[len], 4)); ct_test(pTest, decode_is_opening_tag_number(&service_request[len], 4));
len ++; len++;
/* decode the object property portion of the service request */ /* decode the object property portion of the service request */
/* note: if this was an array, there could have been /* note: if this was an array, there could have been
more than one element to decode */ more than one element to decode */
test_len = bacapp_decode_application_data( test_len = bacapp_decode_application_data(&service_request[len],
&service_request[len], service_request_len - len, &test_application_data);
service_request_len - len,
&test_application_data);
ct_test(pTest, test_len > 0); ct_test(pTest, test_len > 0);
ct_test(pTest, bacapp_compare(&application_data[0],&test_application_data)); ct_test(pTest, bacapp_compare(&application_data[0],
&test_application_data));
len += test_len; len += test_len;
ct_test(pTest,decode_is_closing_tag_number(&service_request[len], 4)); ct_test(pTest, decode_is_closing_tag_number(&service_request[len], 4));
len ++; len++;
/* see if there is another property */ /* see if there is another property */
test_len = rpm_ack_decode_object_property( test_len = rpm_ack_decode_object_property(&service_request[len],
&service_request[len], service_request_len - len, &object_property, &array_index);
service_request_len - len,
&object_property,
&array_index);
ct_test(pTest, test_len != -1); ct_test(pTest, test_len != -1);
ct_test(pTest, object_property == PROP_OBJECT_TYPE); ct_test(pTest, object_property == PROP_OBJECT_TYPE);
ct_test(pTest, array_index == BACNET_ARRAY_ALL); ct_test(pTest, array_index == BACNET_ARRAY_ALL);
len += test_len; len += test_len;
/* what is the result value? */ /* what is the result value? */
ct_test(pTest,decode_is_opening_tag_number(&service_request[len], 4)); ct_test(pTest, decode_is_opening_tag_number(&service_request[len], 4));
len ++; len++;
/* decode the object property portion of the service request */ /* decode the object property portion of the service request */
test_len = bacapp_decode_application_data( test_len = bacapp_decode_application_data(&service_request[len],
&service_request[len], service_request_len - len, &test_application_data);
service_request_len - len,
&test_application_data);
ct_test(pTest, test_len > 0); ct_test(pTest, test_len > 0);
ct_test(pTest, bacapp_compare(&application_data[1],&test_application_data)); ct_test(pTest, bacapp_compare(&application_data[1],
&test_application_data));
len += test_len; len += test_len;
ct_test(pTest,decode_is_closing_tag_number(&service_request[len], 4)); ct_test(pTest, decode_is_closing_tag_number(&service_request[len], 4));
len ++; len++;
/* see if there is another property */ /* see if there is another property */
/* this time we should fail */ /* this time we should fail */
test_len = rpm_ack_decode_object_property( test_len = rpm_ack_decode_object_property(&service_request[len],
&service_request[len], service_request_len - len, &object_property, &array_index);
service_request_len - len,
&object_property,
&array_index);
ct_test(pTest, test_len == -1); ct_test(pTest, test_len == -1);
/* see if it is the end of this object */ /* see if it is the end of this object */
test_len = rpm_ack_decode_object_end( test_len = rpm_ack_decode_object_end(&service_request[len],
&service_request[len],
service_request_len - len); service_request_len - len);
ct_test(pTest, test_len == 1); ct_test(pTest, test_len == 1);
len += test_len; len += test_len;
/* try to decode another object id */ /* try to decode another object id */
test_len = rpm_ack_decode_object_id( test_len = rpm_ack_decode_object_id(&service_request[len],
&service_request[len], service_request_len - len, &object_type, &object_instance);
service_request_len - len,
&object_type,
&object_instance);
ct_test(pTest, test_len != -1); ct_test(pTest, test_len != -1);
ct_test(pTest, object_type == OBJECT_ANALOG_INPUT); ct_test(pTest, object_type == OBJECT_ANALOG_INPUT);
ct_test(pTest, object_instance == 33); ct_test(pTest, object_instance == 33);
len += test_len; len += test_len;
/* decode the object property portion of the service request only */ /* decode the object property portion of the service request only */
test_len = rpm_ack_decode_object_property( test_len = rpm_ack_decode_object_property(&service_request[len],
&service_request[len], service_request_len - len, &object_property, &array_index);
service_request_len - len,
&object_property,
&array_index);
ct_test(pTest, test_len != -1); ct_test(pTest, test_len != -1);
ct_test(pTest, object_property == PROP_PRESENT_VALUE); ct_test(pTest, object_property == PROP_PRESENT_VALUE);
ct_test(pTest, array_index == BACNET_ARRAY_ALL); ct_test(pTest, array_index == BACNET_ARRAY_ALL);
len += test_len; len += test_len;
/* what is the result value? */ /* what is the result value? */
ct_test(pTest,decode_is_opening_tag_number(&service_request[len], 4)); ct_test(pTest, decode_is_opening_tag_number(&service_request[len], 4));
len++; len++;
/* decode the object property portion of the service request */ /* decode the object property portion of the service request */
test_len = bacapp_decode_application_data( test_len = bacapp_decode_application_data(&service_request[len],
&service_request[len], service_request_len - len, &test_application_data);
service_request_len - len,
&test_application_data);
ct_test(pTest, test_len > 0); ct_test(pTest, test_len > 0);
ct_test(pTest, bacapp_compare(&application_data[2],&test_application_data)); ct_test(pTest, bacapp_compare(&application_data[2],
&test_application_data));
len += test_len; len += test_len;
ct_test(pTest,decode_is_closing_tag_number(&service_request[len], 4)); ct_test(pTest, decode_is_closing_tag_number(&service_request[len], 4));
len++; len++;
/* see if there is another property */ /* see if there is another property */
test_len = rpm_ack_decode_object_property( test_len = rpm_ack_decode_object_property(&service_request[len],
&service_request[len], service_request_len - len, &object_property, &array_index);
service_request_len - len,
&object_property,
&array_index);
ct_test(pTest, test_len != -1); ct_test(pTest, test_len != -1);
ct_test(pTest, object_property == PROP_DEADBAND); ct_test(pTest, object_property == PROP_DEADBAND);
ct_test(pTest, array_index == BACNET_ARRAY_ALL); ct_test(pTest, array_index == BACNET_ARRAY_ALL);
len += test_len; len += test_len;
/* what is the result value? */ /* what is the result value? */
ct_test(pTest,decode_is_opening_tag_number(&service_request[len], 5)); ct_test(pTest, decode_is_opening_tag_number(&service_request[len], 5));
len++; len++;
/* it was an error reply */ /* it was an error reply */
test_len = bacerror_decode_error_class_and_code( test_len = bacerror_decode_error_class_and_code(&service_request[len],
&service_request[len], service_request_len - len, &error_class, &error_code);
service_request_len - len,
&error_class,
&error_code);
ct_test(pTest, test_len != 0); ct_test(pTest, test_len != 0);
ct_test(pTest, error_class == ERROR_CLASS_PROPERTY); ct_test(pTest, error_class == ERROR_CLASS_PROPERTY);
ct_test(pTest, error_code == ERROR_CODE_UNKNOWN_PROPERTY); ct_test(pTest, error_code == ERROR_CODE_UNKNOWN_PROPERTY);
len += test_len; len += test_len;
ct_test(pTest,decode_is_closing_tag_number(&service_request[len], 5)); ct_test(pTest, decode_is_closing_tag_number(&service_request[len], 5));
len++; len++;
/* is there another property? */ /* is there another property? */
test_len = rpm_ack_decode_object_property( test_len = rpm_ack_decode_object_property(&service_request[len],
&service_request[len], service_request_len - len, &object_property, &array_index);
service_request_len - len,
&object_property,
&array_index);
ct_test(pTest, test_len == -1); ct_test(pTest, test_len == -1);
/* got an error -1, is it the end of this object? */ /* got an error -1, is it the end of this object? */
test_len = rpm_ack_decode_object_end( test_len = rpm_ack_decode_object_end(&service_request[len],
&service_request[len],
service_request_len - len); service_request_len - len);
ct_test(pTest, test_len == 1); ct_test(pTest, test_len == 1);
len += test_len; len += test_len;
/* check for another object */ /* check for another object */
test_len = rpm_ack_decode_object_id( test_len = rpm_ack_decode_object_id(&service_request[len],
&service_request[len], service_request_len - len, &object_type, &object_instance);
service_request_len - len,
&object_type,
&object_instance);
ct_test(pTest, test_len == 0); ct_test(pTest, test_len == 0);
ct_test(pTest, len == service_request_len); ct_test(pTest, len == service_request_len);
} }
@@ -872,4 +742,3 @@ int main(void)
#endif /* TEST_READ_PROPERTY_MULTIPLE */ #endif /* TEST_READ_PROPERTY_MULTIPLE */
#endif /* TEST */ #endif /* TEST */
+33 -68
View File
@@ -51,104 +51,69 @@ extern "C" {
until the APDU is full.*/ until the APDU is full.*/
/* RPM */ /* RPM */
int rpm_encode_apdu_init( int rpm_encode_apdu_init(uint8_t * apdu, uint8_t invoke_id);
uint8_t *apdu,
uint8_t invoke_id);
int rpm_encode_apdu_object_begin( int rpm_encode_apdu_object_begin(uint8_t * apdu,
uint8_t *apdu, BACNET_OBJECT_TYPE object_type, uint32_t object_instance);
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance);
int rpm_encode_apdu_object_property( int rpm_encode_apdu_object_property(uint8_t * apdu,
uint8_t *apdu, BACNET_PROPERTY_ID object_property, int32_t array_index);
BACNET_PROPERTY_ID object_property,
int32_t array_index);
int rpm_encode_apdu_object_end( int rpm_encode_apdu_object_end(uint8_t * apdu);
uint8_t *apdu);
int rpm_decode_apdu( int rpm_decode_apdu(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
uint8_t *invoke_id, uint8_t * invoke_id,
uint8_t **service_request, uint8_t ** service_request, unsigned *service_request_len);
unsigned *service_request_len);
/* decode the object portion of the service request only */ /* decode the object portion of the service request only */
int rpm_decode_object_id( int rpm_decode_object_id(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
BACNET_OBJECT_TYPE *object_type, BACNET_OBJECT_TYPE * object_type, uint32_t * object_instance);
uint32_t *object_instance);
/* is this the end of this object property list? */ /* is this the end of this object property list? */
int rpm_decode_object_end( int rpm_decode_object_end(uint8_t * apdu, unsigned apdu_len);
uint8_t *apdu,
unsigned apdu_len);
/* decode the object property portion of the service request only */ /* decode the object property portion of the service request only */
int rpm_decode_object_property( int rpm_decode_object_property(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
BACNET_PROPERTY_ID *object_property, BACNET_PROPERTY_ID * object_property, int32_t * array_index);
int32_t *array_index);
/* RPM Ack */ /* RPM Ack */
int rpm_ack_encode_apdu_object_begin( int rpm_ack_encode_apdu_object_begin(uint8_t * apdu,
uint8_t *apdu, BACNET_OBJECT_TYPE object_type, uint32_t object_instance);
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance);
int rpm_ack_encode_apdu_object_property_value( int rpm_ack_encode_apdu_object_property_value(uint8_t * apdu,
uint8_t *apdu, uint8_t * application_data, unsigned application_data_len);
uint8_t *application_data,
unsigned application_data_len);
int rpm_ack_encode_apdu_object_property_error( int rpm_ack_encode_apdu_object_property_error(uint8_t * apdu,
uint8_t *apdu, BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code);
BACNET_ERROR_CLASS error_class,
BACNET_ERROR_CODE error_code);
int rpm_ack_encode_apdu_object_end( int rpm_ack_encode_apdu_object_end(uint8_t * apdu);
uint8_t *apdu);
int rpm_ack_decode_object_id( int rpm_ack_decode_object_id(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
BACNET_OBJECT_TYPE *object_type, BACNET_OBJECT_TYPE * object_type, uint32_t * object_instance);
uint32_t *object_instance);
/* is this the end of the list of this objects properties values? */ /* is this the end of the list of this objects properties values? */
int rpm_ack_decode_object_end( int rpm_ack_decode_object_end(uint8_t * apdu, unsigned apdu_len);
uint8_t *apdu, int rpm_ack_decode_object_property(uint8_t * apdu,
unsigned apdu_len);
int rpm_ack_decode_object_property(
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
BACNET_PROPERTY_ID *object_property, BACNET_PROPERTY_ID * object_property, int32_t * array_index);
int32_t *array_index);
/* decode the object property value portion of the service request only */ /* decode the object property value portion of the service request only */
int rpm_ack_decode_object_property_value( int rpm_ack_decode_object_property_value(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
uint8_t **application_data, uint8_t ** application_data, unsigned *application_data_len);
unsigned *application_data_len); int rpm_ack_decode_apdu(uint8_t * apdu, int apdu_len, /* total length of the apdu */
int rpm_ack_decode_apdu( uint8_t * invoke_id,
uint8_t *apdu, uint8_t ** service_request, unsigned *service_request_len);
int apdu_len, /* total length of the apdu */
uint8_t *invoke_id,
uint8_t **service_request,
unsigned *service_request_len);
#ifdef TEST #ifdef TEST
#include "ctest.h" #include "ctest.h"
void testReadPropertyMultiple(Test * pTest); void testReadPropertyMultiple(Test * pTest);
void testReadPropertyMultipleAck(Test * pTest); void testReadPropertyMultipleAck(Test * pTest);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+5 -8
View File
@@ -43,20 +43,17 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
void RS485_Initialize(void); void RS485_Initialize(void);
void RS485_Send_Frame( void RS485_Send_Frame(volatile struct mstp_port_struct_t *mstp_port, // port specific data
volatile struct mstp_port_struct_t *mstp_port, // port specific data uint8_t * buffer, // frame to send (up to 501 bytes of data)
uint8_t *buffer, // frame to send (up to 501 bytes of data)
uint16_t nbytes); // number of bytes of data (up to 501) uint16_t nbytes); // number of bytes of data (up to 501)
void RS485_Check_UART_Data( void RS485_Check_UART_Data(volatile struct mstp_port_struct_t *mstp_port); // port specific data
volatile struct mstp_port_struct_t *mstp_port); // port specific data
void RS485_Process_Tx_Message(void); void RS485_Process_Tx_Message(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+54 -65
View File
@@ -40,13 +40,11 @@
#include <stddef.h> #include <stddef.h>
#include "sbuf.h" #include "sbuf.h"
void sbuf_init( void sbuf_init(STATIC_BUFFER * b, /* static buffer structure */
STATIC_BUFFER *b, /* static buffer structure */
char *data, /* actual size, in bytes, of the data block or array of data */ char *data, /* actual size, in bytes, of the data block or array of data */
unsigned size) /* number of bytes used */ unsigned size)
{ { /* number of bytes used */
if (b) if (b) {
{
b->data = data; b->data = data;
b->size = size; b->size = size;
b->count = 0; b->count = 0;
@@ -58,40 +56,36 @@ void sbuf_init(
/* returns true if count==0, false if count > 0 */ /* returns true if count==0, false if count > 0 */
bool sbuf_empty(STATIC_BUFFER const *b) bool sbuf_empty(STATIC_BUFFER const *b)
{ {
return (b?(b->count == 0):false); return (b ? (b->count == 0) : false);
} }
char *sbuf_data(STATIC_BUFFER const *b) char *sbuf_data(STATIC_BUFFER const *b)
{ {
return (b?b->data:NULL); return (b ? b->data : NULL);
} }
unsigned sbuf_size(STATIC_BUFFER *b) unsigned sbuf_size(STATIC_BUFFER * b)
{ {
return (b?b->size:0); return (b ? b->size : 0);
} }
unsigned sbuf_count(STATIC_BUFFER *b) unsigned sbuf_count(STATIC_BUFFER * b)
{ {
return (b?b->count:0); return (b ? b->count : 0);
} }
/* returns true if successful, false if not enough room to append data */ /* returns true if successful, false if not enough room to append data */
bool sbuf_put( bool sbuf_put(STATIC_BUFFER * b, /* static buffer structure */
STATIC_BUFFER *b, /* static buffer structure */
unsigned offset, /* where to start */ unsigned offset, /* where to start */
char *data, /* number of bytes used */ char *data, /* number of bytes used */
unsigned data_size) /* how many to add */ unsigned data_size)
{ { /* how many to add */
bool status = false; /* return value */ bool status = false; /* return value */
if (b && b->data) if (b && b->data) {
{ if (((offset + data_size) < b->size)) {
if (((offset + data_size) < b->size))
{
b->count = offset + data_size; b->count = offset + data_size;
while (data_size) while (data_size) {
{
b->data[offset] = *data; b->data[offset] = *data;
offset++; offset++;
data++; data++;
@@ -105,11 +99,10 @@ bool sbuf_put(
} }
/* returns true if successful, false if not enough room to append data */ /* returns true if successful, false if not enough room to append data */
bool sbuf_append( bool sbuf_append(STATIC_BUFFER * b, /* static buffer structure */
STATIC_BUFFER *b, /* static buffer structure */
char *data, /* number of bytes used */ char *data, /* number of bytes used */
unsigned data_size) /* how many to add */ unsigned data_size)
{ { /* how many to add */
unsigned count = 0; unsigned count = 0;
if (b) if (b)
@@ -119,16 +112,13 @@ bool sbuf_append(
} }
/* returns true if successful, false if not enough room to append data */ /* returns true if successful, false if not enough room to append data */
bool sbuf_truncate( bool sbuf_truncate(STATIC_BUFFER * b, /* static buffer structure */
STATIC_BUFFER *b, /* static buffer structure */ unsigned count)
unsigned count) /* total number of bytes in use */ { /* total number of bytes in use */
{
bool status = false; /* return value */ bool status = false; /* return value */
if (b) if (b) {
{ if (count < b->size) {
if (count < b->size)
{
b->count = count; b->count = count;
status = true; status = true;
} }
@@ -143,7 +133,7 @@ bool sbuf_truncate(
#include "ctest.h" #include "ctest.h"
void testStaticBuffer(Test* pTest) void testStaticBuffer(Test * pTest)
{ {
STATIC_BUFFER sbuffer; STATIC_BUFFER sbuffer;
char *data1 = "Joshua"; char *data1 = "Joshua";
@@ -155,42 +145,42 @@ void testStaticBuffer(Test* pTest)
char *data; char *data;
unsigned count; unsigned count;
sbuf_init(&sbuffer,NULL,0); sbuf_init(&sbuffer, NULL, 0);
ct_test(pTest,sbuf_empty(&sbuffer) == true); ct_test(pTest, sbuf_empty(&sbuffer) == true);
ct_test(pTest,sbuf_data(&sbuffer) == NULL); ct_test(pTest, sbuf_data(&sbuffer) == NULL);
ct_test(pTest,sbuf_size(&sbuffer) == 0); ct_test(pTest, sbuf_size(&sbuffer) == 0);
ct_test(pTest,sbuf_count(&sbuffer) == 0); ct_test(pTest, sbuf_count(&sbuffer) == 0);
ct_test(pTest,sbuf_append(&sbuffer,data1,strlen(data1)) == false); ct_test(pTest, sbuf_append(&sbuffer, data1, strlen(data1)) == false);
sbuf_init(&sbuffer,data_buffer,sizeof(data_buffer)); sbuf_init(&sbuffer, data_buffer, sizeof(data_buffer));
ct_test(pTest,sbuf_empty(&sbuffer) == true); ct_test(pTest, sbuf_empty(&sbuffer) == true);
ct_test(pTest,sbuf_data(&sbuffer) == data_buffer); ct_test(pTest, sbuf_data(&sbuffer) == data_buffer);
ct_test(pTest,sbuf_size(&sbuffer) == sizeof(data_buffer)); ct_test(pTest, sbuf_size(&sbuffer) == sizeof(data_buffer));
ct_test(pTest,sbuf_count(&sbuffer) == 0); ct_test(pTest, sbuf_count(&sbuffer) == 0);
ct_test(pTest,sbuf_append(&sbuffer,data1,strlen(data1)) == true); ct_test(pTest, sbuf_append(&sbuffer, data1, strlen(data1)) == true);
ct_test(pTest,sbuf_append(&sbuffer,data2,strlen(data2)) == true); ct_test(pTest, sbuf_append(&sbuffer, data2, strlen(data2)) == true);
ct_test(pTest,sbuf_append(&sbuffer,data3,strlen(data3)) == true); ct_test(pTest, sbuf_append(&sbuffer, data3, strlen(data3)) == true);
ct_test(pTest,sbuf_append(&sbuffer,data4,strlen(data4)) == true); ct_test(pTest, sbuf_append(&sbuffer, data4, strlen(data4)) == true);
strcat(test_data_buffer,data1); strcat(test_data_buffer, data1);
strcat(test_data_buffer,data2); strcat(test_data_buffer, data2);
strcat(test_data_buffer,data3); strcat(test_data_buffer, data3);
strcat(test_data_buffer,data4); strcat(test_data_buffer, data4);
ct_test(pTest,sbuf_count(&sbuffer) == strlen(test_data_buffer)); ct_test(pTest, sbuf_count(&sbuffer) == strlen(test_data_buffer));
data = sbuf_data(&sbuffer); data = sbuf_data(&sbuffer);
count = sbuf_count(&sbuffer); count = sbuf_count(&sbuffer);
ct_test(pTest,memcmp(data,test_data_buffer,count) == 0); ct_test(pTest, memcmp(data, test_data_buffer, count) == 0);
ct_test(pTest,count == strlen(test_data_buffer)); ct_test(pTest, count == strlen(test_data_buffer));
ct_test(pTest,sbuf_truncate(&sbuffer,0) == true); ct_test(pTest, sbuf_truncate(&sbuffer, 0) == true);
ct_test(pTest,sbuf_count(&sbuffer) == 0); ct_test(pTest, sbuf_count(&sbuffer) == 0);
ct_test(pTest,sbuf_size(&sbuffer) == sizeof(data_buffer)); ct_test(pTest, sbuf_size(&sbuffer) == sizeof(data_buffer));
ct_test(pTest,sbuf_append(&sbuffer,data4,strlen(data4)) == true); ct_test(pTest, sbuf_append(&sbuffer, data4, strlen(data4)) == true);
data = sbuf_data(&sbuffer); data = sbuf_data(&sbuffer);
count = sbuf_count(&sbuffer); count = sbuf_count(&sbuffer);
ct_test(pTest,memcmp(data,data4,count) == 0); ct_test(pTest, memcmp(data, data4, count) == 0);
ct_test(pTest,count == strlen(data4)); ct_test(pTest, count == strlen(data4));
return; return;
} }
@@ -209,7 +199,7 @@ int main(void)
ct_setStream(pTest, stdout); ct_setStream(pTest, stdout);
ct_run(pTest); ct_run(pTest);
(void)ct_report(pTest); (void) ct_report(pTest);
ct_destroy(pTest); ct_destroy(pTest);
@@ -217,4 +207,3 @@ int main(void)
} }
#endif /* TEST_STATIC_BUFFER */ #endif /* TEST_STATIC_BUFFER */
#endif /* TEST */ #endif /* TEST */
+9 -15
View File
@@ -42,8 +42,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
struct static_buffer_t struct static_buffer_t {
{
char *data; /* block of memory or array of data */ char *data; /* block of memory or array of data */
unsigned size; /* actual size, in bytes, of the block of data */ unsigned size; /* actual size, in bytes, of the block of data */
unsigned count; /* number of bytes in use */ unsigned count; /* number of bytes in use */
@@ -54,33 +53,28 @@ typedef struct static_buffer_t STATIC_BUFFER;
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
void sbuf_init( void sbuf_init(STATIC_BUFFER * b, /* static buffer structure */
STATIC_BUFFER *b, /* static buffer structure */
char *data, /* actual size, in bytes, of the data block or array of data */ char *data, /* actual size, in bytes, of the data block or array of data */
unsigned size); /* number of bytes used */ unsigned size); /* number of bytes used */
/* returns true if size==0, false if size > 0 */ /* returns true if size==0, false if size > 0 */
bool sbuf_empty(STATIC_BUFFER const *b); bool sbuf_empty(STATIC_BUFFER const *b);
char *sbuf_data(STATIC_BUFFER const *b); char *sbuf_data(STATIC_BUFFER const *b);
unsigned sbuf_size(STATIC_BUFFER *b); unsigned sbuf_size(STATIC_BUFFER * b);
unsigned sbuf_count(STATIC_BUFFER *b); unsigned sbuf_count(STATIC_BUFFER * b);
/* returns true if successful, false if not enough room to append data */ /* returns true if successful, false if not enough room to append data */
bool sbuf_put( bool sbuf_put(STATIC_BUFFER * b, /* static buffer structure */
STATIC_BUFFER *b, /* static buffer structure */
unsigned offset, /* where to start */ unsigned offset, /* where to start */
char *data, /* number of bytes used */ char *data, /* number of bytes used */
unsigned data_size); /* how many to add */ unsigned data_size); /* how many to add */
/* returns true if successful, false if not enough room to append data */ /* returns true if successful, false if not enough room to append data */
bool sbuf_append( bool sbuf_append(STATIC_BUFFER * b, /* static buffer structure */
STATIC_BUFFER *b, /* static buffer structure */
char *data, /* number of bytes used */ char *data, /* number of bytes used */
unsigned data_size); /* how many to add */ unsigned data_size); /* how many to add */
/* returns true if successful, false if not enough room to append data */ /* returns true if successful, false if not enough room to append data */
bool sbuf_truncate( bool sbuf_truncate(STATIC_BUFFER * b, /* static buffer structure */
STATIC_BUFFER *b, /* static buffer structure */
unsigned count); /* total number of bytes in use */ unsigned count); /* total number of bytes in use */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+33 -66
View File
@@ -57,7 +57,7 @@
// declare space for the TSM transactions, and set it up in the init. // declare space for the TSM transactions, and set it up in the init.
/* table rules: an Invoke ID = 0 is an unused spot in the table */ /* table rules: an Invoke ID = 0 is an unused spot in the table */
static BACNET_TSM_DATA TSM_List[MAX_TSM_TRANSACTIONS] = {{0}}; static BACNET_TSM_DATA TSM_List[MAX_TSM_TRANSACTIONS] = { {0} };
// returns MAX_TSM_TRANSACTIONS if not found // returns MAX_TSM_TRANSACTIONS if not found
static uint8_t tsm_find_invokeID_index(uint8_t invokeID) static uint8_t tsm_find_invokeID_index(uint8_t invokeID)
@@ -65,10 +65,8 @@ static uint8_t tsm_find_invokeID_index(uint8_t invokeID)
unsigned i = 0; // counter unsigned i = 0; // counter
uint8_t index = MAX_TSM_TRANSACTIONS; // return value uint8_t index = MAX_TSM_TRANSACTIONS; // return value
for (i = 0; i < MAX_TSM_TRANSACTIONS; i++) for (i = 0; i < MAX_TSM_TRANSACTIONS; i++) {
{ if (TSM_List[i].InvokeID == invokeID) {
if (TSM_List[i].InvokeID == invokeID)
{
index = i; index = i;
break; break;
} }
@@ -82,10 +80,8 @@ static uint8_t tsm_find_first_free_index(void)
unsigned i = 0; // counter unsigned i = 0; // counter
uint8_t index = MAX_TSM_TRANSACTIONS; // return value uint8_t index = MAX_TSM_TRANSACTIONS; // return value
for (i = 0; i < MAX_TSM_TRANSACTIONS; i++) for (i = 0; i < MAX_TSM_TRANSACTIONS; i++) {
{ if (TSM_List[i].InvokeID == 0) {
if (TSM_List[i].InvokeID == 0)
{
index = i; index = i;
break; break;
} }
@@ -99,10 +95,8 @@ bool tsm_transaction_available(void)
bool status = false; // return value bool status = false; // return value
unsigned i = 0; // counter unsigned i = 0; // counter
for (i = 0; i < MAX_TSM_TRANSACTIONS; i++) for (i = 0; i < MAX_TSM_TRANSACTIONS; i++) {
{ if (TSM_List[i].InvokeID == 0) {
if (TSM_List[i].InvokeID == 0)
{
// one is available! // one is available!
status = true; status = true;
break; break;
@@ -117,11 +111,9 @@ uint8_t tsm_transaction_idle_count(void)
uint8_t count = 0; // return value uint8_t count = 0; // return value
unsigned i = 0; // counter unsigned i = 0; // counter
for (i = 0; i < MAX_TSM_TRANSACTIONS; i++) for (i = 0; i < MAX_TSM_TRANSACTIONS; i++) {
{
if ((TSM_List[i].InvokeID == 0) && if ((TSM_List[i].InvokeID == 0) &&
(TSM_List[i].state == TSM_STATE_IDLE)) (TSM_List[i].state == TSM_STATE_IDLE)) {
{
// one is available! // one is available!
count++; count++;
} }
@@ -140,17 +132,14 @@ uint8_t tsm_next_free_invokeID(void)
uint8_t invokeID = 0; uint8_t invokeID = 0;
bool found = false; bool found = false;
while (!found) while (!found) {
{
index = tsm_find_invokeID_index(current_invokeID); index = tsm_find_invokeID_index(current_invokeID);
/* not found - that is good! */ /* not found - that is good! */
if (index == MAX_TSM_TRANSACTIONS) if (index == MAX_TSM_TRANSACTIONS) {
{
found = true; found = true;
/* set this id into the table */ /* set this id into the table */
index = tsm_find_first_free_index(); index = tsm_find_first_free_index();
if (index != MAX_TSM_TRANSACTIONS) if (index != MAX_TSM_TRANSACTIONS) {
{
TSM_List[index].InvokeID = invokeID = current_invokeID; TSM_List[index].InvokeID = invokeID = current_invokeID;
TSM_List[index].state = TSM_STATE_IDLE; TSM_List[index].state = TSM_STATE_IDLE;
TSM_List[index].RequestTimer = Device_APDU_Timeout(); TSM_List[index].RequestTimer = Device_APDU_Timeout();
@@ -166,32 +155,26 @@ uint8_t tsm_next_free_invokeID(void)
return invokeID; return invokeID;
} }
void tsm_set_confirmed_unsegmented_transaction( void tsm_set_confirmed_unsegmented_transaction(uint8_t invokeID,
uint8_t invokeID, BACNET_ADDRESS * dest, uint8_t * pdu, uint16_t pdu_len)
BACNET_ADDRESS *dest,
uint8_t *pdu,
uint16_t pdu_len)
{ {
uint16_t j = 0; uint16_t j = 0;
uint8_t index; uint8_t index;
if (invokeID) if (invokeID) {
{
index = tsm_find_invokeID_index(invokeID); index = tsm_find_invokeID_index(invokeID);
if (index < MAX_TSM_TRANSACTIONS) if (index < MAX_TSM_TRANSACTIONS) {
{
// assign the transaction // assign the transaction
TSM_List[index].state = TSM_STATE_AWAIT_CONFIRMATION; TSM_List[index].state = TSM_STATE_AWAIT_CONFIRMATION;
TSM_List[index].RetryCount = Device_Number_Of_APDU_Retries(); TSM_List[index].RetryCount = Device_Number_Of_APDU_Retries();
// start the timer // start the timer
TSM_List[index].RequestTimer = Device_APDU_Timeout(); TSM_List[index].RequestTimer = Device_APDU_Timeout();
// copy the data // copy the data
for (j = 0; j < pdu_len; j++) for (j = 0; j < pdu_len; j++) {
{
TSM_List[index].pdu[j] = pdu[j]; TSM_List[index].pdu[j] = pdu[j];
} }
TSM_List[index].pdu_len = pdu_len; TSM_List[index].pdu_len = pdu_len;
address_copy(&TSM_List[index].dest,dest); address_copy(&TSM_List[index].dest, dest);
} }
} }
@@ -200,31 +183,25 @@ void tsm_set_confirmed_unsegmented_transaction(
// used to retrieve the transaction payload // used to retrieve the transaction payload
// if we wanted to find out what we sent (i.e. when we get an ack) // if we wanted to find out what we sent (i.e. when we get an ack)
bool tsm_get_transaction_pdu( bool tsm_get_transaction_pdu(uint8_t invokeID,
uint8_t invokeID, BACNET_ADDRESS * dest, uint8_t * pdu, uint16_t * pdu_len)
BACNET_ADDRESS *dest,
uint8_t *pdu,
uint16_t *pdu_len)
{ {
uint16_t j = 0; uint16_t j = 0;
uint8_t index; uint8_t index;
bool found = false; bool found = false;
if (invokeID) if (invokeID) {
{
index = tsm_find_invokeID_index(invokeID); index = tsm_find_invokeID_index(invokeID);
// how much checking is needed? state? dest match? just invokeID? // how much checking is needed? state? dest match? just invokeID?
if (index < MAX_TSM_TRANSACTIONS) if (index < MAX_TSM_TRANSACTIONS) {
{
// FIXME: we may want to free the transaction so it doesn't timeout // FIXME: we may want to free the transaction so it doesn't timeout
// retrieve the transaction // retrieve the transaction
// FIXME: bounds check the pdu_len? // FIXME: bounds check the pdu_len?
*pdu_len = TSM_List[index].pdu_len; *pdu_len = TSM_List[index].pdu_len;
for (j = 0; j < *pdu_len; j++) for (j = 0; j < *pdu_len; j++) {
{
pdu[j] = TSM_List[index].pdu[j]; pdu[j] = TSM_List[index].pdu[j];
} }
address_copy(dest,&TSM_List[index].dest); address_copy(dest, &TSM_List[index].dest);
found = true; found = true;
} }
} }
@@ -238,28 +215,20 @@ void tsm_timer_milliseconds(uint16_t milliseconds)
unsigned i = 0; // counter unsigned i = 0; // counter
int bytes_sent = 0; int bytes_sent = 0;
for (i = 0; i < MAX_TSM_TRANSACTIONS; i++) for (i = 0; i < MAX_TSM_TRANSACTIONS; i++) {
{ if (TSM_List[i].state == TSM_STATE_AWAIT_CONFIRMATION) {
if (TSM_List[i].state == TSM_STATE_AWAIT_CONFIRMATION)
{
if (TSM_List[i].RequestTimer > milliseconds) if (TSM_List[i].RequestTimer > milliseconds)
TSM_List[i].RequestTimer -= milliseconds; TSM_List[i].RequestTimer -= milliseconds;
else else
TSM_List[i].RequestTimer = 0; TSM_List[i].RequestTimer = 0;
/* timeout. retry? */ /* timeout. retry? */
if (TSM_List[i].RequestTimer == 0) if (TSM_List[i].RequestTimer == 0) {
{
TSM_List[i].RetryCount--; TSM_List[i].RetryCount--;
TSM_List[i].RequestTimer = Device_APDU_Timeout(); TSM_List[i].RequestTimer = Device_APDU_Timeout();
if (TSM_List[i].RetryCount) if (TSM_List[i].RetryCount) {
{ bytes_sent = datalink_send_pdu(&TSM_List[i].dest, /* destination address */
bytes_sent = datalink_send_pdu( &TSM_List[i].pdu[0], TSM_List[i].pdu_len); /* number of bytes of data */
&TSM_List[i].dest, /* destination address */ } else {
&TSM_List[i].pdu[0],
TSM_List[i].pdu_len); /* number of bytes of data */
}
else
{
TSM_List[i].InvokeID = 0; TSM_List[i].InvokeID = 0;
TSM_List[i].state = TSM_STATE_IDLE; TSM_List[i].state = TSM_STATE_IDLE;
} }
@@ -273,8 +242,7 @@ void tsm_free_invoke_id(uint8_t invokeID)
uint8_t index; uint8_t index;
index = tsm_find_invokeID_index(invokeID); index = tsm_find_invokeID_index(invokeID);
if (index < MAX_TSM_TRANSACTIONS) if (index < MAX_TSM_TRANSACTIONS) {
{
TSM_List[index].state = TSM_STATE_IDLE; TSM_List[index].state = TSM_STATE_IDLE;
TSM_List[index].InvokeID = 0; TSM_List[index].InvokeID = 0;
} }
@@ -303,7 +271,7 @@ bool I_Am_Request = true;
void testTSM(Test * pTest) void testTSM(Test * pTest)
{ {
/* FIXME: add some unit testing...*/ /* FIXME: add some unit testing... */
return; return;
} }
@@ -327,4 +295,3 @@ int main(void)
} }
#endif /* TEST_TSM */ #endif /* TEST_TSM */
#endif /* TEST */ #endif /* TEST */
+12 -22
View File
@@ -42,8 +42,7 @@
/* note: TSM functionality is optional - only needed if we are /* note: TSM functionality is optional - only needed if we are
doing client requests */ doing client requests */
#if TSM_ENABLED #if TSM_ENABLED
typedef enum typedef enum {
{
TSM_STATE_IDLE, TSM_STATE_IDLE,
TSM_STATE_AWAIT_CONFIRMATION, TSM_STATE_AWAIT_CONFIRMATION,
TSM_STATE_AWAIT_RESPONSE, TSM_STATE_AWAIT_RESPONSE,
@@ -54,8 +53,7 @@ typedef enum
// 5.4.1 Variables And Parameters // 5.4.1 Variables And Parameters
// The following variables are defined for each instance of // The following variables are defined for each instance of
// Transaction State Machine: // Transaction State Machine:
typedef struct BACnet_TSM_Data typedef struct BACnet_TSM_Data {
{
// used to count APDU retries // used to count APDU retries
uint8_t RetryCount; uint8_t RetryCount;
// used to count segment retries // used to count segment retries
@@ -91,32 +89,25 @@ typedef struct BACnet_TSM_Data
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
bool tsm_transaction_available(void); bool tsm_transaction_available(void);
uint8_t tsm_transaction_idle_count(void); uint8_t tsm_transaction_idle_count(void);
void tsm_timer_milliseconds(uint16_t milliseconds); void tsm_timer_milliseconds(uint16_t milliseconds);
// free the invoke ID when the reply comes back // free the invoke ID when the reply comes back
void tsm_free_invoke_id(uint8_t invokeID); void tsm_free_invoke_id(uint8_t invokeID);
// use these in tandem // use these in tandem
uint8_t tsm_next_free_invokeID(void); uint8_t tsm_next_free_invokeID(void);
// returns the same invoke ID that was given // returns the same invoke ID that was given
void tsm_set_confirmed_unsegmented_transaction( void tsm_set_confirmed_unsegmented_transaction(uint8_t invokeID,
uint8_t invokeID, BACNET_ADDRESS * dest, uint8_t * pdu, uint16_t pdu_len);
BACNET_ADDRESS *dest,
uint8_t *pdu,
uint16_t pdu_len);
// returns true if transaction is found // returns true if transaction is found
bool tsm_get_transaction_pdu( bool tsm_get_transaction_pdu(uint8_t invokeID,
uint8_t invokeID, BACNET_ADDRESS * dest, uint8_t * pdu, uint16_t * pdu_len);
BACNET_ADDRESS *dest,
uint8_t *pdu,
uint16_t *pdu_len);
bool tsm_invoke_id_free(uint8_t invokeID); bool tsm_invoke_id_free(uint8_t invokeID);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
/* define out any functions necessary for compile */ /* define out any functions necessary for compile */
#else #else
@@ -125,4 +116,3 @@ bool tsm_invoke_id_free(uint8_t invokeID);
#endif #endif
#endif #endif
+62 -93
View File
@@ -39,9 +39,7 @@
/* encode service - use -1 for limit for unlimited */ /* encode service - use -1 for limit for unlimited */
int whohas_encode_apdu( int whohas_encode_apdu(uint8_t * apdu, BACNET_WHO_HAS_DATA * data)
uint8_t *apdu,
BACNET_WHO_HAS_DATA *data)
{ {
int len = 0; // length of each encoding int len = 0; // length of each encoding
int apdu_len = 0; // total length of the apdu, return value int apdu_len = 0; // total length of the apdu, return value
@@ -51,32 +49,24 @@ int whohas_encode_apdu(
apdu[1] = SERVICE_UNCONFIRMED_WHO_HAS; // service choice apdu[1] = SERVICE_UNCONFIRMED_WHO_HAS; // service choice
apdu_len = 2; apdu_len = 2;
// optional limits - must be used as a pair // optional limits - must be used as a pair
if ((data->low_limit >= 0) && (data->low_limit <= BACNET_MAX_INSTANCE) && if ((data->low_limit >= 0)
(data->high_limit >= 0) && (data->high_limit <= BACNET_MAX_INSTANCE)) && (data->low_limit <= BACNET_MAX_INSTANCE)
{ && (data->high_limit >= 0)
len = encode_context_unsigned( && (data->high_limit <= BACNET_MAX_INSTANCE)) {
&apdu[apdu_len], len =
0, encode_context_unsigned(&apdu[apdu_len], 0,
data->low_limit); data->low_limit);
apdu_len += len; apdu_len += len;
len = encode_context_unsigned( len = encode_context_unsigned(&apdu[apdu_len],
&apdu[apdu_len], 1, data->high_limit);
1,
data->high_limit);
apdu_len += len; apdu_len += len;
} }
if (data->object_name) if (data->object_name) {
{ len = encode_context_character_string(&apdu[apdu_len],
len = encode_context_character_string( 3, &data->object.name);
&apdu[apdu_len],
3,
&data->object.name);
apdu_len += len; apdu_len += len;
} } else {
else len = encode_context_object_id(&apdu[apdu_len],
{
len = encode_context_object_id(
&apdu[apdu_len],
2, 2,
data->object.identifier.type, data->object.identifier.type,
data->object.identifier.instance); data->object.identifier.instance);
@@ -88,10 +78,8 @@ int whohas_encode_apdu(
} }
// decode the service request only // decode the service request only
int whohas_decode_service_request( int whohas_decode_service_request(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, BACNET_WHO_HAS_DATA * data)
unsigned apdu_len,
BACNET_WHO_HAS_DATA *data)
{ {
int len = 0; int len = 0;
uint8_t tag_number = 0; uint8_t tag_number = 0;
@@ -99,43 +87,46 @@ int whohas_decode_service_request(
uint32_t decoded_value = 0; /* for decoding */ uint32_t decoded_value = 0; /* for decoding */
int decoded_type = 0; /* for decoding */ int decoded_type = 0; /* for decoding */
if (apdu_len && data) if (apdu_len && data) {
{
/* optional limits - must be used as a pair */ /* optional limits - must be used as a pair */
if (decode_is_context_tag(&apdu[len], 0)) if (decode_is_context_tag(&apdu[len], 0)) {
{ len +=
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_unsigned(&apdu[len], len_value, &decoded_value); len += decode_unsigned(&apdu[len], len_value, &decoded_value);
if (decoded_value <= BACNET_MAX_INSTANCE) if (decoded_value <= BACNET_MAX_INSTANCE)
data->low_limit = decoded_value; data->low_limit = decoded_value;
if (!decode_is_context_tag(&apdu[len], 1)) if (!decode_is_context_tag(&apdu[len], 1))
return -1; return -1;
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); len +=
len += decode_unsigned(&apdu[len], decode_tag_number_and_value(&apdu[len], &tag_number,
len_value, &decoded_value); &len_value);
len += decode_unsigned(&apdu[len], len_value, &decoded_value);
if (decoded_value <= BACNET_MAX_INSTANCE) if (decoded_value <= BACNET_MAX_INSTANCE)
data->high_limit = decoded_value; data->high_limit = decoded_value;
} } else {
else
{
data->low_limit = -1; data->low_limit = -1;
data->high_limit = -1; data->high_limit = -1;
} }
/* object id */ /* object id */
if (decode_is_context_tag(&apdu[len], 2)) if (decode_is_context_tag(&apdu[len], 2)) {
{
data->object_name = false; data->object_name = false;
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); len +=
len += decode_object_id(&apdu[len], &decoded_type, decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len +=
decode_object_id(&apdu[len], &decoded_type,
&data->object.identifier.instance); &data->object.identifier.instance);
data->object.identifier.type = decoded_type; data->object.identifier.type = decoded_type;
} }
/* object name */ /* object name */
else if (decode_is_context_tag(&apdu[len], 3)) else if (decode_is_context_tag(&apdu[len], 3)) {
{
data->object_name = true; data->object_name = true;
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); len +=
len += decode_character_string(&apdu[len], len_value, decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len +=
decode_character_string(&apdu[len], len_value,
&data->object.name); &data->object.name);
} }
/* missing required parameters */ /* missing required parameters */
@@ -146,10 +137,8 @@ int whohas_decode_service_request(
return len; return len;
} }
int whohas_decode_apdu( int whohas_decode_apdu(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, BACNET_WHO_HAS_DATA * data)
unsigned apdu_len,
BACNET_WHO_HAS_DATA *data)
{ {
int len = 0; int len = 0;
@@ -161,12 +150,8 @@ int whohas_decode_apdu(
if (apdu[1] != SERVICE_UNCONFIRMED_WHO_IS) if (apdu[1] != SERVICE_UNCONFIRMED_WHO_IS)
return -1; return -1;
// optional limits - must be used as a pair // optional limits - must be used as a pair
if (apdu_len > 2) if (apdu_len > 2) {
{ len = whohas_decode_service_request(&apdu[2], apdu_len - 2, data);
len = whohas_decode_service_request(
&apdu[2],
apdu_len - 2,
data);
} }
return len; return len;
@@ -177,40 +162,33 @@ int whohas_decode_apdu(
#include <string.h> #include <string.h>
#include "ctest.h" #include "ctest.h"
void testWhoHasData(Test * pTest, BACNET_WHO_HAS_DATA *data) void testWhoHasData(Test * pTest, BACNET_WHO_HAS_DATA * data)
{ {
uint8_t apdu[480] = {0}; uint8_t apdu[480] = { 0 };
int len = 0; int len = 0;
int apdu_len = 0; int apdu_len = 0;
BACNET_WHO_HAS_DATA test_data; BACNET_WHO_HAS_DATA test_data;
len = whohas_encode_apdu( len = whohas_encode_apdu(&apdu[0], data);
&apdu[0],
data);
ct_test(pTest, len != 0); ct_test(pTest, len != 0);
apdu_len = len; apdu_len = len;
len = whohas_decode_apdu( len = whohas_decode_apdu(&apdu[0], apdu_len, &test_data);
&apdu[0],
apdu_len,
&test_data);
ct_test(pTest, len != -1); ct_test(pTest, len != -1);
ct_test(pTest, test_data.low_limit == data->low_limit); ct_test(pTest, test_data.low_limit == data->low_limit);
ct_test(pTest, test_data.high_limit == data->high_limit); ct_test(pTest, test_data.high_limit == data->high_limit);
ct_test(pTest, test_data.object_name == data->object_name); ct_test(pTest, test_data.object_name == data->object_name);
/* Object ID */ /* Object ID */
if (data->object_name == false) if (data->object_name == false) {
{
ct_test(pTest, test_data.object.identifier.type == ct_test(pTest, test_data.object.identifier.type ==
data->object.identifier.type); data->object.identifier.type);
ct_test(pTest, test_data.object.identifier.instance == ct_test(pTest, test_data.object.identifier.instance ==
data->object.identifier.instance); data->object.identifier.instance);
} }
/* Object Name */ /* Object Name */
else else {
{ ct_test(pTest, characterstring_same(&test_data.object.name,
ct_test(pTest, characterstring_same( &data->object.name));
&test_data.object.name,&data->object.name));
} }
} }
@@ -223,36 +201,27 @@ void testWhoHas(Test * pTest)
data.object_name = false; data.object_name = false;
data.object.identifier.type = OBJECT_ANALOG_INPUT; data.object.identifier.type = OBJECT_ANALOG_INPUT;
data.object.identifier.instance = 1; data.object.identifier.instance = 1;
testWhoHasData(pTest,&data); testWhoHasData(pTest, &data);
for ( for (data.low_limit = 0;
data.low_limit = 0;
data.low_limit <= BACNET_MAX_INSTANCE; data.low_limit <= BACNET_MAX_INSTANCE;
data.low_limit += (BACNET_MAX_INSTANCE/4)) data.low_limit += (BACNET_MAX_INSTANCE / 4)) {
{ for (data.high_limit = 0;
for (
data.high_limit = 0;
data.high_limit <= BACNET_MAX_INSTANCE; data.high_limit <= BACNET_MAX_INSTANCE;
data.high_limit += (BACNET_MAX_INSTANCE/4)) data.high_limit += (BACNET_MAX_INSTANCE / 4)) {
{
data.object_name = false; data.object_name = false;
for ( for (data.object.identifier.type = OBJECT_ANALOG_INPUT;
data.object.identifier.type = OBJECT_ANALOG_INPUT;
data.object.identifier.type <= MAX_BACNET_OBJECT_TYPE; data.object.identifier.type <= MAX_BACNET_OBJECT_TYPE;
data.object.identifier.type++) data.object.identifier.type++) {
{ for (data.object.identifier.instance = 1;
for (
data.object.identifier.instance = 1;
data.object.identifier.instance <= BACNET_MAX_INSTANCE; data.object.identifier.instance <= BACNET_MAX_INSTANCE;
data.object.identifier.instance <<= 1) data.object.identifier.instance <<= 1) {
{ testWhoHasData(pTest, &data);
testWhoHasData(pTest,&data);
} }
} }
data.object_name = true; data.object_name = true;
characterstring_init_ansi( characterstring_init_ansi(&data.object.name, "patricia");
&data.object.name,"patricia"); testWhoHasData(pTest, &data);
testWhoHasData(pTest,&data);
} }
} }
} }
+8 -18
View File
@@ -38,13 +38,11 @@
#include <stdbool.h> #include <stdbool.h>
#include "bacstr.h" #include "bacstr.h"
typedef struct BACnet_Who_Has_Data typedef struct BACnet_Who_Has_Data {
{
int32_t low_limit; /* deviceInstanceRange */ int32_t low_limit; /* deviceInstanceRange */
int32_t high_limit; int32_t high_limit;
bool object_name; /* true if a string */ bool object_name; /* true if a string */
union union {
{
BACNET_OBJECT_ID identifier; BACNET_OBJECT_ID identifier;
BACNET_CHARACTER_STRING name; BACNET_CHARACTER_STRING name;
} object; } object;
@@ -55,28 +53,20 @@ extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
// encode service - use -1 for limit if you want unlimited // encode service - use -1 for limit if you want unlimited
int whohas_encode_apdu( int whohas_encode_apdu(uint8_t * apdu, BACNET_WHO_HAS_DATA * data);
uint8_t *apdu,
BACNET_WHO_HAS_DATA *data);
int whohas_decode_service_request( int whohas_decode_service_request(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, BACNET_WHO_HAS_DATA * data);
unsigned apdu_len,
BACNET_WHO_HAS_DATA *data);
int whohas_decode_apdu( int whohas_decode_apdu(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, BACNET_WHO_HAS_DATA * data);
unsigned apdu_len,
BACNET_WHO_HAS_DATA *data);
#ifdef TEST #ifdef TEST
#include "ctest.h" #include "ctest.h"
void testWhoHas(Test * pTest); void testWhoHas(Test * pTest);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+33 -68
View File
@@ -37,10 +37,8 @@
#include "bacdef.h" #include "bacdef.h"
// encode I-Am service - use -1 for limit if you want unlimited // encode I-Am service - use -1 for limit if you want unlimited
int whois_encode_apdu( int whois_encode_apdu(uint8_t * apdu,
uint8_t *apdu, int32_t low_limit, int32_t high_limit)
int32_t low_limit,
int32_t high_limit)
{ {
int len = 0; // length of each encoding int len = 0; // length of each encoding
int apdu_len = 0; // total length of the apdu, return value int apdu_len = 0; // total length of the apdu, return value
@@ -51,17 +49,10 @@ int whois_encode_apdu(
apdu_len = 2; apdu_len = 2;
// optional limits - must be used as a pair // optional limits - must be used as a pair
if ((low_limit >= 0) && (low_limit <= BACNET_MAX_INSTANCE) && if ((low_limit >= 0) && (low_limit <= BACNET_MAX_INSTANCE) &&
(high_limit >= 0) && (high_limit <= BACNET_MAX_INSTANCE)) (high_limit >= 0) && (high_limit <= BACNET_MAX_INSTANCE)) {
{ len = encode_context_unsigned(&apdu[apdu_len], 0, low_limit);
len = encode_context_unsigned(
&apdu[apdu_len],
0,
low_limit);
apdu_len += len; apdu_len += len;
len = encode_context_unsigned( len = encode_context_unsigned(&apdu[apdu_len], 1, high_limit);
&apdu[apdu_len],
1,
high_limit);
apdu_len += len; apdu_len += len;
} }
} }
@@ -70,11 +61,8 @@ int whois_encode_apdu(
} }
// decode the service request only // decode the service request only
int whois_decode_service_request( int whois_decode_service_request(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, int32_t * pLow_limit, int32_t * pHigh_limit)
unsigned apdu_len,
int32_t *pLow_limit,
int32_t *pHigh_limit)
{ {
int len = 0; int len = 0;
uint8_t tag_number = 0; uint8_t tag_number = 0;
@@ -82,24 +70,24 @@ int whois_decode_service_request(
uint32_t decoded_value = 0; uint32_t decoded_value = 0;
// optional limits - must be used as a pair // optional limits - must be used as a pair
if (apdu_len) if (apdu_len) {
{ len +=
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
if (tag_number != 0) if (tag_number != 0)
return -1; return -1;
len += decode_unsigned(&apdu[len], len_value, &decoded_value); len += decode_unsigned(&apdu[len], len_value, &decoded_value);
if (decoded_value <= BACNET_MAX_INSTANCE) if (decoded_value <= BACNET_MAX_INSTANCE) {
{
if (pLow_limit) if (pLow_limit)
*pLow_limit = decoded_value; *pLow_limit = decoded_value;
} }
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
if (tag_number != 1) if (tag_number != 1)
return -1; return -1;
len += decode_unsigned(&apdu[len], len += decode_unsigned(&apdu[len], len_value, &decoded_value);
len_value, &decoded_value); if (decoded_value <= BACNET_MAX_INSTANCE) {
if (decoded_value <= BACNET_MAX_INSTANCE)
{
if (pHigh_limit) if (pHigh_limit)
*pHigh_limit = decoded_value; *pHigh_limit = decoded_value;
} }
@@ -108,11 +96,8 @@ int whois_decode_service_request(
return len; return len;
} }
int whois_decode_apdu( int whois_decode_apdu(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, int32_t * pLow_limit, int32_t * pHigh_limit)
unsigned apdu_len,
int32_t *pLow_limit,
int32_t *pHigh_limit)
{ {
int len = 0; int len = 0;
@@ -124,13 +109,9 @@ int whois_decode_apdu(
if (apdu[1] != SERVICE_UNCONFIRMED_WHO_IS) if (apdu[1] != SERVICE_UNCONFIRMED_WHO_IS)
return -1; return -1;
// optional limits - must be used as a pair // optional limits - must be used as a pair
if (apdu_len > 2) if (apdu_len > 2) {
{ len = whois_decode_service_request(&apdu[2],
len = whois_decode_service_request( apdu_len - 2, pLow_limit, pHigh_limit);
&apdu[2],
apdu_len - 2,
pLow_limit,
pHigh_limit);
} }
return len; return len;
@@ -143,7 +124,7 @@ int whois_decode_apdu(
void testWhoIs(Test * pTest) void testWhoIs(Test * pTest)
{ {
uint8_t apdu[480] = {0}; uint8_t apdu[480] = { 0 };
int len = 0; int len = 0;
int apdu_len = 0; int apdu_len = 0;
int32_t low_limit = -1; int32_t low_limit = -1;
@@ -151,43 +132,27 @@ void testWhoIs(Test * pTest)
int32_t test_low_limit = -1; int32_t test_low_limit = -1;
int32_t test_high_limit = -1; int32_t test_high_limit = -1;
len = whois_encode_apdu( len = whois_encode_apdu(&apdu[0], low_limit, high_limit);
&apdu[0],
low_limit,
high_limit);
ct_test(pTest, len != 0); ct_test(pTest, len != 0);
apdu_len = len; apdu_len = len;
len = whois_decode_apdu( len = whois_decode_apdu(&apdu[0],
&apdu[0], apdu_len, &test_low_limit, &test_high_limit);
apdu_len,
&test_low_limit,
&test_high_limit);
ct_test(pTest, len != -1); ct_test(pTest, len != -1);
ct_test(pTest, test_low_limit == low_limit); ct_test(pTest, test_low_limit == low_limit);
ct_test(pTest, test_high_limit == high_limit); ct_test(pTest, test_high_limit == high_limit);
for ( for (low_limit = 0;
low_limit = 0;
low_limit <= BACNET_MAX_INSTANCE; low_limit <= BACNET_MAX_INSTANCE;
low_limit += (BACNET_MAX_INSTANCE/4)) low_limit += (BACNET_MAX_INSTANCE / 4)) {
{ for (high_limit = 0;
for (
high_limit = 0;
high_limit <= BACNET_MAX_INSTANCE; high_limit <= BACNET_MAX_INSTANCE;
high_limit += (BACNET_MAX_INSTANCE/4)) high_limit += (BACNET_MAX_INSTANCE / 4)) {
{ len = whois_encode_apdu(&apdu[0], low_limit, high_limit);
len = whois_encode_apdu(
&apdu[0],
low_limit,
high_limit);
apdu_len = len; apdu_len = len;
ct_test(pTest, len != 0); ct_test(pTest, len != 0);
len = whois_decode_apdu( len = whois_decode_apdu(&apdu[0],
&apdu[0], apdu_len, &test_low_limit, &test_high_limit);
apdu_len,
&test_low_limit,
&test_high_limit);
ct_test(pTest, len != -1); ct_test(pTest, len != -1);
ct_test(pTest, test_low_limit == low_limit); ct_test(pTest, test_low_limit == low_limit);
ct_test(pTest, test_high_limit == high_limit); ct_test(pTest, test_high_limit == high_limit);
+7 -17
View File
@@ -42,30 +42,20 @@ extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
// encode service - use -1 for limit if you want unlimited // encode service - use -1 for limit if you want unlimited
int whois_encode_apdu( int whois_encode_apdu(uint8_t * apdu,
uint8_t *apdu, int32_t low_limit, int32_t high_limit);
int32_t low_limit,
int32_t high_limit);
int whois_decode_service_request( int whois_decode_service_request(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, int32_t * pLow_limit, int32_t * pHigh_limit);
unsigned apdu_len,
int32_t *pLow_limit,
int32_t *pHigh_limit);
int whois_decode_apdu( int whois_decode_apdu(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, int32_t * pLow_limit, int32_t * pHigh_limit);
unsigned apdu_len,
int32_t *pLow_limit,
int32_t *pHigh_limit);
#ifdef TEST #ifdef TEST
void testWhoIs(Test * pTest); void testWhoIs(Test * pTest);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif
+36 -61
View File
@@ -39,17 +39,15 @@
#include "wp.h" #include "wp.h"
// encode service // encode service
int wp_encode_apdu( int wp_encode_apdu(uint8_t * apdu,
uint8_t *apdu, uint8_t invoke_id, BACNET_WRITE_PROPERTY_DATA * data)
uint8_t invoke_id,
BACNET_WRITE_PROPERTY_DATA *data)
{ {
int apdu_len = 0; // total length of the apdu, return value int apdu_len = 0; // total length of the apdu, return value
if (apdu) if (apdu) {
{
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST; apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
apdu[1] = encode_max_segs_max_apdu(0, Device_Max_APDU_Length_Accepted()); apdu[1] =
encode_max_segs_max_apdu(0, Device_Max_APDU_Length_Accepted());
apdu[2] = invoke_id; apdu[2] = invoke_id;
apdu[3] = SERVICE_CONFIRMED_WRITE_PROPERTY; // service choice apdu[3] = SERVICE_CONFIRMED_WRITE_PROPERTY; // service choice
apdu_len = 4; apdu_len = 4;
@@ -63,7 +61,8 @@ int wp_encode_apdu(
data->array_index); data->array_index);
// propertyValue // propertyValue
apdu_len += encode_opening_tag(&apdu[apdu_len], 3); apdu_len += encode_opening_tag(&apdu[apdu_len], 3);
apdu_len += bacapp_encode_application_data(&apdu[apdu_len], &data->value); apdu_len +=
bacapp_encode_application_data(&apdu[apdu_len], &data->value);
apdu_len += encode_closing_tag(&apdu[apdu_len], 3); apdu_len += encode_closing_tag(&apdu[apdu_len], 3);
// optional priority - 0 if not set, 1..16 if set // optional priority - 0 if not set, 1..16 if set
if (data->priority != BACNET_NO_PRIORITY) if (data->priority != BACNET_NO_PRIORITY)
@@ -77,10 +76,8 @@ int wp_encode_apdu(
/* decode the service request only */ /* decode the service request only */
/* FIXME: there could be various error messages returned /* FIXME: there could be various error messages returned
using unique values less than zero */ using unique values less than zero */
int wp_decode_service_request( int wp_decode_service_request(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, BACNET_WRITE_PROPERTY_DATA * data)
unsigned apdu_len,
BACNET_WRITE_PROPERTY_DATA *data)
{ {
int len = 0; int len = 0;
int tag_len = 0; int tag_len = 0;
@@ -91,8 +88,7 @@ int wp_decode_service_request(
uint32_t unsigned_value = 0; uint32_t unsigned_value = 0;
// check for value pointers // check for value pointers
if (apdu_len && data) if (apdu_len && data) {
{
// Tag 0: Object ID // Tag 0: Object ID
if (!decode_is_context_tag(&apdu[len++], 0)) if (!decode_is_context_tag(&apdu[len++], 0))
return -1; return -1;
@@ -109,24 +105,20 @@ int wp_decode_service_request(
// note: decode without incrementing len so we can check for opening tag // note: decode without incrementing len so we can check for opening tag
tag_len = decode_tag_number_and_value(&apdu[len], tag_len = decode_tag_number_and_value(&apdu[len],
&tag_number, &len_value_type); &tag_number, &len_value_type);
if (tag_number == 2) if (tag_number == 2) {
{
len += tag_len; len += tag_len;
len += decode_unsigned(&apdu[len], len_value_type, len += decode_unsigned(&apdu[len], len_value_type,
&unsigned_value); &unsigned_value);
data->array_index = unsigned_value; data->array_index = unsigned_value;
} } else
else
data->array_index = BACNET_ARRAY_ALL; data->array_index = BACNET_ARRAY_ALL;
// Tag 3: opening context tag */ // Tag 3: opening context tag */
if (!decode_is_opening_tag_number(&apdu[len], 3)) if (!decode_is_opening_tag_number(&apdu[len], 3))
return -1; return -1;
// a tag number of 3 is not extended so only one octet // a tag number of 3 is not extended so only one octet
len++; len++;
len += bacapp_decode_application_data( len += bacapp_decode_application_data(&apdu[len],
&apdu[len], apdu_len - len, &data->value);
apdu_len - len,
&data->value);
/* FIXME: check the return value; abort if no valid data? */ /* FIXME: check the return value; abort if no valid data? */
/* FIXME: there might be more than one data element in here! */ /* FIXME: there might be more than one data element in here! */
if (!decode_is_closing_tag_number(&apdu[len], 3)) if (!decode_is_closing_tag_number(&apdu[len], 3))
@@ -135,20 +127,18 @@ int wp_decode_service_request(
len++; len++;
// Tag 4: optional Priority - assumed MAX if not explicitly set // Tag 4: optional Priority - assumed MAX if not explicitly set
data->priority = BACNET_MAX_PRIORITY; data->priority = BACNET_MAX_PRIORITY;
if ((unsigned)len < apdu_len) if ((unsigned) len < apdu_len) {
{
tag_len = decode_tag_number_and_value(&apdu[len], tag_len = decode_tag_number_and_value(&apdu[len],
&tag_number, &len_value_type); &tag_number, &len_value_type);
if (tag_number == 4) if (tag_number == 4) {
{
len += tag_len; len += tag_len;
len = decode_unsigned(&apdu[len], len_value_type, &unsigned_value); len =
if ((unsigned_value >= BACNET_MIN_PRIORITY) && decode_unsigned(&apdu[len], len_value_type,
(unsigned_value <= BACNET_MAX_PRIORITY)) &unsigned_value);
{ if ((unsigned_value >= BACNET_MIN_PRIORITY)
data->priority = (uint8_t)unsigned_value; && (unsigned_value <= BACNET_MAX_PRIORITY)) {
} data->priority = (uint8_t) unsigned_value;
else } else
return -1; return -1;
} }
} }
@@ -157,11 +147,9 @@ int wp_decode_service_request(
return len; return len;
} }
int wp_decode_apdu( int wp_decode_apdu(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
uint8_t *invoke_id, uint8_t * invoke_id, BACNET_WRITE_PROPERTY_DATA * data)
BACNET_WRITE_PROPERTY_DATA *data)
{ {
int len = 0; int len = 0;
unsigned offset = 0; unsigned offset = 0;
@@ -177,12 +165,9 @@ int wp_decode_apdu(
return -1; return -1;
offset = 4; offset = 4;
if (apdu_len > offset) if (apdu_len > offset) {
{ len = wp_decode_service_request(&apdu[offset],
len = wp_decode_service_request( apdu_len - offset, data);
&apdu[offset],
apdu_len - offset,
data);
} }
return len; return len;
@@ -197,36 +182,27 @@ int wp_decode_apdu(
#include <string.h> #include <string.h>
#include "ctest.h" #include "ctest.h"
void testWritePropertyTag(Test * pTest, void testWritePropertyTag(Test * pTest, BACNET_WRITE_PROPERTY_DATA * data)
BACNET_WRITE_PROPERTY_DATA *data)
{ {
BACNET_WRITE_PROPERTY_DATA test_data = {0}; BACNET_WRITE_PROPERTY_DATA test_data = { 0 };
uint8_t apdu[480] = {0}; uint8_t apdu[480] = { 0 };
int len = 0; int len = 0;
int apdu_len = 0; int apdu_len = 0;
uint8_t invoke_id = 128; uint8_t invoke_id = 128;
uint8_t test_invoke_id = 0; uint8_t test_invoke_id = 0;
len = wp_encode_apdu( len = wp_encode_apdu(&apdu[0], invoke_id, data);
&apdu[0],
invoke_id,
data);
ct_test(pTest, len != 0); ct_test(pTest, len != 0);
apdu_len = len; apdu_len = len;
len = wp_decode_apdu( len = wp_decode_apdu(&apdu[0], apdu_len, &test_invoke_id, &test_data);
&apdu[0],
apdu_len,
&test_invoke_id,
&test_data);
ct_test(pTest, len != -1); ct_test(pTest, len != -1);
ct_test(pTest, test_data.object_type == data->object_type); ct_test(pTest, test_data.object_type == data->object_type);
ct_test(pTest, test_data.object_instance == data->object_instance); ct_test(pTest, test_data.object_instance == data->object_instance);
ct_test(pTest, test_data.object_property == data->object_property); ct_test(pTest, test_data.object_property == data->object_property);
ct_test(pTest, test_data.array_index == data->array_index); ct_test(pTest, test_data.array_index == data->array_index);
ct_test(pTest, test_data.value.tag == data->value.tag); ct_test(pTest, test_data.value.tag == data->value.tag);
switch (test_data.value.tag) switch (test_data.value.tag) {
{
case BACNET_APPLICATION_TAG_NULL: case BACNET_APPLICATION_TAG_NULL:
break; break;
case BACNET_APPLICATION_TAG_BOOLEAN: case BACNET_APPLICATION_TAG_BOOLEAN:
@@ -242,8 +218,7 @@ void testWritePropertyTag(Test * pTest,
data->value.type.Signed_Int); data->value.type.Signed_Int);
break; break;
case BACNET_APPLICATION_TAG_REAL: case BACNET_APPLICATION_TAG_REAL:
ct_test(pTest, test_data.value.type.Real == ct_test(pTest, test_data.value.type.Real == data->value.type.Real);
data->value.type.Real);
break; break;
case BACNET_APPLICATION_TAG_ENUMERATED: case BACNET_APPLICATION_TAG_ENUMERATED:
ct_test(pTest, test_data.value.type.Enumerated == ct_test(pTest, test_data.value.type.Enumerated ==
@@ -282,7 +257,7 @@ void testWritePropertyTag(Test * pTest,
void testWriteProperty(Test * pTest) void testWriteProperty(Test * pTest)
{ {
BACNET_WRITE_PROPERTY_DATA data = {0}; BACNET_WRITE_PROPERTY_DATA data = { 0 };
data.value.tag = BACNET_APPLICATION_TAG_NULL; data.value.tag = BACNET_APPLICATION_TAG_NULL;
testWritePropertyTag(pTest, &data); testWritePropertyTag(pTest, &data);
+9 -18
View File
@@ -39,8 +39,7 @@
#include "bacdcode.h" #include "bacdcode.h"
#include "bacapp.h" #include "bacapp.h"
typedef struct BACnet_Write_Property_Data typedef struct BACnet_Write_Property_Data {
{
BACNET_OBJECT_TYPE object_type; BACNET_OBJECT_TYPE object_type;
uint32_t object_instance; uint32_t object_instance;
BACNET_PROPERTY_ID object_property; BACNET_PROPERTY_ID object_property;
@@ -54,34 +53,26 @@ extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
// encode service // encode service
int wp_encode_apdu( int wp_encode_apdu(uint8_t * apdu,
uint8_t *apdu, uint8_t invoke_id, BACNET_WRITE_PROPERTY_DATA * data);
uint8_t invoke_id,
BACNET_WRITE_PROPERTY_DATA *data);
// decode the service request only // decode the service request only
int wp_decode_service_request( int wp_decode_service_request(uint8_t * apdu,
uint8_t *apdu, unsigned apdu_len, BACNET_WRITE_PROPERTY_DATA * data);
unsigned apdu_len,
BACNET_WRITE_PROPERTY_DATA *data);
int wp_decode_apdu( int wp_decode_apdu(uint8_t * apdu,
uint8_t *apdu,
unsigned apdu_len, unsigned apdu_len,
uint8_t *invoke_id, uint8_t * invoke_id, BACNET_WRITE_PROPERTY_DATA * data);
BACNET_WRITE_PROPERTY_DATA *data);
#ifdef TEST #ifdef TEST
#include "ctest.h" #include "ctest.h"
void test_ReadProperty(Test * pTest); void test_ReadProperty(Test * pTest);
void test_ReadPropertyAck(Test * pTest); void test_ReadPropertyAck(Test * pTest);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif #endif