ran the indent program on the source files to make them consistent.
This commit is contained in:
+26
-70
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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);
|
||||||
|
|||||||
+6
-16
@@ -41,22 +41,14 @@
|
|||||||
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"
|
||||||
@@ -66,6 +58,4 @@ void testAbort(Test * pTest);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+50
-106
@@ -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,20 +118,16 @@ 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;
|
||||||
@@ -153,12 +135,9 @@ void address_add(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 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;
|
||||||
@@ -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,20 +188,16 @@ 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;
|
||||||
@@ -238,12 +205,9 @@ void address_add_binding(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 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;
|
||||||
@@ -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,20 +311,15 @@ 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));
|
||||||
@@ -389,8 +334,7 @@ void testAddress(Test * pTest)
|
|||||||
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,
|
||||||
|
|||||||
+13
-30
@@ -45,47 +45,30 @@ extern "C" {
|
|||||||
|
|
||||||
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
|
||||||
|
|||||||
+75
-123
@@ -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:
|
||||||
@@ -227,12 +214,10 @@ void apdu_set_confirmed_simple_ack_handler(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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:
|
||||||
@@ -259,11 +244,9 @@ void apdu_set_confirmed_ack_handler(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,10 +294,8 @@ 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 };
|
||||||
@@ -335,39 +312,30 @@ void apdu_handler(
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+35
-60
@@ -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;
|
||||||
@@ -55,8 +54,7 @@ typedef struct _confirmed_service_data
|
|||||||
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;
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -53,33 +53,28 @@ 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
|
||||||
|
|||||||
+61
-118
@@ -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;
|
||||||
@@ -377,28 +342,19 @@ void testAtomicReadFileAckAccess(Test * pTest,
|
|||||||
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,8 +362,7 @@ 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);
|
||||||
}
|
}
|
||||||
@@ -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,8 +385,7 @@ 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;
|
||||||
@@ -448,31 +401,21 @@ void testAtomicReadFileAccess(Test * pTest,
|
|||||||
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 ==
|
||||||
|
|||||||
+16
-34
@@ -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,42 +64,30 @@ 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"
|
||||||
@@ -115,6 +99,4 @@ void test_AtomicReadFileAck(Test * pTest);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+56
-113
@@ -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;
|
||||||
@@ -319,29 +285,19 @@ void testAtomicWriteFileAccess(Test * pTest,
|
|||||||
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,8 +305,7 @@ 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);
|
||||||
}
|
}
|
||||||
@@ -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,8 +329,7 @@ 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;
|
||||||
@@ -392,27 +345,17 @@ void testAtomicWriteFileAckAccess(Test * pTest,
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-34
@@ -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,41 +60,29 @@ 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"
|
||||||
@@ -110,6 +94,4 @@ void test_AtomicWriteFileAck(Test * pTest);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+152
-244
@@ -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;
|
||||||
@@ -121,28 +113,22 @@ int bacapp_decode_application_data(
|
|||||||
|
|
||||||
/* 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
|
||||||
@@ -151,41 +137,33 @@ int bacapp_decode_application_data(
|
|||||||
#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,9 +237,9 @@ 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 */
|
||||||
@@ -271,11 +247,9 @@ bool bacapp_compare(
|
|||||||
/* 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:
|
||||||
@@ -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,20 +318,16 @@ 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;
|
||||||
@@ -375,8 +347,7 @@ bool bacapp_print_value(
|
|||||||
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));
|
||||||
@@ -391,7 +362,8 @@ bool bacapp_print_value(
|
|||||||
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",
|
||||||
@@ -432,18 +404,17 @@ bool bacapp_print_value(
|
|||||||
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 =
|
||||||
|
characterstring_value(&value->type.Character_String);
|
||||||
fprintf(stream, "\"");
|
fprintf(stream, "\"");
|
||||||
for (i = 0; i < len; i++)
|
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
|
||||||
@@ -455,10 +426,10 @@ bool bacapp_print_value(
|
|||||||
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,i)?"true":"false");
|
bitstring_bit(&value->type.Bit_String,
|
||||||
|
i) ? "true" : "false");
|
||||||
if (i < len - 1)
|
if (i < len - 1)
|
||||||
fprintf(stream, ",");
|
fprintf(stream, ",");
|
||||||
}
|
}
|
||||||
@@ -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(
|
|
||||||
&value->type.Character_String,
|
|
||||||
(char *) argv);
|
(char *) argv);
|
||||||
}
|
} else if (tag_number == BACNET_APPLICATION_TAG_OCTET_STRING) {
|
||||||
else if (tag_number == BACNET_APPLICATION_TAG_OCTET_STRING)
|
status = octetstring_init(&value->type.Octet_String,
|
||||||
{
|
(uint8_t *) argv, strlen(argv));
|
||||||
status = octetstring_init(
|
} else if (tag_number == BACNET_APPLICATION_TAG_ENUMERATED) {
|
||||||
&value->type.Octet_String,
|
|
||||||
(uint8_t *)argv,
|
|
||||||
strlen(argv));
|
|
||||||
}
|
|
||||||
else if (tag_number == BACNET_APPLICATION_TAG_ENUMERATED)
|
|
||||||
{
|
|
||||||
unsigned_long_value = strtoul(argv, NULL, 0);
|
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);
|
count = sscanf(argv, "%d:%d", &object_type, &instance);
|
||||||
if (count == 2)
|
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,7 +530,8 @@ 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;
|
||||||
@@ -596,10 +539,7 @@ static bool testBACnetApplicationDataValue(BACNET_APPLICATION_DATA_VALUE *value)
|
|||||||
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);
|
||||||
}
|
}
|
||||||
@@ -610,137 +550,109 @@ void testBACnetApplicationData(Test * pTest)
|
|||||||
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,
|
|
||||||
&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_BOOLEAN,
|
||||||
BACNET_APPLICATION_TAG_BOOLEAN,
|
"1", &value);
|
||||||
"1",
|
|
||||||
&value);
|
|
||||||
ct_test(pTest, status == true);
|
ct_test(pTest, status == true);
|
||||||
ct_test(pTest, value.type.Boolean == true);
|
ct_test(pTest, value.type.Boolean == true);
|
||||||
ct_test(pTest, testBACnetApplicationDataValue(&value));
|
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",
|
|
||||||
&value);
|
|
||||||
ct_test(pTest, status == true);
|
ct_test(pTest, status == true);
|
||||||
ct_test(pTest, value.type.Boolean == false);
|
ct_test(pTest, value.type.Boolean == false);
|
||||||
ct_test(pTest, testBACnetApplicationDataValue(&value));
|
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 = bacapp_parse_application_data(
|
status =
|
||||||
BACNET_APPLICATION_TAG_UNSIGNED_INT,
|
bacapp_parse_application_data(BACNET_APPLICATION_TAG_UNSIGNED_INT,
|
||||||
"0xFFFF",
|
"0xFFFF", &value);
|
||||||
&value);
|
|
||||||
ct_test(pTest, status == true);
|
ct_test(pTest, status == true);
|
||||||
ct_test(pTest, value.type.Unsigned_Int == 0xFFFF);
|
ct_test(pTest, value.type.Unsigned_Int == 0xFFFF);
|
||||||
ct_test(pTest, testBACnetApplicationDataValue(&value));
|
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,
|
||||||
"0xFFFFFFFF",
|
"0xFFFFFFFF", &value);
|
||||||
&value);
|
|
||||||
ct_test(pTest, status == true);
|
ct_test(pTest, status == true);
|
||||||
ct_test(pTest, value.type.Unsigned_Int == 0xFFFFFFFF);
|
ct_test(pTest, value.type.Unsigned_Int == 0xFFFFFFFF);
|
||||||
ct_test(pTest, testBACnetApplicationDataValue(&value));
|
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 = bacapp_parse_application_data(
|
status =
|
||||||
BACNET_APPLICATION_TAG_SIGNED_INT,
|
bacapp_parse_application_data(BACNET_APPLICATION_TAG_SIGNED_INT,
|
||||||
"-1",
|
"-1", &value);
|
||||||
&value);
|
|
||||||
ct_test(pTest, status == true);
|
ct_test(pTest, status == true);
|
||||||
ct_test(pTest, value.type.Signed_Int == -1);
|
ct_test(pTest, value.type.Signed_Int == -1);
|
||||||
ct_test(pTest, testBACnetApplicationDataValue(&value));
|
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,
|
||||||
"32768",
|
"32768", &value);
|
||||||
&value);
|
|
||||||
ct_test(pTest, status == true);
|
ct_test(pTest, status == true);
|
||||||
ct_test(pTest, value.type.Signed_Int == 32768);
|
ct_test(pTest, value.type.Signed_Int == 32768);
|
||||||
ct_test(pTest, testBACnetApplicationDataValue(&value));
|
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,
|
||||||
"-32768",
|
"-32768", &value);
|
||||||
&value);
|
|
||||||
ct_test(pTest, status == true);
|
ct_test(pTest, status == true);
|
||||||
ct_test(pTest, value.type.Signed_Int == -32768);
|
ct_test(pTest, value.type.Signed_Int == -32768);
|
||||||
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,
|
"0.0", &value);
|
||||||
"0.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,
|
"-1.0", &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,
|
"1.0", &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);
|
||||||
"3.14159",
|
|
||||||
&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);
|
||||||
"-3.14159",
|
|
||||||
&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 =
|
||||||
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 = bacapp_parse_application_data(
|
status =
|
||||||
BACNET_APPLICATION_TAG_ENUMERATED,
|
bacapp_parse_application_data(BACNET_APPLICATION_TAG_ENUMERATED,
|
||||||
"0xFFFF",
|
"0xFFFF", &value);
|
||||||
&value);
|
|
||||||
ct_test(pTest, status == true);
|
ct_test(pTest, status == true);
|
||||||
ct_test(pTest, value.type.Enumerated == 0xFFFF);
|
ct_test(pTest, value.type.Enumerated == 0xFFFF);
|
||||||
ct_test(pTest, testBACnetApplicationDataValue(&value));
|
ct_test(pTest, testBACnetApplicationDataValue(&value));
|
||||||
status = bacapp_parse_application_data(
|
status =
|
||||||
BACNET_APPLICATION_TAG_ENUMERATED,
|
bacapp_parse_application_data(BACNET_APPLICATION_TAG_ENUMERATED,
|
||||||
"0xFFFFFFFF",
|
"0xFFFFFFFF", &value);
|
||||||
&value);
|
|
||||||
ct_test(pTest, status == true);
|
ct_test(pTest, status == true);
|
||||||
ct_test(pTest, value.type.Enumerated == 0xFFFFFFFF);
|
ct_test(pTest, value.type.Enumerated == 0xFFFFFFFF);
|
||||||
ct_test(pTest, testBACnetApplicationDataValue(&value));
|
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",
|
|
||||||
&value);
|
|
||||||
ct_test(pTest, status == true);
|
ct_test(pTest, status == true);
|
||||||
ct_test(pTest, value.type.Date.year == 2005);
|
ct_test(pTest, value.type.Date.year == 2005);
|
||||||
ct_test(pTest, value.type.Date.month == 5);
|
ct_test(pTest, value.type.Date.month == 5);
|
||||||
@@ -748,10 +660,8 @@ void testBACnetApplicationData(Test * pTest)
|
|||||||
ct_test(pTest, value.type.Date.wday == 1);
|
ct_test(pTest, value.type.Date.wday == 1);
|
||||||
ct_test(pTest, testBACnetApplicationDataValue(&value));
|
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",
|
|
||||||
&value);
|
|
||||||
ct_test(pTest, status == true);
|
ct_test(pTest, status == true);
|
||||||
ct_test(pTest, value.type.Time.hour == 23);
|
ct_test(pTest, value.type.Time.hour == 23);
|
||||||
ct_test(pTest, value.type.Time.min == 59);
|
ct_test(pTest, value.type.Time.min == 59);
|
||||||
@@ -759,19 +669,17 @@ void testBACnetApplicationData(Test * pTest)
|
|||||||
ct_test(pTest, value.type.Time.hundredths == 12);
|
ct_test(pTest, value.type.Time.hundredths == 12);
|
||||||
ct_test(pTest, testBACnetApplicationDataValue(&value));
|
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));
|
||||||
|
|
||||||
|
|||||||
+11
-23
@@ -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,30 +63,22 @@ 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,
|
|
||||||
|
int bacapp_encode_application_data(uint8_t * apdu,
|
||||||
BACNET_APPLICATION_DATA_VALUE * value);
|
BACNET_APPLICATION_DATA_VALUE * value);
|
||||||
|
|
||||||
int bacapp_encode_application_data(
|
bool bacapp_copy(BACNET_APPLICATION_DATA_VALUE * dest_value,
|
||||||
uint8_t *apdu,
|
|
||||||
BACNET_APPLICATION_DATA_VALUE *value);
|
|
||||||
|
|
||||||
bool bacapp_copy(
|
|
||||||
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);
|
||||||
|
|
||||||
@@ -100,6 +90,4 @@ void testBACnetApplicationData(Test * pTest);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+106
-105
@@ -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()) {
|
||||||
@@ -212,7 +211,8 @@ 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()) {
|
||||||
@@ -253,7 +254,8 @@ 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()) {
|
||||||
@@ -298,7 +301,8 @@ 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;
|
||||||
@@ -335,7 +340,8 @@ 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()) {
|
||||||
@@ -368,7 +375,8 @@ 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()) {
|
||||||
@@ -409,7 +418,8 @@ 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()) {
|
||||||
@@ -462,7 +473,8 @@ 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];
|
||||||
@@ -512,7 +524,8 @@ int encode_tag(uint8_t * apdu, uint8_t tag_number, bool context_specific,
|
|||||||
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);
|
||||||
@@ -794,16 +807,14 @@ 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,
|
||||||
@@ -826,16 +837,15 @@ 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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -924,10 +934,7 @@ 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;
|
||||||
@@ -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;
|
||||||
@@ -961,11 +966,8 @@ 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;
|
||||||
|
|
||||||
@@ -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;
|
||||||
|
|
||||||
@@ -1000,8 +1000,7 @@ 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);
|
||||||
@@ -1019,9 +1018,9 @@ int encode_tagged_octet_string(uint8_t * apdu,
|
|||||||
{
|
{
|
||||||
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 */
|
||||||
@@ -1073,8 +1072,10 @@ int encode_tagged_character_string(uint8_t * apdu,
|
|||||||
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);
|
||||||
@@ -1090,7 +1091,8 @@ int encode_context_character_string(uint8_t * apdu, int tag_number,
|
|||||||
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 =
|
||||||
|
characterstring_length(char_string) + 1 /* for encoding */ ;
|
||||||
len += encode_tag(&apdu[0], (uint8_t) tag_number, true, string_len);
|
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);
|
||||||
@@ -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
|
||||||
@@ -1621,7 +1622,9 @@ 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 =
|
||||||
|
decode_tag_number_and_value(&array[0], &tag_number,
|
||||||
|
&len_value);
|
||||||
len += decode_enumerated(&array[len], len_value, &decoded_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);
|
||||||
@@ -1664,8 +1667,7 @@ 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));
|
||||||
}
|
}
|
||||||
@@ -1714,16 +1716,14 @@ 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));
|
||||||
@@ -1777,10 +1777,7 @@ 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,
|
|
||||||
NULL,
|
|
||||||
0);
|
|
||||||
ct_test(pTest, status == true);
|
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);
|
||||||
@@ -1793,14 +1790,13 @@ void testBACDCodeOctetString(Test * pTest)
|
|||||||
|
|
||||||
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,
|
|
||||||
test_value,
|
|
||||||
i);
|
|
||||||
ct_test(pTest, status == true);
|
ct_test(pTest, status == true);
|
||||||
apdu_len = encode_tagged_octet_string(&encoded_array[0],&octet_string);
|
apdu_len =
|
||||||
len = decode_tag_number_and_value(&encoded_array[0],
|
encode_tagged_octet_string(&encoded_array[0], &octet_string);
|
||||||
&tag_number, &len_value);
|
len =
|
||||||
|
decode_tag_number_and_value(&encoded_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);
|
||||||
len += decode_octet_string(&encoded_array[len], len_value,
|
len += decode_octet_string(&encoded_array[len], len_value,
|
||||||
&test_octet_string);
|
&test_octet_string);
|
||||||
@@ -1834,16 +1830,14 @@ 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,
|
|
||||||
NULL,
|
|
||||||
0);
|
|
||||||
ct_test(pTest, status == true);
|
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));
|
||||||
@@ -1854,14 +1848,19 @@ void testBACDCodeCharacterString(Test * pTest)
|
|||||||
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);
|
||||||
@@ -1921,10 +1921,8 @@ void testBACDCodeMaxSegsApdu(Test * pTest)
|
|||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-11
@@ -46,8 +46,8 @@ 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
|
||||||
@@ -79,7 +79,8 @@ 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
|
||||||
@@ -91,11 +92,14 @@ 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_bacnet_object_id(uint8_t * apdu, int object_type,
|
||||||
|
uint32_t instance);
|
||||||
int encode_context_object_id(uint8_t * apdu, int tag_number,
|
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
|
||||||
@@ -124,16 +128,19 @@ int decode_character_string(uint8_t * apdu, uint32_t len_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,
|
||||||
|
uint32_t value);
|
||||||
int encode_tagged_unsigned(uint8_t * apdu, 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);
|
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,
|
||||||
|
int32_t value);
|
||||||
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);
|
||||||
|
|
||||||
// from clause 20.2.11 Encoding of an Enumerated Value
|
// from clause 20.2.11 Encoding of an Enumerated Value
|
||||||
@@ -142,7 +149,8 @@ int decode_signed(uint8_t * apdu, uint32_t len_value, int32_t *value);
|
|||||||
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
|
||||||
@@ -191,5 +199,4 @@ int encode_simple_ack(uint8_t * apdu, uint8_t invoke_id,
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
+26
-53
@@ -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,8 +694,7 @@ 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,
|
||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
+46
-107
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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);
|
||||||
|
|||||||
+8
-18
@@ -42,34 +42,26 @@
|
|||||||
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"
|
||||||
@@ -79,6 +71,4 @@ void testBACError(Test * pTest);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+45
-33
@@ -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,
|
||||||
|
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}
|
{-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;
|
||||||
}
|
}
|
||||||
@@ -83,13 +97,11 @@ signed bacprop_tag_by_index_default(
|
|||||||
|
|
||||||
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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
+110
-202
@@ -43,19 +43,18 @@ 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;
|
||||||
@@ -73,8 +72,7 @@ bool bitstring_bit(BACNET_BIT_STRING *bit_string, uint8_t bit)
|
|||||||
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;
|
||||||
@@ -95,8 +93,7 @@ int bitstring_bytes_used(BACNET_BIT_STRING *bit_string)
|
|||||||
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
|
||||||
@@ -111,10 +108,8 @@ 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;
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -360,8 +306,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,8 +318,7 @@ 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;
|
||||||
}
|
}
|
||||||
@@ -386,8 +330,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,8 +342,7 @@ 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;
|
||||||
}
|
}
|
||||||
@@ -504,8 +427,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -517,8 +439,7 @@ 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;
|
||||||
}
|
}
|
||||||
@@ -531,8 +452,7 @@ 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,43 +505,39 @@ 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);
|
||||||
|
ct_test(pTest, status == false);
|
||||||
|
status =
|
||||||
|
characterstring_truncate(&bacnet_string,
|
||||||
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,
|
||||||
ct_test(pTest, status == false);
|
characterstring_capacity(&bacnet_string));
|
||||||
status = 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],
|
|
||||||
test_length);
|
|
||||||
strcat(test_append_string, test_value);
|
strcat(test_append_string, test_value);
|
||||||
strcat(test_append_string, test_append_value);
|
strcat(test_append_string, test_append_value);
|
||||||
test_length = strlen(test_append_string);
|
test_length = strlen(test_append_string);
|
||||||
@@ -632,8 +545,7 @@ void testCharacterString(Test * pTest)
|
|||||||
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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -655,8 +567,7 @@ void testOctetString(Test * pTest)
|
|||||||
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 */
|
||||||
@@ -666,30 +577,28 @@ void testOctetString(Test * pTest)
|
|||||||
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],
|
|
||||||
test_length);
|
|
||||||
strcat((char *) test_append_string, (char *) test_value);
|
strcat((char *) test_append_string, (char *) test_value);
|
||||||
strcat((char *) test_append_string, (char *) test_append_value);
|
strcat((char *) test_append_string, (char *) test_append_value);
|
||||||
test_length = strlen((char *) test_append_string);
|
test_length = strlen((char *) test_append_string);
|
||||||
@@ -697,8 +606,7 @@ void testOctetString(Test * pTest)
|
|||||||
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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-51
@@ -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,8 +57,7 @@ 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];
|
||||||
@@ -71,84 +68,66 @@ 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 value);
|
||||||
bool bitstring_bit(BACNET_BIT_STRING * bit_string, uint8_t bit);
|
bool bitstring_bit(BACNET_BIT_STRING * bit_string, uint8_t bit);
|
||||||
uint8_t bitstring_bits_used(BACNET_BIT_STRING * bit_string);
|
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(
|
bool characterstring_ansi_same(BACNET_CHARACTER_STRING * dest,
|
||||||
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 *
|
||||||
|
char_string);
|
||||||
size_t characterstring_capacity(BACNET_CHARACTER_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);
|
|
||||||
bool octetstring_copy(
|
|
||||||
BACNET_OCTET_STRING *dest,
|
|
||||||
BACNET_OCTET_STRING * src);
|
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);
|
||||||
@@ -159,5 +138,4 @@ size_t octetstring_capacity(BACNET_OCTET_STRING *octet_string);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+1137
-616
File diff suppressed because it is too large
Load Diff
@@ -66,5 +66,4 @@ const char *bactext_segmentation_name(int index);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -26,5 +26,4 @@ int big_endian(void);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+32
-54
@@ -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,22 +150,22 @@ 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
|
||||||
{
|
{
|
||||||
@@ -179,20 +173,18 @@ int bip_send_pdu(
|
|||||||
|
|
||||||
/* 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,8 +196,7 @@ 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
|
||||||
@@ -226,14 +217,11 @@ 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;
|
||||||
}
|
}
|
||||||
@@ -261,20 +249,16 @@ 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 */
|
||||||
@@ -300,12 +284,10 @@ void bip_get_my_address(BACNET_ADDRESS *my_address)
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-7
@@ -55,21 +55,18 @@ bool bip_init(void);
|
|||||||
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
|
||||||
@@ -99,5 +96,4 @@ void bip_set_interface(char *ifname);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -68,4 +68,3 @@
|
|||||||
|
|
||||||
|
|
||||||
#endif // end of header file
|
#endif // end of header file
|
||||||
|
|
||||||
|
|||||||
@@ -48,5 +48,4 @@ uint16_t CRC_Calc_Data(uint8_t dataValue, uint16_t crcValue);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+12
-45
@@ -41,71 +41,41 @@
|
|||||||
// 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,
|
|
||||||
pdu,
|
|
||||||
max_pdu,
|
|
||||||
timeout);
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef BACDL_MSTP
|
#ifdef BACDL_MSTP
|
||||||
return dlmstp_receive(
|
return dlmstp_receive(src, pdu, max_pdu, timeout);
|
||||||
src,
|
|
||||||
pdu,
|
|
||||||
max_pdu,
|
|
||||||
timeout);
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef BACDL_ETHERNET
|
#ifdef BACDL_ETHERNET
|
||||||
return ethernet_receive(
|
return ethernet_receive(src, pdu, max_pdu, timeout);
|
||||||
src,
|
|
||||||
pdu,
|
|
||||||
max_pdu,
|
|
||||||
timeout);
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef BACDL_BIP
|
#ifdef BACDL_BIP
|
||||||
return bip_receive(
|
return bip_receive(src, pdu, max_pdu, timeout);
|
||||||
src,
|
|
||||||
pdu,
|
|
||||||
max_pdu,
|
|
||||||
timeout);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
+38
-69
@@ -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,8 +154,7 @@ 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,
|
||||||
@@ -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,23 +186,22 @@ 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);
|
||||||
|
} else if (password)
|
||||||
characterstring_init_ansi(password, NULL);
|
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,
|
||||||
@@ -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,8 +235,7 @@ 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,
|
||||||
@@ -265,22 +249,15 @@ 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);
|
||||||
@@ -298,21 +275,13 @@ 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;
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-15
@@ -54,28 +54,21 @@ 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);
|
||||||
/* 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,
|
||||||
@@ -90,6 +83,4 @@ void test_DeviceCommunicationControl(Test * pTest);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -50,8 +50,7 @@ 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
|
||||||
{
|
{
|
||||||
@@ -64,8 +63,7 @@ int dlmstp_send_pdu(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
@@ -88,8 +86,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,25 +52,21 @@ 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
|
||||||
|
|||||||
@@ -53,34 +53,29 @@ 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
|
||||||
|
|||||||
@@ -39,8 +39,7 @@ 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, '/');
|
||||||
@@ -100,4 +99,3 @@ int main(void)
|
|||||||
}
|
}
|
||||||
#endif /* TEST_FILENAME */
|
#endif /* TEST_FILENAME */
|
||||||
#endif /* TEST */
|
#endif /* TEST */
|
||||||
|
|
||||||
|
|||||||
@@ -43,5 +43,4 @@ char *filename_remove_path(const char *filename_in);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+40
-72
@@ -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,
|
unsigned *pMax_apdu, int *pSegmentation, uint16_t * pVendor_id)
|
||||||
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,7 +105,9 @@ 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;
|
||||||
@@ -125,7 +118,9 @@ int iam_decode_service_request(
|
|||||||
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;
|
||||||
@@ -139,12 +134,9 @@ int iam_decode_service_request(
|
|||||||
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,
|
unsigned *pMax_apdu, int *pSegmentation, uint16_t * pVendor_id)
|
||||||
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,12 +148,8 @@ 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;
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -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,14 +213,12 @@ 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
|
||||||
{
|
{
|
||||||
@@ -268,10 +238,8 @@ 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;
|
||||||
|
|||||||
+6
-16
@@ -42,26 +42,17 @@
|
|||||||
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,
|
unsigned *pMax_apdu, int *pSegmentation, uint16_t * pVendor_id);
|
||||||
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,
|
unsigned *pMax_apdu, int *pSegmentation, uint16_t * pVendor_id);
|
||||||
int *pSegmentation,
|
|
||||||
uint16_t *pVendor_id);
|
|
||||||
|
|
||||||
int iam_send(uint8_t * buffer);
|
int iam_send(uint8_t * buffer);
|
||||||
|
|
||||||
@@ -73,5 +64,4 @@ void testIAm(Test * pTest);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+41
-71
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -153,51 +137,37 @@ void testIHaveData(Test * pTest, BACNET_I_HAVE_DATA *data)
|
|||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-15
@@ -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,19 +48,13 @@ 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"
|
||||||
@@ -71,6 +64,4 @@ void testIHave(Test * pTest);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+35
-64
@@ -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,10 +86,8 @@ 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;
|
||||||
|
|
||||||
@@ -109,10 +97,8 @@ unsigned indtext_by_string_default(
|
|||||||
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;
|
||||||
|
|
||||||
@@ -122,19 +108,14 @@ unsigned indtext_by_istring_default(
|
|||||||
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;
|
||||||
}
|
}
|
||||||
@@ -145,39 +126,30 @@ 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"},
|
||||||
@@ -207,16 +178,15 @@ 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);
|
||||||
@@ -230,7 +200,8 @@ void testIndexText(Test* pTest)
|
|||||||
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
|
||||||
|
|
||||||
|
|||||||
+15
-32
@@ -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,51 +53,36 @@ 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"
|
||||||
@@ -108,5 +92,4 @@ unsigned indtext_count(
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+1
-2
@@ -49,8 +49,7 @@ int main(void)
|
|||||||
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);
|
||||||
|
|||||||
+220
-338
File diff suppressed because it is too large
Load Diff
+10
-12
@@ -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
|
||||||
|
|||||||
+60
-129
@@ -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_ADDRESS * src, BACNET_NPDU_DATA * npdu_data)
|
||||||
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,11 +135,7 @@ 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 };
|
||||||
@@ -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_ADDRESS * src, BACNET_NPDU_DATA * npdu_data)
|
||||||
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,23 +255,21 @@ 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
|
||||||
{
|
{
|
||||||
@@ -314,22 +277,16 @@ void npdu_handler(
|
|||||||
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;
|
||||||
@@ -360,60 +317,47 @@ void testNPDU2(Test * pTest)
|
|||||||
|
|
||||||
// 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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -437,45 +381,34 @@ void testNPDU1(Test * pTest)
|
|||||||
|
|
||||||
// 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);
|
||||||
@@ -490,10 +423,8 @@ 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;
|
||||||
|
|||||||
+7
-18
@@ -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
|
||||||
@@ -58,32 +57,22 @@ 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_ADDRESS * src, BACNET_NPDU_DATA * npdu_data);
|
||||||
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_ADDRESS * src, BACNET_NPDU_DATA * npdu_data);
|
||||||
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
|
||||||
|
|||||||
+20
-41
@@ -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;
|
||||||
@@ -159,20 +146,12 @@ void test_ReinitializeDevice(Test * pTest)
|
|||||||
|
|
||||||
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);
|
||||||
|
|||||||
+3
-8
@@ -42,21 +42,18 @@ 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,
|
||||||
@@ -70,6 +67,4 @@ void test_ReinitializeDevice(Test * pTest);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+26
-70
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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);
|
||||||
|
|||||||
+6
-16
@@ -41,22 +41,14 @@
|
|||||||
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);
|
||||||
@@ -65,6 +57,4 @@ void testReject(Test * pTest);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+31
-46
@@ -72,8 +72,7 @@ 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
|
||||||
@@ -162,11 +156,11 @@ 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,
|
||||||
|
RING_BUFFER_SIZE);
|
||||||
ct_test(pTest, Ringbuf_Empty(&test_buffer));
|
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);
|
||||||
@@ -174,24 +168,21 @@ void testRingBuf(Test* pTest)
|
|||||||
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);
|
||||||
@@ -199,10 +190,9 @@ void testRingBuf(Test* pTest)
|
|||||||
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);
|
||||||
@@ -211,48 +201,44 @@ void testRingBuf(Test* pTest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -285,4 +271,3 @@ int main(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -59,11 +58,9 @@ extern "C" {
|
|||||||
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
|
||||||
|
|||||||
+44
-96
@@ -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,9 +167,7 @@ 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,
|
|
||||||
int apdu_len, // total length of the apdu
|
|
||||||
BACNET_READ_PROPERTY_DATA * data)
|
BACNET_READ_PROPERTY_DATA * data)
|
||||||
{
|
{
|
||||||
uint8_t tag_number = 0;
|
uint8_t tag_number = 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;
|
||||||
@@ -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);
|
||||||
@@ -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);
|
||||||
|
|||||||
+15
-31
@@ -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,38 +51,25 @@ 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,
|
||||||
|
uint8_t * invoke_id, BACNET_READ_PROPERTY_DATA * data);
|
||||||
|
|
||||||
|
int rp_ack_encode_apdu(uint8_t * apdu,
|
||||||
|
uint8_t invoke_id, BACNET_READ_PROPERTY_DATA * data);
|
||||||
|
|
||||||
|
int rp_ack_decode_service_request(uint8_t * apdu, int apdu_len, // total length of the apdu
|
||||||
BACNET_READ_PROPERTY_DATA * data);
|
BACNET_READ_PROPERTY_DATA * data);
|
||||||
|
|
||||||
int rp_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);
|
||||||
unsigned apdu_len,
|
|
||||||
uint8_t *invoke_id,
|
|
||||||
BACNET_READ_PROPERTY_DATA *data);
|
|
||||||
|
|
||||||
int rp_ack_encode_apdu(
|
|
||||||
uint8_t *apdu,
|
|
||||||
uint8_t invoke_id,
|
|
||||||
BACNET_READ_PROPERTY_DATA *data);
|
|
||||||
|
|
||||||
int rp_ack_decode_service_request(
|
|
||||||
uint8_t *apdu,
|
|
||||||
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
|
||||||
@@ -96,6 +82,4 @@ void test_ReadPropertyAck(Test * pTest);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+128
-259
@@ -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;
|
||||||
@@ -137,14 +122,11 @@ int rpm_decode_object_id(
|
|||||||
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;
|
||||||
@@ -370,14 +321,11 @@ int rpm_ack_decode_object_id(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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;
|
||||||
}
|
}
|
||||||
@@ -385,11 +333,9 @@ int rpm_ack_decode_object_end(
|
|||||||
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);
|
||||||
@@ -412,26 +357,21 @@ int rpm_ack_decode_object_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,
|
|
||||||
int apdu_len, /* total length of the apdu */
|
|
||||||
uint8_t * invoke_id,
|
uint8_t * invoke_id,
|
||||||
uint8_t **service_request,
|
uint8_t ** service_request, unsigned *service_request_len)
|
||||||
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)
|
||||||
@@ -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;
|
||||||
@@ -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,32 +596,22 @@ 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;
|
||||||
@@ -722,21 +621,17 @@ void testReadPropertyMultipleAck(Test * pTest)
|
|||||||
/* 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);
|
||||||
@@ -745,45 +640,34 @@ void testReadPropertyMultipleAck(Test * pTest)
|
|||||||
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);
|
||||||
@@ -792,21 +676,17 @@ void testReadPropertyMultipleAck(Test * pTest)
|
|||||||
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);
|
||||||
@@ -815,11 +695,8 @@ void testReadPropertyMultipleAck(Test * pTest)
|
|||||||
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);
|
||||||
@@ -827,24 +704,17 @@ void testReadPropertyMultipleAck(Test * pTest)
|
|||||||
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 */
|
||||||
|
|
||||||
|
|||||||
+29
-64
@@ -51,94 +51,61 @@ 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 *apdu,
|
|
||||||
int apdu_len, /* total length of the apdu */
|
|
||||||
uint8_t * invoke_id,
|
uint8_t * invoke_id,
|
||||||
uint8_t **service_request,
|
uint8_t ** service_request, unsigned *service_request_len);
|
||||||
unsigned *service_request_len);
|
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
@@ -149,6 +116,4 @@ void testReadPropertyMultipleAck(Test * pTest);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -45,18 +45,15 @@ extern "C" {
|
|||||||
|
|
||||||
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
|
||||||
|
|||||||
+18
-29
@@ -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;
|
||||||
@@ -77,21 +75,17 @@ 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 */
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -217,4 +207,3 @@ int main(void)
|
|||||||
}
|
}
|
||||||
#endif /* TEST_STATIC_BUFFER */
|
#endif /* TEST_STATIC_BUFFER */
|
||||||
#endif /* TEST */
|
#endif /* TEST */
|
||||||
|
|
||||||
|
|||||||
+5
-11
@@ -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,8 +53,7 @@ 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 */
|
||||||
@@ -64,23 +62,19 @@ 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
|
||||||
|
|||||||
+29
-62
@@ -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,28 +155,22 @@ 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;
|
||||||
@@ -200,28 +183,22 @@ 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);
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -327,4 +295,3 @@ int main(void)
|
|||||||
}
|
}
|
||||||
#endif /* TEST_TSM */
|
#endif /* TEST_TSM */
|
||||||
#endif /* TEST */
|
#endif /* TEST */
|
||||||
|
|
||||||
|
|||||||
+6
-16
@@ -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
|
||||||
@@ -99,24 +97,17 @@ 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
|
||||||
|
|
||||||
|
|||||||
+57
-88
@@ -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;
|
||||||
@@ -184,33 +169,26 @@ void testWhoHasData(Test * pTest, BACNET_WHO_HAS_DATA *data)
|
|||||||
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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,33 +203,24 @@ void testWhoHas(Test * pTest)
|
|||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-17
@@ -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,19 +53,13 @@ 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"
|
||||||
@@ -77,6 +69,4 @@ void testWhoHas(Test * pTest);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+32
-67
@@ -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;
|
||||||
@@ -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);
|
||||||
|
|||||||
+6
-16
@@ -42,22 +42,14 @@ 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);
|
||||||
@@ -66,6 +58,4 @@ void testWhoIs(Test * pTest);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+32
-57
@@ -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)
|
||||||
|
&& (unsigned_value <= BACNET_MAX_PRIORITY)) {
|
||||||
data->priority = (uint8_t) unsigned_value;
|
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,8 +182,7 @@ 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 };
|
||||||
@@ -207,26 +191,18 @@ void testWritePropertyTag(Test * pTest,
|
|||||||
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 ==
|
||||||
|
|||||||
+7
-16
@@ -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,22 +53,16 @@ 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
|
||||||
@@ -82,6 +75,4 @@ void test_ReadPropertyAck(Test * pTest);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user