added clang format C and H files.

This commit is contained in:
Steve Karg
2019-10-24 16:23:10 -05:00
parent da91a11454
commit 710173d6e0
205 changed files with 19377 additions and 25754 deletions
+31 -55
View File
@@ -38,14 +38,12 @@
#include "abort.h"
/** @file abort.c Abort Encoding/Decoding */
/* Helper function to avoid needing additional entries in service data structures
* when passing back abort status.
* Convert from error code to abort code.
* Anything not defined converts to ABORT_REASON_OTHER.
* Will need reworking if it is required to return proprietary abort codes.
/* Helper function to avoid needing additional entries in service data
* structures when passing back abort status. Convert from error code to abort
* code. Anything not defined converts to ABORT_REASON_OTHER. Will need
* reworking if it is required to return proprietary abort codes.
*/
BACNET_ABORT_REASON abort_convert_error_code(
BACNET_ERROR_CODE error_code)
BACNET_ABORT_REASON abort_convert_error_code(BACNET_ERROR_CODE error_code)
{
BACNET_ABORT_REASON abort_code = ABORT_REASON_OTHER;
@@ -75,13 +73,10 @@ BACNET_ABORT_REASON abort_convert_error_code(
}
/* encode service */
int abort_encode_apdu(
uint8_t * apdu,
uint8_t invoke_id,
uint8_t abort_reason,
bool server)
int abort_encode_apdu(uint8_t *apdu, uint8_t invoke_id, uint8_t abort_reason,
bool server)
{
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 (server)
@@ -98,11 +93,8 @@ int abort_encode_apdu(
#if !BACNET_SVC_SERVER
/* decode the service request only */
int abort_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
uint8_t * invoke_id,
uint8_t * abort_reason)
int abort_decode_service_request(uint8_t *apdu, unsigned apdu_len,
uint8_t *invoke_id, uint8_t *abort_reason)
{
int len = 0;
@@ -123,12 +115,8 @@ int abort_decode_service_request(
#include "ctest.h"
/* decode the whole APDU - mainly used for unit testing */
int abort_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
uint8_t * invoke_id,
uint8_t * abort_reason,
bool * server)
int abort_decode_apdu(uint8_t *apdu, unsigned apdu_len, uint8_t *invoke_id,
uint8_t *abort_reason, bool *server)
{
int len = 0;
@@ -143,22 +131,18 @@ int abort_decode_apdu(
else
*server = false;
if (apdu_len > 1) {
len =
abort_decode_service_request(&apdu[1], apdu_len - 1, invoke_id,
abort_reason);
len = abort_decode_service_request(&apdu[1], apdu_len - 1,
invoke_id, abort_reason);
}
}
return len;
}
void testAbortAPDU(
Test * pTest,
uint8_t invoke_id,
uint8_t abort_reason,
bool server)
void testAbortAPDU(Test *pTest, uint8_t invoke_id, uint8_t abort_reason,
bool server)
{
uint8_t apdu[480] = { 0 };
uint8_t apdu[480] = {0};
int len = 0;
int apdu_len = 0;
uint8_t test_invoke_id = 0;
@@ -168,9 +152,8 @@ void testAbortAPDU(
len = abort_encode_apdu(&apdu[0], invoke_id, abort_reason, server);
apdu_len = len;
ct_test(pTest, len != 0);
len =
abort_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_abort_reason, &test_server);
len = abort_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_abort_reason, &test_server);
ct_test(pTest, len != -1);
ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest, test_abort_reason == abort_reason);
@@ -179,11 +162,9 @@ void testAbortAPDU(
return;
}
void testAbort(
Test * pTest)
void testAbort(Test *pTest)
{
uint8_t apdu[480] = { 0 };
uint8_t apdu[480] = {0};
int len = 0;
int apdu_len = 0;
uint8_t invoke_id = 0;
@@ -196,9 +177,8 @@ void testAbort(
len = abort_encode_apdu(&apdu[0], invoke_id, abort_reason, server);
ct_test(pTest, len != 0);
apdu_len = len;
len =
abort_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_abort_reason, &test_server);
len = abort_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_abort_reason, &test_server);
ct_test(pTest, len != -1);
ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest, test_abort_reason == abort_reason);
@@ -206,21 +186,18 @@ void testAbort(
/* change type to get negative response */
apdu[0] = PDU_TYPE_REJECT;
len =
abort_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_abort_reason, &test_server);
len = abort_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_abort_reason, &test_server);
ct_test(pTest, len == -1);
/* test NULL APDU */
len =
abort_decode_apdu(NULL, apdu_len, &test_invoke_id, &test_abort_reason,
&test_server);
len = abort_decode_apdu(NULL, apdu_len, &test_invoke_id, &test_abort_reason,
&test_server);
ct_test(pTest, len == -1);
/* force a zero length */
len =
abort_decode_apdu(&apdu[0], 0, &test_invoke_id, &test_abort_reason,
&test_server);
len = abort_decode_apdu(&apdu[0], 0, &test_invoke_id, &test_abort_reason,
&test_server);
ct_test(pTest, len == 0);
/* check them all... */
@@ -233,8 +210,7 @@ void testAbort(
}
#ifdef TEST_ABORT
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -246,7 +222,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+42 -57
View File
@@ -1,36 +1,34 @@
/**************************************************************************
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include "access_rule.h"
#include "bacdcode.h"
int bacapp_encode_access_rule(
uint8_t * apdu,
BACNET_ACCESS_RULE * rule)
int bacapp_encode_access_rule(uint8_t* apdu, BACNET_ACCESS_RULE* rule)
{
int len;
int apdu_len = 0;
@@ -39,9 +37,8 @@ int bacapp_encode_access_rule(
apdu_len += len;
if (rule->time_range_specifier == TIME_RANGE_SPECIFIER_SPECIFIED) {
len =
bacapp_encode_context_device_obj_property_ref(&apdu[apdu_len], 1,
&rule->time_range);
len = bacapp_encode_context_device_obj_property_ref(&apdu[apdu_len], 1,
&rule->time_range);
if (len > 0)
apdu_len += len;
else
@@ -49,14 +46,12 @@ int bacapp_encode_access_rule(
}
len =
encode_context_enumerated(&apdu[apdu_len], 2,
rule->location_specifier);
encode_context_enumerated(&apdu[apdu_len], 2, rule->location_specifier);
apdu_len += len;
if (rule->location_specifier == LOCATION_SPECIFIER_SPECIFIED) {
len =
bacapp_encode_context_device_obj_property_ref(&apdu[apdu_len], 3,
&rule->location);
len = bacapp_encode_context_device_obj_property_ref(&apdu[apdu_len], 3,
&rule->location);
if (len > 0)
apdu_len += len;
else
@@ -69,10 +64,8 @@ int bacapp_encode_access_rule(
return apdu_len;
}
int bacapp_encode_context_access_rule(
uint8_t * apdu,
uint8_t tag_number,
BACNET_ACCESS_RULE * rule)
int bacapp_encode_context_access_rule(uint8_t* apdu, uint8_t tag_number,
BACNET_ACCESS_RULE* rule)
{
int len;
int apdu_len = 0;
@@ -89,17 +82,14 @@ int bacapp_encode_context_access_rule(
return apdu_len;
}
int bacapp_decode_access_rule(
uint8_t * apdu,
BACNET_ACCESS_RULE * rule)
int bacapp_decode_access_rule(uint8_t* apdu, BACNET_ACCESS_RULE* rule)
{
int len;
int apdu_len = 0;
if (decode_is_context_tag(&apdu[apdu_len], 0)) {
len =
decode_context_enumerated(&apdu[apdu_len], 0,
&rule->time_range_specifier);
len = decode_context_enumerated(&apdu[apdu_len], 0,
&rule->time_range_specifier);
if (len < 0)
return -1;
else
@@ -109,9 +99,8 @@ int bacapp_decode_access_rule(
if (rule->time_range_specifier == TIME_RANGE_SPECIFIER_SPECIFIED) {
if (decode_is_context_tag(&apdu[apdu_len], 1)) {
len =
bacapp_decode_context_device_obj_property_ref(&apdu[apdu_len],
1, &rule->time_range);
len = bacapp_decode_context_device_obj_property_ref(
&apdu[apdu_len], 1, &rule->time_range);
if (len < 0)
return -1;
else
@@ -121,9 +110,8 @@ int bacapp_decode_access_rule(
}
if (decode_is_context_tag(&apdu[apdu_len], 2)) {
len =
decode_context_enumerated(&apdu[apdu_len], 2,
&rule->location_specifier);
len = decode_context_enumerated(&apdu[apdu_len], 2,
&rule->location_specifier);
if (len < 0)
return -1;
else
@@ -133,9 +121,8 @@ int bacapp_decode_access_rule(
if (rule->location_specifier == LOCATION_SPECIFIER_SPECIFIED) {
if (decode_is_context_tag(&apdu[apdu_len], 3)) {
len =
bacapp_decode_context_device_obj_property_ref(&apdu[apdu_len],
3, &rule->location);
len = bacapp_decode_context_device_obj_property_ref(
&apdu[apdu_len], 3, &rule->location);
if (len < 0)
return -1;
else
@@ -156,10 +143,8 @@ int bacapp_decode_access_rule(
return apdu_len;
}
int bacapp_decode_context_access_rule(
uint8_t * apdu,
uint8_t tag_number,
BACNET_ACCESS_RULE * rule)
int bacapp_decode_context_access_rule(uint8_t* apdu, uint8_t tag_number,
BACNET_ACCESS_RULE* rule)
{
int len = 0;
int section_length;
+190 -220
View File
@@ -69,19 +69,20 @@ static struct Address_Cache_Entry {
/* State flags for cache entries */
#define BAC_ADDR_IN_USE 1 /* Address cache entry in use */
#define BAC_ADDR_BIND_REQ 2 /* Bind request outstanding for entry */
#define BAC_ADDR_STATIC 4 /* Static address mapping - does not expire */
#define BAC_ADDR_SHORT_TTL 8 /* Oppertunistaclly added address with short TTL */
#define BAC_ADDR_RESERVED 128 /* Freed up but held for caller to fill */
#define BAC_ADDR_IN_USE 1 /* Address cache entry in use */
#define BAC_ADDR_BIND_REQ 2 /* Bind request outstanding for entry */
#define BAC_ADDR_STATIC 4 /* Static address mapping - does not expire */
#define BAC_ADDR_SHORT_TTL \
8 /* Oppertunistaclly added address with short TTL \
*/
#define BAC_ADDR_RESERVED 128 /* Freed up but held for caller to fill */
#define BAC_ADDR_SECS_1HOUR 3600 /* 60x60 */
#define BAC_ADDR_SECS_1DAY 86400 /* 60x60x24 */
#define BAC_ADDR_SECS_1HOUR 3600 /* 60x60 */
#define BAC_ADDR_SECS_1DAY 86400 /* 60x60x24 */
#define BAC_ADDR_LONG_TIME BAC_ADDR_SECS_1DAY
#define BAC_ADDR_LONG_TIME BAC_ADDR_SECS_1DAY
#define BAC_ADDR_SHORT_TIME BAC_ADDR_SECS_1HOUR
#define BAC_ADDR_FOREVER 0xFFFFFFFF /* Permenant entry */
#define BAC_ADDR_FOREVER 0xFFFFFFFF /* Permenant entry */
void address_protected_entry_index_set(uint32_t top_protected_entry_index)
{
@@ -93,9 +94,7 @@ void address_own_device_id_set(uint32_t own_id)
Own_Device_ID = own_id;
}
bool address_match(
BACNET_ADDRESS * dest,
BACNET_ADDRESS * src)
bool address_match(BACNET_ADDRESS *dest, BACNET_ADDRESS *src)
{
uint8_t i = 0;
uint8_t max_len = 0;
@@ -129,8 +128,7 @@ bool address_match(
return true;
}
void address_remove_device(
uint32_t device_id)
void address_remove_device(uint32_t device_id)
{
struct Address_Cache_Entry *pMatch;
uint32_t index = 0;
@@ -160,9 +158,7 @@ void address_remove_device(
* assumed we are calling this due to the lack of those. *
*****************************************************************************/
static struct Address_Cache_Entry *address_remove_oldest(
void)
static struct Address_Cache_Entry *address_remove_oldest(void)
{
struct Address_Cache_Entry *pMatch;
struct Address_Cache_Entry *pCandidate;
@@ -170,17 +166,17 @@ static struct Address_Cache_Entry *address_remove_oldest(
pCandidate = NULL;
if (Top_Protected_Entry > (MAX_ADDRESS_CACHE - 1)) {
return pCandidate;
return pCandidate;
}
ulTime = BAC_ADDR_FOREVER - 1; /* Longest possible non static time to live */
ulTime =
BAC_ADDR_FOREVER - 1; /* Longest possible non static time to live */
/* First pass - try only in use and bound entries */
pMatch = &Address_Cache[Top_Protected_Entry];
while (pMatch <= &Address_Cache[MAX_ADDRESS_CACHE - 1]) {
if ((pMatch->
Flags & (BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ |
BAC_ADDR_STATIC)) == BAC_ADDR_IN_USE) {
if ((pMatch->Flags & (BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ |
BAC_ADDR_STATIC)) == BAC_ADDR_IN_USE) {
if (pMatch->TimeToLive <= ulTime) { /* Shorter lived entry found */
ulTime = pMatch->TimeToLive;
pCandidate = pMatch;
@@ -189,19 +185,19 @@ static struct Address_Cache_Entry *address_remove_oldest(
pMatch++;
}
if (pCandidate != NULL) { /* Found something to free up */
if (pCandidate != NULL) { /* Found something to free up */
pCandidate->Flags = BAC_ADDR_RESERVED;
pCandidate->TimeToLive = BAC_ADDR_SHORT_TIME; /* only reserve it for a short while */
pCandidate->TimeToLive =
BAC_ADDR_SHORT_TIME; /* only reserve it for a short while */
return (pCandidate);
}
/* Second pass - try in use and un bound as last resort */
pMatch = Address_Cache;
while (pMatch <= &Address_Cache[MAX_ADDRESS_CACHE - 1]) {
if ((pMatch->
Flags & (BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ |
BAC_ADDR_STATIC)) ==
((uint8_t) (BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ))) {
if ((pMatch->Flags &
(BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ | BAC_ADDR_STATIC)) ==
((uint8_t)(BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ))) {
if (pMatch->TimeToLive <= ulTime) { /* Shorter lived entry found */
ulTime = pMatch->TimeToLive;
pCandidate = pMatch;
@@ -210,9 +206,10 @@ static struct Address_Cache_Entry *address_remove_oldest(
pMatch++;
}
if (pCandidate != NULL) { /* Found something to free up */
if (pCandidate != NULL) { /* Found something to free up */
pCandidate->Flags = BAC_ADDR_RESERVED;
pCandidate->TimeToLive = BAC_ADDR_SHORT_TIME; /* only reserve it for a short while */
pCandidate->TimeToLive =
BAC_ADDR_SHORT_TIME; /* only reserve it for a short while */
}
return (pCandidate);
@@ -224,10 +221,7 @@ static struct Address_Cache_Entry *address_remove_oldest(
* @param adr [in] address to initialize, null if empty
* @param len [in] length of address in bytes
*/
void address_mac_init(
BACNET_MAC_ADDRESS *mac,
uint8_t *adr,
uint8_t len)
void address_mac_init(BACNET_MAC_ADDRESS *mac, uint8_t *adr, uint8_t len)
{
uint8_t i = 0;
@@ -248,9 +242,7 @@ void address_mac_init(
*
* @return true if the address was parsed
*/
bool address_mac_from_ascii(
BACNET_MAC_ADDRESS *mac,
char *arg)
bool address_mac_from_ascii(BACNET_MAC_ADDRESS *mac, char *arg)
{
unsigned a[6] = {0}, p = 0;
uint16_t port = 0;
@@ -260,7 +252,7 @@ bool address_mac_from_ascii(
if (!(mac && arg)) {
return false;
}
c = sscanf(arg, "%3u.%3u.%3u.%3u:%5u", &a[0],&a[1],&a[2],&a[3],&p);
c = sscanf(arg, "%3u.%3u.%3u.%3u:%5u", &a[0], &a[1], &a[2], &a[3], &p);
if ((c == 4) || (c == 5)) {
mac->adr[0] = a[0];
mac->adr[1] = a[1];
@@ -275,8 +267,8 @@ bool address_mac_from_ascii(
mac->len = 6;
status = true;
} else {
c = sscanf(arg, "%2x:%2x:%2x:%2x:%2x:%2x",
&a[0],&a[1],&a[2],&a[3],&a[4],&a[5]);
c = sscanf(arg, "%2x:%2x:%2x:%2x:%2x:%2x", &a[0], &a[1], &a[2], &a[3],
&a[4], &a[5]);
if (c == 6) {
mac->adr[0] = a[0];
mac->adr[1] = a[1];
@@ -307,35 +299,33 @@ note: useful for MS/TP Slave static binding
*/
static const char *Address_Cache_Filename = "address_cache";
static void address_file_init(
const char *pFilename)
static void address_file_init(const char *pFilename)
{
FILE *pFile = NULL; /* stream pointer */
char line[256] = { "" }; /* holds line from file */
FILE *pFile = NULL; /* stream pointer */
char line[256] = {""}; /* holds line from file */
long device_id = 0;
unsigned snet = 0;
unsigned max_apdu = 0;
char mac_string[80] = { "" }, sadr_string[80] = {
""};
BACNET_ADDRESS src = { 0 };
BACNET_MAC_ADDRESS mac = { 0 };
char mac_string[80] = {""}, sadr_string[80] = {""};
BACNET_ADDRESS src = {0};
BACNET_MAC_ADDRESS mac = {0};
int index = 0;
pFile = fopen(pFilename, "r");
if (pFile) {
while (fgets(line, (int) sizeof(line), pFile) != NULL) {
while (fgets(line, (int)sizeof(line), pFile) != NULL) {
/* ignore comments */
if (line[0] != ';') {
if (sscanf(line, "%7ld %79s %5u %79s %4u", &device_id,
&mac_string[0], &snet, &sadr_string[0],
&max_apdu) == 5) {
&mac_string[0], &snet, &sadr_string[0],
&max_apdu) == 5) {
if (address_mac_from_ascii(&mac, mac_string)) {
src.mac_len = mac.len;
for (index = 0; index < MAX_MAC_LEN; index++) {
src.mac[index] = mac.adr[index];
}
}
src.net = (uint16_t) snet;
src.net = (uint16_t)snet;
if (snet) {
if (address_mac_from_ascii(&mac, sadr_string)) {
src.len = mac.len;
@@ -349,8 +339,9 @@ static void address_file_init(
src.adr[index] = 0;
}
}
address_add((uint32_t) device_id, max_apdu, &src);
address_set_device_TTL((uint32_t) device_id, 0, true); /* Mark as static entry */
address_add((uint32_t)device_id, max_apdu, &src);
address_set_device_TTL((uint32_t)device_id, 0,
true); /* Mark as static entry */
}
}
}
@@ -366,12 +357,11 @@ static void address_file_init(
* available. Assume no persistance of memory. *
****************************************************************************/
void address_init(
void)
void address_init(void)
{
struct Address_Cache_Entry *pMatch;
Top_Protected_Entry = 0;
Top_Protected_Entry = 0;
pMatch = Address_Cache;
while (pMatch <= &Address_Cache[MAX_ADDRESS_CACHE - 1]) {
@@ -392,33 +382,33 @@ void address_init(
* of its entries intact. *
****************************************************************************/
void address_init_partial(
void)
void address_init_partial(void)
{
struct Address_Cache_Entry *pMatch;
pMatch = Address_Cache;
while (pMatch <= &Address_Cache[MAX_ADDRESS_CACHE - 1]) {
if ((pMatch->Flags & BAC_ADDR_IN_USE) != 0) { /* It's in use so let's check further */
if ((pMatch->Flags & BAC_ADDR_IN_USE) !=
0) { /* It's in use so let's check further */
if (((pMatch->Flags & BAC_ADDR_BIND_REQ) != 0) ||
(pMatch->TimeToLive == 0))
pMatch->Flags = 0;
}
if ((pMatch->Flags & BAC_ADDR_RESERVED) != 0) { /* Reserved entries should be cleared */
if ((pMatch->Flags & BAC_ADDR_RESERVED) !=
0) { /* Reserved entries should be cleared */
pMatch->Flags = 0;
}
pMatch++;
}
#ifdef BACNET_ADDRESS_CACHE_FILE
#ifdef BACNET_ADDRESS_CACHE_FILE
address_file_init(Address_Cache_Filename);
#endif
return;
}
/****************************************************************************
* Set the TTL info for the given device entry. If it is a bound entry we *
* set it to static or normal and can change the TTL. If it is unbound we *
@@ -426,10 +416,8 @@ void address_init_partial(
* to avoid breaking the current API. *
****************************************************************************/
void address_set_device_TTL(
uint32_t device_id,
uint32_t TimeOut,
bool StaticFlag)
void address_set_device_TTL(uint32_t device_id, uint32_t TimeOut,
bool StaticFlag)
{
struct Address_Cache_Entry *pMatch;
@@ -437,7 +425,8 @@ void address_set_device_TTL(
while (pMatch <= &Address_Cache[MAX_ADDRESS_CACHE - 1]) {
if (((pMatch->Flags & BAC_ADDR_IN_USE) != 0) &&
(pMatch->device_id == device_id)) {
if ((pMatch->Flags & BAC_ADDR_BIND_REQ) == 0) { /* If bound then we have either static or normaal */
if ((pMatch->Flags & BAC_ADDR_BIND_REQ) ==
0) { /* If bound then we have either static or normaal */
if (StaticFlag) {
pMatch->Flags |= BAC_ADDR_STATIC;
pMatch->TimeToLive = BAC_ADDR_FOREVER;
@@ -446,19 +435,17 @@ void address_set_device_TTL(
pMatch->TimeToLive = TimeOut;
}
} else {
pMatch->TimeToLive = TimeOut; /* For unbound we can only set the time to live */
pMatch->TimeToLive =
TimeOut; /* For unbound we can only set the time to live */
}
break; /* Exit now if found at all - bound or unbound */
break; /* Exit now if found at all - bound or unbound */
}
pMatch++;
}
}
bool address_get_by_device(
uint32_t device_id,
unsigned *max_apdu,
BACNET_ADDRESS * src)
bool address_get_by_device(uint32_t device_id, unsigned *max_apdu,
BACNET_ADDRESS *src)
{
struct Address_Cache_Entry *pMatch;
bool found = false; /* return value */
@@ -467,12 +454,13 @@ bool address_get_by_device(
while (pMatch <= &Address_Cache[MAX_ADDRESS_CACHE - 1]) {
if (((pMatch->Flags & BAC_ADDR_IN_USE) != 0) &&
(pMatch->device_id == device_id)) {
if ((pMatch->Flags & BAC_ADDR_BIND_REQ) == 0) { /* If bound then fetch data */
if ((pMatch->Flags & BAC_ADDR_BIND_REQ) ==
0) { /* If bound then fetch data */
bacnet_address_copy(src, &pMatch->address);
*max_apdu = pMatch->max_apdu;
found = true; /* Prove we found it */
found = true; /* Prove we found it */
}
break; /* Exit now if found at all - bound or unbound */
break; /* Exit now if found at all - bound or unbound */
}
pMatch++;
}
@@ -482,16 +470,15 @@ bool address_get_by_device(
/* find a device id from a given MAC address */
bool address_get_device_id(
BACNET_ADDRESS * src,
uint32_t * device_id)
bool address_get_device_id(BACNET_ADDRESS *src, uint32_t *device_id)
{
struct Address_Cache_Entry *pMatch;
bool found = false; /* return value */
pMatch = Address_Cache;
while (pMatch <= &Address_Cache[MAX_ADDRESS_CACHE - 1]) {
if ((pMatch->Flags & (BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ)) == BAC_ADDR_IN_USE) { /* If bound */
if ((pMatch->Flags & (BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ)) ==
BAC_ADDR_IN_USE) { /* If bound */
if (bacnet_address_same(&pMatch->address, src)) {
if (device_id) {
*device_id = pMatch->device_id;
@@ -506,10 +493,7 @@ bool address_get_device_id(
return found;
}
void address_add(
uint32_t device_id,
unsigned max_apdu,
BACNET_ADDRESS * src)
void address_add(uint32_t device_id, unsigned max_apdu, BACNET_ADDRESS *src)
{
bool found = false; /* return value */
struct Address_Cache_Entry *pMatch;
@@ -534,16 +518,21 @@ void address_add(
/* Pick the right time to live */
if ((pMatch->Flags & BAC_ADDR_BIND_REQ) != 0) /* Bind requested so long time */
if ((pMatch->Flags & BAC_ADDR_BIND_REQ) !=
0) /* Bind requested so long time */
pMatch->TimeToLive = BAC_ADDR_LONG_TIME;
else if ((pMatch->Flags & BAC_ADDR_STATIC) != 0) /* Static already so make sure it never expires */
else if ((pMatch->Flags & BAC_ADDR_STATIC) !=
0) /* Static already so make sure it never expires */
pMatch->TimeToLive = BAC_ADDR_FOREVER;
else if ((pMatch->Flags & BAC_ADDR_SHORT_TTL) != 0) /* Opportunistic entry so leave on short fuse */
else if ((pMatch->Flags & BAC_ADDR_SHORT_TTL) !=
0) /* Opportunistic entry so leave on short fuse */
pMatch->TimeToLive = BAC_ADDR_SHORT_TIME;
else
pMatch->TimeToLive = BAC_ADDR_LONG_TIME; /* Renewing existing entry */
pMatch->TimeToLive =
BAC_ADDR_LONG_TIME; /* Renewing existing entry */
pMatch->Flags &= ~BAC_ADDR_BIND_REQ; /* Clear bind request flag just in case */
pMatch->Flags &=
~BAC_ADDR_BIND_REQ; /* Clear bind request flag just in case */
found = true;
break;
}
@@ -559,7 +548,9 @@ void address_add(
pMatch->device_id = device_id;
pMatch->max_apdu = max_apdu;
bacnet_address_copy(&pMatch->address, src);
pMatch->TimeToLive = BAC_ADDR_SHORT_TIME; /* Opportunistic entry so leave on short fuse */
pMatch->TimeToLive =
BAC_ADDR_SHORT_TIME; /* Opportunistic entry so leave on
short fuse */
found = true;
break;
}
@@ -575,7 +566,8 @@ void address_add(
pMatch->device_id = device_id;
pMatch->max_apdu = max_apdu;
bacnet_address_copy(&pMatch->address, src);
pMatch->TimeToLive = BAC_ADDR_SHORT_TIME; /* Opportunistic entry so leave on short fuse */
pMatch->TimeToLive = BAC_ADDR_SHORT_TIME; /* Opportunistic entry so
leave on short fuse */
}
}
return;
@@ -583,11 +575,8 @@ void address_add(
/* returns true if device is already bound */
/* also returns the address and max apdu if already bound */
bool address_device_bind_request(
uint32_t device_id,
uint32_t * device_ttl,
unsigned *max_apdu,
BACNET_ADDRESS * src)
bool address_device_bind_request(uint32_t device_id, uint32_t *device_ttl,
unsigned *max_apdu, BACNET_ADDRESS *src)
{
bool found = false; /* return value */
struct Address_Cache_Entry *pMatch;
@@ -597,7 +586,7 @@ bool address_device_bind_request(
while (pMatch <= &Address_Cache[MAX_ADDRESS_CACHE - 1]) {
if (((pMatch->Flags & BAC_ADDR_IN_USE) != 0) &&
(pMatch->device_id == device_id)) {
if ((pMatch->Flags & BAC_ADDR_BIND_REQ) == 0) { /* Already bound */
if ((pMatch->Flags & BAC_ADDR_BIND_REQ) == 0) { /* Already bound */
found = true;
if (src) {
bacnet_address_copy(src, &pMatch->address);
@@ -608,12 +597,17 @@ bool address_device_bind_request(
if (device_ttl) {
*device_ttl = pMatch->TimeToLive;
}
if ((pMatch->Flags & BAC_ADDR_SHORT_TTL) != 0) { /* Was picked up opportunistacilly */
pMatch->Flags &= ~BAC_ADDR_SHORT_TTL; /* Convert to normal entry */
pMatch->TimeToLive = BAC_ADDR_LONG_TIME; /* And give it a decent time to live */
if ((pMatch->Flags & BAC_ADDR_SHORT_TTL) !=
0) { /* Was picked up opportunistacilly */
pMatch->Flags &=
~BAC_ADDR_SHORT_TTL; /* Convert to normal entry */
pMatch->TimeToLive =
BAC_ADDR_LONG_TIME; /* And give it a decent time to live
*/
}
}
return (found); /* True if bound, false if bind request outstanding */
return (
found); /* True if bound, false if bind request outstanding */
}
pMatch++;
}
@@ -623,7 +617,7 @@ bool address_device_bind_request(
while (pMatch <= &Address_Cache[MAX_ADDRESS_CACHE - 1]) {
if ((pMatch->Flags & (BAC_ADDR_IN_USE | BAC_ADDR_RESERVED)) == 0) {
/* In use and awaiting binding */
pMatch->Flags = (uint8_t) (BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ);
pMatch->Flags = (uint8_t)(BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ);
pMatch->device_id = device_id;
/* No point in leaving bind requests in for long haul */
pMatch->TimeToLive = BAC_ADDR_SHORT_TIME;
@@ -633,10 +627,11 @@ bool address_device_bind_request(
pMatch++;
}
/* No free entries, See if we can squeeze it in by dropping an existing one */
/* No free entries, See if we can squeeze it in by dropping an existing one
*/
pMatch = address_remove_oldest();
if (pMatch != NULL) {
pMatch->Flags = (uint8_t) (BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ);
pMatch->Flags = (uint8_t)(BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ);
pMatch->device_id = device_id;
/* No point in leaving bind requests in for long haul */
pMatch->TimeToLive = BAC_ADDR_SHORT_TIME;
@@ -646,18 +641,14 @@ bool address_device_bind_request(
/* returns true if device is already bound */
/* also returns the address and max apdu if already bound */
bool address_bind_request(
uint32_t device_id,
unsigned *max_apdu,
BACNET_ADDRESS * src)
bool address_bind_request(uint32_t device_id, unsigned *max_apdu,
BACNET_ADDRESS *src)
{
return address_device_bind_request(device_id, NULL, max_apdu, src);
}
void address_add_binding(
uint32_t device_id,
unsigned max_apdu,
BACNET_ADDRESS * src)
void address_add_binding(uint32_t device_id, unsigned max_apdu,
BACNET_ADDRESS *src)
{
struct Address_Cache_Entry *pMatch;
@@ -682,12 +673,9 @@ void address_add_binding(
return;
}
bool address_device_get_by_index(
unsigned index,
uint32_t * device_id,
uint32_t * device_ttl,
unsigned *max_apdu,
BACNET_ADDRESS * src)
bool address_device_get_by_index(unsigned index, uint32_t *device_id,
uint32_t *device_ttl, unsigned *max_apdu,
BACNET_ADDRESS *src)
{
struct Address_Cache_Entry *pMatch;
bool found = false; /* return value */
@@ -715,17 +703,13 @@ bool address_device_get_by_index(
return found;
}
bool address_get_by_index(
unsigned index,
uint32_t * device_id,
unsigned *max_apdu,
BACNET_ADDRESS * src)
bool address_get_by_index(unsigned index, uint32_t *device_id,
unsigned *max_apdu, BACNET_ADDRESS *src)
{
return address_device_get_by_index(index, device_id, NULL, max_apdu, src);
}
unsigned address_count(
void)
unsigned address_count(void)
{
struct Address_Cache_Entry *pMatch;
unsigned count = 0; /* return value */
@@ -748,9 +732,7 @@ unsigned address_count(
* property. *
****************************************************************************/
int address_list_encode(
uint8_t * apdu,
unsigned apdu_len)
int address_list_encode(uint8_t *apdu, unsigned apdu_len)
{
int iLen = 0;
struct Address_Cache_Entry *pMatch;
@@ -765,9 +747,8 @@ int address_list_encode(
while (pMatch <= &Address_Cache[MAX_ADDRESS_CACHE - 1]) {
if ((pMatch->Flags & (BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ)) ==
BAC_ADDR_IN_USE) {
iLen +=
encode_application_object_id(&apdu[iLen], OBJECT_DEVICE,
pMatch->device_id);
iLen += encode_application_object_id(&apdu[iLen], OBJECT_DEVICE,
pMatch->device_id);
iLen +=
encode_application_unsigned(&apdu[iLen], pMatch->address.net);
@@ -775,12 +756,12 @@ int address_list_encode(
if (pMatch->address.len != 0) {
octetstring_init(&MAC_Address, pMatch->address.adr,
pMatch->address.len);
pMatch->address.len);
iLen +=
encode_application_octet_string(&apdu[iLen], &MAC_Address);
} else {
octetstring_init(&MAC_Address, pMatch->address.mac,
pMatch->address.mac_len);
pMatch->address.mac_len);
iLen +=
encode_application_octet_string(&apdu[iLen], &MAC_Address);
}
@@ -814,22 +795,20 @@ int address_list_encode(
* oct string to give 17 bytes (the minimum possible is 5 + 2 + 3 = 10). *
****************************************************************************/
#define ACACHE_MAX_ENC 17 /* Maximum size of encoded cache entry, see above */
#define ACACHE_MAX_ENC 17 /* Maximum size of encoded cache entry, see above */
int rr_address_list_encode(
uint8_t * apdu,
BACNET_READ_RANGE_DATA * pRequest)
int rr_address_list_encode(uint8_t *apdu, BACNET_READ_RANGE_DATA *pRequest)
{
int iLen = 0;
int32_t iTemp = 0;
struct Address_Cache_Entry *pMatch = NULL;
BACNET_OCTET_STRING MAC_Address;
uint32_t uiTotal = 0; /* Number of bound entries in the cache */
uint32_t uiIndex = 0; /* Current entry number */
uint32_t uiFirst = 0; /* Entry number we started encoding from */
uint32_t uiLast = 0; /* Entry number we finished encoding on */
uint32_t uiTarget = 0; /* Last entry we are required to encode */
uint32_t uiRemaining = 0; /* Amount of unused space in packet */
uint32_t uiTotal = 0; /* Number of bound entries in the cache */
uint32_t uiIndex = 0; /* Current entry number */
uint32_t uiFirst = 0; /* Entry number we started encoding from */
uint32_t uiLast = 0; /* Entry number we finished encoding on */
uint32_t uiTarget = 0; /* Last entry we are required to encode */
uint32_t uiRemaining = 0; /* Amount of unused space in packet */
/* Initialise result flags to all false */
bitstring_init(&pRequest->ResultFlags);
@@ -837,11 +816,11 @@ int rr_address_list_encode(
bitstring_set_bit(&pRequest->ResultFlags, RESULT_FLAG_LAST_ITEM, false);
bitstring_set_bit(&pRequest->ResultFlags, RESULT_FLAG_MORE_ITEMS, false);
/* See how much space we have */
uiRemaining = (uint32_t) (MAX_APDU - pRequest->Overhead);
uiRemaining = (uint32_t)(MAX_APDU - pRequest->Overhead);
pRequest->ItemCount = 0; /* Start out with nothing */
uiTotal = address_count(); /* What do we have to work with here ? */
if (uiTotal == 0) /* Bail out now if nowt */
pRequest->ItemCount = 0; /* Start out with nothing */
uiTotal = address_count(); /* What do we have to work with here ? */
if (uiTotal == 0) /* Bail out now if nowt */
return (0);
if (pRequest->RequestType == RR_READ_ALL) {
@@ -850,11 +829,12 @@ int rr_address_list_encode(
* a range that covers the whole list and falling through to the next
* section of code
*/
pRequest->Count = uiTotal; /* Full list */
pRequest->Range.RefIndex = 1; /* Starting at the beginning */
pRequest->Count = uiTotal; /* Full list */
pRequest->Range.RefIndex = 1; /* Starting at the beginning */
}
if (pRequest->Count < 0) { /* negative count means work from index backwards */
if (pRequest->Count <
0) { /* negative count means work from index backwards */
/*
* Convert from end index/negative count to
* start index/positive count and then process as
@@ -868,12 +848,14 @@ int rr_address_list_encode(
* implications of the data type conversions!
*/
iTemp = pRequest->Range.RefIndex; /* pull out and convert to signed */
iTemp += pRequest->Count + 1; /* Adjust backwards, remember count is -ve */
if (iTemp < 1) { /* if count is too much, return from 1 to start index */
iTemp = pRequest->Range.RefIndex; /* pull out and convert to signed */
iTemp +=
pRequest->Count + 1; /* Adjust backwards, remember count is -ve */
if (iTemp <
1) { /* if count is too much, return from 1 to start index */
pRequest->Count = pRequest->Range.RefIndex;
pRequest->Range.RefIndex = 1;
} else { /* Otherwise adjust the start index and make count +ve */
} else { /* Otherwise adjust the start index and make count +ve */
pRequest->Range.RefIndex = iTemp;
pRequest->Count = -pRequest->Count;
}
@@ -881,28 +863,32 @@ int rr_address_list_encode(
/* From here on in we only have a starting point and a positive count */
if (pRequest->Range.RefIndex > uiTotal) /* Nothing to return as we are past the end of the list */
if (pRequest->Range.RefIndex >
uiTotal) /* Nothing to return as we are past the end of the list */
return (0);
uiTarget = pRequest->Range.RefIndex + pRequest->Count - 1; /* Index of last required entry */
if (uiTarget > uiTotal) /* Capped at end of list if necessary */
uiTarget = pRequest->Range.RefIndex + pRequest->Count -
1; /* Index of last required entry */
if (uiTarget > uiTotal) /* Capped at end of list if necessary */
uiTarget = uiTotal;
pMatch = Address_Cache;
uiIndex = 1;
while ((pMatch->Flags & (BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ)) != BAC_ADDR_IN_USE) /* Find first bound entry */
while ((pMatch->Flags & (BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ)) !=
BAC_ADDR_IN_USE) /* Find first bound entry */
pMatch++;
/* Seek to start position */
while (uiIndex != pRequest->Range.RefIndex) {
if ((pMatch->Flags & (BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ)) == BAC_ADDR_IN_USE) { /* Only count bound entries */
if ((pMatch->Flags & (BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ)) ==
BAC_ADDR_IN_USE) { /* Only count bound entries */
pMatch++;
uiIndex++;
} else
pMatch++;
}
uiFirst = uiIndex; /* Record where we started from */
uiFirst = uiIndex; /* Record where we started from */
while (uiIndex <= uiTarget) {
if (uiRemaining < ACACHE_MAX_ENC) {
/*
@@ -910,49 +896,45 @@ int rr_address_list_encode(
* was more and drop out of the loop early
*/
bitstring_set_bit(&pRequest->ResultFlags, RESULT_FLAG_MORE_ITEMS,
true);
true);
break;
}
iTemp =
(int32_t) encode_application_object_id(&apdu[iLen], OBJECT_DEVICE,
pMatch->device_id);
iTemp +=
encode_application_unsigned(&apdu[iLen + iTemp],
pMatch->address.net);
iTemp = (int32_t)encode_application_object_id(
&apdu[iLen], OBJECT_DEVICE, pMatch->device_id);
iTemp += encode_application_unsigned(&apdu[iLen + iTemp],
pMatch->address.net);
/* pick the appropriate type of entry from the cache */
if (pMatch->address.len != 0) {
octetstring_init(&MAC_Address, pMatch->address.adr,
pMatch->address.len);
iTemp +=
encode_application_octet_string(&apdu[iLen + iTemp],
&MAC_Address);
pMatch->address.len);
iTemp += encode_application_octet_string(&apdu[iLen + iTemp],
&MAC_Address);
} else {
octetstring_init(&MAC_Address, pMatch->address.mac,
pMatch->address.mac_len);
iTemp +=
encode_application_octet_string(&apdu[iLen + iTemp],
&MAC_Address);
pMatch->address.mac_len);
iTemp += encode_application_octet_string(&apdu[iLen + iTemp],
&MAC_Address);
}
uiRemaining -= iTemp; /* Reduce the remaining space */
iLen += iTemp; /* and increase the length consumed */
uiRemaining -= iTemp; /* Reduce the remaining space */
iLen += iTemp; /* and increase the length consumed */
uiLast = uiIndex; /* Record the last entry encoded */
uiIndex++; /* and get ready for next one */
uiLast = uiIndex; /* Record the last entry encoded */
uiIndex++; /* and get ready for next one */
pMatch++;
pRequest->ItemCount++; /* Chalk up another one for the response count */
pRequest->ItemCount++; /* Chalk up another one for the response count */
while ((pMatch->Flags & (BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ)) != BAC_ADDR_IN_USE) /* Find next bound entry */
while ((pMatch->Flags & (BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ)) !=
BAC_ADDR_IN_USE) /* Find next bound entry */
pMatch++;
}
/* Set remaining result flags if necessary */
if (uiFirst == 1)
bitstring_set_bit(&pRequest->ResultFlags, RESULT_FLAG_FIRST_ITEM,
true);
bitstring_set_bit(&pRequest->ResultFlags, RESULT_FLAG_FIRST_ITEM, true);
if (uiLast == uiTotal)
bitstring_set_bit(&pRequest->ResultFlags, RESULT_FLAG_LAST_ITEM, true);
@@ -967,15 +949,15 @@ int rr_address_list_encode(
* entries never expire unless explictely deleted. *
****************************************************************************/
void address_cache_timer(
uint16_t uSeconds)
{ /* Approximate number of seconds since last call to this function */
void address_cache_timer(uint16_t uSeconds)
{ /* Approximate number of seconds since last call to this function */
struct Address_Cache_Entry *pMatch;
pMatch = Address_Cache;
while (pMatch <= &Address_Cache[MAX_ADDRESS_CACHE - 1]) {
if (((pMatch->Flags & (BAC_ADDR_IN_USE | BAC_ADDR_RESERVED)) != 0)
&& ((pMatch->Flags & BAC_ADDR_STATIC) == 0)) { /* Check all entries holding a slot except statics */
if (((pMatch->Flags & (BAC_ADDR_IN_USE | BAC_ADDR_RESERVED)) != 0) &&
((pMatch->Flags & BAC_ADDR_STATIC) ==
0)) { /* Check all entries holding a slot except statics */
if (pMatch->TimeToLive >= uSeconds)
pMatch->TimeToLive -= uSeconds;
else
@@ -986,16 +968,12 @@ void address_cache_timer(
}
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
static void set_address(
unsigned index,
BACNET_ADDRESS * dest)
static void set_address(unsigned index, BACNET_ADDRESS *dest)
{
unsigned i;
@@ -1010,11 +988,8 @@ static void set_address(
}
}
static void set_file_address(
const char *pFilename,
uint32_t device_id,
BACNET_ADDRESS * dest,
uint16_t max_apdu)
static void set_file_address(const char *pFilename, uint32_t device_id,
BACNET_ADDRESS *dest, uint16_t max_apdu)
{
unsigned i;
FILE *pFile = NULL;
@@ -1022,7 +997,7 @@ static void set_file_address(
pFile = fopen(pFilename, "w");
if (pFile) {
fprintf(pFile, "%lu ", (long unsigned int) device_id);
fprintf(pFile, "%lu ", (long unsigned int)device_id);
for (i = 0; i < dest->mac_len; i++) {
fprintf(pFile, "%02x", dest->mac[i]);
if ((i + 1) < dest->mac_len) {
@@ -1046,13 +1021,12 @@ static void set_file_address(
}
#ifdef BACNET_ADDRESS_CACHE_FILE
void testAddressFile(
Test * pTest)
void testAddressFile(Test *pTest)
{
BACNET_ADDRESS src = { 0 };
BACNET_ADDRESS src = {0};
uint32_t device_id = 0;
unsigned max_apdu = 480;
BACNET_ADDRESS test_address = { 0 };
BACNET_ADDRESS test_address = {0};
unsigned test_max_apdu = 0;
/* create a fake address */
@@ -1065,8 +1039,8 @@ void testAddressFile(
set_file_address(Address_Cache_Filename, device_id, &src, max_apdu);
/* retrieve it from the file, and see if we can find it */
address_file_init(Address_Cache_Filename);
ct_test(pTest, address_get_by_device(device_id, &test_max_apdu,
&test_address));
ct_test(pTest,
address_get_by_device(device_id, &test_max_apdu, &test_address));
ct_test(pTest, test_max_apdu == max_apdu);
ct_test(pTest, bacnet_address_same(&test_address, &src));
@@ -1086,16 +1060,14 @@ void testAddressFile(
set_file_address(Address_Cache_Filename, device_id, &src, max_apdu);
/* retrieve it from the file, and see if we can find it */
address_file_init(Address_Cache_Filename);
ct_test(pTest, address_get_by_device(device_id, &test_max_apdu,
&test_address));
ct_test(pTest,
address_get_by_device(device_id, &test_max_apdu, &test_address));
ct_test(pTest, test_max_apdu == max_apdu);
ct_test(pTest, bacnet_address_same(&test_address, &src));
}
#endif
void testAddress(
Test * pTest)
void testAddress(Test *pTest)
{
unsigned i, count;
BACNET_ADDRESS src;
@@ -1119,11 +1091,11 @@ void testAddress(
set_address(i, &src);
/* test the lookup by device id */
ct_test(pTest, address_get_by_device(device_id, &test_max_apdu,
&test_address));
&test_address));
ct_test(pTest, test_max_apdu == max_apdu);
ct_test(pTest, bacnet_address_same(&test_address, &src));
ct_test(pTest, address_get_by_index(i, &test_device_id, &test_max_apdu,
&test_address));
&test_address));
ct_test(pTest, test_device_id == device_id);
ct_test(pTest, test_max_apdu == max_apdu);
ct_test(pTest, bacnet_address_same(&test_address, &src));
@@ -1137,15 +1109,14 @@ void testAddress(
device_id = i * 255;
address_remove_device(device_id);
ct_test(pTest, !address_get_by_device(device_id, &test_max_apdu,
&test_address));
&test_address));
count = address_count();
ct_test(pTest, count == (MAX_ADDRESS_CACHE - i - 1));
}
}
#ifdef TEST_ADDRESS
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -1159,10 +1130,9 @@ int main(
assert(rc);
#endif
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+67 -102
View File
@@ -41,19 +41,17 @@
** Creates an Unconfirmed Event Notification APDU
**
****************************************************/
int alarm_ack_encode_apdu(
uint8_t * apdu,
uint8_t invoke_id,
BACNET_ALARM_ACK_DATA * data)
int alarm_ack_encode_apdu(uint8_t *apdu, uint8_t invoke_id,
BACNET_ALARM_ACK_DATA *data)
{
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) {
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU);
apdu[2] = invoke_id;
apdu[3] = SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM; /* service choice */
apdu[3] = SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM; /* service choice */
apdu_len = 4;
len = alarm_ack_encode_service_request(&apdu[apdu_len], data);
@@ -63,65 +61,53 @@ int alarm_ack_encode_apdu(
return apdu_len;
}
/***************************************************
**
** Encodes the service data part of Event Notification
**
****************************************************/
int alarm_ack_encode_service_request(
uint8_t * apdu,
BACNET_ALARM_ACK_DATA * data)
int alarm_ack_encode_service_request(uint8_t *apdu, BACNET_ALARM_ACK_DATA *data)
{
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) {
len =
encode_context_unsigned(&apdu[apdu_len], 0,
data->ackProcessIdentifier);
len = encode_context_unsigned(&apdu[apdu_len], 0,
data->ackProcessIdentifier);
apdu_len += len;
len =
encode_context_object_id(&apdu[apdu_len], 1,
(int) data->eventObjectIdentifier.type,
data->eventObjectIdentifier.instance);
len = encode_context_object_id(&apdu[apdu_len], 1,
(int)data->eventObjectIdentifier.type,
data->eventObjectIdentifier.instance);
apdu_len += len;
len =
encode_context_enumerated(&apdu[apdu_len], 2,
data->eventStateAcked);
len = encode_context_enumerated(&apdu[apdu_len], 2,
data->eventStateAcked);
apdu_len += len;
len =
bacapp_encode_context_timestamp(&apdu[apdu_len], 3,
&data->eventTimeStamp);
len = bacapp_encode_context_timestamp(&apdu[apdu_len], 3,
&data->eventTimeStamp);
apdu_len += len;
len =
encode_context_character_string(&apdu[apdu_len], 4,
&data->ackSource);
len = encode_context_character_string(&apdu[apdu_len], 4,
&data->ackSource);
apdu_len += len;
len =
bacapp_encode_context_timestamp(&apdu[apdu_len], 5,
&data->ackTimeStamp);
len = bacapp_encode_context_timestamp(&apdu[apdu_len], 5,
&data->ackTimeStamp);
apdu_len += len;
}
return apdu_len;
}
/***************************************************
**
** Decodes the service data part of Event Notification
**
****************************************************/
int alarm_ack_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
BACNET_ALARM_ACK_DATA * data)
int alarm_ack_decode_service_request(uint8_t *apdu, unsigned apdu_len,
BACNET_ALARM_ACK_DATA *data)
{
int len = 0;
int section_len;
@@ -130,45 +116,40 @@ int alarm_ack_decode_service_request(
/* unused parameter */
apdu_len = apdu_len;
if (-1 == (section_len =
decode_context_unsigned(&apdu[len], 0,
&data->ackProcessIdentifier))) {
if (-1 == (section_len = decode_context_unsigned(
&apdu[len], 0, &data->ackProcessIdentifier))) {
return -1;
}
len += section_len;
if (-1 == (section_len =
decode_context_object_id(&apdu[len], 1,
&data->eventObjectIdentifier.type,
&data->eventObjectIdentifier.instance))) {
if (-1 == (section_len = decode_context_object_id(
&apdu[len], 1, &data->eventObjectIdentifier.type,
&data->eventObjectIdentifier.instance))) {
return -1;
}
len += section_len;
if (-1 == (section_len =
decode_context_enumerated(&apdu[len], 2, &enumValue))) {
if (-1 ==
(section_len = decode_context_enumerated(&apdu[len], 2, &enumValue))) {
return -1;
}
data->eventStateAcked = (BACNET_EVENT_STATE) enumValue;
data->eventStateAcked = (BACNET_EVENT_STATE)enumValue;
len += section_len;
if (-1 == (section_len =
bacapp_decode_context_timestamp(&apdu[len], 3,
&data->eventTimeStamp))) {
if (-1 == (section_len = bacapp_decode_context_timestamp(
&apdu[len], 3, &data->eventTimeStamp))) {
return -1;
}
len += section_len;
if (-1 == (section_len =
decode_context_character_string(&apdu[len], 4,
&data->ackSource))) {
if (-1 == (section_len = decode_context_character_string(
&apdu[len], 4, &data->ackSource))) {
return -1;
}
len += section_len;
if (-1 == (section_len =
bacapp_decode_context_timestamp(&apdu[len], 5,
&data->ackTimeStamp))) {
if (-1 == (section_len = bacapp_decode_context_timestamp(
&apdu[len], 5, &data->ackTimeStamp))) {
return -1;
}
len += section_len;
@@ -182,9 +163,7 @@ int alarm_ack_decode_service_request(
#include <string.h>
#include "ctest.h"
void testAlarmAck(
Test * pTest)
void testAlarmAck(Test *pTest)
{
BACNET_ALARM_ACK_DATA testAlarmAckIn;
BACNET_ALARM_ACK_DATA testAlarmAckOut;
@@ -208,58 +187,44 @@ void testAlarmAck(
memset(&testAlarmAckOut, 0, sizeof(testAlarmAckOut));
inLen = alarm_ack_encode_service_request(buffer, &testAlarmAckIn);
outLen = alarm_ack_decode_service_request(buffer, inLen, &testAlarmAckOut);
ct_test(pTest, inLen == outLen);
ct_test(pTest,
testAlarmAckIn.ackProcessIdentifier ==
testAlarmAckOut.ackProcessIdentifier);
ct_test(pTest, testAlarmAckIn.ackProcessIdentifier ==
testAlarmAckOut.ackProcessIdentifier);
ct_test(pTest, testAlarmAckIn.ackTimeStamp.tag ==
testAlarmAckOut.ackTimeStamp.tag);
ct_test(pTest, testAlarmAckIn.ackTimeStamp.value.sequenceNum ==
testAlarmAckOut.ackTimeStamp.value.sequenceNum);
ct_test(pTest, testAlarmAckIn.ackProcessIdentifier ==
testAlarmAckOut.ackProcessIdentifier);
ct_test(pTest, testAlarmAckIn.eventObjectIdentifier.instance ==
testAlarmAckOut.eventObjectIdentifier.instance);
ct_test(pTest, testAlarmAckIn.eventObjectIdentifier.type ==
testAlarmAckOut.eventObjectIdentifier.type);
ct_test(pTest, testAlarmAckIn.eventTimeStamp.tag ==
testAlarmAckOut.eventTimeStamp.tag);
ct_test(pTest, testAlarmAckIn.eventTimeStamp.value.time.hour ==
testAlarmAckOut.eventTimeStamp.value.time.hour);
ct_test(pTest, testAlarmAckIn.eventTimeStamp.value.time.min ==
testAlarmAckOut.eventTimeStamp.value.time.min);
ct_test(pTest, testAlarmAckIn.eventTimeStamp.value.time.sec ==
testAlarmAckOut.eventTimeStamp.value.time.sec);
ct_test(pTest, testAlarmAckIn.eventTimeStamp.value.time.hundredths ==
testAlarmAckOut.eventTimeStamp.value.time.hundredths);
ct_test(pTest,
testAlarmAckIn.ackTimeStamp.tag == testAlarmAckOut.ackTimeStamp.tag);
ct_test(pTest,
testAlarmAckIn.ackTimeStamp.value.sequenceNum ==
testAlarmAckOut.ackTimeStamp.value.sequenceNum);
ct_test(pTest,
testAlarmAckIn.ackProcessIdentifier ==
testAlarmAckOut.ackProcessIdentifier);
ct_test(pTest,
testAlarmAckIn.eventObjectIdentifier.instance ==
testAlarmAckOut.eventObjectIdentifier.instance);
ct_test(pTest,
testAlarmAckIn.eventObjectIdentifier.type ==
testAlarmAckOut.eventObjectIdentifier.type);
ct_test(pTest,
testAlarmAckIn.eventTimeStamp.tag ==
testAlarmAckOut.eventTimeStamp.tag);
ct_test(pTest,
testAlarmAckIn.eventTimeStamp.value.time.hour ==
testAlarmAckOut.eventTimeStamp.value.time.hour);
ct_test(pTest,
testAlarmAckIn.eventTimeStamp.value.time.min ==
testAlarmAckOut.eventTimeStamp.value.time.min);
ct_test(pTest,
testAlarmAckIn.eventTimeStamp.value.time.sec ==
testAlarmAckOut.eventTimeStamp.value.time.sec);
ct_test(pTest,
testAlarmAckIn.eventTimeStamp.value.time.hundredths ==
testAlarmAckOut.eventTimeStamp.value.time.hundredths);
ct_test(pTest,
testAlarmAckIn.eventStateAcked == testAlarmAckOut.eventStateAcked);
testAlarmAckIn.eventStateAcked == testAlarmAckOut.eventStateAcked);
}
#ifdef TEST_ALARM_ACK
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -271,7 +236,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+126 -142
View File
@@ -45,12 +45,10 @@
/** @file apdu.c Handles APDU services */
extern int Routed_Device_Service_Approval(
BACNET_CONFIRMED_SERVICE service,
int service_argument,
uint8_t * apdu_buff,
uint8_t invoke_id);
extern int Routed_Device_Service_Approval(BACNET_CONFIRMED_SERVICE service,
int service_argument,
uint8_t *apdu_buff,
uint8_t invoke_id);
/* APDU Timeout in Milliseconds */
static uint16_t Timeout_Milliseconds = 3000;
@@ -60,60 +58,57 @@ static uint8_t Number_Of_Retries = 3;
/* a simple table for crossing the services supported */
static BACNET_SERVICES_SUPPORTED
confirmed_service_supported[MAX_BACNET_CONFIRMED_SERVICE] = {
SERVICE_SUPPORTED_ACKNOWLEDGE_ALARM,
SERVICE_SUPPORTED_CONFIRMED_COV_NOTIFICATION,
SERVICE_SUPPORTED_CONFIRMED_EVENT_NOTIFICATION,
SERVICE_SUPPORTED_GET_ALARM_SUMMARY,
SERVICE_SUPPORTED_GET_ENROLLMENT_SUMMARY,
SERVICE_SUPPORTED_SUBSCRIBE_COV,
SERVICE_SUPPORTED_ATOMIC_READ_FILE,
SERVICE_SUPPORTED_ATOMIC_WRITE_FILE,
SERVICE_SUPPORTED_ADD_LIST_ELEMENT,
SERVICE_SUPPORTED_REMOVE_LIST_ELEMENT,
SERVICE_SUPPORTED_CREATE_OBJECT,
SERVICE_SUPPORTED_DELETE_OBJECT,
SERVICE_SUPPORTED_READ_PROPERTY,
SERVICE_SUPPORTED_READ_PROP_CONDITIONAL,
SERVICE_SUPPORTED_READ_PROP_MULTIPLE,
SERVICE_SUPPORTED_WRITE_PROPERTY,
SERVICE_SUPPORTED_WRITE_PROP_MULTIPLE,
SERVICE_SUPPORTED_DEVICE_COMMUNICATION_CONTROL,
SERVICE_SUPPORTED_PRIVATE_TRANSFER,
SERVICE_SUPPORTED_TEXT_MESSAGE,
SERVICE_SUPPORTED_REINITIALIZE_DEVICE,
SERVICE_SUPPORTED_VT_OPEN,
SERVICE_SUPPORTED_VT_CLOSE,
SERVICE_SUPPORTED_VT_DATA,
SERVICE_SUPPORTED_AUTHENTICATE,
SERVICE_SUPPORTED_REQUEST_KEY,
SERVICE_SUPPORTED_READ_RANGE,
SERVICE_SUPPORTED_LIFE_SAFETY_OPERATION,
SERVICE_SUPPORTED_SUBSCRIBE_COV_PROPERTY,
SERVICE_SUPPORTED_GET_EVENT_INFORMATION
};
SERVICE_SUPPORTED_ACKNOWLEDGE_ALARM,
SERVICE_SUPPORTED_CONFIRMED_COV_NOTIFICATION,
SERVICE_SUPPORTED_CONFIRMED_EVENT_NOTIFICATION,
SERVICE_SUPPORTED_GET_ALARM_SUMMARY,
SERVICE_SUPPORTED_GET_ENROLLMENT_SUMMARY,
SERVICE_SUPPORTED_SUBSCRIBE_COV,
SERVICE_SUPPORTED_ATOMIC_READ_FILE,
SERVICE_SUPPORTED_ATOMIC_WRITE_FILE,
SERVICE_SUPPORTED_ADD_LIST_ELEMENT,
SERVICE_SUPPORTED_REMOVE_LIST_ELEMENT,
SERVICE_SUPPORTED_CREATE_OBJECT,
SERVICE_SUPPORTED_DELETE_OBJECT,
SERVICE_SUPPORTED_READ_PROPERTY,
SERVICE_SUPPORTED_READ_PROP_CONDITIONAL,
SERVICE_SUPPORTED_READ_PROP_MULTIPLE,
SERVICE_SUPPORTED_WRITE_PROPERTY,
SERVICE_SUPPORTED_WRITE_PROP_MULTIPLE,
SERVICE_SUPPORTED_DEVICE_COMMUNICATION_CONTROL,
SERVICE_SUPPORTED_PRIVATE_TRANSFER,
SERVICE_SUPPORTED_TEXT_MESSAGE,
SERVICE_SUPPORTED_REINITIALIZE_DEVICE,
SERVICE_SUPPORTED_VT_OPEN,
SERVICE_SUPPORTED_VT_CLOSE,
SERVICE_SUPPORTED_VT_DATA,
SERVICE_SUPPORTED_AUTHENTICATE,
SERVICE_SUPPORTED_REQUEST_KEY,
SERVICE_SUPPORTED_READ_RANGE,
SERVICE_SUPPORTED_LIFE_SAFETY_OPERATION,
SERVICE_SUPPORTED_SUBSCRIBE_COV_PROPERTY,
SERVICE_SUPPORTED_GET_EVENT_INFORMATION};
/* a simple table for crossing the services supported */
static BACNET_SERVICES_SUPPORTED
unconfirmed_service_supported[MAX_BACNET_UNCONFIRMED_SERVICE] = {
SERVICE_SUPPORTED_I_AM,
SERVICE_SUPPORTED_I_HAVE,
SERVICE_SUPPORTED_UNCONFIRMED_COV_NOTIFICATION,
SERVICE_SUPPORTED_UNCONFIRMED_EVENT_NOTIFICATION,
SERVICE_SUPPORTED_UNCONFIRMED_PRIVATE_TRANSFER,
SERVICE_SUPPORTED_UNCONFIRMED_TEXT_MESSAGE,
SERVICE_SUPPORTED_TIME_SYNCHRONIZATION,
SERVICE_SUPPORTED_WHO_HAS,
SERVICE_SUPPORTED_WHO_IS,
SERVICE_SUPPORTED_UTC_TIME_SYNCHRONIZATION
};
SERVICE_SUPPORTED_I_AM,
SERVICE_SUPPORTED_I_HAVE,
SERVICE_SUPPORTED_UNCONFIRMED_COV_NOTIFICATION,
SERVICE_SUPPORTED_UNCONFIRMED_EVENT_NOTIFICATION,
SERVICE_SUPPORTED_UNCONFIRMED_PRIVATE_TRANSFER,
SERVICE_SUPPORTED_UNCONFIRMED_TEXT_MESSAGE,
SERVICE_SUPPORTED_TIME_SYNCHRONIZATION,
SERVICE_SUPPORTED_WHO_HAS,
SERVICE_SUPPORTED_WHO_IS,
SERVICE_SUPPORTED_UTC_TIME_SYNCHRONIZATION};
/* Confirmed Function Handlers */
/* If they are not set, they are handled by a reject message */
static confirmed_function Confirmed_Function[MAX_BACNET_CONFIRMED_SERVICE];
void apdu_set_confirmed_handler(
BACNET_CONFIRMED_SERVICE service_choice,
confirmed_function pFunction)
void apdu_set_confirmed_handler(BACNET_CONFIRMED_SERVICE service_choice,
confirmed_function pFunction)
{
if (service_choice < MAX_BACNET_CONFIRMED_SERVICE)
Confirmed_Function[service_choice] = pFunction;
@@ -122,8 +117,7 @@ void apdu_set_confirmed_handler(
/* Allow the APDU handler to automatically reject */
static confirmed_function Unrecognized_Service_Handler;
void apdu_set_unrecognized_service_handler_handler(
confirmed_function pFunction)
void apdu_set_unrecognized_service_handler_handler(confirmed_function pFunction)
{
Unrecognized_Service_Handler = pFunction;
}
@@ -133,16 +127,14 @@ void apdu_set_unrecognized_service_handler_handler(
static unconfirmed_function
Unconfirmed_Function[MAX_BACNET_UNCONFIRMED_SERVICE];
void apdu_set_unconfirmed_handler(
BACNET_UNCONFIRMED_SERVICE service_choice,
unconfirmed_function pFunction)
void apdu_set_unconfirmed_handler(BACNET_UNCONFIRMED_SERVICE service_choice,
unconfirmed_function pFunction)
{
if (service_choice < MAX_BACNET_UNCONFIRMED_SERVICE)
Unconfirmed_Function[service_choice] = pFunction;
}
bool apdu_service_supported(
BACNET_SERVICES_SUPPORTED service_supported)
bool apdu_service_supported(BACNET_SERVICES_SUPPORTED service_supported)
{
int i = 0;
bool status = false;
@@ -155,12 +147,12 @@ bool apdu_service_supported(
found = true;
if (Confirmed_Function[i] != NULL) {
#if BAC_ROUTING
/* Check to see if the current Device supports this service. */
int len =
Routed_Device_Service_Approval(service_supported, 0,
NULL, 0);
/* Check to see if the current Device supports this service.
*/
int len = Routed_Device_Service_Approval(service_supported,
0, NULL, 0);
if (len > 0)
break; /* Not supported - return false */
break; /* Not supported - return false */
#endif
status = true;
@@ -194,9 +186,8 @@ bool apdu_service_supported(
* @return True if a match was found and index and bIsConfirmed are valid.
*/
bool apdu_service_supported_to_index(
BACNET_SERVICES_SUPPORTED service_supported,
size_t * index,
bool * bIsConfirmed)
BACNET_SERVICES_SUPPORTED service_supported, size_t *index,
bool *bIsConfirmed)
{
int i = 0;
bool found = false;
@@ -207,7 +198,7 @@ bool apdu_service_supported_to_index(
for (i = 0; i < MAX_BACNET_CONFIRMED_SERVICE; i++) {
if (confirmed_service_supported[i] == service_supported) {
found = true;
*index = (size_t) i;
*index = (size_t)i;
*bIsConfirmed = true;
break;
}
@@ -218,7 +209,7 @@ bool apdu_service_supported_to_index(
for (i = 0; i < MAX_BACNET_UNCONFIRMED_SERVICE; i++) {
if (unconfirmed_service_supported[i] == service_supported) {
found = true;
*index = (size_t) i;
*index = (size_t)i;
break;
}
}
@@ -257,16 +248,15 @@ void apdu_set_confirmed_simple_ack_handler(
/* Security Services */
case SERVICE_CONFIRMED_REQUEST_KEY:
Confirmed_ACK_Function[service_choice] =
(confirmed_ack_function) pFunction;
(confirmed_ack_function)pFunction;
break;
default:
break;
}
}
void apdu_set_confirmed_ack_handler(
BACNET_CONFIRMED_SERVICE service_choice,
confirmed_ack_function pFunction)
void apdu_set_confirmed_ack_handler(BACNET_CONFIRMED_SERVICE service_choice,
confirmed_ack_function pFunction)
{
switch (service_choice) {
case SERVICE_CONFIRMED_GET_ALARM_SUMMARY:
@@ -297,9 +287,8 @@ void apdu_set_confirmed_ack_handler(
static error_function Error_Function[MAX_BACNET_CONFIRMED_SERVICE];
void apdu_set_error_handler(
BACNET_CONFIRMED_SERVICE service_choice,
error_function pFunction)
void apdu_set_error_handler(BACNET_CONFIRMED_SERVICE service_choice,
error_function pFunction)
{
if (service_choice < MAX_BACNET_CONFIRMED_SERVICE)
Error_Function[service_choice] = pFunction;
@@ -307,29 +296,25 @@ void apdu_set_error_handler(
static abort_function Abort_Function;
void apdu_set_abort_handler(
abort_function pFunction)
void apdu_set_abort_handler(abort_function pFunction)
{
Abort_Function = pFunction;
}
static reject_function Reject_Function;
void apdu_set_reject_handler(
reject_function pFunction)
void apdu_set_reject_handler(reject_function pFunction)
{
Reject_Function = pFunction;
}
uint16_t apdu_decode_confirmed_service_request(
uint8_t * apdu, /* APDU data */
uint16_t apdu_len,
BACNET_CONFIRMED_SERVICE_DATA * service_data,
uint8_t * service_choice,
uint8_t ** service_request,
uint16_t * service_request_len)
uint8_t *apdu, /* APDU data */
uint16_t apdu_len, BACNET_CONFIRMED_SERVICE_DATA *service_data,
uint8_t *service_choice, uint8_t **service_request,
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] & BIT(3)) ? true : false;
service_data->more_follows = (apdu[0] & BIT(2)) ? true : false;
@@ -350,39 +335,33 @@ uint16_t apdu_decode_confirmed_service_request(
return len;
}
uint16_t apdu_timeout(
void)
uint16_t apdu_timeout(void)
{
return Timeout_Milliseconds;
}
void apdu_timeout_set(
uint16_t milliseconds)
void apdu_timeout_set(uint16_t milliseconds)
{
Timeout_Milliseconds = milliseconds;
}
uint8_t apdu_retries(
void)
uint8_t apdu_retries(void)
{
return Number_Of_Retries;
}
void apdu_retries_set(
uint8_t value)
void apdu_retries_set(uint8_t value)
{
Number_Of_Retries = value;
}
/* When network communications are completely disabled,
only DeviceCommunicationControl and ReinitializeDevice APDUs
shall be processed and no messages shall be initiated.
When the initiation of communications is disabled,
all APDUs shall be processed and responses returned as
required... */
static bool apdu_confirmed_dcc_disabled(
uint8_t service_choice)
static bool apdu_confirmed_dcc_disabled(uint8_t service_choice)
{
bool status = false;
@@ -407,8 +386,7 @@ static bool apdu_confirmed_dcc_disabled(
DISABLE_INITIATION, the responding BACnet-user shall
discontinue the initiation of messages except for I-Am
requests issued in accordance with the Who-Is service procedure.*/
static bool apdu_unconfirmed_dcc_disabled(
uint8_t service_choice)
static bool apdu_unconfirmed_dcc_disabled(uint8_t service_choice)
{
bool status = false;
@@ -439,18 +417,16 @@ static bool apdu_unconfirmed_dcc_disabled(
* @param apdu [in] The apdu portion of the request, to be processed.
* @param apdu_len [in] The total (remaining) length of the apdu.
*/
void apdu_handler(
BACNET_ADDRESS * src,
uint8_t * apdu, /* APDU data */
uint16_t apdu_len)
void apdu_handler(BACNET_ADDRESS *src, uint8_t *apdu, /* APDU data */
uint16_t apdu_len)
{
BACNET_CONFIRMED_SERVICE_DATA service_data = { 0 };
BACNET_CONFIRMED_SERVICE_ACK_DATA service_ack_data = { 0 };
BACNET_CONFIRMED_SERVICE_DATA service_data = {0};
BACNET_CONFIRMED_SERVICE_ACK_DATA service_ack_data = {0};
uint8_t invoke_id = 0;
uint8_t service_choice = 0;
uint8_t *service_request = NULL;
uint16_t service_request_len = 0;
int len = 0; /* counts where we are in PDU */
int len = 0; /* counts where we are in PDU */
uint8_t tag_number = 0;
uint32_t len_value = 0;
uint32_t error_code = 0;
@@ -462,22 +438,25 @@ void apdu_handler(
/* PDU Type */
switch (apdu[0] & 0xF0) {
case PDU_TYPE_CONFIRMED_SERVICE_REQUEST:
(void)apdu_decode_confirmed_service_request(&apdu[0],
apdu_len, &service_data, &service_choice, &service_request,
&service_request_len);
(void)apdu_decode_confirmed_service_request(
&apdu[0], apdu_len, &service_data, &service_choice,
&service_request, &service_request_len);
if (apdu_confirmed_dcc_disabled(service_choice)) {
/* When network communications are completely disabled,
only DeviceCommunicationControl and ReinitializeDevice APDUs
shall be processed and no messages shall be initiated. */
only DeviceCommunicationControl and ReinitializeDevice
APDUs shall be processed and no messages shall be
initiated. */
break;
}
if ((service_choice < MAX_BACNET_CONFIRMED_SERVICE) &&
(Confirmed_Function[service_choice]))
Confirmed_Function[service_choice] (service_request,
service_request_len, src, &service_data);
Confirmed_Function[service_choice](service_request,
service_request_len, src,
&service_data);
else if (Unrecognized_Service_Handler)
Unrecognized_Service_Handler(service_request,
service_request_len, src, &service_data);
service_request_len, src,
&service_data);
break;
case PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST:
service_choice = apdu[1];
@@ -485,16 +464,16 @@ void apdu_handler(
service_request_len = apdu_len - 2;
if (apdu_unconfirmed_dcc_disabled(service_choice)) {
/* When network communications are disabled,
only DeviceCommunicationControl and ReinitializeDevice APDUs
shall be processed and no messages shall be initiated.
If communications have been initiation disabled, then
WhoIs may be processed. */
only DeviceCommunicationControl and ReinitializeDevice
APDUs shall be processed and no messages shall be
initiated. If communications have been initiation
disabled, then WhoIs may be processed. */
break;
}
if (service_choice < MAX_BACNET_UNCONFIRMED_SERVICE) {
if (Unconfirmed_Function[service_choice])
Unconfirmed_Function[service_choice] (service_request,
service_request_len, src);
Unconfirmed_Function[service_choice](
service_request, service_request_len, src);
}
break;
case PDU_TYPE_SIMPLE_ACK:
@@ -523,8 +502,8 @@ void apdu_handler(
case SERVICE_CONFIRMED_REQUEST_KEY:
if (Confirmed_ACK_Function[service_choice] != NULL) {
((confirmed_simple_ack_function)
Confirmed_ACK_Function[service_choice]) (src,
invoke_id);
Confirmed_ACK_Function[service_choice])(
src, invoke_id);
}
tsm_free_invoke_id(invoke_id);
break;
@@ -545,7 +524,7 @@ void apdu_handler(
}
service_choice = apdu[len++];
service_request = &apdu[len];
service_request_len = apdu_len - (uint16_t) len;
service_request_len = apdu_len - (uint16_t)len;
switch (service_choice) {
case SERVICE_CONFIRMED_GET_ALARM_SUMMARY:
case SERVICE_CONFIRMED_GET_ENROLLMENT_SUMMARY:
@@ -566,8 +545,8 @@ void apdu_handler(
/* Security Services */
case SERVICE_CONFIRMED_AUTHENTICATE:
if (Confirmed_ACK_Function[service_choice] != NULL) {
(Confirmed_ACK_Function[service_choice])
(service_request, service_request_len, src,
(Confirmed_ACK_Function[service_choice])(
service_request, service_request_len, src,
&service_ack_data);
}
tsm_free_invoke_id(invoke_id);
@@ -586,37 +565,42 @@ void apdu_handler(
service_choice = apdu[2];
len = 3;
/* FIXME: Currently special case for C_P_T but there are others which may
need consideration such as ChangeList-Error, CreateObject-Error,
WritePropertyMultiple-Error and VTClose_Error but they may be left as
is for now until support for these services is added */
/* FIXME: Currently special case for C_P_T but there are others
which may need consideration such as ChangeList-Error,
CreateObject-Error, WritePropertyMultiple-Error and
VTClose_Error but they may be left as is for now until
support for these services is added */
if (service_choice == SERVICE_CONFIRMED_PRIVATE_TRANSFER) { /* skip over opening tag 0 */
if (service_choice ==
SERVICE_CONFIRMED_PRIVATE_TRANSFER) { /* skip over opening
tag 0 */
if (decode_is_opening_tag_number(&apdu[len], 0)) {
len++; /* a tag number of 0 is not extended so only one octet */
len++; /* a tag number of 0 is not extended so only one
octet */
}
}
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... */
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... */
len += decode_enumerated(&apdu[len], len_value, &error_code);
if (service_choice == SERVICE_CONFIRMED_PRIVATE_TRANSFER) { /* skip over closing tag 0 */
if (service_choice ==
SERVICE_CONFIRMED_PRIVATE_TRANSFER) { /* skip over closing
tag 0 */
if (decode_is_closing_tag_number(&apdu[len], 0)) {
len++; /* a tag number of 0 is not extended so only one octet */
len++; /* a tag number of 0 is not extended so only one
octet */
}
}
if (service_choice < MAX_BACNET_CONFIRMED_SERVICE) {
if (Error_Function[service_choice])
Error_Function[service_choice] (src, invoke_id,
(BACNET_ERROR_CLASS) error_class,
(BACNET_ERROR_CODE) error_code);
Error_Function[service_choice](
src, invoke_id, (BACNET_ERROR_CLASS)error_class,
(BACNET_ERROR_CODE)error_code);
}
tsm_free_invoke_id(invoke_id);
break;
+118 -178
View File
@@ -40,41 +40,34 @@
/** @file arf.c Atomic Read File */
/* encode service */
int arf_encode_apdu(
uint8_t * apdu,
uint8_t invoke_id,
BACNET_ATOMIC_READ_FILE_DATA * data)
int arf_encode_apdu(uint8_t *apdu, 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) {
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU);
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 +=
encode_application_object_id(&apdu[apdu_len], data->object_type,
data->object_instance);
apdu_len += encode_application_object_id(
&apdu[apdu_len], data->object_type, data->object_instance);
switch (data->access) {
case FILE_STREAM_ACCESS:
apdu_len += encode_opening_tag(&apdu[apdu_len], 0);
apdu_len +=
encode_application_signed(&apdu[apdu_len],
data->type.stream.fileStartPosition);
apdu_len +=
encode_application_unsigned(&apdu[apdu_len],
data->type.stream.requestedOctetCount);
apdu_len += encode_application_signed(
&apdu[apdu_len], data->type.stream.fileStartPosition);
apdu_len += encode_application_unsigned(
&apdu[apdu_len], data->type.stream.requestedOctetCount);
apdu_len += encode_closing_tag(&apdu[apdu_len], 0);
break;
case FILE_RECORD_ACCESS:
apdu_len += encode_opening_tag(&apdu[apdu_len], 1);
apdu_len +=
encode_application_signed(&apdu[apdu_len],
data->type.record.fileStartRecord);
apdu_len +=
encode_application_unsigned(&apdu[apdu_len],
data->type.record.RecordCount);
apdu_len += encode_application_signed(
&apdu[apdu_len], data->type.record.fileStartRecord);
apdu_len += encode_application_unsigned(
&apdu[apdu_len], data->type.record.RecordCount);
apdu_len += encode_closing_tag(&apdu[apdu_len], 1);
break;
default:
@@ -86,50 +79,43 @@ int arf_encode_apdu(
}
/* decode the service request only */
int arf_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
BACNET_ATOMIC_READ_FILE_DATA * data)
int arf_decode_service_request(uint8_t *apdu, unsigned apdu_len,
BACNET_ATOMIC_READ_FILE_DATA *data)
{
int len = 0;
int tag_len = 0;
uint8_t tag_number = 0;
uint32_t len_value_type = 0;
uint16_t type = 0; /* for decoding */
uint16_t type = 0; /* for decoding */
/* check for value pointers */
if (apdu_len && data) {
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)
return -1;
len += decode_object_id(&apdu[len], &type, &data->object_instance);
data->object_type = (BACNET_OBJECT_TYPE) type;
data->object_type = (BACNET_OBJECT_TYPE)type;
if (decode_is_opening_tag_number(&apdu[len], 0)) {
data->access = FILE_STREAM_ACCESS;
/* a tag number is not extended so only one octet */
len++;
/* fileStartPosition */
tag_len =
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
tag_len = decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_SIGNED_INT)
return -1;
len +=
decode_signed(&apdu[len], len_value_type,
&data->type.stream.fileStartPosition);
len += decode_signed(&apdu[len], len_value_type,
&data->type.stream.fileStartPosition);
/* requestedOctetCount */
tag_len =
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
tag_len = decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT)
return -1;
len +=
decode_unsigned(&apdu[len], len_value_type,
&data->type.stream.requestedOctetCount);
len += decode_unsigned(&apdu[len], len_value_type,
&data->type.stream.requestedOctetCount);
if (!decode_is_closing_tag_number(&apdu[len], 0))
return -1;
/* a tag number is not extended so only one octet */
@@ -139,25 +125,21 @@ int arf_decode_service_request(
/* a tag number is not extended so only one octet */
len++;
/* fileStartRecord */
tag_len =
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
tag_len = decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_SIGNED_INT)
return -1;
len +=
decode_signed(&apdu[len], len_value_type,
&data->type.record.fileStartRecord);
len += decode_signed(&apdu[len], len_value_type,
&data->type.record.fileStartRecord);
/* RecordCount */
tag_len =
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
tag_len = decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT)
return -1;
len +=
decode_unsigned(&apdu[len], len_value_type,
&data->type.record.RecordCount);
len += decode_unsigned(&apdu[len], len_value_type,
&data->type.record.RecordCount);
if (!decode_is_closing_tag_number(&apdu[len], 1))
return -1;
/* a tag number is not extended so only one octet */
@@ -169,11 +151,8 @@ int arf_decode_service_request(
return len;
}
int arf_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
uint8_t * invoke_id,
BACNET_ATOMIC_READ_FILE_DATA * data)
int arf_decode_apdu(uint8_t *apdu, unsigned apdu_len, uint8_t *invoke_id,
BACNET_ATOMIC_READ_FILE_DATA *data)
{
int len = 0;
unsigned offset = 0;
@@ -184,7 +163,7 @@ int arf_decode_apdu(
if (apdu[0] != PDU_TYPE_CONFIRMED_SERVICE_REQUEST)
return -1;
/* apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU); */
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
if (apdu[3] != SERVICE_CONFIRMED_ATOMIC_READ_FILE)
return -1;
offset = 4;
@@ -198,18 +177,16 @@ int arf_decode_apdu(
}
/* encode service */
int arf_ack_encode_apdu(
uint8_t * apdu,
uint8_t invoke_id,
BACNET_ATOMIC_READ_FILE_DATA * data)
int arf_ack_encode_apdu(uint8_t *apdu, 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 */
uint32_t i = 0;
if (apdu) {
apdu[0] = PDU_TYPE_COMPLEX_ACK;
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;
/* endOfFile */
apdu_len +=
@@ -217,26 +194,21 @@ int arf_ack_encode_apdu(
switch (data->access) {
case FILE_STREAM_ACCESS:
apdu_len += encode_opening_tag(&apdu[apdu_len], 0);
apdu_len +=
encode_application_signed(&apdu[apdu_len],
data->type.stream.fileStartPosition);
apdu_len +=
encode_application_octet_string(&apdu[apdu_len],
&data->fileData[0]);
apdu_len += encode_application_signed(
&apdu[apdu_len], data->type.stream.fileStartPosition);
apdu_len += encode_application_octet_string(&apdu[apdu_len],
&data->fileData[0]);
apdu_len += encode_closing_tag(&apdu[apdu_len], 0);
break;
case FILE_RECORD_ACCESS:
apdu_len += encode_opening_tag(&apdu[apdu_len], 1);
apdu_len +=
encode_application_signed(&apdu[apdu_len],
data->type.record.fileStartRecord);
apdu_len +=
encode_application_unsigned(&apdu[apdu_len],
data->type.record.RecordCount);
apdu_len += encode_application_signed(
&apdu[apdu_len], data->type.record.fileStartRecord);
apdu_len += encode_application_unsigned(
&apdu[apdu_len], data->type.record.RecordCount);
for (i = 0; i < data->type.record.RecordCount; i++) {
apdu_len +=
encode_application_octet_string(&apdu[apdu_len],
&data->fileData[i]);
apdu_len += encode_application_octet_string(
&apdu[apdu_len], &data->fileData[i]);
}
apdu_len += encode_closing_tag(&apdu[apdu_len], 1);
break;
@@ -249,10 +221,8 @@ int arf_ack_encode_apdu(
}
/* decode the service request only */
int arf_ack_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
BACNET_ATOMIC_READ_FILE_DATA * data)
int arf_ack_decode_service_request(uint8_t *apdu, unsigned apdu_len,
BACNET_ATOMIC_READ_FILE_DATA *data)
{
int len = 0;
int tag_len = 0;
@@ -264,8 +234,7 @@ int arf_ack_decode_service_request(
/* check for value pointers */
if (apdu_len && data) {
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) {
return -1;
}
@@ -275,27 +244,23 @@ int arf_ack_decode_service_request(
/* a tag number is not extended so only one octet */
len++;
/* fileStartPosition */
tag_len =
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
tag_len = decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_SIGNED_INT) {
return -1;
}
len +=
decode_signed(&apdu[len], len_value_type,
&data->type.stream.fileStartPosition);
len += decode_signed(&apdu[len], len_value_type,
&data->type.stream.fileStartPosition);
/* fileData */
tag_len =
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
tag_len = decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_OCTET_STRING) {
return -1;
}
decoded_len =
decode_octet_string(&apdu[len], len_value_type,
&data->fileData[0]);
decoded_len = decode_octet_string(&apdu[len], len_value_type,
&data->fileData[0]);
if ((uint32_t)decoded_len != len_value_type) {
return -1;
}
@@ -310,39 +275,33 @@ int arf_ack_decode_service_request(
/* a tag number is not extended so only one octet */
len++;
/* fileStartRecord */
tag_len =
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
tag_len = decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_SIGNED_INT) {
return -1;
}
len +=
decode_signed(&apdu[len], len_value_type,
&data->type.record.fileStartRecord);
len += decode_signed(&apdu[len], len_value_type,
&data->type.record.fileStartRecord);
/* returnedRecordCount */
tag_len =
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
tag_len = decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT) {
return -1;
}
len +=
decode_unsigned(&apdu[len], len_value_type,
&data->type.record.RecordCount);
len += decode_unsigned(&apdu[len], len_value_type,
&data->type.record.RecordCount);
for (i = 0; i < data->type.record.RecordCount; i++) {
/* fileData */
tag_len =
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
tag_len = decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_OCTET_STRING) {
return -1;
}
decoded_len =
decode_octet_string(&apdu[len], len_value_type,
&data->fileData[i]);
decoded_len = decode_octet_string(&apdu[len], len_value_type,
&data->fileData[i]);
if ((uint32_t)decoded_len != len_value_type) {
return -1;
}
@@ -361,11 +320,8 @@ int arf_ack_decode_service_request(
return len;
}
int arf_ack_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
uint8_t * invoke_id,
BACNET_ATOMIC_READ_FILE_DATA * data)
int arf_ack_decode_apdu(uint8_t *apdu, unsigned apdu_len, uint8_t *invoke_id,
BACNET_ATOMIC_READ_FILE_DATA *data)
{
int len = 0;
unsigned offset = 0;
@@ -375,32 +331,29 @@ int arf_ack_decode_apdu(
/* optional checking - most likely was already done prior to this call */
if (apdu[0] != PDU_TYPE_COMPLEX_ACK)
return -1;
*invoke_id = apdu[1]; /* invoke id - filled in by net layer */
*invoke_id = apdu[1]; /* invoke id - filled in by net layer */
if (apdu[2] != SERVICE_CONFIRMED_ATOMIC_READ_FILE)
return -1;
offset = 3;
if (apdu_len > offset) {
len =
arf_ack_decode_service_request(&apdu[offset], apdu_len - offset,
data);
len = arf_ack_decode_service_request(&apdu[offset], apdu_len - offset,
data);
}
return len;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
void testAtomicReadFileAckAccess(
Test * pTest,
BACNET_ATOMIC_READ_FILE_DATA * data)
void testAtomicReadFileAckAccess(Test *pTest,
BACNET_ATOMIC_READ_FILE_DATA *data)
{
BACNET_ATOMIC_READ_FILE_DATA test_data = { 0 };
uint8_t apdu[480] = { 0 };
BACNET_ATOMIC_READ_FILE_DATA test_data = {0};
uint8_t apdu[480] = {0};
int len = 0;
int apdu_len = 0;
uint8_t invoke_id = 128;
@@ -416,37 +369,32 @@ void testAtomicReadFileAckAccess(
ct_test(pTest, test_data.endOfFile == data->endOfFile);
ct_test(pTest, test_data.access == data->access);
if (test_data.access == FILE_STREAM_ACCESS) {
ct_test(pTest,
test_data.type.stream.fileStartPosition ==
data->type.stream.fileStartPosition);
ct_test(pTest,
octetstring_length(&test_data.fileData[0]) ==
octetstring_length(&data->fileData[0]));
ct_test(pTest, test_data.type.stream.fileStartPosition ==
data->type.stream.fileStartPosition);
ct_test(pTest, octetstring_length(&test_data.fileData[0]) ==
octetstring_length(&data->fileData[0]));
ct_test(pTest, memcmp(octetstring_value(&test_data.fileData[0]),
octetstring_value(&data->fileData[0]),
octetstring_length(&test_data.fileData[0])) == 0);
octetstring_value(&data->fileData[0]),
octetstring_length(&test_data.fileData[0])) == 0);
} else if (test_data.access == FILE_RECORD_ACCESS) {
ct_test(pTest,
test_data.type.record.fileStartRecord ==
data->type.record.fileStartRecord);
ct_test(pTest,
test_data.type.record.RecordCount ==
data->type.record.RecordCount);
ct_test(pTest, test_data.type.record.fileStartRecord ==
data->type.record.fileStartRecord);
ct_test(pTest, test_data.type.record.RecordCount ==
data->type.record.RecordCount);
for (i = 0; i < data->type.record.RecordCount; i++) {
ct_test(pTest, octetstring_length(&test_data.fileData[i]) ==
octetstring_length(&data->fileData[i]));
ct_test(pTest,
octetstring_length(&test_data.fileData[i]) ==
octetstring_length(&data->fileData[i]));
ct_test(pTest, memcmp(octetstring_value(&test_data.fileData[i]),
octetstring_value(&data->fileData[i]),
octetstring_length(&test_data.fileData[i])) == 0);
memcmp(octetstring_value(&test_data.fileData[i]),
octetstring_value(&data->fileData[i]),
octetstring_length(&test_data.fileData[i])) == 0);
}
}
}
void testAtomicReadFileAck(
Test * pTest)
void testAtomicReadFileAck(Test *pTest)
{
BACNET_ATOMIC_READ_FILE_DATA data = { 0 };
BACNET_ATOMIC_READ_FILE_DATA data = {0};
uint8_t test_octet_string[32] = "Joshua-Mary-Anna-Christopher";
unsigned int i = 0;
@@ -454,7 +402,7 @@ void testAtomicReadFileAck(
data.access = FILE_STREAM_ACCESS;
data.type.stream.fileStartPosition = 0;
octetstring_init(&data.fileData[0], test_octet_string,
sizeof(test_octet_string));
sizeof(test_octet_string));
testAtomicReadFileAckAccess(pTest, &data);
data.endOfFile = false;
@@ -463,19 +411,17 @@ void testAtomicReadFileAck(
data.type.record.RecordCount = BACNET_READ_FILE_RECORD_COUNT;
for (i = 0; i < data.type.record.RecordCount; i++) {
octetstring_init(&data.fileData[i], test_octet_string,
sizeof(test_octet_string));
sizeof(test_octet_string));
}
testAtomicReadFileAckAccess(pTest, &data);
return;
}
void testAtomicReadFileAccess(
Test * pTest,
BACNET_ATOMIC_READ_FILE_DATA * data)
void testAtomicReadFileAccess(Test *pTest, BACNET_ATOMIC_READ_FILE_DATA *data)
{
BACNET_ATOMIC_READ_FILE_DATA test_data = { 0 };
uint8_t apdu[480] = { 0 };
BACNET_ATOMIC_READ_FILE_DATA test_data = {0};
uint8_t apdu[480] = {0};
int len = 0;
int apdu_len = 0;
uint8_t invoke_id = 128;
@@ -491,26 +437,21 @@ void testAtomicReadFileAccess(
ct_test(pTest, test_data.object_instance == data->object_instance);
ct_test(pTest, test_data.access == data->access);
if (test_data.access == FILE_STREAM_ACCESS) {
ct_test(pTest,
test_data.type.stream.fileStartPosition ==
data->type.stream.fileStartPosition);
ct_test(pTest,
test_data.type.stream.requestedOctetCount ==
data->type.stream.requestedOctetCount);
ct_test(pTest, test_data.type.stream.fileStartPosition ==
data->type.stream.fileStartPosition);
ct_test(pTest, test_data.type.stream.requestedOctetCount ==
data->type.stream.requestedOctetCount);
} else if (test_data.access == FILE_RECORD_ACCESS) {
ct_test(pTest,
test_data.type.record.fileStartRecord ==
data->type.record.fileStartRecord);
ct_test(pTest,
test_data.type.record.RecordCount ==
data->type.record.RecordCount);
ct_test(pTest, test_data.type.record.fileStartRecord ==
data->type.record.fileStartRecord);
ct_test(pTest, test_data.type.record.RecordCount ==
data->type.record.RecordCount);
}
}
void testAtomicReadFile(
Test * pTest)
void testAtomicReadFile(Test *pTest)
{
BACNET_ATOMIC_READ_FILE_DATA data = { 0 };
BACNET_ATOMIC_READ_FILE_DATA data = {0};
data.object_type = OBJECT_FILE;
data.object_instance = 1;
@@ -530,8 +471,7 @@ void testAtomicReadFile(
}
#ifdef TEST_ATOMIC_READ_FILE
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -545,7 +485,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+33 -43
View File
@@ -1,42 +1,39 @@
/**************************************************************************
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include "assigned_access_rights.h"
#include "bacdcode.h"
int bacapp_encode_assigned_access_rights(
uint8_t * apdu,
BACNET_ASSIGNED_ACCESS_RIGHTS * aar)
int bacapp_encode_assigned_access_rights(uint8_t* apdu,
BACNET_ASSIGNED_ACCESS_RIGHTS* aar)
{
int len;
int apdu_len = 0;
len =
bacapp_encode_context_device_obj_ref(&apdu[apdu_len], 0,
&aar->assigned_access_rights);
len = bacapp_encode_context_device_obj_ref(&apdu[apdu_len], 0,
&aar->assigned_access_rights);
if (len < 0)
return -1;
else
@@ -52,9 +49,7 @@ int bacapp_encode_assigned_access_rights(
}
int bacapp_encode_context_assigned_access_rights(
uint8_t * apdu,
uint8_t tag,
BACNET_ASSIGNED_ACCESS_RIGHTS * aar)
uint8_t* apdu, uint8_t tag, BACNET_ASSIGNED_ACCESS_RIGHTS* aar)
{
int len;
int apdu_len = 0;
@@ -69,20 +64,17 @@ int bacapp_encode_context_assigned_access_rights(
apdu_len += len;
return apdu_len;
}
int bacapp_decode_assigned_access_rights(
uint8_t * apdu,
BACNET_ASSIGNED_ACCESS_RIGHTS * aar)
int bacapp_decode_assigned_access_rights(uint8_t* apdu,
BACNET_ASSIGNED_ACCESS_RIGHTS* aar)
{
int len;
int apdu_len = 0;
if (decode_is_context_tag(&apdu[apdu_len], 0)) {
len =
bacapp_decode_context_device_obj_ref(&apdu[apdu_len], 0,
&aar->assigned_access_rights);
len = bacapp_decode_context_device_obj_ref(
&apdu[apdu_len], 0, &aar->assigned_access_rights);
if (len < 0)
return -1;
else
@@ -103,9 +95,7 @@ int bacapp_decode_assigned_access_rights(
}
int bacapp_decode_context_assigned_access_rights(
uint8_t * apdu,
uint8_t tag,
BACNET_ASSIGNED_ACCESS_RIGHTS * aar)
uint8_t* apdu, uint8_t tag, BACNET_ASSIGNED_ACCESS_RIGHTS* aar)
{
int len = 0;
int section_length;
+30 -38
View File
@@ -1,35 +1,33 @@
/**************************************************************************
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include "authentication_factor.h"
#include "bacdcode.h"
int bacapp_encode_authentication_factor(
uint8_t * apdu,
BACNET_AUTHENTICATION_FACTOR * af)
int bacapp_encode_authentication_factor(uint8_t* apdu,
BACNET_AUTHENTICATION_FACTOR* af)
{
int len;
int apdu_len = 0;
@@ -56,9 +54,7 @@ int bacapp_encode_authentication_factor(
}
int bacapp_encode_context_authentication_factor(
uint8_t * apdu,
uint8_t tag,
BACNET_AUTHENTICATION_FACTOR * af)
uint8_t* apdu, uint8_t tag, BACNET_AUTHENTICATION_FACTOR* af)
{
int len;
int apdu_len = 0;
@@ -73,12 +69,10 @@ int bacapp_encode_context_authentication_factor(
apdu_len += len;
return apdu_len;
}
int bacapp_decode_authentication_factor(
uint8_t * apdu,
BACNET_AUTHENTICATION_FACTOR * af)
int bacapp_decode_authentication_factor(uint8_t* apdu,
BACNET_AUTHENTICATION_FACTOR* af)
{
int len;
int apdu_len = 0;
@@ -109,14 +103,12 @@ int bacapp_decode_authentication_factor(
apdu_len += len;
} else
return -1;
return apdu_len;
}
int bacapp_decode_context_authentication_factor(
uint8_t * apdu,
uint8_t tag,
BACNET_AUTHENTICATION_FACTOR * af)
uint8_t* apdu, uint8_t tag, BACNET_AUTHENTICATION_FACTOR* af)
{
int len = 0;
int section_length;
+32 -43
View File
@@ -1,35 +1,33 @@
/**************************************************************************
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include "bacdcode.h"
#include "authentication_factor_format.h"
int bacapp_encode_authentication_factor_format(
uint8_t * apdu,
BACNET_AUTHENTICATION_FACTOR_FORMAT * aff)
uint8_t* apdu, BACNET_AUTHENTICATION_FACTOR_FORMAT* aff)
{
int len;
int apdu_len = 0;
@@ -57,9 +55,7 @@ int bacapp_encode_authentication_factor_format(
}
int bacapp_encode_context_authentication_factor_format(
uint8_t * apdu,
uint8_t tag,
BACNET_AUTHENTICATION_FACTOR_FORMAT * aff)
uint8_t* apdu, uint8_t tag, BACNET_AUTHENTICATION_FACTOR_FORMAT* aff)
{
int len;
int apdu_len = 0;
@@ -74,20 +70,16 @@ int bacapp_encode_context_authentication_factor_format(
apdu_len += len;
return apdu_len;
}
int bacapp_decode_authentication_factor_format(
uint8_t * apdu,
BACNET_AUTHENTICATION_FACTOR_FORMAT * aff)
uint8_t* apdu, BACNET_AUTHENTICATION_FACTOR_FORMAT* aff)
{
int len;
int apdu_len = 0;
if (decode_is_context_tag(&apdu[apdu_len], 0)) {
len =
decode_context_enumerated(&apdu[apdu_len], 0,
&aff->format_type);
len = decode_context_enumerated(&apdu[apdu_len], 0, &aff->format_type);
if (len < 0)
return -1;
else
@@ -101,8 +93,8 @@ int bacapp_decode_authentication_factor_format(
return -1;
else
apdu_len += len;
if ((aff->format_type != AUTHENTICATION_FACTOR_CUSTOM)
&& (aff->vendor_id != 0))
if ((aff->format_type != AUTHENTICATION_FACTOR_CUSTOM) &&
(aff->vendor_id != 0))
return -1;
}
@@ -112,8 +104,8 @@ int bacapp_decode_authentication_factor_format(
return -1;
else
apdu_len += len;
if ((aff->format_type != AUTHENTICATION_FACTOR_CUSTOM)
&& (aff->vendor_format != 0))
if ((aff->format_type != AUTHENTICATION_FACTOR_CUSTOM) &&
(aff->vendor_format != 0))
return -1;
}
@@ -121,9 +113,7 @@ int bacapp_decode_authentication_factor_format(
}
int bacapp_decode_context_authentication_factor_format(
uint8_t * apdu,
uint8_t tag,
BACNET_AUTHENTICATION_FACTOR_FORMAT * aff)
uint8_t* apdu, uint8_t tag, BACNET_AUTHENTICATION_FACTOR_FORMAT* aff)
{
int len = 0;
int section_length;
@@ -147,5 +137,4 @@ int bacapp_decode_context_authentication_factor_format(
len = -1;
}
return len;
}
+88 -135
View File
@@ -40,46 +40,38 @@
/** @file awf.c Atomic Write File */
/* encode service */
int awf_encode_apdu(
uint8_t * apdu,
uint8_t invoke_id,
BACNET_ATOMIC_WRITE_FILE_DATA * data)
int awf_encode_apdu(uint8_t *apdu, 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 */
uint32_t i = 0;
if (apdu) {
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU);
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 +=
encode_application_object_id(&apdu[apdu_len], data->object_type,
data->object_instance);
apdu_len += encode_application_object_id(
&apdu[apdu_len], data->object_type, data->object_instance);
switch (data->access) {
case FILE_STREAM_ACCESS:
apdu_len += encode_opening_tag(&apdu[apdu_len], 0);
apdu_len +=
encode_application_signed(&apdu[apdu_len],
data->type.stream.fileStartPosition);
apdu_len +=
encode_application_octet_string(&apdu[apdu_len],
&data->fileData[0]);
apdu_len += encode_application_signed(
&apdu[apdu_len], data->type.stream.fileStartPosition);
apdu_len += encode_application_octet_string(&apdu[apdu_len],
&data->fileData[0]);
apdu_len += encode_closing_tag(&apdu[apdu_len], 0);
break;
case FILE_RECORD_ACCESS:
apdu_len += encode_opening_tag(&apdu[apdu_len], 1);
apdu_len +=
encode_application_signed(&apdu[apdu_len],
data->type.record.fileStartRecord);
apdu_len +=
encode_application_unsigned(&apdu[apdu_len],
data->type.record.returnedRecordCount);
apdu_len += encode_application_signed(
&apdu[apdu_len], data->type.record.fileStartRecord);
apdu_len += encode_application_unsigned(
&apdu[apdu_len], data->type.record.returnedRecordCount);
for (i = 0; i < data->type.record.returnedRecordCount; i++) {
apdu_len +=
encode_application_octet_string(&apdu[apdu_len],
&data->fileData[i]);
apdu_len += encode_application_octet_string(
&apdu[apdu_len], &data->fileData[i]);
}
apdu_len += encode_closing_tag(&apdu[apdu_len], 1);
break;
@@ -92,10 +84,8 @@ int awf_encode_apdu(
}
/* decode the service request only */
int awf_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
BACNET_ATOMIC_WRITE_FILE_DATA * data)
int awf_decode_service_request(uint8_t *apdu, unsigned apdu_len,
BACNET_ATOMIC_WRITE_FILE_DATA *data)
{
int len = 0;
int tag_len = 0;
@@ -104,41 +94,37 @@ int awf_decode_service_request(
uint32_t len_value_type = 0;
int32_t signed_value = 0;
uint32_t unsigned_value = 0;
uint16_t type = 0; /* for decoding */
uint16_t type = 0; /* for decoding */
uint32_t i = 0;
/* check for value pointers */
if (apdu_len && data) {
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)
return -1;
len += decode_object_id(&apdu[len], &type, &data->object_instance);
data->object_type = (BACNET_OBJECT_TYPE) type;
data->object_type = (BACNET_OBJECT_TYPE)type;
if (decode_is_opening_tag_number(&apdu[len], 0)) {
data->access = FILE_STREAM_ACCESS;
/* a tag number of 2 is not extended so only one octet */
len++;
/* fileStartPosition */
tag_len =
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
tag_len = decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_SIGNED_INT)
return -1;
len += decode_signed(&apdu[len], len_value_type, &signed_value);
data->type.stream.fileStartPosition = signed_value;
/* fileData */
tag_len =
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
tag_len = decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_OCTET_STRING)
return -1;
decoded_len =
decode_octet_string(&apdu[len], len_value_type,
&data->fileData[0]);
decoded_len = decode_octet_string(&apdu[len], len_value_type,
&data->fileData[0]);
if ((uint32_t)decoded_len != len_value_type) {
return -1;
}
@@ -152,35 +138,30 @@ int awf_decode_service_request(
/* a tag number is not extended so only one octet */
len++;
/* fileStartRecord */
tag_len =
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
tag_len = decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_SIGNED_INT)
return -1;
len += decode_signed(&apdu[len], len_value_type, &signed_value);
data->type.record.fileStartRecord = signed_value;
/* returnedRecordCount */
tag_len =
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
tag_len = decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT)
return -1;
len +=
decode_unsigned(&apdu[len], len_value_type, &unsigned_value);
len += decode_unsigned(&apdu[len], len_value_type, &unsigned_value);
data->type.record.returnedRecordCount = unsigned_value;
/* fileData */
for (i = 0; i < data->type.record.returnedRecordCount; i++) {
tag_len =
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
tag_len = decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_OCTET_STRING)
return -1;
decoded_len =
decode_octet_string(&apdu[len], len_value_type,
&data->fileData[i]);
decoded_len = decode_octet_string(&apdu[len], len_value_type,
&data->fileData[i]);
if ((uint32_t)decoded_len != len_value_type) {
return -1;
}
@@ -197,11 +178,8 @@ int awf_decode_service_request(
return len;
}
int awf_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
uint8_t * invoke_id,
BACNET_ATOMIC_WRITE_FILE_DATA * data)
int awf_decode_apdu(uint8_t *apdu, unsigned apdu_len, uint8_t *invoke_id,
BACNET_ATOMIC_WRITE_FILE_DATA *data)
{
int len = 0;
unsigned offset = 0;
@@ -212,7 +190,7 @@ int awf_decode_apdu(
if (apdu[0] != PDU_TYPE_CONFIRMED_SERVICE_REQUEST)
return -1;
/* apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU); */
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
if (apdu[3] != SERVICE_CONFIRMED_ATOMIC_WRITE_FILE)
return -1;
offset = 4;
@@ -225,28 +203,24 @@ int awf_decode_apdu(
return len;
}
int awf_ack_encode_apdu(
uint8_t * apdu,
uint8_t invoke_id,
BACNET_ATOMIC_WRITE_FILE_DATA * data)
int awf_ack_encode_apdu(uint8_t *apdu, 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) {
apdu[0] = PDU_TYPE_COMPLEX_ACK;
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;
switch (data->access) {
case FILE_STREAM_ACCESS:
apdu_len +=
encode_context_signed(&apdu[apdu_len], 0,
data->type.stream.fileStartPosition);
apdu_len += encode_context_signed(
&apdu[apdu_len], 0, data->type.stream.fileStartPosition);
break;
case FILE_RECORD_ACCESS:
apdu_len +=
encode_context_signed(&apdu[apdu_len], 1,
data->type.record.fileStartRecord);
apdu_len += encode_context_signed(
&apdu[apdu_len], 1, data->type.record.fileStartRecord);
break;
default:
break;
@@ -257,10 +231,8 @@ int awf_ack_encode_apdu(
}
/* decode the service request only */
int awf_ack_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
BACNET_ATOMIC_WRITE_FILE_DATA * data)
int awf_ack_decode_service_request(uint8_t *apdu, unsigned apdu_len,
BACNET_ATOMIC_WRITE_FILE_DATA *data)
{
int len = 0;
uint8_t tag_number = 0;
@@ -269,18 +241,15 @@ int awf_ack_decode_service_request(
/* check for value pointers */
if (apdu_len && data) {
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 == 0) {
data->access = FILE_STREAM_ACCESS;
len +=
decode_signed(&apdu[len], len_value_type,
&data->type.stream.fileStartPosition);
len += decode_signed(&apdu[len], len_value_type,
&data->type.stream.fileStartPosition);
} else if (tag_number == 1) {
data->access = FILE_RECORD_ACCESS;
len +=
decode_signed(&apdu[len], len_value_type,
&data->type.record.fileStartRecord);
len += decode_signed(&apdu[len], len_value_type,
&data->type.record.fileStartRecord);
} else
return -1;
}
@@ -288,11 +257,8 @@ int awf_ack_decode_service_request(
return len;
}
int awf_ack_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
uint8_t * invoke_id,
BACNET_ATOMIC_WRITE_FILE_DATA * data)
int awf_ack_decode_apdu(uint8_t *apdu, unsigned apdu_len, uint8_t *invoke_id,
BACNET_ATOMIC_WRITE_FILE_DATA *data)
{
int len = 0;
unsigned offset = 0;
@@ -302,15 +268,14 @@ int awf_ack_decode_apdu(
/* optional checking - most likely was already done prior to this call */
if (apdu[0] != PDU_TYPE_COMPLEX_ACK)
return -1;
*invoke_id = apdu[1]; /* invoke id - filled in by net layer */
*invoke_id = apdu[1]; /* invoke id - filled in by net layer */
if (apdu[2] != SERVICE_CONFIRMED_ATOMIC_WRITE_FILE)
return -1;
offset = 3;
if (apdu_len > offset) {
len =
awf_ack_decode_service_request(&apdu[offset], apdu_len - offset,
data);
len = awf_ack_decode_service_request(&apdu[offset], apdu_len - offset,
data);
}
return len;
@@ -321,12 +286,10 @@ int awf_ack_decode_apdu(
#include <string.h>
#include "ctest.h"
void testAtomicWriteFileAccess(
Test * pTest,
BACNET_ATOMIC_WRITE_FILE_DATA * data)
void testAtomicWriteFileAccess(Test *pTest, BACNET_ATOMIC_WRITE_FILE_DATA *data)
{
BACNET_ATOMIC_WRITE_FILE_DATA test_data = { 0 };
uint8_t apdu[480] = { 0 };
BACNET_ATOMIC_WRITE_FILE_DATA test_data = {0};
uint8_t apdu[480] = {0};
int len = 0;
int apdu_len = 0;
uint8_t invoke_id = 128;
@@ -342,29 +305,24 @@ void testAtomicWriteFileAccess(
ct_test(pTest, test_data.object_instance == data->object_instance);
ct_test(pTest, test_data.access == data->access);
if (test_data.access == FILE_STREAM_ACCESS) {
ct_test(pTest,
test_data.type.stream.fileStartPosition ==
data->type.stream.fileStartPosition);
ct_test(pTest, test_data.type.stream.fileStartPosition ==
data->type.stream.fileStartPosition);
} else if (test_data.access == FILE_RECORD_ACCESS) {
ct_test(pTest,
test_data.type.record.fileStartRecord ==
data->type.record.fileStartRecord);
ct_test(pTest,
test_data.type.record.returnedRecordCount ==
data->type.record.returnedRecordCount);
ct_test(pTest, test_data.type.record.fileStartRecord ==
data->type.record.fileStartRecord);
ct_test(pTest, test_data.type.record.returnedRecordCount ==
data->type.record.returnedRecordCount);
}
ct_test(pTest,
octetstring_length(&test_data.fileData[0]) ==
octetstring_length(&data->fileData[0]));
ct_test(pTest, octetstring_length(&test_data.fileData[0]) ==
octetstring_length(&data->fileData[0]));
ct_test(pTest, memcmp(octetstring_value(&test_data.fileData[0]),
octetstring_value(&data->fileData[0]),
octetstring_length(&test_data.fileData[0])) == 0);
octetstring_value(&data->fileData[0]),
octetstring_length(&test_data.fileData[0])) == 0);
}
void testAtomicWriteFile(
Test * pTest)
void testAtomicWriteFile(Test *pTest)
{
BACNET_ATOMIC_WRITE_FILE_DATA data = { 0 };
BACNET_ATOMIC_WRITE_FILE_DATA data = {0};
uint8_t test_octet_string[32] = "Joshua-Mary-Anna-Christopher";
data.object_type = OBJECT_FILE;
@@ -372,7 +330,7 @@ void testAtomicWriteFile(
data.access = FILE_STREAM_ACCESS;
data.type.stream.fileStartPosition = 0;
octetstring_init(&data.fileData[0], test_octet_string,
sizeof(test_octet_string));
sizeof(test_octet_string));
testAtomicWriteFileAccess(pTest, &data);
data.object_type = OBJECT_FILE;
@@ -381,18 +339,17 @@ void testAtomicWriteFile(
data.type.record.fileStartRecord = 1;
data.type.record.returnedRecordCount = 1;
octetstring_init(&data.fileData[0], test_octet_string,
sizeof(test_octet_string));
sizeof(test_octet_string));
testAtomicWriteFileAccess(pTest, &data);
return;
}
void testAtomicWriteFileAckAccess(
Test * pTest,
BACNET_ATOMIC_WRITE_FILE_DATA * data)
void testAtomicWriteFileAckAccess(Test *pTest,
BACNET_ATOMIC_WRITE_FILE_DATA *data)
{
BACNET_ATOMIC_WRITE_FILE_DATA test_data = { 0 };
uint8_t apdu[480] = { 0 };
BACNET_ATOMIC_WRITE_FILE_DATA test_data = {0};
uint8_t apdu[480] = {0};
int len = 0;
int apdu_len = 0;
uint8_t invoke_id = 128;
@@ -406,20 +363,17 @@ void testAtomicWriteFileAckAccess(
ct_test(pTest, len != -1);
ct_test(pTest, test_data.access == data->access);
if (test_data.access == FILE_STREAM_ACCESS) {
ct_test(pTest,
test_data.type.stream.fileStartPosition ==
data->type.stream.fileStartPosition);
ct_test(pTest, test_data.type.stream.fileStartPosition ==
data->type.stream.fileStartPosition);
} else if (test_data.access == FILE_RECORD_ACCESS) {
ct_test(pTest,
test_data.type.record.fileStartRecord ==
data->type.record.fileStartRecord);
ct_test(pTest, test_data.type.record.fileStartRecord ==
data->type.record.fileStartRecord);
}
}
void testAtomicWriteFileAck(
Test * pTest)
void testAtomicWriteFileAck(Test *pTest)
{
BACNET_ATOMIC_WRITE_FILE_DATA data = { 0 };
BACNET_ATOMIC_WRITE_FILE_DATA data = {0};
data.access = FILE_STREAM_ACCESS;
data.type.stream.fileStartPosition = 42;
@@ -433,8 +387,7 @@ void testAtomicWriteFileAck(
}
#ifdef TEST_ATOMIC_WRITE_FILE
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -448,7 +401,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+5 -9
View File
@@ -40,9 +40,7 @@
/** @file bacaddr.c BACnet Address structure utilities */
void bacnet_address_copy(
BACNET_ADDRESS * dest,
BACNET_ADDRESS * src)
void bacnet_address_copy(BACNET_ADDRESS* dest, BACNET_ADDRESS* src)
{
int i = 0;
@@ -59,14 +57,12 @@ void bacnet_address_copy(
}
}
bool bacnet_address_same(
BACNET_ADDRESS * dest,
BACNET_ADDRESS * src)
bool bacnet_address_same(BACNET_ADDRESS* dest, BACNET_ADDRESS* src)
{
uint8_t i = 0; /* loop counter */
uint8_t max_len = 0; /* used for dynamic max */
uint8_t i = 0; /* loop counter */
uint8_t max_len = 0; /* used for dynamic max */
if (dest == src) /* same ? */
if (dest == src) /* same ? */
return true;
if (dest->net != src->net)
+458 -612
View File
File diff suppressed because it is too large Load Diff
+320 -600
View File
File diff suppressed because it is too large Load Diff
+71 -96
View File
@@ -38,12 +38,12 @@
#include "timestamp.h"
#include "bacdevobjpropref.h"
/** @file bacdevobjpropref.c BACnet Application Device Object (Property) Reference */
/** @file bacdevobjpropref.c BACnet Application Device Object (Property)
* Reference */
int bacapp_encode_context_device_obj_property_ref(
uint8_t * apdu,
uint8_t tag_number,
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value)
uint8_t *apdu, uint8_t tag_number,
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE *value)
{
int len;
int apdu_len = 0;
@@ -71,21 +71,19 @@ int bacapp_encode_context_device_obj_property_ref(
}
*/
int bacapp_encode_device_obj_property_ref(
uint8_t * apdu,
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value)
uint8_t *apdu, BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE *value)
{
int len;
int apdu_len = 0;
/* object-identifier [0] BACnetObjectIdentifier */
len =
encode_context_object_id(&apdu[apdu_len], 0,
(int) value->objectIdentifier.type, value->objectIdentifier.instance);
len = encode_context_object_id(&apdu[apdu_len], 0,
(int)value->objectIdentifier.type,
value->objectIdentifier.instance);
apdu_len += len;
/* property-identifier [1] BACnetPropertyIdentifier */
len =
encode_context_enumerated(&apdu[apdu_len], 1,
value->propertyIdentifier);
len = encode_context_enumerated(&apdu[apdu_len], 1,
value->propertyIdentifier);
apdu_len += len;
/* property-array-index [2] Unsigned OPTIONAL */
/* Check if needed before inserting */
@@ -96,12 +94,11 @@ int bacapp_encode_device_obj_property_ref(
/* device-identifier [3] BACnetObjectIdentifier OPTIONAL */
/* Likewise, device id is optional so see if needed
* (set type to BACNET_NO_DEV_TYPE or something other than OBJECT_DEVICE to
* omit */
* omit */
if (value->deviceIdentifier.type == OBJECT_DEVICE) {
len =
encode_context_object_id(&apdu[apdu_len], 3,
(int) value->deviceIdentifier.type,
value->deviceIdentifier.instance);
len = encode_context_object_id(&apdu[apdu_len], 3,
(int)value->deviceIdentifier.type,
value->deviceIdentifier.instance);
apdu_len += len;
}
return apdu_len;
@@ -118,34 +115,31 @@ int bacapp_encode_device_obj_property_ref(
}
*/
int bacapp_decode_device_obj_property_ref(
uint8_t * apdu,
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value)
uint8_t *apdu, BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE *value)
{
int len;
int apdu_len = 0;
uint32_t enumValue;
/* object-identifier [0] BACnetObjectIdentifier */
if (-1 == (len =
decode_context_object_id(&apdu[apdu_len], 0,
&value->objectIdentifier.type,
&value->objectIdentifier.instance))) {
if (-1 == (len = decode_context_object_id(
&apdu[apdu_len], 0, &value->objectIdentifier.type,
&value->objectIdentifier.instance))) {
return -1;
}
apdu_len += len;
/* property-identifier [1] BACnetPropertyIdentifier */
if (-1 == (len =
decode_context_enumerated(&apdu[apdu_len], 1, &enumValue))) {
if (-1 ==
(len = decode_context_enumerated(&apdu[apdu_len], 1, &enumValue))) {
return -1;
}
value->propertyIdentifier = (BACNET_PROPERTY_ID) enumValue;
value->propertyIdentifier = (BACNET_PROPERTY_ID)enumValue;
apdu_len += len;
/* property-array-index [2] Unsigned OPTIONAL */
if (decode_is_context_tag(&apdu[apdu_len], 2) &&
!decode_is_closing_tag(&apdu[apdu_len])) {
if (-1 == (len =
decode_context_unsigned(&apdu[apdu_len], 2,
&value->arrayIndex))) {
if (-1 == (len = decode_context_unsigned(&apdu[apdu_len], 2,
&value->arrayIndex))) {
return -1;
}
apdu_len += len;
@@ -155,25 +149,23 @@ int bacapp_decode_device_obj_property_ref(
/* device-identifier [3] BACnetObjectIdentifier OPTIONAL */
if (decode_is_context_tag(&apdu[apdu_len], 3) &&
!decode_is_closing_tag(&apdu[apdu_len])) {
if (-1 == (len =
decode_context_object_id(&apdu[apdu_len], 3,
&value->deviceIdentifier.type,
&value->deviceIdentifier.instance))) {
if (-1 == (len = decode_context_object_id(
&apdu[apdu_len], 3, &value->deviceIdentifier.type,
&value->deviceIdentifier.instance))) {
return -1;
}
apdu_len += len;
} else {
value->deviceIdentifier.type = BACNET_NO_DEV_TYPE;
value->deviceIdentifier.instance = BACNET_NO_DEV_ID;
value->deviceIdentifier.type = BACNET_NO_DEV_TYPE;
value->deviceIdentifier.instance = BACNET_NO_DEV_ID;
}
return apdu_len;
}
int bacapp_decode_context_device_obj_property_ref(
uint8_t * apdu,
uint8_t tag_number,
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value)
uint8_t *apdu, uint8_t tag_number,
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE *value)
{
int len = 0;
int section_length;
@@ -199,15 +191,12 @@ int bacapp_decode_context_device_obj_property_ref(
return len;
}
/* BACnetDeviceObjectReference ::= SEQUENCE {
device-identifier [0] BACnetObjectIdentifier OPTIONAL,
object-identifier [1] BACnetObjectIdentifier
}*/
int bacapp_encode_context_device_obj_ref(
uint8_t * apdu,
uint8_t tag_number,
BACNET_DEVICE_OBJECT_REFERENCE * value)
int bacapp_encode_context_device_obj_ref(uint8_t *apdu, uint8_t tag_number,
BACNET_DEVICE_OBJECT_REFERENCE *value)
{
int len;
int apdu_len = 0;
@@ -228,9 +217,8 @@ int bacapp_encode_context_device_obj_ref(
device-identifier [0] BACnetObjectIdentifier OPTIONAL,
object-identifier [1] BACnetObjectIdentifier
}*/
int bacapp_encode_device_obj_ref(
uint8_t * apdu,
BACNET_DEVICE_OBJECT_REFERENCE * value)
int bacapp_encode_device_obj_ref(uint8_t *apdu,
BACNET_DEVICE_OBJECT_REFERENCE *value)
{
int len;
int apdu_len = 0;
@@ -238,18 +226,17 @@ int bacapp_encode_device_obj_ref(
/* device-identifier [0] BACnetObjectIdentifier OPTIONAL */
/* Device id is optional so see if needed
* (set type to BACNET_NO_DEV_TYPE or something other than OBJECT_DEVICE to
* omit */
* omit */
if (value->deviceIdentifier.type == OBJECT_DEVICE) {
len =
encode_context_object_id(&apdu[apdu_len], 0,
(int) value->deviceIdentifier.type,
value->deviceIdentifier.instance);
len = encode_context_object_id(&apdu[apdu_len], 0,
(int)value->deviceIdentifier.type,
value->deviceIdentifier.instance);
apdu_len += len;
}
/* object-identifier [1] BACnetObjectIdentifier */
len =
encode_context_object_id(&apdu[apdu_len], 1,
(int) value->objectIdentifier.type, value->objectIdentifier.instance);
len = encode_context_object_id(&apdu[apdu_len], 1,
(int)value->objectIdentifier.type,
value->objectIdentifier.instance);
apdu_len += len;
return apdu_len;
@@ -259,9 +246,8 @@ int bacapp_encode_device_obj_ref(
device-identifier [0] BACnetObjectIdentifier OPTIONAL,
object-identifier [1] BACnetObjectIdentifier
}*/
int bacapp_decode_device_obj_ref(
uint8_t * apdu,
BACNET_DEVICE_OBJECT_REFERENCE * value)
int bacapp_decode_device_obj_ref(uint8_t *apdu,
BACNET_DEVICE_OBJECT_REFERENCE *value)
{
int len;
int apdu_len = 0;
@@ -269,22 +255,20 @@ int bacapp_decode_device_obj_ref(
/* device-identifier [0] BACnetObjectIdentifier OPTIONAL */
if (decode_is_context_tag(&apdu[apdu_len], 0) &&
!decode_is_closing_tag(&apdu[apdu_len])) {
if (-1 == (len =
decode_context_object_id(&apdu[apdu_len], 0,
&value->deviceIdentifier.type,
&value->deviceIdentifier.instance))) {
if (-1 == (len = decode_context_object_id(
&apdu[apdu_len], 0, &value->deviceIdentifier.type,
&value->deviceIdentifier.instance))) {
return -1;
}
apdu_len += len;
} else {
value->deviceIdentifier.type = BACNET_NO_DEV_TYPE;
value->deviceIdentifier.instance = BACNET_NO_DEV_ID;
value->deviceIdentifier.type = BACNET_NO_DEV_TYPE;
value->deviceIdentifier.instance = BACNET_NO_DEV_ID;
}
/* object-identifier [1] BACnetObjectIdentifier */
if (-1 == (len =
decode_context_object_id(&apdu[apdu_len], 1,
&value->objectIdentifier.type,
&value->objectIdentifier.instance))) {
if (-1 == (len = decode_context_object_id(
&apdu[apdu_len], 1, &value->objectIdentifier.type,
&value->objectIdentifier.instance))) {
return -1;
}
apdu_len += len;
@@ -292,10 +276,8 @@ int bacapp_decode_device_obj_ref(
return apdu_len;
}
int bacapp_decode_context_device_obj_ref(
uint8_t * apdu,
uint8_t tag_number,
BACNET_DEVICE_OBJECT_REFERENCE * value)
int bacapp_decode_context_device_obj_ref(uint8_t *apdu, uint8_t tag_number,
BACNET_DEVICE_OBJECT_REFERENCE *value)
{
int len = 0;
int section_length;
@@ -324,9 +306,8 @@ int bacapp_decode_context_device_obj_ref(
#include <assert.h>
#include <string.h>
#include "ctest.h"
static void testDevObjPropRef(
Test * pTest,
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE *inData)
static void testDevObjPropRef(Test *pTest,
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE *inData)
{
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE outData;
uint8_t buffer[MAX_APDU] = {0};
@@ -341,10 +322,10 @@ static void testDevObjPropRef(
/* decode */
outLen = bacapp_decode_device_obj_property_ref(buffer, &outData);
ct_test(pTest, outLen == inLen);
ct_test(pTest, inData->objectIdentifier.instance ==
outData.objectIdentifier.instance);
ct_test(pTest,
inData->objectIdentifier.instance == outData.objectIdentifier.instance);
ct_test(pTest,
inData->objectIdentifier.type == outData.objectIdentifier.type);
inData->objectIdentifier.type == outData.objectIdentifier.type);
ct_test(pTest, inData->propertyIdentifier == outData.propertyIdentifier);
if (inData->arrayIndex != BACNET_ARRAY_ALL) {
ct_test(pTest, inData->arrayIndex == outData.arrayIndex);
@@ -352,19 +333,17 @@ static void testDevObjPropRef(
ct_test(pTest, outData.arrayIndex == BACNET_ARRAY_ALL);
}
if (inData->deviceIdentifier.type == OBJECT_DEVICE) {
ct_test(pTest, inData->deviceIdentifier.instance ==
outData.deviceIdentifier.instance);
ct_test(pTest,
inData->deviceIdentifier.instance ==
outData.deviceIdentifier.instance);
ct_test(pTest,
inData->deviceIdentifier.type == outData.deviceIdentifier.type);
inData->deviceIdentifier.type == outData.deviceIdentifier.type);
} else {
ct_test(pTest,outData.deviceIdentifier.instance == BACNET_NO_DEV_ID);
ct_test(pTest,outData.deviceIdentifier.type == BACNET_NO_DEV_TYPE);
ct_test(pTest, outData.deviceIdentifier.instance == BACNET_NO_DEV_ID);
ct_test(pTest, outData.deviceIdentifier.type == BACNET_NO_DEV_TYPE);
}
}
static void testDevIdPropRef(
Test * pTest)
static void testDevIdPropRef(Test *pTest)
{
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE inData;
@@ -402,8 +381,7 @@ static void testDevIdPropRef(
testDevObjPropRef(pTest, &inData);
}
static void testDevIdRef(
Test * pTest)
static void testDevIdRef(Test *pTest)
{
BACNET_DEVICE_OBJECT_REFERENCE inData;
BACNET_DEVICE_OBJECT_REFERENCE outData;
@@ -416,15 +394,13 @@ static void testDevIdRef(
inLen = bacapp_encode_device_obj_ref(buffer, &inData);
outLen = bacapp_decode_device_obj_ref(buffer, &outData);
ct_test(pTest, outLen == inLen);
ct_test(pTest, inData.deviceIdentifier.instance ==
outData.deviceIdentifier.instance);
ct_test(pTest,
inData.deviceIdentifier.instance ==
outData.deviceIdentifier.instance);
ct_test(pTest,
inData.deviceIdentifier.type == outData.deviceIdentifier.type);
inData.deviceIdentifier.type == outData.deviceIdentifier.type);
}
void testBACnetDeviceObjectPropertyReference(
Test * pTest)
void testBACnetDeviceObjectPropertyReference(Test *pTest)
{
bool rc;
@@ -437,8 +413,7 @@ void testBACnetDeviceObjectPropertyReference(
#ifdef TEST_DEV_ID_PROP_REF
#include <assert.h>
int main(
void)
int main(void)
{
Test *pTest;
@@ -447,7 +422,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+55 -77
View File
@@ -40,14 +40,12 @@
/** @file bacerror.c Encode/Decode BACnet Errors */
/* encode service */
int bacerror_encode_apdu(
uint8_t * apdu,
uint8_t invoke_id,
BACNET_CONFIRMED_SERVICE service,
BACNET_ERROR_CLASS error_class,
BACNET_ERROR_CODE error_code)
int bacerror_encode_apdu(uint8_t *apdu, uint8_t invoke_id,
BACNET_CONFIRMED_SERVICE service,
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) {
apdu[0] = PDU_TYPE_ERROR;
@@ -55,8 +53,7 @@ int bacerror_encode_apdu(
apdu[2] = service;
apdu_len = 3;
/* service parameters */
apdu_len +=
encode_application_enumerated(&apdu[apdu_len], error_class);
apdu_len += encode_application_enumerated(&apdu[apdu_len], error_class);
apdu_len += encode_application_enumerated(&apdu[apdu_len], error_code);
}
@@ -65,11 +62,9 @@ int bacerror_encode_apdu(
#if !BACNET_SVC_SERVER
/* decode the application class and code */
int bacerror_decode_error_class_and_code(
uint8_t * apdu,
unsigned apdu_len,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
int bacerror_decode_error_class_and_code(uint8_t *apdu, unsigned apdu_len,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code)
{
int len = 0;
uint8_t tag_number = 0;
@@ -78,36 +73,32 @@ int bacerror_decode_error_class_and_code(
if (apdu_len) {
/* error class */
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
if (tag_number != BACNET_APPLICATION_TAG_ENUMERATED)
return 0;
len += decode_enumerated(&apdu[len], len_value_type, &decoded_value);
if (error_class)
*error_class = (BACNET_ERROR_CLASS) decoded_value;
*error_class = (BACNET_ERROR_CLASS)decoded_value;
/* error code */
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
if (tag_number != BACNET_APPLICATION_TAG_ENUMERATED)
return 0;
len += decode_enumerated(&apdu[len], len_value_type, &decoded_value);
if (error_code)
*error_code = (BACNET_ERROR_CODE) decoded_value;
*error_code = (BACNET_ERROR_CODE)decoded_value;
}
return len;
}
/* decode the service request only */
int bacerror_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
uint8_t * invoke_id,
BACNET_CONFIRMED_SERVICE * service,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
int bacerror_decode_service_request(uint8_t *apdu, unsigned apdu_len,
uint8_t *invoke_id,
BACNET_CONFIRMED_SERVICE *service,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code)
{
int len = 0;
@@ -115,11 +106,10 @@ int bacerror_decode_service_request(
if (invoke_id)
*invoke_id = apdu[0];
if (service)
*service = (BACNET_CONFIRMED_SERVICE) apdu[1];
*service = (BACNET_CONFIRMED_SERVICE)apdu[1];
/* decode the application class and code */
len =
bacerror_decode_error_class_and_code(&apdu[2], apdu_len - 2,
error_class, error_code);
len = bacerror_decode_error_class_and_code(&apdu[2], apdu_len - 2,
error_class, error_code);
}
return len;
@@ -132,13 +122,10 @@ int bacerror_decode_service_request(
#include "ctest.h"
/* decode the whole APDU - mainly used for unit testing */
int bacerror_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
uint8_t * invoke_id,
BACNET_CONFIRMED_SERVICE * service,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
int bacerror_decode_apdu(uint8_t *apdu, unsigned apdu_len, uint8_t *invoke_id,
BACNET_CONFIRMED_SERVICE *service,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code)
{
int len = 0;
@@ -149,19 +136,18 @@ int bacerror_decode_apdu(
if (apdu[0] != PDU_TYPE_ERROR)
return -1;
if (apdu_len > 1) {
len =
bacerror_decode_service_request(&apdu[1], apdu_len - 1,
invoke_id, service, error_class, error_code);
len = bacerror_decode_service_request(&apdu[1], apdu_len - 1,
invoke_id, service,
error_class, error_code);
}
}
return len;
}
void testBACError(
Test * pTest)
void testBACError(Test *pTest)
{
uint8_t apdu[480] = { 0 };
uint8_t apdu[480] = {0};
int len = 0;
int apdu_len = 0;
uint8_t invoke_id = 0;
@@ -173,15 +159,14 @@ void testBACError(
BACNET_ERROR_CLASS test_error_class = 0;
BACNET_ERROR_CODE test_error_code = 0;
len =
bacerror_encode_apdu(&apdu[0], invoke_id, service, error_class,
error_code);
len = bacerror_encode_apdu(&apdu[0], invoke_id, service, error_class,
error_code);
ct_test(pTest, len != 0);
apdu_len = len;
len =
bacerror_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_service, &test_error_class, &test_error_code);
bacerror_decode_apdu(&apdu[0], apdu_len, &test_invoke_id, &test_service,
&test_error_class, &test_error_code);
ct_test(pTest, len != -1);
ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest, test_service == service);
@@ -191,37 +176,33 @@ void testBACError(
/* change type to get negative response */
apdu[0] = PDU_TYPE_ABORT;
len =
bacerror_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_service, &test_error_class, &test_error_code);
bacerror_decode_apdu(&apdu[0], apdu_len, &test_invoke_id, &test_service,
&test_error_class, &test_error_code);
ct_test(pTest, len == -1);
/* test NULL APDU */
len =
bacerror_decode_apdu(NULL, apdu_len, &test_invoke_id, &test_service,
&test_error_class, &test_error_code);
len = bacerror_decode_apdu(NULL, apdu_len, &test_invoke_id, &test_service,
&test_error_class, &test_error_code);
ct_test(pTest, len == -1);
/* force a zero length */
len =
bacerror_decode_apdu(&apdu[0], 0, &test_invoke_id, &test_service,
&test_error_class, &test_error_code);
len = bacerror_decode_apdu(&apdu[0], 0, &test_invoke_id, &test_service,
&test_error_class, &test_error_code);
ct_test(pTest, len == 0);
/* check them all... */
for (service = 0; service < MAX_BACNET_CONFIRMED_SERVICE; service++) {
for (error_class = 0; error_class < ERROR_CLASS_PROPRIETARY_FIRST;
error_class++) {
error_class++) {
for (error_code = 0; error_code < ERROR_CODE_PROPRIETARY_FIRST;
error_code++) {
len =
bacerror_encode_apdu(&apdu[0], invoke_id, service,
error_class, error_code);
error_code++) {
len = bacerror_encode_apdu(&apdu[0], invoke_id, service,
error_class, error_code);
apdu_len = len;
ct_test(pTest, len != 0);
len =
bacerror_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_service, &test_error_class, &test_error_code);
len = bacerror_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_service, &test_error_class,
&test_error_code);
ct_test(pTest, len != -1);
ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest, test_service == service);
@@ -235,25 +216,22 @@ void testBACError(
service = 255;
error_class = ERROR_CLASS_PROPRIETARY_LAST;
error_code = ERROR_CODE_PROPRIETARY_LAST;
len =
bacerror_encode_apdu(&apdu[0], invoke_id, service, error_class,
error_code);
len = bacerror_encode_apdu(&apdu[0], invoke_id, service, error_class,
error_code);
apdu_len = len;
ct_test(pTest, len != 0);
len =
bacerror_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_service, &test_error_class, &test_error_code);
bacerror_decode_apdu(&apdu[0], apdu_len, &test_invoke_id, &test_service,
&test_error_class, &test_error_code);
ct_test(pTest, len != -1);
ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest, test_service == service);
ct_test(pTest, test_error_class == error_class);
ct_test(pTest, test_error_code == error_code);
}
#ifdef TEST_BACERROR
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -265,7 +243,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+94 -128
View File
@@ -41,73 +41,61 @@
/** @file bacint.c Encode/Decode Integer Types */
int encode_unsigned16(
uint8_t * apdu,
uint16_t value)
int encode_unsigned16(uint8_t *apdu, uint16_t value)
{
apdu[0] = (uint8_t) ((value & 0xff00) >> 8);
apdu[1] = (uint8_t) (value & 0x00ff);
apdu[0] = (uint8_t)((value & 0xff00) >> 8);
apdu[1] = (uint8_t)(value & 0x00ff);
return 2;
}
int decode_unsigned16(
uint8_t * apdu,
uint16_t * value)
int decode_unsigned16(uint8_t *apdu, uint16_t *value)
{
if (value) {
*value = (uint16_t) ((((uint16_t) apdu[0]) << 8) & 0xff00);
*value |= ((uint16_t) (((uint16_t) apdu[1]) & 0x00ff));
*value = (uint16_t)((((uint16_t)apdu[0]) << 8) & 0xff00);
*value |= ((uint16_t)(((uint16_t)apdu[1]) & 0x00ff));
}
return 2;
}
int encode_unsigned24(
uint8_t * apdu,
uint32_t value)
int encode_unsigned24(uint8_t *apdu, uint32_t value)
{
apdu[0] = (uint8_t) ((value & 0xff0000) >> 16);
apdu[1] = (uint8_t) ((value & 0x00ff00) >> 8);
apdu[2] = (uint8_t) (value & 0x0000ff);
apdu[0] = (uint8_t)((value & 0xff0000) >> 16);
apdu[1] = (uint8_t)((value & 0x00ff00) >> 8);
apdu[2] = (uint8_t)(value & 0x0000ff);
return 3;
}
int decode_unsigned24(
uint8_t * apdu,
uint32_t * value)
int decode_unsigned24(uint8_t *apdu, uint32_t *value)
{
if (value) {
*value = ((uint32_t) ((((uint32_t) apdu[0]) << 16) & 0x00ff0000));
*value |= (uint32_t) ((((uint32_t) apdu[1]) << 8) & 0x0000ff00);
*value |= ((uint32_t) (((uint32_t) apdu[2]) & 0x000000ff));
*value = ((uint32_t)((((uint32_t)apdu[0]) << 16) & 0x00ff0000));
*value |= (uint32_t)((((uint32_t)apdu[1]) << 8) & 0x0000ff00);
*value |= ((uint32_t)(((uint32_t)apdu[2]) & 0x000000ff));
}
return 3;
}
int encode_unsigned32(
uint8_t * apdu,
uint32_t value)
int encode_unsigned32(uint8_t *apdu, uint32_t value)
{
apdu[0] = (uint8_t) ((value & 0xff000000) >> 24);
apdu[1] = (uint8_t) ((value & 0x00ff0000) >> 16);
apdu[2] = (uint8_t) ((value & 0x0000ff00) >> 8);
apdu[3] = (uint8_t) (value & 0x000000ff);
apdu[0] = (uint8_t)((value & 0xff000000) >> 24);
apdu[1] = (uint8_t)((value & 0x00ff0000) >> 16);
apdu[2] = (uint8_t)((value & 0x0000ff00) >> 8);
apdu[3] = (uint8_t)(value & 0x000000ff);
return 4;
}
int decode_unsigned32(
uint8_t * apdu,
uint32_t * value)
int decode_unsigned32(uint8_t *apdu, uint32_t *value)
{
if (value) {
*value = ((uint32_t) ((((uint32_t) apdu[0]) << 24) & 0xff000000));
*value |= ((uint32_t) ((((uint32_t) apdu[1]) << 16) & 0x00ff0000));
*value |= ((uint32_t) ((((uint32_t) apdu[2]) << 8) & 0x0000ff00));
*value |= ((uint32_t) (((uint32_t) apdu[3]) & 0x000000ff));
*value = ((uint32_t)((((uint32_t)apdu[0]) << 24) & 0xff000000));
*value |= ((uint32_t)((((uint32_t)apdu[1]) << 16) & 0x00ff0000));
*value |= ((uint32_t)((((uint32_t)apdu[2]) << 8) & 0x0000ff00));
*value |= ((uint32_t)(((uint32_t)apdu[3]) & 0x000000ff));
}
return 4;
@@ -120,18 +108,16 @@ int decode_unsigned32(
* @param value - 16-bit value to encode
* @return Returns the number of bytes encoded
*/
int encode_unsigned64(
uint8_t * buffer,
uint64_t value)
int encode_unsigned64(uint8_t *buffer, uint64_t value)
{
buffer[0] = (uint8_t) ((value & 0xff00000000000000) >> 56);
buffer[1] = (uint8_t) ((value & 0x00ff000000000000) >> 48);
buffer[2] = (uint8_t) ((value & 0x0000ff0000000000) >> 40);
buffer[3] = (uint8_t) ((value & 0x000000ff00000000) >> 32);
buffer[4] = (uint8_t) ((value & 0x00000000ff000000) >> 24);
buffer[5] = (uint8_t) ((value & 0x0000000000ff0000) >> 16);
buffer[6] = (uint8_t) ((value & 0x000000000000ff00) >> 8);
buffer[7] = (uint8_t) (value & 0x00000000000000ff);
buffer[0] = (uint8_t)((value & 0xff00000000000000) >> 56);
buffer[1] = (uint8_t)((value & 0x00ff000000000000) >> 48);
buffer[2] = (uint8_t)((value & 0x0000ff0000000000) >> 40);
buffer[3] = (uint8_t)((value & 0x000000ff00000000) >> 32);
buffer[4] = (uint8_t)((value & 0x00000000ff000000) >> 24);
buffer[5] = (uint8_t)((value & 0x0000000000ff0000) >> 16);
buffer[6] = (uint8_t)((value & 0x000000000000ff00) >> 8);
buffer[7] = (uint8_t)(value & 0x00000000000000ff);
return 8;
}
@@ -142,19 +128,24 @@ int encode_unsigned64(
* @param value - pointer to 64-bit value to store the decoded value
* @return Returns the number of bytes decoded
*/
int decode_unsigned64(
uint8_t * buffer,
uint64_t * value)
int decode_unsigned64(uint8_t *buffer, uint64_t *value)
{
if (value) {
*value = ((uint64_t) ((((uint64_t) buffer[0]) << 56) & 0xff00000000000000));
*value |= ((uint64_t) ((((uint64_t) buffer[1]) << 48) & 0x00ff000000000000));
*value |= ((uint64_t) ((((uint64_t) buffer[2]) << 40) & 0x0000ff0000000000));
*value |= ((uint64_t) ((((uint64_t) buffer[3]) << 32) & 0x000000ff00000000));
*value |= ((uint64_t) ((((uint64_t) buffer[4]) << 24) & 0x00000000ff000000));
*value |= ((uint64_t) ((((uint64_t) buffer[5]) << 16) & 0x0000000000ff0000));
*value |= ((uint64_t) ((((uint64_t) buffer[6]) << 8) & 0x000000000000ff00));
*value |= ((uint64_t) (((uint64_t) buffer[7]) & 0x00000000000000ff));
*value =
((uint64_t)((((uint64_t)buffer[0]) << 56) & 0xff00000000000000));
*value |=
((uint64_t)((((uint64_t)buffer[1]) << 48) & 0x00ff000000000000));
*value |=
((uint64_t)((((uint64_t)buffer[2]) << 40) & 0x0000ff0000000000));
*value |=
((uint64_t)((((uint64_t)buffer[3]) << 32) & 0x000000ff00000000));
*value |=
((uint64_t)((((uint64_t)buffer[4]) << 24) & 0x00000000ff000000));
*value |=
((uint64_t)((((uint64_t)buffer[5]) << 16) & 0x0000000000ff0000));
*value |=
((uint64_t)((((uint64_t)buffer[6]) << 8) & 0x000000000000ff00));
*value |= ((uint64_t)(((uint64_t)buffer[7]) & 0x00000000000000ff));
}
return 8;
@@ -162,18 +153,14 @@ int decode_unsigned64(
#endif
#if BACNET_USE_SIGNED
int encode_signed8(
uint8_t * apdu,
int8_t value)
int encode_signed8(uint8_t *apdu, int8_t value)
{
apdu[0] = (uint8_t) value;
apdu[0] = (uint8_t)value;
return 1;
}
int decode_signed8(
uint8_t * apdu,
int32_t * value)
int decode_signed8(uint8_t *apdu, int32_t *value)
{
if (value) {
/* negative - bit 7 is set */
@@ -181,25 +168,21 @@ int decode_signed8(
*value = 0xFFFFFF00;
else
*value = 0;
*value |= ((int32_t) (((int32_t) apdu[0]) & 0x000000ff));
*value |= ((int32_t)(((int32_t)apdu[0]) & 0x000000ff));
}
return 1;
}
int encode_signed16(
uint8_t * apdu,
int16_t value)
int encode_signed16(uint8_t *apdu, int16_t value)
{
apdu[0] = (uint8_t) ((value & 0xff00) >> 8);
apdu[1] = (uint8_t) (value & 0x00ff);
apdu[0] = (uint8_t)((value & 0xff00) >> 8);
apdu[1] = (uint8_t)(value & 0x00ff);
return 2;
}
int decode_signed16(
uint8_t * apdu,
int32_t * value)
int decode_signed16(uint8_t *apdu, int32_t *value)
{
if (value) {
/* negative - bit 7 is set */
@@ -207,27 +190,23 @@ int decode_signed16(
*value = 0xFFFF0000;
else
*value = 0;
*value |= ((int32_t) ((((int32_t) apdu[0]) << 8) & 0x0000ff00));
*value |= ((int32_t) (((int32_t) apdu[1]) & 0x000000ff));
*value |= ((int32_t)((((int32_t)apdu[0]) << 8) & 0x0000ff00));
*value |= ((int32_t)(((int32_t)apdu[1]) & 0x000000ff));
}
return 2;
}
int encode_signed24(
uint8_t * apdu,
int32_t value)
int encode_signed24(uint8_t *apdu, int32_t value)
{
apdu[0] = (uint8_t) ((value & 0xff0000) >> 16);
apdu[1] = (uint8_t) ((value & 0x00ff00) >> 8);
apdu[2] = (uint8_t) (value & 0x0000ff);
apdu[0] = (uint8_t)((value & 0xff0000) >> 16);
apdu[1] = (uint8_t)((value & 0x00ff00) >> 8);
apdu[2] = (uint8_t)(value & 0x0000ff);
return 3;
}
int decode_signed24(
uint8_t * apdu,
int32_t * value)
int decode_signed24(uint8_t *apdu, int32_t *value)
{
if (value) {
/* negative - bit 7 is set */
@@ -235,35 +214,31 @@ int decode_signed24(
*value = 0xFF000000;
else
*value = 0;
*value |= ((int32_t) ((((int32_t) apdu[0]) << 16) & 0x00ff0000));
*value |= ((int32_t) ((((int32_t) apdu[1]) << 8) & 0x0000ff00));
*value |= ((int32_t) (((int32_t) apdu[2]) & 0x000000ff));
*value |= ((int32_t)((((int32_t)apdu[0]) << 16) & 0x00ff0000));
*value |= ((int32_t)((((int32_t)apdu[1]) << 8) & 0x0000ff00));
*value |= ((int32_t)(((int32_t)apdu[2]) & 0x000000ff));
}
return 3;
}
int encode_signed32(
uint8_t * apdu,
int32_t value)
int encode_signed32(uint8_t *apdu, int32_t value)
{
apdu[0] = (uint8_t) ((value & 0xff000000) >> 24);
apdu[1] = (uint8_t) ((value & 0x00ff0000) >> 16);
apdu[2] = (uint8_t) ((value & 0x0000ff00) >> 8);
apdu[3] = (uint8_t) (value & 0x000000ff);
apdu[0] = (uint8_t)((value & 0xff000000) >> 24);
apdu[1] = (uint8_t)((value & 0x00ff0000) >> 16);
apdu[2] = (uint8_t)((value & 0x0000ff00) >> 8);
apdu[3] = (uint8_t)(value & 0x000000ff);
return 4;
}
int decode_signed32(
uint8_t * apdu,
int32_t * value)
int decode_signed32(uint8_t *apdu, int32_t *value)
{
if (value) {
*value = ((int32_t) ((((int32_t) apdu[0]) << 24) & 0xff000000));
*value |= ((int32_t) ((((int32_t) apdu[1]) << 16) & 0x00ff0000));
*value |= ((int32_t) ((((int32_t) apdu[2]) << 8) & 0x0000ff00));
*value |= ((int32_t) (((int32_t) apdu[3]) & 0x000000ff));
*value = ((int32_t)((((int32_t)apdu[0]) << 24) & 0xff000000));
*value |= ((int32_t)((((int32_t)apdu[1]) << 16) & 0x00ff0000));
*value |= ((int32_t)((((int32_t)apdu[2]) << 8) & 0x0000ff00));
*value |= ((int32_t)(((int32_t)apdu[3]) & 0x000000ff));
}
return 4;
@@ -276,10 +251,9 @@ int decode_signed32(
#include <ctype.h>
#include "ctest.h"
static void testBACnetUnsigned16(
Test * pTest)
static void testBACnetUnsigned16(Test *pTest)
{
uint8_t apdu[32] = { 0 };
uint8_t apdu[32] = {0};
uint16_t value = 0, test_value = 0;
int len = 0;
@@ -293,10 +267,9 @@ static void testBACnetUnsigned16(
}
}
static void testBACnetUnsigned24(
Test * pTest)
static void testBACnetUnsigned24(Test *pTest)
{
uint8_t apdu[32] = { 0 };
uint8_t apdu[32] = {0};
uint32_t value = 0, test_value = 0;
int len = 0;
@@ -310,10 +283,9 @@ static void testBACnetUnsigned24(
}
}
static void testBACnetUnsigned32(
Test * pTest)
static void testBACnetUnsigned32(Test *pTest)
{
uint8_t apdu[32] = { 0 };
uint8_t apdu[32] = {0};
uint32_t value = 0, test_value = 0;
int len = 0;
@@ -327,10 +299,9 @@ static void testBACnetUnsigned32(
}
}
static void testBACnetSigned8(
Test * pTest)
static void testBACnetSigned8(Test *pTest)
{
uint8_t apdu[32] = { 0 };
uint8_t apdu[32] = {0};
int32_t value = 0, test_value = 0;
int len = 0;
@@ -344,10 +315,9 @@ static void testBACnetSigned8(
}
}
static void testBACnetSigned16(
Test * pTest)
static void testBACnetSigned16(Test *pTest)
{
uint8_t apdu[32] = { 0 };
uint8_t apdu[32] = {0};
int32_t value = 0, test_value = 0;
int len = 0;
@@ -361,10 +331,9 @@ static void testBACnetSigned16(
}
}
static void testBACnetSigned24(
Test * pTest)
static void testBACnetSigned24(Test *pTest)
{
uint8_t apdu[32] = { 0 };
uint8_t apdu[32] = {0};
int32_t value = 0, test_value = 0;
int len = 0;
@@ -376,10 +345,9 @@ static void testBACnetSigned24(
}
}
static void testBACnetSigned32(
Test * pTest)
static void testBACnetSigned32(Test *pTest)
{
uint8_t apdu[32] = { 0 };
uint8_t apdu[32] = {0};
int32_t value = 0, test_value = 0;
int len = 0;
@@ -397,8 +365,7 @@ static void testBACnetSigned32(
}
}
void testBACnetIntegers(
Test * pTest)
void testBACnetIntegers(Test *pTest)
{
bool rc;
@@ -421,8 +388,7 @@ void testBACnetIntegers(
}
#ifdef TEST_BACINT
int main(
void)
int main(void)
{
Test *pTest;
@@ -431,7 +397,7 @@ int main(
/* configure output */
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+25 -50
View File
@@ -13,9 +13,9 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to
along with this program; if not, write to
The Free Software Foundation, Inc.
59 Temple Place - Suite 330
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA.
As a special exception, if other files instantiate templates or
@@ -41,49 +41,28 @@
/** @file bacprop.c Lookup BACnet Property Tags */
PROP_TAG_DATA bacnet_object_device_property_tag_map[] = {
{PROP_OBJECT_IDENTIFIER, BACNET_APPLICATION_TAG_OBJECT_ID}
,
{PROP_OBJECT_NAME, BACNET_APPLICATION_TAG_CHARACTER_STRING}
,
{PROP_OBJECT_TYPE, BACNET_APPLICATION_TAG_ENUMERATED}
,
{PROP_SYSTEM_STATUS, BACNET_APPLICATION_TAG_ENUMERATED}
,
{PROP_VENDOR_NAME, BACNET_APPLICATION_TAG_CHARACTER_STRING}
,
{PROP_VENDOR_IDENTIFIER, BACNET_APPLICATION_TAG_UNSIGNED_INT}
,
{PROP_MODEL_NAME, BACNET_APPLICATION_TAG_CHARACTER_STRING}
,
{PROP_FIRMWARE_REVISION, BACNET_APPLICATION_TAG_CHARACTER_STRING}
,
{PROP_OBJECT_IDENTIFIER, BACNET_APPLICATION_TAG_OBJECT_ID},
{PROP_OBJECT_NAME, BACNET_APPLICATION_TAG_CHARACTER_STRING},
{PROP_OBJECT_TYPE, BACNET_APPLICATION_TAG_ENUMERATED},
{PROP_SYSTEM_STATUS, BACNET_APPLICATION_TAG_ENUMERATED},
{PROP_VENDOR_NAME, BACNET_APPLICATION_TAG_CHARACTER_STRING},
{PROP_VENDOR_IDENTIFIER, BACNET_APPLICATION_TAG_UNSIGNED_INT},
{PROP_MODEL_NAME, BACNET_APPLICATION_TAG_CHARACTER_STRING},
{PROP_FIRMWARE_REVISION, BACNET_APPLICATION_TAG_CHARACTER_STRING},
{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}
};
BACNET_APPLICATION_TAG_CHARACTER_STRING},
{PROP_PROTOCOL_VERSION, BACNET_APPLICATION_TAG_UNSIGNED_INT},
{PROP_PROTOCOL_CONFORMANCE_CLASS, BACNET_APPLICATION_TAG_UNSIGNED_INT},
{PROP_PROTOCOL_SERVICES_SUPPORTED, BACNET_APPLICATION_TAG_BIT_STRING},
{PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED, BACNET_APPLICATION_TAG_BIT_STRING},
{PROP_MAX_APDU_LENGTH_ACCEPTED, BACNET_APPLICATION_TAG_UNSIGNED_INT},
{PROP_SEGMENTATION_SUPPORTED, BACNET_APPLICATION_TAG_ENUMERATED},
{PROP_APDU_TIMEOUT, BACNET_APPLICATION_TAG_UNSIGNED_INT},
{PROP_NUMBER_OF_APDU_RETRIES, BACNET_APPLICATION_TAG_UNSIGNED_INT},
{-1, -1}};
signed bacprop_tag_by_index_default(
PROP_TAG_DATA * data_list,
signed index,
signed default_ret)
signed bacprop_tag_by_index_default(PROP_TAG_DATA* data_list, signed index,
signed default_ret)
{
signed pUnsigned = 0;
@@ -100,16 +79,12 @@ signed bacprop_tag_by_index_default(
return pUnsigned ? pUnsigned : default_ret;
}
signed bacprop_property_tag(
BACNET_OBJECT_TYPE type,
signed prop)
signed bacprop_property_tag(BACNET_OBJECT_TYPE type, signed prop)
{
switch (type) {
case OBJECT_DEVICE:
return
bacprop_tag_by_index_default
(bacnet_object_device_property_tag_map, prop, -1);
return bacprop_tag_by_index_default(
bacnet_object_device_property_tag_map, prop, -1);
default:
#if PRINT_ENABLED
fprintf(stderr, "Unsupported object type");
+87 -122
View File
@@ -39,9 +39,7 @@
/** @file bacpropstates.c Encode/Decode BACnet Application Property States */
int bacapp_decode_property_state(
uint8_t * apdu,
BACNET_PROPERTY_STATE * value)
int bacapp_decode_property_state(uint8_t *apdu, BACNET_PROPERTY_STATE *value)
{
int len = 0;
uint32_t len_value_type;
@@ -63,120 +61,107 @@ int bacapp_decode_property_state(
break;
case BINARY_VALUE:
if (-1 == (section_length =
decode_enumerated(&apdu[len], len_value_type,
&enumValue))) {
if (-1 == (section_length = decode_enumerated(
&apdu[len], len_value_type, &enumValue))) {
return -1;
}
value->state.binaryValue = (BACNET_BINARY_PV) enumValue;
value->state.binaryValue = (BACNET_BINARY_PV)enumValue;
break;
case EVENT_TYPE:
if (-1 == (section_length =
decode_enumerated(&apdu[len], len_value_type,
&enumValue))) {
if (-1 == (section_length = decode_enumerated(
&apdu[len], len_value_type, &enumValue))) {
return -1;
}
value->state.eventType = (BACNET_EVENT_TYPE) enumValue;
value->state.eventType = (BACNET_EVENT_TYPE)enumValue;
break;
case POLARITY:
if (-1 == (section_length =
decode_enumerated(&apdu[len], len_value_type,
&enumValue))) {
if (-1 == (section_length = decode_enumerated(
&apdu[len], len_value_type, &enumValue))) {
return -1;
}
value->state.polarity = (BACNET_POLARITY) enumValue;
value->state.polarity = (BACNET_POLARITY)enumValue;
break;
case PROGRAM_CHANGE:
if (-1 == (section_length =
decode_enumerated(&apdu[len], len_value_type,
&enumValue))) {
if (-1 == (section_length = decode_enumerated(
&apdu[len], len_value_type, &enumValue))) {
return -1;
}
value->state.programChange = (BACNET_PROGRAM_REQUEST) enumValue;
value->state.programChange = (BACNET_PROGRAM_REQUEST)enumValue;
break;
case PROGRAM_STATE:
if (-1 == (section_length =
decode_enumerated(&apdu[len], len_value_type,
&enumValue))) {
if (-1 == (section_length = decode_enumerated(
&apdu[len], len_value_type, &enumValue))) {
return -1;
}
value->state.programState = (BACNET_PROGRAM_STATE) enumValue;
value->state.programState = (BACNET_PROGRAM_STATE)enumValue;
break;
case REASON_FOR_HALT:
if (-1 == (section_length =
decode_enumerated(&apdu[len], len_value_type,
&enumValue))) {
if (-1 == (section_length = decode_enumerated(
&apdu[len], len_value_type, &enumValue))) {
return -1;
}
value->state.programError = (BACNET_PROGRAM_ERROR) enumValue;
value->state.programError = (BACNET_PROGRAM_ERROR)enumValue;
break;
case RELIABILITY:
if (-1 == (section_length =
decode_enumerated(&apdu[len], len_value_type,
&enumValue))) {
if (-1 == (section_length = decode_enumerated(
&apdu[len], len_value_type, &enumValue))) {
return -1;
}
value->state.reliability = (BACNET_RELIABILITY) enumValue;
value->state.reliability = (BACNET_RELIABILITY)enumValue;
break;
case STATE:
if (-1 == (section_length =
decode_enumerated(&apdu[len], len_value_type,
&enumValue))) {
if (-1 == (section_length = decode_enumerated(
&apdu[len], len_value_type, &enumValue))) {
return -1;
}
value->state.state = (BACNET_EVENT_STATE) enumValue;
value->state.state = (BACNET_EVENT_STATE)enumValue;
break;
case SYSTEM_STATUS:
if (-1 == (section_length =
decode_enumerated(&apdu[len], len_value_type,
&enumValue))) {
if (-1 == (section_length = decode_enumerated(
&apdu[len], len_value_type, &enumValue))) {
return -1;
}
value->state.systemStatus = (BACNET_DEVICE_STATUS) enumValue;
value->state.systemStatus = (BACNET_DEVICE_STATUS)enumValue;
break;
case UNITS:
if (-1 == (section_length =
decode_enumerated(&apdu[len], len_value_type,
&enumValue))) {
if (-1 == (section_length = decode_enumerated(
&apdu[len], len_value_type, &enumValue))) {
return -1;
}
value->state.units = (BACNET_ENGINEERING_UNITS) enumValue;
value->state.units = (BACNET_ENGINEERING_UNITS)enumValue;
break;
case UNSIGNED_VALUE:
if (-1 == (section_length =
decode_unsigned(&apdu[len], len_value_type,
&value->state.unsignedValue))) {
decode_unsigned(&apdu[len], len_value_type,
&value->state.unsignedValue))) {
return -1;
}
break;
case LIFE_SAFETY_MODE:
if (-1 == (section_length =
decode_enumerated(&apdu[len], len_value_type,
&enumValue))) {
if (-1 == (section_length = decode_enumerated(
&apdu[len], len_value_type, &enumValue))) {
return -1;
}
value->state.lifeSafetyMode = (BACNET_LIFE_SAFETY_MODE) enumValue;
value->state.lifeSafetyMode = (BACNET_LIFE_SAFETY_MODE)enumValue;
break;
case LIFE_SAFETY_STATE:
if (-1 == (section_length =
decode_enumerated(&apdu[len], len_value_type,
&enumValue))) {
if (-1 == (section_length = decode_enumerated(
&apdu[len], len_value_type, &enumValue))) {
return -1;
}
value->state.lifeSafetyState =
(BACNET_LIFE_SAFETY_STATE) enumValue;
value->state.lifeSafetyState = (BACNET_LIFE_SAFETY_STATE)enumValue;
break;
default:
@@ -187,10 +172,8 @@ int bacapp_decode_property_state(
return len;
}
int bacapp_decode_context_property_state(
uint8_t * apdu,
uint8_t tag_number,
BACNET_PROPERTY_STATE * value)
int bacapp_decode_context_property_state(uint8_t *apdu, uint8_t tag_number,
BACNET_PROPERTY_STATE *value)
{
int len = 0;
int section_length;
@@ -215,59 +198,49 @@ int bacapp_decode_context_property_state(
return len;
}
int bacapp_encode_property_state(
uint8_t * apdu,
BACNET_PROPERTY_STATE * value)
int bacapp_encode_property_state(uint8_t *apdu, BACNET_PROPERTY_STATE *value)
{
int len = 0; /* length of each encoding */
int len = 0; /* length of each encoding */
if (value && apdu) {
switch (value->tag) {
case BOOLEAN_VALUE:
len =
encode_context_boolean(&apdu[0], 0,
value->state.booleanValue);
len = encode_context_boolean(&apdu[0], 0,
value->state.booleanValue);
break;
case BINARY_VALUE:
len =
encode_context_enumerated(&apdu[0], 1,
value->state.binaryValue);
len = encode_context_enumerated(&apdu[0], 1,
value->state.binaryValue);
break;
case EVENT_TYPE:
len =
encode_context_enumerated(&apdu[0], 2,
value->state.eventType);
len = encode_context_enumerated(&apdu[0], 2,
value->state.eventType);
break;
case POLARITY:
len =
encode_context_enumerated(&apdu[0], 3,
value->state.polarity);
len = encode_context_enumerated(&apdu[0], 3,
value->state.polarity);
break;
case PROGRAM_CHANGE:
len =
encode_context_enumerated(&apdu[0], 4,
value->state.programChange);
len = encode_context_enumerated(&apdu[0], 4,
value->state.programChange);
break;
case PROGRAM_STATE:
len =
encode_context_enumerated(&apdu[0], 5,
value->state.programState);
len = encode_context_enumerated(&apdu[0], 5,
value->state.programState);
break;
case REASON_FOR_HALT:
len =
encode_context_enumerated(&apdu[0], 6,
value->state.programError);
len = encode_context_enumerated(&apdu[0], 6,
value->state.programError);
break;
case RELIABILITY:
len =
encode_context_enumerated(&apdu[0], 7,
value->state.reliability);
len = encode_context_enumerated(&apdu[0], 7,
value->state.reliability);
break;
case STATE:
@@ -276,33 +249,28 @@ int bacapp_encode_property_state(
break;
case SYSTEM_STATUS:
len =
encode_context_enumerated(&apdu[0], 9,
value->state.systemStatus);
len = encode_context_enumerated(&apdu[0], 9,
value->state.systemStatus);
break;
case UNITS:
len =
encode_context_enumerated(&apdu[0], 10,
value->state.units);
encode_context_enumerated(&apdu[0], 10, value->state.units);
break;
case UNSIGNED_VALUE:
len =
encode_context_unsigned(&apdu[0], 11,
value->state.unsignedValue);
len = encode_context_unsigned(&apdu[0], 11,
value->state.unsignedValue);
break;
case LIFE_SAFETY_MODE:
len =
encode_context_enumerated(&apdu[0], 12,
value->state.lifeSafetyMode);
len = encode_context_enumerated(&apdu[0], 12,
value->state.lifeSafetyMode);
break;
case LIFE_SAFETY_STATE:
len =
encode_context_enumerated(&apdu[0], 13,
value->state.lifeSafetyState);
len = encode_context_enumerated(&apdu[0], 13,
value->state.lifeSafetyState);
break;
default:
@@ -314,10 +282,9 @@ int bacapp_encode_property_state(
}
#ifdef TEST
#include <string.h> /* for memset */
#include <string.h> /* for memset */
void testPropStates(
Test * pTest)
void testPropStates(Test *pTest)
{
BACNET_PROPERTY_STATE inData;
BACNET_PROPERTY_STATE outData;
@@ -338,9 +305,9 @@ void testPropStates(
ct_test(pTest, inData.tag == outData.tag);
ct_test(pTest, inData.state.booleanValue == outData.state.booleanValue);
/****************
*****************
****************/
/****************
*****************
****************/
inData.tag = BINARY_VALUE;
inData.state.binaryValue = BINARY_ACTIVE;
@@ -354,9 +321,9 @@ void testPropStates(
ct_test(pTest, inData.tag == outData.tag);
ct_test(pTest, inData.state.binaryValue == outData.state.binaryValue);
/****************
*****************
****************/
/****************
*****************
****************/
inData.tag = EVENT_TYPE;
inData.state.eventType = EVENT_BUFFER_READY;
@@ -370,9 +337,9 @@ void testPropStates(
ct_test(pTest, inData.tag == outData.tag);
ct_test(pTest, inData.state.eventType == outData.state.eventType);
/****************
*****************
****************/
/****************
*****************
****************/
inData.tag = POLARITY;
inData.state.polarity = POLARITY_REVERSE;
@@ -386,9 +353,9 @@ void testPropStates(
ct_test(pTest, inData.tag == outData.tag);
ct_test(pTest, inData.state.polarity == outData.state.polarity);
/****************
*****************
****************/
/****************
*****************
****************/
inData.tag = PROGRAM_CHANGE;
inData.state.programChange = PROGRAM_REQUEST_RESTART;
@@ -402,9 +369,9 @@ void testPropStates(
ct_test(pTest, inData.tag == outData.tag);
ct_test(pTest, inData.state.programChange == outData.state.programChange);
/****************
*****************
****************/
/****************
*****************
****************/
inData.tag = UNSIGNED_VALUE;
inData.state.unsignedValue = 0xdeadbeef;
@@ -417,13 +384,11 @@ void testPropStates(
ct_test(pTest, outLen == inLen);
ct_test(pTest, inData.tag == outData.tag);
ct_test(pTest, inData.state.unsignedValue == outData.state.unsignedValue);
}
#ifdef TEST_PROP_STATES
#include <assert.h>
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -435,7 +400,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+19 -43
View File
@@ -52,9 +52,7 @@
/* from clause 20.2.6 Encoding of a Real Number Value */
/* returns the number of apdu bytes consumed */
int decode_real(
uint8_t * apdu,
float *real_value)
int decode_real(uint8_t *apdu, float *real_value)
{
union {
uint8_t byte[4];
@@ -79,30 +77,23 @@ int decode_real(
return 4;
}
int decode_real_safe(
uint8_t * apdu,
uint32_t len_value,
float *real_value)
int decode_real_safe(uint8_t *apdu, uint32_t len_value, float *real_value)
{
if (len_value != 4) {
*real_value = 0.0f;
return (int) len_value;
return (int)len_value;
} else {
return decode_real(apdu, real_value);
}
}
int decode_context_real(
uint8_t * apdu,
uint8_t tag_number,
float *real_value)
int decode_context_real(uint8_t *apdu, uint8_t tag_number, float *real_value)
{
uint32_t len_value;
int len = 0;
if (decode_is_context_tag(&apdu[len], tag_number)) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number, &len_value);
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value);
len += decode_real(&apdu[len], real_value);
} else {
len = -1;
@@ -112,9 +103,7 @@ int decode_context_real(
/* from clause 20.2.6 Encoding of a Real Number Value */
/* returns the number of apdu bytes consumed */
int encode_bacnet_real(
float value,
uint8_t * apdu)
int encode_bacnet_real(float value, uint8_t *apdu)
{
union {
uint8_t byte[4];
@@ -142,9 +131,7 @@ int encode_bacnet_real(
/* from clause 20.2.7 Encoding of a Double Precision Real Number Value */
/* returns the number of apdu bytes consumed */
int decode_double(
uint8_t * apdu,
double *double_value)
int decode_double(uint8_t *apdu, double *double_value)
{
union {
uint8_t byte[8];
@@ -177,14 +164,11 @@ int decode_double(
return 8;
}
int decode_double_safe(
uint8_t * apdu,
uint32_t len_value,
double *double_value)
int decode_double_safe(uint8_t *apdu, uint32_t len_value, double *double_value)
{
if (len_value != 8) {
*double_value = 0.0;
return (int) len_value;
return (int)len_value;
} else {
return decode_double(apdu, double_value);
}
@@ -192,9 +176,7 @@ int decode_double_safe(
/* from clause 20.2.7 Encoding of a Double Precision Real Number Value */
/* returns the number of apdu bytes consumed */
int encode_bacnet_double(
double value,
uint8_t * apdu)
int encode_bacnet_double(double value, uint8_t *apdu)
{
union {
uint8_t byte[8];
@@ -226,17 +208,14 @@ int encode_bacnet_double(
return 8;
}
int decode_context_double(
uint8_t * apdu,
uint8_t tag_number,
double *double_value)
int decode_context_double(uint8_t *apdu, uint8_t tag_number,
double *double_value)
{
uint32_t len_value;
int len = 0;
if (decode_is_context_tag(&apdu[len], tag_number)) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number, &len_value);
len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value);
len += decode_double(&apdu[len], double_value);
} else {
len = -1;
@@ -252,11 +231,10 @@ int decode_context_double(
#include <ctype.h>
#include "ctest.h"
void testBACreal(
Test * pTest)
void testBACreal(Test *pTest)
{
float real_value = 3.14159F, test_real_value = 0.0;
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t apdu[MAX_APDU] = {0};
int len = 0, test_len = 0;
len = encode_bacnet_real(real_value, &apdu[0]);
@@ -266,11 +244,10 @@ void testBACreal(
ct_test(pTest, test_real_value == real_value);
}
void testBACdouble(
Test * pTest)
void testBACdouble(Test *pTest)
{
double double_value = 3.1415927, test_double_value = 0.0;
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t apdu[MAX_APDU] = {0};
int len = 0, test_len = 0;
len = encode_bacnet_double(double_value, &apdu[0]);
@@ -281,8 +258,7 @@ void testBACdouble(
}
#ifdef TEST_BACNET_REAL
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -297,7 +273,7 @@ int main(
/* configure output */
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+133 -168
View File
@@ -1,27 +1,27 @@
/**************************************************************************
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
@@ -30,17 +30,16 @@
BACNET_KEY_IDENTIFIER_ALGORITHM key_algorithm(uint16_t id)
{
return (BACNET_KEY_IDENTIFIER_ALGORITHM) ((id >> 8) & 0xFF);
return (BACNET_KEY_IDENTIFIER_ALGORITHM)((id >> 8) & 0xFF);
}
BACNET_KEY_IDENTIFIER_KEY_NUMBER key_number(uint16_t id)
{
return (BACNET_KEY_IDENTIFIER_KEY_NUMBER) (id & 0xFF);
return (BACNET_KEY_IDENTIFIER_KEY_NUMBER)(id & 0xFF);
}
int encode_security_wrapper(int bytes_before,
uint8_t * apdu,
BACNET_SECURITY_WRAPPER * wrapper)
int encode_security_wrapper(int bytes_before, uint8_t* apdu,
BACNET_SECURITY_WRAPPER* wrapper)
{
int curr = 0;
int enc_begin = 0;
@@ -115,19 +114,17 @@ int encode_security_wrapper(int bytes_before,
apdu[curr++] = wrapper->user_role;
if ((wrapper->authentication_mechanism >= 1) &&
(wrapper->authentication_mechanism <= 199)) {
curr +=
encode_unsigned16(&apdu[curr],
wrapper->authentication_data_length + 5);
curr += encode_unsigned16(&apdu[curr],
wrapper->authentication_data_length + 5);
memcpy(&apdu[curr], wrapper->authentication_data,
wrapper->authentication_data_length);
wrapper->authentication_data_length);
curr += wrapper->authentication_data_length;
} else if (wrapper->authentication_mechanism >= 200) {
curr +=
encode_unsigned16(&apdu[curr],
wrapper->authentication_data_length + 7);
curr += encode_unsigned16(&apdu[curr],
wrapper->authentication_data_length + 7);
curr += encode_unsigned16(&apdu[curr], wrapper->vendor_id);
memcpy(&apdu[curr], wrapper->authentication_data,
wrapper->authentication_data_length);
wrapper->authentication_data_length);
curr += wrapper->authentication_data_length;
}
}
@@ -135,14 +132,14 @@ int encode_security_wrapper(int bytes_before,
curr += wrapper->service_data_len;
/* signature calculation */
key_sign_msg(&key, &apdu[-bytes_before], (uint32_t)(bytes_before + curr),
wrapper->signature);
wrapper->signature);
/* padding and encryption */
if (wrapper->encrypted_flag) {
/* set encryption flag, signing is done */
apdu[0] |= 1 << 6;
/* handle padding */
key_set_padding(&key, curr - enc_begin, &wrapper->padding_len,
wrapper->padding);
wrapper->padding);
if (wrapper->padding_len > 2) {
memcpy(&apdu[curr], wrapper->padding, wrapper->padding_len - 2);
curr += wrapper->padding_len - 2;
@@ -150,7 +147,7 @@ int encode_security_wrapper(int bytes_before,
curr += encode_unsigned16(&apdu[curr], wrapper->padding_len);
/* encryption */
key_encrypt_msg(&key, &apdu[enc_begin], (uint32_t)(curr - enc_begin),
wrapper->signature);
wrapper->signature);
}
memcpy(&apdu[curr], wrapper->signature, SIGNATURE_LEN);
curr += SIGNATURE_LEN;
@@ -158,8 +155,7 @@ int encode_security_wrapper(int bytes_before,
return curr;
}
int encode_challenge_request(uint8_t * apdu,
BACNET_CHALLENGE_REQUEST * bc_req)
int encode_challenge_request(uint8_t* apdu, BACNET_CHALLENGE_REQUEST* bc_req)
{
int curr = 0;
@@ -170,8 +166,7 @@ int encode_challenge_request(uint8_t * apdu,
return curr;
}
int encode_security_payload(uint8_t * apdu,
BACNET_SECURITY_PAYLOAD * payload)
int encode_security_payload(uint8_t* apdu, BACNET_SECURITY_PAYLOAD* payload)
{
encode_unsigned16(&apdu[0], payload->payload_length);
memcpy(&apdu[2], payload->payload, payload->payload_length);
@@ -179,8 +174,7 @@ int encode_security_payload(uint8_t * apdu,
return (int)(2 + payload->payload_length);
}
int encode_security_response(uint8_t * apdu,
BACNET_SECURITY_RESPONSE * resp)
int encode_security_response(uint8_t* apdu, BACNET_SECURITY_RESPONSE* resp)
{
int curr = 0;
int i;
@@ -188,37 +182,33 @@ int encode_security_response(uint8_t * apdu,
apdu[curr++] = resp->response_code;
curr += encode_unsigned32(&apdu[curr], resp->orig_message_id);
curr += encode_unsigned32(&apdu[curr], resp->orig_timestamp);
switch ((BACNET_SECURITY_RESPONSE_CODE) resp->response_code) {
switch ((BACNET_SECURITY_RESPONSE_CODE)resp->response_code) {
case SEC_RESP_BAD_TIMESTAMP:
curr +=
encode_unsigned32(&apdu[curr],
resp->response.bad_timestamp.expected_timestamp);
curr += encode_unsigned32(
&apdu[curr], resp->response.bad_timestamp.expected_timestamp);
break;
case SEC_RESP_CANNOT_USE_KEY:
curr +=
encode_unsigned16(&apdu[curr],
resp->response.cannot_use_key.key);
curr += encode_unsigned16(&apdu[curr],
resp->response.cannot_use_key.key);
break;
case SEC_RESP_INCORRECT_KEY:
apdu[curr++] = resp->response.incorrect_key.number_of_keys;
for (i = 0; i < (int)resp->response.incorrect_key.number_of_keys; i++) {
curr +=
encode_unsigned16(&apdu[curr],
resp->response.incorrect_key.keys[i]);
for (i = 0; i < (int)resp->response.incorrect_key.number_of_keys;
i++) {
curr += encode_unsigned16(&apdu[curr],
resp->response.incorrect_key.keys[i]);
}
break;
case SEC_RESP_UNKNOWN_AUTHENTICATION_TYPE:
apdu[curr++] =
resp->response.unknown_authentication_type.
original_authentication_type;
curr +=
encode_unsigned16(&apdu[curr],
apdu[curr++] = resp->response.unknown_authentication_type
.original_authentication_type;
curr += encode_unsigned16(
&apdu[curr],
resp->response.unknown_authentication_type.vendor_id);
break;
case SEC_RESP_UNKNOWN_KEY:
curr +=
encode_unsigned16(&apdu[curr],
resp->response.unknown_key.original_key);
curr += encode_unsigned16(&apdu[curr],
resp->response.unknown_key.original_key);
break;
case SEC_RESP_UNKNOWN_KEY_REVISION:
apdu[curr++] =
@@ -228,9 +218,8 @@ int encode_security_response(uint8_t * apdu,
apdu[curr++] = resp->response.too_many_keys.max_num_of_keys;
break;
case SEC_RESP_INVALID_KEY_DATA:
curr +=
encode_unsigned16(&apdu[curr],
resp->response.invalid_key_data.key);
curr += encode_unsigned16(&apdu[curr],
resp->response.invalid_key_data.key);
break;
case SEC_RESP_SUCCESS:
case SEC_RESP_ACCESS_DENIED:
@@ -252,14 +241,13 @@ int encode_security_response(uint8_t * apdu,
case SEC_RESP_UNKNOWN_SOURCE_MESSAGE:
break;
default:
return -1; /* unknown message type */
return -1; /* unknown message type */
}
return curr;
}
int encode_request_key_update(uint8_t * apdu,
BACNET_REQUEST_KEY_UPDATE * req)
int encode_request_key_update(uint8_t* apdu, BACNET_REQUEST_KEY_UPDATE* req)
{
int curr = 0;
@@ -274,8 +262,7 @@ int encode_request_key_update(uint8_t * apdu,
return curr;
}
int encode_key_entry(uint8_t * apdu,
BACNET_KEY_ENTRY * entry)
int encode_key_entry(uint8_t* apdu, BACNET_KEY_ENTRY* entry)
{
int curr = 0;
@@ -287,8 +274,7 @@ int encode_key_entry(uint8_t * apdu,
return curr;
}
int encode_update_key_set(uint8_t * apdu,
BACNET_UPDATE_KEY_SET * key_set)
int encode_update_key_set(uint8_t* apdu, BACNET_UPDATE_KEY_SET* key_set)
{
int curr = 0;
int i, res;
@@ -321,10 +307,8 @@ int encode_update_key_set(uint8_t * apdu,
curr++;
if (key_set->set_rae[0]) {
apdu[curr++] = key_set->set_key_revision[0];
curr +=
encode_unsigned32(&apdu[curr], key_set->set_activation_time[0]);
curr +=
encode_unsigned32(&apdu[curr], key_set->set_expiration_time[0]);
curr += encode_unsigned32(&apdu[curr], key_set->set_activation_time[0]);
curr += encode_unsigned32(&apdu[curr], key_set->set_expiration_time[0]);
}
if (key_set->set_ck[0]) {
apdu[curr++] = key_set->set_key_count[0];
@@ -341,10 +325,8 @@ int encode_update_key_set(uint8_t * apdu,
}
if (key_set->set_rae[1]) {
apdu[curr++] = key_set->set_key_revision[1];
curr +=
encode_unsigned32(&apdu[curr], key_set->set_activation_time[1]);
curr +=
encode_unsigned32(&apdu[curr], key_set->set_expiration_time[1]);
curr += encode_unsigned32(&apdu[curr], key_set->set_activation_time[1]);
curr += encode_unsigned32(&apdu[curr], key_set->set_expiration_time[1]);
}
if (key_set->set_ck[1]) {
apdu[curr++] = key_set->set_key_count[1];
@@ -362,8 +344,8 @@ int encode_update_key_set(uint8_t * apdu,
return curr;
}
int encode_update_distribution_key(uint8_t * apdu,
BACNET_UPDATE_DISTRIBUTION_KEY * dist_key)
int encode_update_distribution_key(uint8_t* apdu,
BACNET_UPDATE_DISTRIBUTION_KEY* dist_key)
{
int curr = 0;
int res;
@@ -377,28 +359,26 @@ int encode_update_distribution_key(uint8_t * apdu,
return curr + res;
}
int encode_request_master_key(uint8_t * apdu,
BACNET_REQUEST_MASTER_KEY * req_master_key)
int encode_request_master_key(uint8_t* apdu,
BACNET_REQUEST_MASTER_KEY* req_master_key)
{
int curr = 0;
apdu[curr++] = req_master_key->no_supported_algorithms;
memcpy(&apdu[curr], req_master_key->es_algorithms,
req_master_key->no_supported_algorithms);
req_master_key->no_supported_algorithms);
return (int)(curr + req_master_key->no_supported_algorithms);
}
int encode_set_master_key(uint8_t * apdu,
BACNET_SET_MASTER_KEY * set_master_key)
int encode_set_master_key(uint8_t* apdu, BACNET_SET_MASTER_KEY* set_master_key)
{
return encode_key_entry(apdu, &set_master_key->key);
}
int decode_security_wrapper_safe(int bytes_before,
uint8_t * apdu,
uint32_t apdu_len_remaining,
BACNET_SECURITY_WRAPPER * wrapper)
int decode_security_wrapper_safe(int bytes_before, uint8_t* apdu,
uint32_t apdu_len_remaining,
BACNET_SECURITY_WRAPPER* wrapper)
{
int curr = 0;
int enc_begin = 0;
@@ -424,7 +404,7 @@ int decode_security_wrapper_safe(int bytes_before,
return -SEC_RESP_MALFORMED_MESSAGE;
}
/* remove encryption flag for signature validation */
apdu[curr] &= ~((uint8_t) (1 << 6));
apdu[curr] &= ~((uint8_t)(1 << 6));
curr++;
/* key */
wrapper->key_revision = apdu[curr++];
@@ -447,13 +427,14 @@ int decode_security_wrapper_safe(int bytes_before,
memcpy(wrapper->signature, &apdu[real_len], SIGNATURE_LEN);
if (wrapper->encrypted_flag) {
if (!key_decrypt_msg(&key, &apdu[enc_begin],
(uint32_t)(real_len - enc_begin), wrapper->signature)) {
(uint32_t)(real_len - enc_begin),
wrapper->signature)) {
return -SEC_RESP_MALFORMED_MESSAGE;
}
curr += decode_unsigned16(&apdu[real_len - 2], &wrapper->padding_len);
real_len -= wrapper->padding_len;
memcpy(wrapper->padding, &apdu[wrapper->padding_len],
wrapper->padding_len - 2);
wrapper->padding_len - 2);
}
/* destination device instance */
curr +=
@@ -476,21 +457,19 @@ int decode_security_wrapper_safe(int bytes_before,
wrapper->user_role = apdu[curr++];
if ((wrapper->authentication_mechanism >= 1) &&
(wrapper->authentication_mechanism <= 199)) {
curr +=
decode_unsigned16(&apdu[curr],
&wrapper->authentication_data_length);
curr += decode_unsigned16(&apdu[curr],
&wrapper->authentication_data_length);
wrapper->authentication_data_length -= 5;
memcpy(wrapper->authentication_data, &apdu[curr],
wrapper->authentication_data_length);
wrapper->authentication_data_length);
curr += wrapper->authentication_data_length;
} else if (wrapper->authentication_mechanism >= 200) {
curr +=
decode_unsigned16(&apdu[curr],
&wrapper->authentication_data_length);
curr += decode_unsigned16(&apdu[curr],
&wrapper->authentication_data_length);
wrapper->authentication_data_length -= 7;
curr += decode_unsigned16(&apdu[curr], &wrapper->vendor_id);
memcpy(wrapper->authentication_data, &apdu[curr],
wrapper->authentication_data_length);
wrapper->authentication_data_length);
curr += wrapper->authentication_data_length;
}
}
@@ -498,16 +477,16 @@ int decode_security_wrapper_safe(int bytes_before,
memcpy(wrapper->service_data, &apdu[curr], wrapper->service_data_len);
curr += wrapper->service_data_len;
if (!key_verify_sign_msg(&key, &apdu[-bytes_before],
(uint32_t)(bytes_before + real_len), wrapper->signature)) {
(uint32_t)(bytes_before + real_len),
wrapper->signature)) {
return -SEC_RESP_BAD_SIGNATURE;
}
return curr;
}
int decode_challenge_request_safe(uint8_t * apdu,
uint32_t apdu_len_remaining,
BACNET_CHALLENGE_REQUEST * bc_req)
int decode_challenge_request_safe(uint8_t* apdu, uint32_t apdu_len_remaining,
BACNET_CHALLENGE_REQUEST* bc_req)
{
int curr = 0;
@@ -518,12 +497,11 @@ int decode_challenge_request_safe(uint8_t * apdu,
curr += decode_unsigned32(&apdu[curr], &bc_req->orig_message_id);
curr += decode_unsigned32(&apdu[curr], &bc_req->orig_timestamp);
return curr; /* always 9! */
return curr; /* always 9! */
}
int decode_security_payload_safe(uint8_t * apdu,
uint32_t apdu_len_remaining,
BACNET_SECURITY_PAYLOAD * payload)
int decode_security_payload_safe(uint8_t* apdu, uint32_t apdu_len_remaining,
BACNET_SECURITY_PAYLOAD* payload)
{
if (apdu_len_remaining < 2) {
return -1;
@@ -536,9 +514,8 @@ int decode_security_payload_safe(uint8_t * apdu,
return (int)(2 + payload->payload_length);
}
int decode_security_response_safe(uint8_t * apdu,
uint32_t apdu_len_remaining,
BACNET_SECURITY_RESPONSE * resp)
int decode_security_response_safe(uint8_t* apdu, uint32_t apdu_len_remaining,
BACNET_SECURITY_RESPONSE* resp)
{
int curr = 0;
int i;
@@ -549,22 +526,20 @@ int decode_security_response_safe(uint8_t * apdu,
resp->response_code = apdu[curr++];
curr += decode_unsigned32(&apdu[curr], &resp->orig_message_id);
curr += decode_unsigned32(&apdu[curr], &resp->orig_timestamp);
switch ((BACNET_SECURITY_RESPONSE_CODE) resp->response_code) {
switch ((BACNET_SECURITY_RESPONSE_CODE)resp->response_code) {
case SEC_RESP_BAD_TIMESTAMP:
if (apdu_len_remaining < 13) {
return -1;
}
curr +=
decode_unsigned32(&apdu[curr],
&resp->response.bad_timestamp.expected_timestamp);
curr += decode_unsigned32(
&apdu[curr], &resp->response.bad_timestamp.expected_timestamp);
break;
case SEC_RESP_CANNOT_USE_KEY:
if (apdu_len_remaining < 11) {
return -1;
}
curr +=
decode_unsigned16(&apdu[curr],
&resp->response.cannot_use_key.key);
curr += decode_unsigned16(&apdu[curr],
&resp->response.cannot_use_key.key);
break;
case SEC_RESP_INCORRECT_KEY:
if (apdu_len_remaining < 10) {
@@ -575,23 +550,23 @@ int decode_security_response_safe(uint8_t * apdu,
resp->response.incorrect_key.number_of_keys * 2) {
return -1;
}
for (i = 0; i < (int)resp->response.incorrect_key.number_of_keys; i++) {
curr +=
decode_unsigned16(&apdu[curr],
&resp->response.incorrect_key.keys[i]);
for (i = 0; i < (int)resp->response.incorrect_key.number_of_keys;
i++) {
curr += decode_unsigned16(
&apdu[curr], &resp->response.incorrect_key.keys[i]);
}
break;
case SEC_RESP_UNKNOWN_AUTHENTICATION_TYPE:
if (apdu_len_remaining < 12) {
return -1;
}
resp->response.unknown_authentication_type.
original_authentication_type = apdu[curr++];
curr +=
decode_unsigned16(&apdu[curr],
resp->response.unknown_authentication_type
.original_authentication_type = apdu[curr++];
curr += decode_unsigned16(
&apdu[curr],
&resp->response.unknown_authentication_type.vendor_id);
if (resp->response.unknown_authentication_type.
original_authentication_type < 200 &&
if (resp->response.unknown_authentication_type
.original_authentication_type < 200 &&
resp->response.unknown_authentication_type.vendor_id != 0) {
return -1;
}
@@ -600,9 +575,8 @@ int decode_security_response_safe(uint8_t * apdu,
if (apdu_len_remaining < 11) {
return -1;
}
curr +=
decode_unsigned16(&apdu[curr],
&resp->response.unknown_key.original_key);
curr += decode_unsigned16(&apdu[curr],
&resp->response.unknown_key.original_key);
break;
case SEC_RESP_UNKNOWN_KEY_REVISION:
if (apdu_len_remaining < 10) {
@@ -621,9 +595,8 @@ int decode_security_response_safe(uint8_t * apdu,
if (apdu_len_remaining < 11) {
return -1;
}
curr +=
decode_unsigned16(&apdu[curr],
&resp->response.invalid_key_data.key);
curr += decode_unsigned16(&apdu[curr],
&resp->response.invalid_key_data.key);
break;
case SEC_RESP_SUCCESS:
case SEC_RESP_ACCESS_DENIED:
@@ -645,14 +618,13 @@ int decode_security_response_safe(uint8_t * apdu,
case SEC_RESP_UNKNOWN_SOURCE_MESSAGE:
break;
default:
return -1; /* unknown message type */
return -1; /* unknown message type */
}
return curr;
}
int decode_request_key_update_safe(uint8_t * apdu,
uint32_t apdu_len_remaining,
BACNET_REQUEST_KEY_UPDATE * req)
int decode_request_key_update_safe(uint8_t* apdu, uint32_t apdu_len_remaining,
BACNET_REQUEST_KEY_UPDATE* req)
{
int curr = 0;
@@ -670,9 +642,8 @@ int decode_request_key_update_safe(uint8_t * apdu,
return curr;
}
int decode_key_entry_safe(uint8_t * apdu,
uint32_t apdu_len_remaining,
BACNET_KEY_ENTRY * entry)
int decode_key_entry_safe(uint8_t* apdu, uint32_t apdu_len_remaining,
BACNET_KEY_ENTRY* entry)
{
int curr = 0;
@@ -691,9 +662,8 @@ int decode_key_entry_safe(uint8_t * apdu,
return curr;
}
int decode_update_key_set_safe(uint8_t * apdu,
uint32_t apdu_len_remaining,
BACNET_UPDATE_KEY_SET * key_set)
int decode_update_key_set_safe(uint8_t* apdu, uint32_t apdu_len_remaining,
BACNET_UPDATE_KEY_SET* key_set)
{
int curr = 0;
int i, res;
@@ -745,9 +715,8 @@ int decode_update_key_set_safe(uint8_t * apdu,
return -1;
}
for (i = 0; i < (int)key_set->set_key_count[0]; i++) {
res =
decode_key_entry_safe(apdu + curr, apdu_len_remaining - curr,
&key_set->set_keys[0][i]);
res = decode_key_entry_safe(apdu + curr, apdu_len_remaining - curr,
&key_set->set_keys[0][i]);
if (res < 0) {
return -1;
}
@@ -773,9 +742,8 @@ int decode_update_key_set_safe(uint8_t * apdu,
return -1;
}
for (i = 0; i < (int)key_set->set_key_count[1]; i++) {
res =
decode_key_entry_safe(apdu + curr, apdu_len_remaining - curr,
&key_set->set_keys[1][i]);
res = decode_key_entry_safe(apdu + curr, apdu_len_remaining - curr,
&key_set->set_keys[1][i]);
if (res < 0) {
return -1;
}
@@ -786,9 +754,9 @@ int decode_update_key_set_safe(uint8_t * apdu,
return curr;
}
int decode_update_distribution_key_safe(uint8_t * apdu,
uint32_t apdu_len_remaining,
BACNET_UPDATE_DISTRIBUTION_KEY * dist_key)
int decode_update_distribution_key_safe(
uint8_t* apdu, uint32_t apdu_len_remaining,
BACNET_UPDATE_DISTRIBUTION_KEY* dist_key)
{
int curr = 0;
int res;
@@ -796,9 +764,8 @@ int decode_update_distribution_key_safe(uint8_t * apdu,
return -1;
}
dist_key->key_revision = apdu[curr++];
res =
decode_key_entry_safe(&apdu[curr], apdu_len_remaining - curr,
&dist_key->key);
res = decode_key_entry_safe(&apdu[curr], apdu_len_remaining - curr,
&dist_key->key);
if (res < 0) {
return -1;
}
@@ -806,9 +773,8 @@ int decode_update_distribution_key_safe(uint8_t * apdu,
return curr + res;
}
int decode_request_master_key_safe(uint8_t * apdu,
uint32_t apdu_len_remaining,
BACNET_REQUEST_MASTER_KEY * req_master_key)
int decode_request_master_key_safe(uint8_t* apdu, uint32_t apdu_len_remaining,
BACNET_REQUEST_MASTER_KEY* req_master_key)
{
uint32_t curr = 0;
@@ -820,15 +786,14 @@ int decode_request_master_key_safe(uint8_t * apdu,
return -1;
}
memcpy(req_master_key->es_algorithms, &apdu[curr],
req_master_key->no_supported_algorithms);
req_master_key->no_supported_algorithms);
return (int)(curr + req_master_key->no_supported_algorithms);
}
int decode_set_master_key_safe(uint8_t * apdu,
uint32_t apdu_len_remaining,
BACNET_SET_MASTER_KEY * set_master_key)
int decode_set_master_key_safe(uint8_t* apdu, uint32_t apdu_len_remaining,
BACNET_SET_MASTER_KEY* set_master_key)
{
return decode_key_entry_safe(apdu, apdu_len_remaining,
&set_master_key->key);
&set_master_key->key);
}
+136 -208
View File
@@ -34,19 +34,18 @@
#include <stdbool.h>
#include <stdint.h>
#include <string.h> /* for strlen */
#include <string.h> /* for strlen */
#include "config.h"
#include "bacstr.h"
#include "bits.h"
#if PRINT_ENABLED
#include <stdlib.h> /* for strtol */
#include <ctype.h> /* for isalnum */
#include <stdlib.h> /* for strtol */
#include <ctype.h> /* for isalnum */
#endif
/** @file bacstr.c Manipulate Bit/Char/Octet Strings */
void bitstring_init(
BACNET_BIT_STRING * bit_string)
void bitstring_init(BACNET_BIT_STRING *bit_string)
{
int i;
@@ -56,10 +55,8 @@ void bitstring_init(
}
}
void bitstring_set_bit(
BACNET_BIT_STRING * bit_string,
uint8_t bit_number,
bool value)
void bitstring_set_bit(BACNET_BIT_STRING *bit_string, uint8_t bit_number,
bool value)
{
uint8_t byte_number = bit_number / 8;
uint8_t bit_mask = 1;
@@ -78,9 +75,7 @@ void bitstring_set_bit(
}
}
bool bitstring_bit(
BACNET_BIT_STRING * bit_string,
uint8_t bit_number)
bool bitstring_bit(BACNET_BIT_STRING *bit_string, uint8_t bit_number)
{
bool value = false;
uint8_t byte_number = bit_number / 8;
@@ -96,17 +91,15 @@ bool bitstring_bit(
return value;
}
uint8_t bitstring_bits_used(
BACNET_BIT_STRING * bit_string)
uint8_t bitstring_bits_used(BACNET_BIT_STRING *bit_string)
{
return bit_string->bits_used;
}
/* returns the number of bytes that a bit string is using */
uint8_t bitstring_bytes_used(
BACNET_BIT_STRING * bit_string)
uint8_t bitstring_bytes_used(BACNET_BIT_STRING *bit_string)
{
uint8_t len = 0; /* return value */
uint8_t len = 0; /* return value */
uint8_t used_bytes = 0;
uint8_t last_bit = 0;
@@ -121,9 +114,7 @@ uint8_t bitstring_bytes_used(
return len;
}
uint8_t bitstring_octet(
BACNET_BIT_STRING * bit_string,
uint8_t octet_index)
uint8_t bitstring_octet(BACNET_BIT_STRING *bit_string, uint8_t octet_index)
{
uint8_t octet = 0;
@@ -136,10 +127,8 @@ uint8_t bitstring_octet(
return octet;
}
bool bitstring_set_octet(
BACNET_BIT_STRING * bit_string,
uint8_t index,
uint8_t octet)
bool bitstring_set_octet(BACNET_BIT_STRING *bit_string, uint8_t index,
uint8_t octet)
{
bool status = false;
@@ -153,10 +142,8 @@ bool bitstring_set_octet(
return status;
}
bool bitstring_set_bits_used(
BACNET_BIT_STRING * bit_string,
uint8_t bytes_used,
uint8_t unused_bits)
bool bitstring_set_bits_used(BACNET_BIT_STRING *bit_string, uint8_t bytes_used,
uint8_t unused_bits)
{
bool status = false;
@@ -170,8 +157,7 @@ bool bitstring_set_bits_used(
return status;
}
uint8_t bitstring_bits_capacity(
BACNET_BIT_STRING * bit_string)
uint8_t bitstring_bits_capacity(BACNET_BIT_STRING *bit_string)
{
if (bit_string) {
return (MAX_BITSTRING_BYTES * 8);
@@ -180,9 +166,7 @@ uint8_t bitstring_bits_capacity(
}
}
bool bitstring_copy(
BACNET_BIT_STRING * dest,
BACNET_BIT_STRING * src)
bool bitstring_copy(BACNET_BIT_STRING *dest, BACNET_BIT_STRING *src)
{
unsigned i;
bool status = false;
@@ -199,18 +183,17 @@ bool bitstring_copy(
}
/* returns true if the same length and contents */
bool bitstring_same(
BACNET_BIT_STRING * bitstring1,
BACNET_BIT_STRING * bitstring2)
bool bitstring_same(BACNET_BIT_STRING *bitstring1,
BACNET_BIT_STRING *bitstring2)
{
int i = 0; /* loop counter */
int i = 0; /* loop counter */
int bytes_used = 0;
uint8_t compare_mask = 0;
if (bitstring1 && bitstring2) {
if ((bitstring1->bits_used == bitstring2->bits_used) &&
(bitstring1->bits_used / 8 <= MAX_BITSTRING_BYTES)) {
bytes_used = (int) (bitstring1->bits_used / 8);
bytes_used = (int)(bitstring1->bits_used / 8);
compare_mask = 0xFF >> (8 - (bitstring1->bits_used % 8));
for (i = 0; i < bytes_used; i++) {
@@ -234,12 +217,10 @@ bool bitstring_same(
/* converts an null terminated ASCII string to an bitstring.
Expects "1,0,1,0,1,1" or "101011" as the bits
returns true if successfully converted and fits; false if too long */
bool bitstring_init_ascii(
BACNET_BIT_STRING * bit_string,
const char *ascii)
bool bitstring_init_ascii(BACNET_BIT_STRING *bit_string, const char *ascii)
{
bool status = false; /* return value */
unsigned index = 0; /* offset into buffer */
bool status = false; /* return value */
unsigned index = 0; /* offset into buffer */
uint8_t bit_number = 0;
if (bit_string) {
@@ -280,14 +261,11 @@ bool bitstring_init_ascii(
#define CHARACTER_STRING_CAPACITY (MAX_CHARACTER_STRING_BYTES - 1)
/* returns false if the string exceeds capacity
initialize by using value=NULL */
bool characterstring_init(
BACNET_CHARACTER_STRING * char_string,
uint8_t encoding,
const char *value,
size_t length)
bool characterstring_init(BACNET_CHARACTER_STRING *char_string,
uint8_t encoding, const char *value, size_t length)
{
bool status = false; /* return value */
size_t i; /* counter */
bool status = false; /* return value */
size_t i; /* counter */
if (char_string) {
char_string->length = 0;
@@ -316,28 +294,25 @@ bool characterstring_init(
return status;
}
bool characterstring_init_ansi(
BACNET_CHARACTER_STRING * char_string,
const char *value)
bool characterstring_init_ansi(BACNET_CHARACTER_STRING *char_string,
const char *value)
{
return characterstring_init(char_string, CHARACTER_ANSI_X34, value,
value ? strlen(value) : 0);
value ? strlen(value) : 0);
}
bool characterstring_copy(
BACNET_CHARACTER_STRING * dest,
BACNET_CHARACTER_STRING * src)
bool characterstring_copy(BACNET_CHARACTER_STRING *dest,
BACNET_CHARACTER_STRING *src)
{
return characterstring_init(dest, characterstring_encoding(src),
characterstring_value(src), characterstring_length(src));
characterstring_value(src),
characterstring_length(src));
}
bool characterstring_ansi_copy(
char *dest,
size_t dest_max_len,
BACNET_CHARACTER_STRING * src)
bool characterstring_ansi_copy(char *dest, size_t dest_max_len,
BACNET_CHARACTER_STRING *src)
{
size_t i; /* counter */
size_t i; /* counter */
if (dest && src && (src->encoding == CHARACTER_ANSI_X34) &&
(src->length < dest_max_len)) {
@@ -355,15 +330,15 @@ bool characterstring_ansi_copy(
}
/* returns true if the character encoding and string contents are the same */
bool characterstring_same(
BACNET_CHARACTER_STRING * dest,
BACNET_CHARACTER_STRING * src)
bool characterstring_same(BACNET_CHARACTER_STRING *dest,
BACNET_CHARACTER_STRING *src)
{
size_t i; /* counter */
size_t i; /* counter */
bool same_status = false;
if (src && dest) {
if ((src->length == dest->length) && (src->encoding == dest->encoding)) {
if ((src->length == dest->length) &&
(src->encoding == dest->encoding)) {
same_status = true;
for (i = 0; (i < src->length) && same_status; i++) {
if (src->value[i] != dest->value[i]) {
@@ -384,11 +359,9 @@ bool characterstring_same(
return same_status;
}
bool characterstring_ansi_same(
BACNET_CHARACTER_STRING * dest,
const char *src)
bool characterstring_ansi_same(BACNET_CHARACTER_STRING *dest, const char *src)
{
size_t i; /* counter */
size_t i; /* counter */
bool same_status = false;
if (src && dest) {
@@ -417,13 +390,11 @@ bool characterstring_ansi_same(
}
/* returns false if the string exceeds capacity */
bool characterstring_append(
BACNET_CHARACTER_STRING * char_string,
const char *value,
size_t length)
bool characterstring_append(BACNET_CHARACTER_STRING *char_string,
const char *value, size_t length)
{
size_t i; /* counter */
bool status = false; /* return value */
size_t i; /* counter */
bool status = false; /* return value */
if (char_string) {
if ((length + char_string->length) <= CHARACTER_STRING_CAPACITY) {
@@ -441,11 +412,10 @@ bool characterstring_append(
/* This function sets a new length without changing the value.
If length exceeds capacity, no modification happens and
function returns false. */
bool characterstring_truncate(
BACNET_CHARACTER_STRING * char_string,
size_t length)
bool characterstring_truncate(BACNET_CHARACTER_STRING *char_string,
size_t length)
{
bool status = false; /* return value */
bool status = false; /* return value */
if (char_string) {
if (length <= CHARACTER_STRING_CAPACITY) {
@@ -458,8 +428,7 @@ bool characterstring_truncate(
}
/* Returns the value. */
char *characterstring_value(
BACNET_CHARACTER_STRING * char_string)
char *characterstring_value(BACNET_CHARACTER_STRING *char_string)
{
char *value = NULL;
@@ -471,8 +440,7 @@ char *characterstring_value(
}
/* returns the length. */
size_t characterstring_length(
BACNET_CHARACTER_STRING * char_string)
size_t characterstring_length(BACNET_CHARACTER_STRING *char_string)
{
size_t length = 0;
@@ -484,8 +452,7 @@ size_t characterstring_length(
return length;
}
size_t characterstring_capacity(
BACNET_CHARACTER_STRING * char_string)
size_t characterstring_capacity(BACNET_CHARACTER_STRING *char_string)
{
size_t length = 0;
@@ -497,8 +464,7 @@ size_t characterstring_capacity(
}
/* returns the encoding. */
uint8_t characterstring_encoding(
BACNET_CHARACTER_STRING * char_string)
uint8_t characterstring_encoding(BACNET_CHARACTER_STRING *char_string)
{
uint8_t encoding = 0;
@@ -510,9 +476,8 @@ uint8_t characterstring_encoding(
}
/* returns the encoding. */
bool characterstring_set_encoding(
BACNET_CHARACTER_STRING * char_string,
uint8_t encoding)
bool characterstring_set_encoding(BACNET_CHARACTER_STRING *char_string,
uint8_t encoding)
{
bool status = false;
@@ -535,11 +500,10 @@ punctuation marks, and mathematical symbols. The exact set
depends upon the character set being used. In ANSI X3.4 the
printable characters are represented by single octets in the range
X'20' - X'7E'.*/
bool characterstring_printable(
BACNET_CHARACTER_STRING * char_string)
bool characterstring_printable(BACNET_CHARACTER_STRING *char_string)
{
bool status = false; /* return value */
size_t i; /* counter */
bool status = false; /* return value */
size_t i; /* counter */
if (char_string) {
if (char_string->encoding == CHARACTER_ANSI_X34) {
@@ -566,32 +530,24 @@ bool characterstring_printable(
by Jeff Bezanson
placed in the public domain Fall 2005 */
static const char trailingBytesForUTF8[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4,
4, 4, 4, 5, 5, 5, 5
};
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5};
/* based on the valid_utf8 routine from the PCRE library by Philip Hazel
length is in bytes, since without knowing whether the string is valid
it's hard to know how many characters there are! */
bool utf8_isvalid(
const char *str,
size_t length)
bool utf8_isvalid(const char *str, size_t length)
{
const unsigned char *p, *pend = (unsigned char *) str + length;
const unsigned char *p, *pend = (unsigned char *)str + length;
unsigned char c;
size_t ab;
@@ -599,7 +555,7 @@ bool utf8_isvalid(
if (length == 0) {
return true;
}
for (p = (const unsigned char *) str; p < pend; p++) {
for (p = (const unsigned char *)str; p < pend; p++) {
c = *p;
/* null in middle of string */
if (c == 0) {
@@ -612,7 +568,7 @@ bool utf8_isvalid(
if ((c & 0xc0) != 0xc0) {
return false;
}
ab = (size_t) trailingBytesForUTF8[c];
ab = (size_t)trailingBytesForUTF8[c];
if (length < ab) {
return false;
}
@@ -629,7 +585,7 @@ bool utf8_isvalid(
case 1:
if ((c & 0x3e) == 0)
return false;
continue; /* We know there aren't any more bytes to check */
continue; /* We know there aren't any more bytes to check */
/* Check for 1110 0000, xx0x xxxx */
case 2:
@@ -667,8 +623,7 @@ bool utf8_isvalid(
return true;
}
bool characterstring_valid(
BACNET_CHARACTER_STRING * char_string)
bool characterstring_valid(BACNET_CHARACTER_STRING *char_string)
{
bool valid = false; /* return value */
@@ -688,13 +643,11 @@ bool characterstring_valid(
#if BACNET_USE_OCTETSTRING
/* returns false if the string exceeds capacity
initialize by using value=NULL */
bool octetstring_init(
BACNET_OCTET_STRING * octet_string,
uint8_t * value,
size_t length)
bool octetstring_init(BACNET_OCTET_STRING *octet_string, uint8_t *value,
size_t length)
{
bool status = false; /* return value */
size_t i; /* counter */
bool status = false; /* return value */
size_t i; /* counter */
if (octet_string && (length <= MAX_OCTET_STRING_BYTES)) {
octet_string->length = 0;
@@ -721,12 +674,11 @@ bool octetstring_init(
#if PRINT_ENABLED
/* converts an null terminated ASCII Hex string to an octet string.
returns true if successfully converted and fits; false if too long */
bool octetstring_init_ascii_hex(
BACNET_OCTET_STRING * octet_string,
const char *ascii_hex)
bool octetstring_init_ascii_hex(BACNET_OCTET_STRING *octet_string,
const char *ascii_hex)
{
bool status = false; /* return value */
unsigned index = 0; /* offset into buffer */
bool status = false; /* return value */
unsigned index = 0; /* offset into buffer */
uint8_t value = 0;
char hex_pair_string[3] = "";
@@ -747,7 +699,7 @@ bool octetstring_init_ascii_hex(
}
hex_pair_string[0] = ascii_hex[index];
hex_pair_string[1] = ascii_hex[index + 1];
value = (uint8_t) strtol(hex_pair_string, NULL, 16);
value = (uint8_t)strtol(hex_pair_string, NULL, 16);
if (octet_string->length <= MAX_OCTET_STRING_BYTES) {
octet_string->value[octet_string->length] = value;
octet_string->length++;
@@ -767,23 +719,19 @@ bool octetstring_init_ascii_hex(
}
#endif
bool octetstring_copy(
BACNET_OCTET_STRING * dest,
BACNET_OCTET_STRING * src)
bool octetstring_copy(BACNET_OCTET_STRING *dest, BACNET_OCTET_STRING *src)
{
return octetstring_init(dest, octetstring_value(src),
octetstring_length(src));
octetstring_length(src));
}
/* returns the number of bytes copied, or 0 if the dest
cannot hold entire octetstring value */
size_t octetstring_copy_value(
uint8_t * dest,
size_t length,
BACNET_OCTET_STRING * src)
size_t octetstring_copy_value(uint8_t *dest, size_t length,
BACNET_OCTET_STRING *src)
{
size_t bytes_copied = 0;
size_t i; /* counter */
size_t i; /* counter */
if (src && dest) {
if (length <= src->length) {
@@ -798,13 +746,11 @@ size_t octetstring_copy_value(
}
/* returns false if the string exceeds capacity */
bool octetstring_append(
BACNET_OCTET_STRING * octet_string,
uint8_t * value,
size_t length)
bool octetstring_append(BACNET_OCTET_STRING *octet_string, uint8_t *value,
size_t length)
{
size_t i; /* counter */
bool status = false; /* return value */
size_t i; /* counter */
bool status = false; /* return value */
if (octet_string) {
if ((length + octet_string->length) <= MAX_OCTET_STRING_BYTES) {
@@ -822,11 +768,9 @@ bool octetstring_append(
/* This function sets a new length without changing the value.
If length exceeds capacity, no modification happens and
function returns false. */
bool octetstring_truncate(
BACNET_OCTET_STRING * octet_string,
size_t length)
bool octetstring_truncate(BACNET_OCTET_STRING *octet_string, size_t length)
{
bool status = false; /* return value */
bool status = false; /* return value */
if (octet_string) {
if (length <= MAX_OCTET_STRING_BYTES) {
@@ -839,8 +783,7 @@ bool octetstring_truncate(
}
/* returns a pointer to the value. */
uint8_t *octetstring_value(
BACNET_OCTET_STRING * octet_string)
uint8_t *octetstring_value(BACNET_OCTET_STRING *octet_string)
{
uint8_t *value = NULL;
@@ -852,8 +795,7 @@ uint8_t *octetstring_value(
}
/* returns the length. */
size_t octetstring_length(
BACNET_OCTET_STRING * octet_string)
size_t octetstring_length(BACNET_OCTET_STRING *octet_string)
{
size_t length = 0;
@@ -866,8 +808,7 @@ size_t octetstring_length(
}
/* returns the maximum capacity. */
size_t octetstring_capacity(
BACNET_OCTET_STRING * octet_string)
size_t octetstring_capacity(BACNET_OCTET_STRING *octet_string)
{
size_t length = 0;
@@ -880,11 +821,10 @@ size_t octetstring_capacity(
}
/* returns true if the same length and contents */
bool octetstring_value_same(
BACNET_OCTET_STRING * octet_string1,
BACNET_OCTET_STRING * octet_string2)
bool octetstring_value_same(BACNET_OCTET_STRING *octet_string1,
BACNET_OCTET_STRING *octet_string2)
{
size_t i = 0; /* loop counter */
size_t i = 0; /* loop counter */
if (octet_string1 && octet_string2) {
if ((octet_string1->length == octet_string2->length) &&
@@ -909,8 +849,7 @@ bool octetstring_value_same(
#include <time.h>
#include "ctest.h"
void testBitString(
Test * pTest)
void testBitString(Test *pTest)
{
uint8_t bit = 0;
int max_bit;
@@ -962,17 +901,17 @@ void testBitString(
bitstring_set_bit(&bit_string2, bit, bit_value);
bitstring_set_bit(&bit_string3, bit, bit_value);
}
/* Set the first bit of bit_string2 and the last bit of bit_string3 to be different */
/* Set the first bit of bit_string2 and the last bit of bit_string3 to
* be different */
bitstring_set_bit(&bit_string2, 0, !bitstring_bit(&bit_string, 0));
bitstring_set_bit(&bit_string3, max_bit - 1,
!bitstring_bit(&bit_string, max_bit - 1));
!bitstring_bit(&bit_string, max_bit - 1));
ct_test(pTest, !bitstring_same(&bit_string, &bit_string2));
ct_test(pTest, !bitstring_same(&bit_string, &bit_string3));
}
}
void testCharacterString(
Test * pTest)
void testCharacterString(Test *pTest)
{
BACNET_CHARACTER_STRING bacnet_string;
char *value = "Joshua,Mary,Anna,Christopher";
@@ -989,25 +928,21 @@ void testCharacterString(
ct_test(pTest, status == true);
ct_test(pTest, characterstring_length(&bacnet_string) == 0);
ct_test(pTest,
characterstring_encoding(&bacnet_string) == CHARACTER_ANSI_X34);
characterstring_encoding(&bacnet_string) == CHARACTER_ANSI_X34);
/* bounds check */
status =
characterstring_init(&bacnet_string, CHARACTER_ANSI_X34, NULL,
characterstring_capacity(&bacnet_string) + 1);
status = characterstring_init(&bacnet_string, CHARACTER_ANSI_X34, NULL,
characterstring_capacity(&bacnet_string) + 1);
ct_test(pTest, status == false);
status =
characterstring_truncate(&bacnet_string,
characterstring_capacity(&bacnet_string) + 1);
status = characterstring_truncate(
&bacnet_string, characterstring_capacity(&bacnet_string) + 1);
ct_test(pTest, status == false);
status =
characterstring_truncate(&bacnet_string,
characterstring_capacity(&bacnet_string));
status = characterstring_truncate(&bacnet_string,
characterstring_capacity(&bacnet_string));
ct_test(pTest, status == true);
test_length = strlen(test_value);
status =
characterstring_init(&bacnet_string, CHARACTER_ANSI_X34,
&test_value[0], test_length);
status = characterstring_init(&bacnet_string, CHARACTER_ANSI_X34,
&test_value[0], test_length);
ct_test(pTest, status == true);
value = characterstring_value(&bacnet_string);
length = characterstring_length(&bacnet_string);
@@ -1016,9 +951,8 @@ void testCharacterString(
ct_test(pTest, value[i] == test_value[i]);
}
test_length = strlen(test_append_value);
status =
characterstring_append(&bacnet_string, &test_append_value[0],
test_length);
status = characterstring_append(&bacnet_string, &test_append_value[0],
test_length);
strcat(test_append_string, test_value);
strcat(test_append_string, test_append_value);
test_length = strlen(test_append_string);
@@ -1031,8 +965,7 @@ void testCharacterString(
}
}
void testOctetString(
Test * pTest)
void testOctetString(Test *pTest)
{
BACNET_OCTET_STRING bacnet_string;
uint8_t *value = NULL;
@@ -1053,24 +986,20 @@ void testOctetString(
ct_test(pTest, value[i] == 0);
}
/* bounds check */
status =
octetstring_init(&bacnet_string, NULL,
octetstring_capacity(&bacnet_string) + 1);
status = octetstring_init(&bacnet_string, NULL,
octetstring_capacity(&bacnet_string) + 1);
ct_test(pTest, status == false);
status =
octetstring_init(&bacnet_string, NULL,
octetstring_capacity(&bacnet_string));
status = octetstring_init(&bacnet_string, NULL,
octetstring_capacity(&bacnet_string));
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);
status =
octetstring_truncate(&bacnet_string,
octetstring_capacity(&bacnet_string));
status = octetstring_truncate(&bacnet_string,
octetstring_capacity(&bacnet_string));
ct_test(pTest, status == true);
test_length = strlen((char *) test_value);
test_length = strlen((char *)test_value);
status = octetstring_init(&bacnet_string, &test_value[0], test_length);
ct_test(pTest, status == true);
length = octetstring_length(&bacnet_string);
@@ -1080,12 +1009,12 @@ void testOctetString(
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(&bacnet_string, &test_append_value[0], test_length);
strcat((char *) test_append_string, (char *) test_value);
strcat((char *) test_append_string, (char *) test_append_value);
test_length = strlen((char *) test_append_string);
strcat((char *)test_append_string, (char *)test_value);
strcat((char *)test_append_string, (char *)test_append_value);
test_length = strlen((char *)test_append_string);
ct_test(pTest, status == true);
length = octetstring_length(&bacnet_string);
value = octetstring_value(&bacnet_string);
@@ -1096,8 +1025,7 @@ void testOctetString(
}
#ifdef TEST_BACSTR
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -1113,7 +1041,7 @@ int main(
/* configure output */
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+1106 -2141
View File
File diff suppressed because it is too large Load Diff
+6 -10
View File
@@ -37,8 +37,7 @@
#include "bacdcode.h"
#include "bactimevalue.h"
int bacapp_encode_time_value(uint8_t * apdu,
BACNET_TIME_VALUE * value)
int bacapp_encode_time_value(uint8_t* apdu, BACNET_TIME_VALUE* value)
{
int len;
int apdu_len = 0;
@@ -52,9 +51,8 @@ int bacapp_encode_time_value(uint8_t * apdu,
return apdu_len;
}
int bacapp_encode_context_time_value(uint8_t * apdu,
uint8_t tag_number,
BACNET_TIME_VALUE * value)
int bacapp_encode_context_time_value(uint8_t* apdu, uint8_t tag_number,
BACNET_TIME_VALUE* value)
{
int len;
int apdu_len = 0;
@@ -71,8 +69,7 @@ int bacapp_encode_context_time_value(uint8_t * apdu,
return apdu_len;
}
int bacapp_decode_time_value(uint8_t * apdu,
BACNET_TIME_VALUE * value)
int bacapp_decode_time_value(uint8_t* apdu, BACNET_TIME_VALUE* value)
{
int len;
int apdu_len = 0;
@@ -90,9 +87,8 @@ int bacapp_decode_time_value(uint8_t * apdu,
return apdu_len;
}
int bacapp_decode_context_time_value(uint8_t * apdu,
uint8_t tag_number,
BACNET_TIME_VALUE * value)
int bacapp_decode_context_time_value(uint8_t* apdu, uint8_t tag_number,
BACNET_TIME_VALUE* value)
{
int len = 0;
int section_length;
+1 -2
View File
@@ -35,8 +35,7 @@
/* function to return true on Big-Endian architectures */
/* (based on Harbison & Steele) */
int big_endian(
void)
int big_endian(void)
{
union {
long l;
+50 -66
View File
@@ -32,22 +32,22 @@
-------------------------------------------
####COPYRIGHTEND####*/
#include <stdint.h> /* for standard integer types uint8_t etc. */
#include <stdbool.h> /* for the standard bool type. */
#include <stdint.h> /* for standard integer types uint8_t etc. */
#include <stdbool.h> /* for the standard bool type. */
#include "bacdcode.h"
#include "bacint.h"
#include "bip.h"
#include "bvlc.h"
#include "net.h" /* custom per port */
#include "net.h" /* custom per port */
#if PRINT_ENABLED
#include <stdio.h> /* for standard i/o, like printing */
#include <stdio.h> /* for standard i/o, like printing */
#endif
/** @file bip.c Configuration and Operations for BACnet/IP */
static int BIP_Socket = -1;
/* port to use - stored in network byte order */
static uint16_t BIP_Port = 0; /* this will force initialization in demos */
static uint16_t BIP_Port = 0; /* this will force initialization in demos */
/* IP Address - stored in network byte order */
static struct in_addr BIP_Address;
/* Broadcast Address - stored in network byte order */
@@ -57,8 +57,7 @@ static struct in_addr BIP_Broadcast_Address;
*
* @param sock_fd [in] Handle for the BACnet/IP socket.
*/
void bip_set_socket(
int sock_fd)
void bip_set_socket(int sock_fd)
{
BIP_Socket = sock_fd;
}
@@ -67,63 +66,53 @@ void bip_set_socket(
*
* @return The handle to the BACnet/IP socket.
*/
int bip_socket(
void)
int bip_socket(void)
{
return BIP_Socket;
}
bool bip_valid(
void)
bool bip_valid(void)
{
return (BIP_Socket != -1);
}
void bip_set_addr(
uint32_t net_address)
{ /* in network byte order */
void bip_set_addr(uint32_t net_address)
{ /* in network byte order */
BIP_Address.s_addr = net_address;
}
/* returns network byte order */
uint32_t bip_get_addr(
void)
uint32_t bip_get_addr(void)
{
return BIP_Address.s_addr;
}
void bip_set_broadcast_addr(
uint32_t net_address)
{ /* in network byte order */
void bip_set_broadcast_addr(uint32_t net_address)
{ /* in network byte order */
BIP_Broadcast_Address.s_addr = net_address;
}
/* returns network byte order */
uint32_t bip_get_broadcast_addr(
void)
uint32_t bip_get_broadcast_addr(void)
{
return BIP_Broadcast_Address.s_addr;
}
void bip_set_port(
uint16_t port)
{ /* in network byte order */
void bip_set_port(uint16_t port)
{ /* in network byte order */
BIP_Port = port;
}
/* returns network byte order */
uint16_t bip_get_port(
void)
uint16_t bip_get_port(void)
{
return BIP_Port;
}
static int bip_decode_bip_address(
BACNET_ADDRESS * bac_addr,
struct in_addr *address, /* in network format */
uint16_t * port)
{ /* in network format */
BACNET_ADDRESS *bac_addr, struct in_addr *address, /* in network format */
uint16_t *port)
{ /* in network format */
int len = 0;
if (bac_addr) {
@@ -144,21 +133,20 @@ static int bip_decode_bip_address(
* @param pdu_len [in] Number of bytes in the pdu buffer.
* @return Number of bytes sent on success, negative number on failure.
*/
int bip_send_pdu(
BACNET_ADDRESS * dest, /* destination address */
BACNET_NPDU_DATA * npdu_data, /* network information */
uint8_t * pdu, /* any data to be sent - may be null */
unsigned pdu_len)
{ /* number of bytes of data */
int bip_send_pdu(BACNET_ADDRESS *dest, /* destination address */
BACNET_NPDU_DATA *npdu_data, /* network information */
uint8_t *pdu, /* any data to be sent - may be null */
unsigned pdu_len)
{ /* number of bytes of data */
struct sockaddr_in bip_dest;
uint8_t mtu[MAX_MPDU] = { 0 };
uint8_t mtu[MAX_MPDU] = {0};
int mtu_len = 0;
int bytes_sent = 0;
/* addr and port in host format */
struct in_addr address;
uint16_t port = 0;
(void) npdu_data;
(void)npdu_data;
/* assumes that the driver has already been initialized */
if (BIP_Socket < 0) {
return BIP_Socket;
@@ -191,16 +179,14 @@ int bip_send_pdu(
bip_dest.sin_port = port;
memset(&(bip_dest.sin_zero), '\0', 8);
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);
mtu_len += pdu_len;
/* Send the packet */
bytes_sent =
sendto(BIP_Socket, (char *) mtu, mtu_len, 0,
(struct sockaddr *) &bip_dest, sizeof(struct sockaddr));
bytes_sent = sendto(BIP_Socket, (char *)mtu, mtu_len, 0,
(struct sockaddr *)&bip_dest, sizeof(struct sockaddr));
return bytes_sent;
}
@@ -211,23 +197,24 @@ int bip_send_pdu(
*
* @param src [out] Source of the packet - who should receive any response.
* @param pdu [out] A buffer to hold the PDU portion of the received packet,
* after the BVLC portion has been stripped off.
* after the BVLC portion has been stripped
* off.
* @param max_pdu [in] Size of the pdu[] buffer.
* @param timeout [in] The number of milliseconds to wait for a packet.
* @return The number of octets (remaining) in the PDU, or zero on failure.
*/
uint16_t bip_receive(
BACNET_ADDRESS * src, /* source address */
uint8_t * pdu, /* PDU data */
uint16_t max_pdu, /* amount of space available in the PDU */
BACNET_ADDRESS *src, /* source address */
uint8_t *pdu, /* PDU data */
uint16_t max_pdu, /* amount of space available in the PDU */
unsigned timeout)
{
int received_bytes = 0;
uint16_t pdu_len = 0; /* return value */
uint16_t pdu_len = 0; /* return value */
fd_set read_fds;
int max = 0;
struct timeval select_timeout;
struct sockaddr_in sin = { 0 };
struct sockaddr_in sin = {0};
socklen_t sin_len = sizeof(sin);
uint16_t i = 0;
int function = 0;
@@ -252,9 +239,8 @@ uint16_t bip_receive(
max = BIP_Socket;
/* see if there is a packet for us */
if (select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0)
received_bytes =
recvfrom(BIP_Socket, (char *) &pdu[0], max_pdu, 0,
(struct sockaddr *) &sin, &sin_len);
received_bytes = recvfrom(BIP_Socket, (char *)&pdu[0], max_pdu, 0,
(struct sockaddr *)&sin, &sin_len);
else
return 0;
@@ -279,7 +265,7 @@ uint16_t bip_receive(
return 0;
}
function = bvlc_get_function_code(); /* aka, pdu[1] */
function = bvlc_get_function_code(); /* aka, pdu[1] */
if ((function == BVLC_ORIGINAL_UNICAST_NPDU) ||
(function == BVLC_ORIGINAL_BROADCAST_NPDU)) {
/* ignore messages from me */
@@ -297,7 +283,7 @@ uint16_t bip_receive(
/* FIXME: check destination address */
/* see if it is broadcast or for us */
/* decode the length of the PDU - length is inclusive of BVLC */
(void) decode_unsigned16(&pdu[2], &pdu_len);
(void)decode_unsigned16(&pdu[2], &pdu_len);
/* subtract off the BVLC header */
pdu_len -= 4;
if (pdu_len < max_pdu) {
@@ -339,7 +325,7 @@ uint16_t bip_receive(
/* FIXME: check destination address */
/* see if it is broadcast or for us */
/* decode the length of the PDU - length is inclusive of BVLC */
(void) decode_unsigned16(&pdu[2], &pdu_len);
(void)decode_unsigned16(&pdu[2], &pdu_len);
/* subtract off the BVLC header */
pdu_len -= 10;
if (pdu_len < max_pdu) {
@@ -358,8 +344,7 @@ uint16_t bip_receive(
return pdu_len;
}
void bip_get_my_address(
BACNET_ADDRESS * my_address)
void bip_get_my_address(BACNET_ADDRESS *my_address)
{
int i = 0;
@@ -367,8 +352,8 @@ void bip_get_my_address(
my_address->mac_len = 6;
memcpy(&my_address->mac[0], &BIP_Address.s_addr, 4);
memcpy(&my_address->mac[4], &BIP_Port, 2);
my_address->net = 0; /* local only, no routing */
my_address->len = 0; /* no SLEN */
my_address->net = 0; /* local only, no routing */
my_address->len = 0; /* no SLEN */
for (i = 0; i < MAX_MAC_LEN; i++) {
/* no SADR */
my_address->adr[i] = 0;
@@ -378,17 +363,16 @@ void bip_get_my_address(
return;
}
void bip_get_broadcast_address(
BACNET_ADDRESS * dest)
{ /* destination address */
int i = 0; /* counter */
void bip_get_broadcast_address(BACNET_ADDRESS *dest)
{ /* destination address */
int i = 0; /* counter */
if (dest) {
dest->mac_len = 6;
memcpy(&dest->mac[0], &BIP_Broadcast_Address.s_addr, 4);
memcpy(&dest->mac[4], &BIP_Port, 2);
dest->net = BACNET_BROADCAST_NETWORK;
dest->len = 0; /* no SLEN */
dest->len = 0; /* no SLEN */
for (i = 0; i < MAX_MAC_LEN; i++) {
/* no SADR */
dest->adr[i] = 0;
+241 -325
View File
File diff suppressed because it is too large Load Diff
+354 -567
View File
File diff suppressed because it is too large Load Diff
+211 -321
View File
@@ -48,31 +48,26 @@ COV Subscribe Property
COV Notification
Unconfirmed COV Notification
*/
static int notify_encode_apdu(
uint8_t * apdu,
unsigned max_apdu_len,
BACNET_COV_DATA * data)
static int notify_encode_apdu(uint8_t *apdu, unsigned max_apdu_len,
BACNET_COV_DATA *data)
{
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
BACNET_PROPERTY_VALUE *value = NULL; /* value in list */
BACNET_APPLICATION_DATA_VALUE *app_data = NULL;
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
BACNET_PROPERTY_VALUE *value = NULL; /* value in list */
BACNET_APPLICATION_DATA_VALUE *app_data = NULL;
if (apdu) {
/* tag 0 - subscriberProcessIdentifier */
len =
encode_context_unsigned(&apdu[apdu_len], 0,
data->subscriberProcessIdentifier);
len = encode_context_unsigned(&apdu[apdu_len], 0,
data->subscriberProcessIdentifier);
apdu_len += len;
/* tag 1 - initiatingDeviceIdentifier */
len =
encode_context_object_id(&apdu[apdu_len], 1, OBJECT_DEVICE,
data->initiatingDeviceIdentifier);
len = encode_context_object_id(&apdu[apdu_len], 1, OBJECT_DEVICE,
data->initiatingDeviceIdentifier);
apdu_len += len;
/* tag 2 - monitoredObjectIdentifier */
len =
encode_context_object_id(&apdu[apdu_len], 2,
(int) data->monitoredObjectIdentifier.type,
len = encode_context_object_id(
&apdu[apdu_len], 2, (int)data->monitoredObjectIdentifier.type,
data->monitoredObjectIdentifier.instance);
apdu_len += len;
/* tag 3 - timeRemaining */
@@ -88,15 +83,13 @@ static int notify_encode_apdu(
value = data->listOfValues;
while (value != NULL) {
/* tag 0 - propertyIdentifier */
len =
encode_context_enumerated(&apdu[apdu_len], 0,
value->propertyIdentifier);
len = encode_context_enumerated(&apdu[apdu_len], 0,
value->propertyIdentifier);
apdu_len += len;
/* tag 1 - propertyArrayIndex OPTIONAL */
if (value->propertyArrayIndex != BACNET_ARRAY_ALL) {
len =
encode_context_unsigned(&apdu[apdu_len], 1,
value->propertyArrayIndex);
len = encode_context_unsigned(&apdu[apdu_len], 1,
value->propertyArrayIndex);
apdu_len += len;
}
/* tag 2 - value */
@@ -104,21 +97,18 @@ static int notify_encode_apdu(
len = encode_opening_tag(&apdu[apdu_len], 2);
apdu_len += len;
app_data = &value->value;
while (app_data != NULL)
{
len =
bacapp_encode_application_data(&apdu[apdu_len], app_data);
while (app_data != NULL) {
len = bacapp_encode_application_data(&apdu[apdu_len], app_data);
apdu_len += len;
app_data = app_data->next;
app_data = app_data->next;
}
len = encode_closing_tag(&apdu[apdu_len], 2);
apdu_len += len;
/* tag 3 - priority OPTIONAL */
if (value->priority != BACNET_NO_PRIORITY) {
len =
encode_context_unsigned(&apdu[apdu_len], 3,
value->priority);
len = encode_context_unsigned(&apdu[apdu_len], 3,
value->priority);
apdu_len += len;
}
/* is there another one to encode? */
@@ -132,14 +122,11 @@ static int notify_encode_apdu(
return apdu_len;
}
int ccov_notify_encode_apdu(
uint8_t * apdu,
unsigned max_apdu_len,
uint8_t invoke_id,
BACNET_COV_DATA * data)
int ccov_notify_encode_apdu(uint8_t *apdu, unsigned max_apdu_len,
uint8_t invoke_id, BACNET_COV_DATA *data)
{
int len = 0; /* length of each encoding */
int apdu_len = BACNET_STATUS_ERROR; /* return value */
int len = 0; /* length of each encoding */
int apdu_len = BACNET_STATUS_ERROR; /* return value */
if (apdu && data && memcopylen(0, max_apdu_len, 4)) {
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
@@ -147,39 +134,37 @@ int ccov_notify_encode_apdu(
apdu[2] = invoke_id;
apdu[3] = SERVICE_CONFIRMED_COV_NOTIFICATION;
apdu_len = 4;
len = notify_encode_apdu(&apdu[apdu_len],
max_apdu_len-apdu_len, data);
len =
notify_encode_apdu(&apdu[apdu_len], max_apdu_len - apdu_len, data);
if (len < 0) {
/* return the error */
apdu_len = len;
} else {
apdu_len += len;
}
apdu_len += len;
}
}
return apdu_len;
}
int ucov_notify_encode_apdu(
uint8_t * apdu,
unsigned max_apdu_len,
BACNET_COV_DATA * data)
int ucov_notify_encode_apdu(uint8_t *apdu, unsigned max_apdu_len,
BACNET_COV_DATA *data)
{
int len = 0; /* length of each encoding */
int apdu_len = BACNET_STATUS_ERROR; /* return value */
int len = 0; /* length of each encoding */
int apdu_len = BACNET_STATUS_ERROR; /* return value */
if (apdu && data && memcopylen(0, max_apdu_len, 2)) {
apdu[0] = PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST;
apdu[1] = SERVICE_UNCONFIRMED_COV_NOTIFICATION; /* service choice */
apdu_len = 2;
len = notify_encode_apdu(&apdu[apdu_len],
max_apdu_len-apdu_len, data);
len =
notify_encode_apdu(&apdu[apdu_len], max_apdu_len - apdu_len, data);
if (len < 0) {
/* return the error */
apdu_len = len;
} else {
apdu_len += len;
}
apdu_len += len;
}
}
return apdu_len;
@@ -187,27 +172,24 @@ int ucov_notify_encode_apdu(
/* decode the service request only */
/* COV and Unconfirmed COV are the same */
int cov_notify_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
BACNET_COV_DATA * data)
int cov_notify_decode_service_request(uint8_t *apdu, unsigned apdu_len,
BACNET_COV_DATA *data)
{
int len = 0; /* return value */
int len = 0; /* return value */
int app_len = 0;
uint8_t tag_number = 0;
uint32_t len_value = 0;
uint32_t decoded_value = 0; /* for decoding */
uint16_t decoded_type = 0; /* for decoding */
uint32_t property = 0; /* for decoding */
BACNET_PROPERTY_VALUE *value = NULL; /* value in list */
BACNET_APPLICATION_DATA_VALUE *app_data = NULL;
uint32_t decoded_value = 0; /* for decoding */
uint16_t decoded_type = 0; /* for decoding */
uint32_t property = 0; /* for decoding */
BACNET_PROPERTY_VALUE *value = NULL; /* value in list */
BACNET_APPLICATION_DATA_VALUE *app_data = NULL;
if (apdu_len && data) {
/* tag 0 - subscriberProcessIdentifier */
if (decode_is_context_tag(&apdu[len], 0)) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_unsigned(&apdu[len], len_value, &decoded_value);
data->subscriberProcessIdentifier = decoded_value;
} else {
@@ -215,12 +197,10 @@ int cov_notify_decode_service_request(
}
/* tag 1 - initiatingDeviceIdentifier */
if (decode_is_context_tag(&apdu[len], 1)) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len +=
decode_object_id(&apdu[len], &decoded_type,
&data->initiatingDeviceIdentifier);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_object_id(&apdu[len], &decoded_type,
&data->initiatingDeviceIdentifier);
if (decoded_type != OBJECT_DEVICE) {
return BACNET_STATUS_ERROR;
}
@@ -229,21 +209,18 @@ int cov_notify_decode_service_request(
}
/* tag 2 - monitoredObjectIdentifier */
if (decode_is_context_tag(&apdu[len], 2)) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len +=
decode_object_id(&apdu[len], &decoded_type,
&data->monitoredObjectIdentifier.instance);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_object_id(&apdu[len], &decoded_type,
&data->monitoredObjectIdentifier.instance);
data->monitoredObjectIdentifier.type = decoded_type;
} else {
return BACNET_STATUS_ERROR;
}
/* tag 3 - timeRemaining */
if (decode_is_context_tag(&apdu[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);
len += decode_unsigned(&apdu[len], len_value, &decoded_value);
data->timeRemaining = decoded_value;
} else {
@@ -264,19 +241,17 @@ int cov_notify_decode_service_request(
while (value != NULL) {
/* tag 0 - propertyIdentifier */
if (decode_is_context_tag(&apdu[len], 0)) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_enumerated(&apdu[len], len_value, &property);
value->propertyIdentifier = (BACNET_PROPERTY_ID) property;
value->propertyIdentifier = (BACNET_PROPERTY_ID)property;
} else {
return BACNET_STATUS_ERROR;
}
/* tag 1 - propertyArrayIndex OPTIONAL */
if (decode_is_context_tag(&apdu[len], 1)) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_unsigned(&apdu[len], len_value, &decoded_value);
value->propertyArrayIndex = decoded_value;
} else {
@@ -289,18 +264,16 @@ int cov_notify_decode_service_request(
/* a tag number of 2 is not extended so only one octet */
len++;
app_data = &value->value;
while (!decode_is_closing_tag_number(&apdu[len], 2))
{
while (!decode_is_closing_tag_number(&apdu[len], 2)) {
if (app_data == NULL) {
/* out of room to store more values */
return BACNET_STATUS_ERROR;
}
app_len =
bacapp_decode_application_data(&apdu[len], apdu_len - len, app_data);
if (app_len < 0)
{
return BACNET_STATUS_ERROR;
}
app_len = bacapp_decode_application_data(
&apdu[len], apdu_len - len, app_data);
if (app_len < 0) {
return BACNET_STATUS_ERROR;
}
len += app_len;
app_data = app_data->next;
@@ -309,11 +282,10 @@ int cov_notify_decode_service_request(
len++;
/* tag 3 - priority OPTIONAL */
if (decode_is_context_tag(&apdu[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);
len += decode_unsigned(&apdu[len], len_value, &decoded_value);
value->priority = (uint8_t) decoded_value;
value->priority = (uint8_t)decoded_value;
} else {
value->priority = BACNET_NO_PRIORITY;
}
@@ -356,14 +328,12 @@ SubscribeCOV-Request ::= SEQUENCE {
}
*/
int cov_subscribe_encode_apdu(
uint8_t * apdu,
unsigned max_apdu_len,
uint8_t invoke_id,
BACNET_SUBSCRIBE_COV_DATA * data)
int cov_subscribe_encode_apdu(uint8_t *apdu, unsigned max_apdu_len,
uint8_t invoke_id,
BACNET_SUBSCRIBE_COV_DATA *data)
{
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
if (apdu && data) {
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
@@ -372,14 +342,12 @@ int cov_subscribe_encode_apdu(
apdu[3] = SERVICE_CONFIRMED_SUBSCRIBE_COV;
apdu_len = 4;
/* tag 0 - subscriberProcessIdentifier */
len =
encode_context_unsigned(&apdu[apdu_len], 0,
data->subscriberProcessIdentifier);
len = encode_context_unsigned(&apdu[apdu_len], 0,
data->subscriberProcessIdentifier);
apdu_len += len;
/* tag 1 - monitoredObjectIdentifier */
len =
encode_context_object_id(&apdu[apdu_len], 1,
(int) data->monitoredObjectIdentifier.type,
len = encode_context_object_id(
&apdu[apdu_len], 1, (int)data->monitoredObjectIdentifier.type,
data->monitoredObjectIdentifier.instance);
apdu_len += len;
/*
@@ -389,9 +357,8 @@ int cov_subscribe_encode_apdu(
*/
if (!data->cancellationRequest) {
/* tag 2 - issueConfirmedNotifications */
len =
encode_context_boolean(&apdu[apdu_len], 2,
data->issueConfirmedNotifications);
len = encode_context_boolean(&apdu[apdu_len], 2,
data->issueConfirmedNotifications);
apdu_len += len;
/* tag 3 - lifetime */
len = encode_context_unsigned(&apdu[apdu_len], 3, data->lifetime);
@@ -403,12 +370,10 @@ int cov_subscribe_encode_apdu(
}
/* decode the service request only */
int cov_subscribe_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
BACNET_SUBSCRIBE_COV_DATA * data)
int cov_subscribe_decode_service_request(uint8_t *apdu, unsigned apdu_len,
BACNET_SUBSCRIBE_COV_DATA *data)
{
int len = 0; /* return value */
int len = 0; /* return value */
uint8_t tag_number = 0;
uint32_t len_value = 0;
uint32_t decoded_value = 0; /* for decoding */
@@ -417,9 +382,8 @@ int cov_subscribe_decode_service_request(
if (apdu_len && data) {
/* tag 0 - subscriberProcessIdentifier */
if (decode_is_context_tag(&apdu[len], 0)) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_unsigned(&apdu[len], len_value, &decoded_value);
data->subscriberProcessIdentifier = decoded_value;
} else {
@@ -428,25 +392,22 @@ int cov_subscribe_decode_service_request(
}
/* tag 1 - monitoredObjectIdentifier */
if (decode_is_context_tag(&apdu[len], 1)) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len +=
decode_object_id(&apdu[len], &decoded_type,
&data->monitoredObjectIdentifier.instance);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_object_id(&apdu[len], &decoded_type,
&data->monitoredObjectIdentifier.instance);
data->monitoredObjectIdentifier.type = decoded_type;
} else {
data->error_code = ERROR_CODE_REJECT_INVALID_TAG;
return BACNET_STATUS_REJECT;
}
/* optional parameters - if missing, means cancellation */
if ((unsigned) len < apdu_len) {
if ((unsigned)len < apdu_len) {
/* tag 2 - issueConfirmedNotifications - optional */
if (decode_is_context_tag(&apdu[len], 2)) {
data->cancellationRequest = false;
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
data->issueConfirmedNotifications =
decode_context_boolean(&apdu[len]);
len += len_value;
@@ -455,9 +416,8 @@ int cov_subscribe_decode_service_request(
}
/* tag 3 - lifetime - optional */
if (decode_is_context_tag(&apdu[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);
len += decode_unsigned(&apdu[len], len_value, &decoded_value);
data->lifetime = decoded_value;
} else {
@@ -471,7 +431,6 @@ int cov_subscribe_decode_service_request(
return len;
}
/*
SubscribeCOVProperty-Request ::= SEQUENCE {
subscriberProcessIdentifier [0] Unsigned32,
@@ -491,14 +450,12 @@ BACnetPropertyReference ::= SEQUENCE {
*/
int cov_subscribe_property_encode_apdu(
uint8_t * apdu,
unsigned max_apdu_len,
uint8_t invoke_id,
BACNET_SUBSCRIBE_COV_DATA * data)
int cov_subscribe_property_encode_apdu(uint8_t *apdu, unsigned max_apdu_len,
uint8_t invoke_id,
BACNET_SUBSCRIBE_COV_DATA *data)
{
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
if (apdu && data) {
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
@@ -507,21 +464,18 @@ int cov_subscribe_property_encode_apdu(
apdu[3] = SERVICE_CONFIRMED_SUBSCRIBE_COV_PROPERTY;
apdu_len = 4;
/* tag 0 - subscriberProcessIdentifier */
len =
encode_context_unsigned(&apdu[apdu_len], 0,
data->subscriberProcessIdentifier);
len = encode_context_unsigned(&apdu[apdu_len], 0,
data->subscriberProcessIdentifier);
apdu_len += len;
/* tag 1 - monitoredObjectIdentifier */
len =
encode_context_object_id(&apdu[apdu_len], 1,
(int) data->monitoredObjectIdentifier.type,
len = encode_context_object_id(
&apdu[apdu_len], 1, (int)data->monitoredObjectIdentifier.type,
data->monitoredObjectIdentifier.instance);
apdu_len += len;
if (!data->cancellationRequest) {
/* tag 2 - issueConfirmedNotifications */
len =
encode_context_boolean(&apdu[apdu_len], 2,
data->issueConfirmedNotifications);
len = encode_context_boolean(&apdu[apdu_len], 2,
data->issueConfirmedNotifications);
apdu_len += len;
/* tag 3 - lifetime */
len = encode_context_unsigned(&apdu[apdu_len], 3, data->lifetime);
@@ -530,16 +484,13 @@ int cov_subscribe_property_encode_apdu(
/* tag 4 - monitoredPropertyIdentifier */
len = encode_opening_tag(&apdu[apdu_len], 4);
apdu_len += len;
len =
encode_context_enumerated(&apdu[apdu_len], 0,
data->monitoredProperty.propertyIdentifier);
len = encode_context_enumerated(
&apdu[apdu_len], 0, data->monitoredProperty.propertyIdentifier);
apdu_len += len;
if (data->monitoredProperty.propertyArrayIndex != BACNET_ARRAY_ALL) {
len =
encode_context_unsigned(&apdu[apdu_len], 1,
data->monitoredProperty.propertyArrayIndex);
len = encode_context_unsigned(
&apdu[apdu_len], 1, data->monitoredProperty.propertyArrayIndex);
apdu_len += len;
}
len = encode_closing_tag(&apdu[apdu_len], 4);
apdu_len += len;
@@ -556,11 +507,9 @@ int cov_subscribe_property_encode_apdu(
/* decode the service request only */
int cov_subscribe_property_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
BACNET_SUBSCRIBE_COV_DATA * data)
uint8_t *apdu, unsigned apdu_len, BACNET_SUBSCRIBE_COV_DATA *data)
{
int len = 0; /* return value */
int len = 0; /* return value */
uint8_t tag_number = 0;
uint32_t len_value = 0;
uint32_t decoded_value = 0; /* for decoding */
@@ -570,9 +519,8 @@ int cov_subscribe_property_decode_service_request(
if (apdu_len && data) {
/* tag 0 - subscriberProcessIdentifier */
if (decode_is_context_tag(&apdu[len], 0)) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_unsigned(&apdu[len], len_value, &decoded_value);
data->subscriberProcessIdentifier = decoded_value;
} else {
@@ -581,12 +529,10 @@ int cov_subscribe_property_decode_service_request(
}
/* tag 1 - monitoredObjectIdentifier */
if (decode_is_context_tag(&apdu[len], 1)) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len +=
decode_object_id(&apdu[len], &decoded_type,
&data->monitoredObjectIdentifier.instance);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_object_id(&apdu[len], &decoded_type,
&data->monitoredObjectIdentifier.instance);
data->monitoredObjectIdentifier.type = decoded_type;
} else {
data->error_code = ERROR_CODE_REJECT_INVALID_TAG;
@@ -595,9 +541,8 @@ int cov_subscribe_property_decode_service_request(
/* tag 2 - issueConfirmedNotifications - optional */
if (decode_is_context_tag(&apdu[len], 2)) {
data->cancellationRequest = false;
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
data->issueConfirmedNotifications =
decode_context_boolean(&apdu[len]);
len++;
@@ -606,9 +551,8 @@ int cov_subscribe_property_decode_service_request(
}
/* tag 3 - lifetime - optional */
if (decode_is_context_tag(&apdu[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);
len += decode_unsigned(&apdu[len], len_value, &decoded_value);
data->lifetime = decoded_value;
} else {
@@ -623,21 +567,19 @@ int cov_subscribe_property_decode_service_request(
len++;
/* the propertyIdentifier is tag 0 */
if (decode_is_context_tag(&apdu[len], 0)) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_enumerated(&apdu[len], len_value, &property);
data->monitoredProperty.propertyIdentifier =
(BACNET_PROPERTY_ID) property;
(BACNET_PROPERTY_ID)property;
} else {
data->error_code = ERROR_CODE_REJECT_INVALID_TAG;
return BACNET_STATUS_REJECT;
}
/* the optional array index is tag 1 */
if (decode_is_context_tag(&apdu[len], 1)) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_unsigned(&apdu[len], len_value, &decoded_value);
data->monitoredProperty.propertyArrayIndex = decoded_value;
} else {
@@ -653,9 +595,8 @@ int cov_subscribe_property_decode_service_request(
/* tag 5 - covIncrement - optional */
if (decode_is_context_tag(&apdu[len], 5)) {
data->covIncrementPresent = true;
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_real(&apdu[len], &data->covIncrement);
} else {
data->covIncrementPresent = false;
@@ -675,10 +616,8 @@ int cov_subscribe_property_decode_service_request(
* a buffer or array.
* @param count - number of BACNET_PROPERTY_VALUE elements
*/
void cov_data_value_list_link(
BACNET_COV_DATA *data,
BACNET_PROPERTY_VALUE *value_list,
size_t count)
void cov_data_value_list_link(BACNET_COV_DATA *data,
BACNET_PROPERTY_VALUE *value_list, size_t count)
{
BACNET_PROPERTY_VALUE *current_value_list = NULL;
@@ -703,11 +642,8 @@ void cov_data_value_list_link(
#include "ctest.h"
#include "bacapp.h"
int ccov_notify_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
uint8_t * invoke_id,
BACNET_COV_DATA * data)
int ccov_notify_decode_apdu(uint8_t *apdu, unsigned apdu_len,
uint8_t *invoke_id, BACNET_COV_DATA *data)
{
int len = 0;
unsigned offset = 0;
@@ -719,25 +655,22 @@ int ccov_notify_decode_apdu(
if (apdu[0] != PDU_TYPE_CONFIRMED_SERVICE_REQUEST)
return -2;
/* apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU); */
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
if (apdu[3] != SERVICE_CONFIRMED_COV_NOTIFICATION)
return -3;
offset = 4;
/* optional limits - must be used as a pair */
if (apdu_len > offset) {
len =
cov_notify_decode_service_request(&apdu[offset], apdu_len - offset,
data);
len = cov_notify_decode_service_request(&apdu[offset],
apdu_len - offset, data);
}
return len;
}
int ucov_notify_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
BACNET_COV_DATA * data)
int ucov_notify_decode_apdu(uint8_t *apdu, unsigned apdu_len,
BACNET_COV_DATA *data)
{
int len = 0;
unsigned offset = 0;
@@ -752,19 +685,16 @@ int ucov_notify_decode_apdu(
/* optional limits - must be used as a pair */
offset = 2;
if (apdu_len > offset) {
len =
cov_notify_decode_service_request(&apdu[offset], apdu_len - offset,
data);
len = cov_notify_decode_service_request(&apdu[offset],
apdu_len - offset, data);
}
return len;
}
int cov_subscribe_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
uint8_t * invoke_id,
BACNET_SUBSCRIBE_COV_DATA * data)
int cov_subscribe_decode_apdu(uint8_t *apdu, unsigned apdu_len,
uint8_t *invoke_id,
BACNET_SUBSCRIBE_COV_DATA *data)
{
int len = 0;
unsigned offset = 0;
@@ -775,26 +705,23 @@ int cov_subscribe_decode_apdu(
if (apdu[0] != PDU_TYPE_CONFIRMED_SERVICE_REQUEST)
return -2;
/* apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU); */
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
if (apdu[3] != SERVICE_CONFIRMED_SUBSCRIBE_COV)
return -3;
offset = 4;
/* optional limits - must be used as a pair */
if (apdu_len > offset) {
len =
cov_subscribe_decode_service_request(&apdu[offset],
apdu_len - offset, data);
len = cov_subscribe_decode_service_request(&apdu[offset],
apdu_len - offset, data);
}
return len;
}
int cov_subscribe_property_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
uint8_t * invoke_id,
BACNET_SUBSCRIBE_COV_DATA * data)
int cov_subscribe_property_decode_apdu(uint8_t *apdu, unsigned apdu_len,
uint8_t *invoke_id,
BACNET_SUBSCRIBE_COV_DATA *data)
{
int len = 0;
unsigned offset = 0;
@@ -805,42 +732,35 @@ int cov_subscribe_property_decode_apdu(
if (apdu[0] != PDU_TYPE_CONFIRMED_SERVICE_REQUEST)
return -2;
/* apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU); */
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
if (apdu[3] != SERVICE_CONFIRMED_SUBSCRIBE_COV_PROPERTY)
return -3;
offset = 4;
/* optional limits - must be used as a pair */
if (apdu_len > offset) {
len =
cov_subscribe_property_decode_service_request(&apdu[offset],
apdu_len - offset, data);
len = cov_subscribe_property_decode_service_request(
&apdu[offset], apdu_len - offset, data);
}
return len;
}
/* dummy function stubs */
void testCOVNotifyData(
Test * pTest,
BACNET_COV_DATA * data,
BACNET_COV_DATA * test_data)
void testCOVNotifyData(Test *pTest, BACNET_COV_DATA *data,
BACNET_COV_DATA *test_data)
{
BACNET_PROPERTY_VALUE *value = NULL;
BACNET_PROPERTY_VALUE *test_value = NULL;
ct_test(pTest,
test_data->subscriberProcessIdentifier ==
data->subscriberProcessIdentifier);
ct_test(pTest,
test_data->initiatingDeviceIdentifier ==
data->initiatingDeviceIdentifier);
ct_test(pTest,
test_data->monitoredObjectIdentifier.type ==
data->monitoredObjectIdentifier.type);
ct_test(pTest,
test_data->monitoredObjectIdentifier.instance ==
data->monitoredObjectIdentifier.instance);
ct_test(pTest, test_data->subscriberProcessIdentifier ==
data->subscriberProcessIdentifier);
ct_test(pTest, test_data->initiatingDeviceIdentifier ==
data->initiatingDeviceIdentifier);
ct_test(pTest, test_data->monitoredObjectIdentifier.type ==
data->monitoredObjectIdentifier.type);
ct_test(pTest, test_data->monitoredObjectIdentifier.instance ==
data->monitoredObjectIdentifier.instance);
ct_test(pTest, test_data->timeRemaining == data->timeRemaining);
/* test the listOfValues in some clever manner */
value = data->listOfValues;
@@ -848,25 +768,22 @@ void testCOVNotifyData(
while (value) {
ct_test(pTest, test_value);
if (test_value) {
ct_test(pTest, test_value->propertyIdentifier ==
value->propertyIdentifier);
ct_test(pTest, test_value->propertyArrayIndex ==
value->propertyArrayIndex);
ct_test(pTest, test_value->priority == value->priority);
ct_test(pTest,
test_value->propertyIdentifier == value->propertyIdentifier);
ct_test(pTest,
test_value->propertyArrayIndex == value->propertyArrayIndex);
ct_test(pTest,
test_value->priority == value->priority);
ct_test(pTest,
bacapp_same_value(&test_value->value, &value->value));
bacapp_same_value(&test_value->value, &value->value));
test_value = test_value->next;
}
value = value->next;
}
}
void testUCOVNotifyData(
Test * pTest,
BACNET_COV_DATA * data)
void testUCOVNotifyData(Test *pTest, BACNET_COV_DATA *data)
{
uint8_t apdu[480] = { 0 };
uint8_t apdu[480] = {0};
int len = 0;
int apdu_len = 0;
BACNET_COV_DATA test_data;
@@ -882,12 +799,9 @@ void testUCOVNotifyData(
testCOVNotifyData(pTest, data, &test_data);
}
void testCCOVNotifyData(
Test * pTest,
uint8_t invoke_id,
BACNET_COV_DATA * data)
void testCCOVNotifyData(Test *pTest, uint8_t invoke_id, BACNET_COV_DATA *data)
{
uint8_t apdu[480] = { 0 };
uint8_t apdu[480] = {0};
int len = 0;
int apdu_len = 0;
BACNET_COV_DATA test_data;
@@ -899,16 +813,14 @@ void testCCOVNotifyData(
apdu_len = len;
cov_data_value_list_link(&test_data, &value_list[0], 2);
len =
ccov_notify_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_data);
len = ccov_notify_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_data);
ct_test(pTest, len > 0);
ct_test(pTest, test_invoke_id == invoke_id);
testCOVNotifyData(pTest, data, &test_data);
}
void testCOVNotify(
Test * pTest)
void testCOVNotify(Test *pTest)
{
uint8_t invoke_id = 12;
BACNET_COV_DATA data;
@@ -925,71 +837,57 @@ void testCOVNotify(
value_list[0].propertyIdentifier = PROP_PRESENT_VALUE;
value_list[0].propertyArrayIndex = BACNET_ARRAY_ALL;
bacapp_parse_application_data(BACNET_APPLICATION_TAG_REAL, "21.0",
&value_list[0].value);
&value_list[0].value);
value_list[0].priority = 0;
/* second value */
value_list[1].propertyIdentifier = PROP_STATUS_FLAGS;
value_list[1].propertyArrayIndex = BACNET_ARRAY_ALL;
bacapp_parse_application_data(BACNET_APPLICATION_TAG_BIT_STRING, "0000",
&value_list[1].value);
&value_list[1].value);
value_list[1].priority = 0;
testUCOVNotifyData(pTest, &data);
testCCOVNotifyData(pTest, invoke_id, &data);
}
void testCOVSubscribeData(
Test * pTest,
BACNET_SUBSCRIBE_COV_DATA * data,
BACNET_SUBSCRIBE_COV_DATA * test_data)
void testCOVSubscribeData(Test *pTest, BACNET_SUBSCRIBE_COV_DATA *data,
BACNET_SUBSCRIBE_COV_DATA *test_data)
{
ct_test(pTest,
test_data->subscriberProcessIdentifier ==
data->subscriberProcessIdentifier);
ct_test(pTest,
test_data->monitoredObjectIdentifier.type ==
data->monitoredObjectIdentifier.type);
ct_test(pTest,
test_data->monitoredObjectIdentifier.instance ==
data->monitoredObjectIdentifier.instance);
ct_test(pTest,
test_data->cancellationRequest == data->cancellationRequest);
ct_test(pTest, test_data->subscriberProcessIdentifier ==
data->subscriberProcessIdentifier);
ct_test(pTest, test_data->monitoredObjectIdentifier.type ==
data->monitoredObjectIdentifier.type);
ct_test(pTest, test_data->monitoredObjectIdentifier.instance ==
data->monitoredObjectIdentifier.instance);
ct_test(pTest, test_data->cancellationRequest == data->cancellationRequest);
if (test_data->cancellationRequest != data->cancellationRequest) {
printf("cancellation request failed!\n");
}
if (!test_data->cancellationRequest) {
ct_test(pTest,
test_data->issueConfirmedNotifications ==
data->issueConfirmedNotifications);
ct_test(pTest, test_data->issueConfirmedNotifications ==
data->issueConfirmedNotifications);
ct_test(pTest, test_data->lifetime == data->lifetime);
}
}
void testCOVSubscribePropertyData(
Test * pTest,
BACNET_SUBSCRIBE_COV_DATA * data,
BACNET_SUBSCRIBE_COV_DATA * test_data)
void testCOVSubscribePropertyData(Test *pTest, BACNET_SUBSCRIBE_COV_DATA *data,
BACNET_SUBSCRIBE_COV_DATA *test_data)
{
testCOVSubscribeData(pTest, data, test_data);
ct_test(pTest,
test_data->monitoredProperty.propertyIdentifier ==
data->monitoredProperty.propertyIdentifier);
ct_test(pTest,
test_data->monitoredProperty.propertyArrayIndex ==
data->monitoredProperty.propertyArrayIndex);
ct_test(pTest,
test_data->covIncrementPresent == data->covIncrementPresent);
ct_test(pTest, test_data->monitoredProperty.propertyIdentifier ==
data->monitoredProperty.propertyIdentifier);
ct_test(pTest, test_data->monitoredProperty.propertyArrayIndex ==
data->monitoredProperty.propertyArrayIndex);
ct_test(pTest, test_data->covIncrementPresent == data->covIncrementPresent);
if (test_data->covIncrementPresent) {
ct_test(pTest, test_data->covIncrement == data->covIncrement);
}
}
void testCOVSubscribeEncoding(
Test * pTest,
uint8_t invoke_id,
BACNET_SUBSCRIBE_COV_DATA * data)
void testCOVSubscribeEncoding(Test *pTest, uint8_t invoke_id,
BACNET_SUBSCRIBE_COV_DATA *data)
{
uint8_t apdu[480] = { 0 };
uint8_t apdu[480] = {0};
int len = 0;
int apdu_len = 0;
BACNET_SUBSCRIBE_COV_DATA test_data;
@@ -999,40 +897,35 @@ void testCOVSubscribeEncoding(
ct_test(pTest, len != 0);
apdu_len = len;
len =
cov_subscribe_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_data);
len = cov_subscribe_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_data);
ct_test(pTest, len > 0);
ct_test(pTest, test_invoke_id == invoke_id);
testCOVSubscribeData(pTest, data, &test_data);
}
void testCOVSubscribePropertyEncoding(
Test * pTest,
uint8_t invoke_id,
BACNET_SUBSCRIBE_COV_DATA * data)
void testCOVSubscribePropertyEncoding(Test *pTest, uint8_t invoke_id,
BACNET_SUBSCRIBE_COV_DATA *data)
{
uint8_t apdu[480] = { 0 };
uint8_t apdu[480] = {0};
int len = 0;
int apdu_len = 0;
BACNET_SUBSCRIBE_COV_DATA test_data;
uint8_t test_invoke_id = 0;
len = cov_subscribe_property_encode_apdu(&apdu[0], sizeof(apdu), invoke_id,
data);
data);
ct_test(pTest, len != 0);
apdu_len = len;
len =
cov_subscribe_property_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_data);
len = cov_subscribe_property_decode_apdu(&apdu[0], apdu_len,
&test_invoke_id, &test_data);
ct_test(pTest, len > 0);
ct_test(pTest, test_invoke_id == invoke_id);
testCOVSubscribePropertyData(pTest, data, &test_data);
}
void testCOVSubscribe(
Test * pTest)
void testCOVSubscribe(Test *pTest)
{
uint8_t invoke_id = 12;
BACNET_SUBSCRIBE_COV_DATA data;
@@ -1049,8 +942,7 @@ void testCOVSubscribe(
testCOVSubscribeEncoding(pTest, invoke_id, &data);
}
void testCOVSubscribeProperty(
Test * pTest)
void testCOVSubscribeProperty(Test *pTest)
{
uint8_t invoke_id = 12;
BACNET_SUBSCRIBE_COV_DATA data;
@@ -1077,9 +969,7 @@ void testCOVSubscribeProperty(
}
#ifdef TEST_COV
int main(
int argc,
char *argv[])
int main(int argc, char *argv[])
{
Test *pTest;
bool rc;
@@ -1095,7 +985,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+68 -99
View File
@@ -42,89 +42,69 @@
#if defined(CRC_USE_TABLE)
/* note: table is created using unit test below */
static const uint8_t HeaderCRC[256] = {
0x00, 0xfe, 0xff, 0x01, 0xfd, 0x03, 0x02, 0xfc,
0xf9, 0x07, 0x06, 0xf8, 0x04, 0xfa, 0xfb, 0x05,
0xf1, 0x0f, 0x0e, 0xf0, 0x0c, 0xf2, 0xf3, 0x0d,
0x08, 0xf6, 0xf7, 0x09, 0xf5, 0x0b, 0x0a, 0xf4,
0xe1, 0x1f, 0x1e, 0xe0, 0x1c, 0xe2, 0xe3, 0x1d,
0x18, 0xe6, 0xe7, 0x19, 0xe5, 0x1b, 0x1a, 0xe4,
0x10, 0xee, 0xef, 0x11, 0xed, 0x13, 0x12, 0xec,
0xe9, 0x17, 0x16, 0xe8, 0x14, 0xea, 0xeb, 0x15,
0xc1, 0x3f, 0x3e, 0xc0, 0x3c, 0xc2, 0xc3, 0x3d,
0x38, 0xc6, 0xc7, 0x39, 0xc5, 0x3b, 0x3a, 0xc4,
0x30, 0xce, 0xcf, 0x31, 0xcd, 0x33, 0x32, 0xcc,
0xc9, 0x37, 0x36, 0xc8, 0x34, 0xca, 0xcb, 0x35,
0x20, 0xde, 0xdf, 0x21, 0xdd, 0x23, 0x22, 0xdc,
0xd9, 0x27, 0x26, 0xd8, 0x24, 0xda, 0xdb, 0x25,
0xd1, 0x2f, 0x2e, 0xd0, 0x2c, 0xd2, 0xd3, 0x2d,
0x28, 0xd6, 0xd7, 0x29, 0xd5, 0x2b, 0x2a, 0xd4,
0x81, 0x7f, 0x7e, 0x80, 0x7c, 0x82, 0x83, 0x7d,
0x78, 0x86, 0x87, 0x79, 0x85, 0x7b, 0x7a, 0x84,
0x70, 0x8e, 0x8f, 0x71, 0x8d, 0x73, 0x72, 0x8c,
0x89, 0x77, 0x76, 0x88, 0x74, 0x8a, 0x8b, 0x75,
0x60, 0x9e, 0x9f, 0x61, 0x9d, 0x63, 0x62, 0x9c,
0x99, 0x67, 0x66, 0x98, 0x64, 0x9a, 0x9b, 0x65,
0x91, 0x6f, 0x6e, 0x90, 0x6c, 0x92, 0x93, 0x6d,
0x68, 0x96, 0x97, 0x69, 0x95, 0x6b, 0x6a, 0x94,
0x40, 0xbe, 0xbf, 0x41, 0xbd, 0x43, 0x42, 0xbc,
0xb9, 0x47, 0x46, 0xb8, 0x44, 0xba, 0xbb, 0x45,
0xb1, 0x4f, 0x4e, 0xb0, 0x4c, 0xb2, 0xb3, 0x4d,
0x48, 0xb6, 0xb7, 0x49, 0xb5, 0x4b, 0x4a, 0xb4,
0xa1, 0x5f, 0x5e, 0xa0, 0x5c, 0xa2, 0xa3, 0x5d,
0x58, 0xa6, 0xa7, 0x59, 0xa5, 0x5b, 0x5a, 0xa4,
0x50, 0xae, 0xaf, 0x51, 0xad, 0x53, 0x52, 0xac,
0xa9, 0x57, 0x56, 0xa8, 0x54, 0xaa, 0xab, 0x55
};
0x00, 0xfe, 0xff, 0x01, 0xfd, 0x03, 0x02, 0xfc, 0xf9, 0x07, 0x06, 0xf8,
0x04, 0xfa, 0xfb, 0x05, 0xf1, 0x0f, 0x0e, 0xf0, 0x0c, 0xf2, 0xf3, 0x0d,
0x08, 0xf6, 0xf7, 0x09, 0xf5, 0x0b, 0x0a, 0xf4, 0xe1, 0x1f, 0x1e, 0xe0,
0x1c, 0xe2, 0xe3, 0x1d, 0x18, 0xe6, 0xe7, 0x19, 0xe5, 0x1b, 0x1a, 0xe4,
0x10, 0xee, 0xef, 0x11, 0xed, 0x13, 0x12, 0xec, 0xe9, 0x17, 0x16, 0xe8,
0x14, 0xea, 0xeb, 0x15, 0xc1, 0x3f, 0x3e, 0xc0, 0x3c, 0xc2, 0xc3, 0x3d,
0x38, 0xc6, 0xc7, 0x39, 0xc5, 0x3b, 0x3a, 0xc4, 0x30, 0xce, 0xcf, 0x31,
0xcd, 0x33, 0x32, 0xcc, 0xc9, 0x37, 0x36, 0xc8, 0x34, 0xca, 0xcb, 0x35,
0x20, 0xde, 0xdf, 0x21, 0xdd, 0x23, 0x22, 0xdc, 0xd9, 0x27, 0x26, 0xd8,
0x24, 0xda, 0xdb, 0x25, 0xd1, 0x2f, 0x2e, 0xd0, 0x2c, 0xd2, 0xd3, 0x2d,
0x28, 0xd6, 0xd7, 0x29, 0xd5, 0x2b, 0x2a, 0xd4, 0x81, 0x7f, 0x7e, 0x80,
0x7c, 0x82, 0x83, 0x7d, 0x78, 0x86, 0x87, 0x79, 0x85, 0x7b, 0x7a, 0x84,
0x70, 0x8e, 0x8f, 0x71, 0x8d, 0x73, 0x72, 0x8c, 0x89, 0x77, 0x76, 0x88,
0x74, 0x8a, 0x8b, 0x75, 0x60, 0x9e, 0x9f, 0x61, 0x9d, 0x63, 0x62, 0x9c,
0x99, 0x67, 0x66, 0x98, 0x64, 0x9a, 0x9b, 0x65, 0x91, 0x6f, 0x6e, 0x90,
0x6c, 0x92, 0x93, 0x6d, 0x68, 0x96, 0x97, 0x69, 0x95, 0x6b, 0x6a, 0x94,
0x40, 0xbe, 0xbf, 0x41, 0xbd, 0x43, 0x42, 0xbc, 0xb9, 0x47, 0x46, 0xb8,
0x44, 0xba, 0xbb, 0x45, 0xb1, 0x4f, 0x4e, 0xb0, 0x4c, 0xb2, 0xb3, 0x4d,
0x48, 0xb6, 0xb7, 0x49, 0xb5, 0x4b, 0x4a, 0xb4, 0xa1, 0x5f, 0x5e, 0xa0,
0x5c, 0xa2, 0xa3, 0x5d, 0x58, 0xa6, 0xa7, 0x59, 0xa5, 0x5b, 0x5a, 0xa4,
0x50, 0xae, 0xaf, 0x51, 0xad, 0x53, 0x52, 0xac, 0xa9, 0x57, 0x56, 0xa8,
0x54, 0xaa, 0xab, 0x55};
uint8_t CRC_Calc_Header(
uint8_t dataValue,
uint8_t crcValue)
uint8_t CRC_Calc_Header(uint8_t dataValue, uint8_t crcValue)
{
return HeaderCRC[crcValue ^ dataValue];
}
/* note: table is created using unit test below */
static const uint16_t DataCRC[256] = {
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
};
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48,
0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081, 0x0108,
0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb,
0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102, 0x308b, 0x0210, 0x1399,
0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e,
0xfae7, 0xc87c, 0xd9f5, 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e,
0x54b5, 0x453c, 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd,
0xc974, 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 0x5285,
0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd, 0xcf44,
0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306, 0x728f, 0x4014,
0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e, 0xfec7, 0xcc5c, 0xddd5,
0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3,
0x242a, 0x16b1, 0x0738, 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862,
0x9af9, 0x8b70, 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e,
0xf0b7, 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1,
0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0xa50a, 0xb483,
0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0x2942, 0x38cb, 0x0a50,
0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b, 0xa402, 0x9699, 0x8710,
0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7,
0x6e6e, 0x5cf5, 0x4d7c, 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1,
0xa33a, 0xb2b3, 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72,
0x3efb, 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e,
0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0x6b46, 0x7acf,
0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 0xf78f, 0xe606, 0xd49d,
0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 0x6a4e, 0x58d5, 0x495c,
0x3de3, 0x2c6a, 0x1ef1, 0x0f78};
uint16_t CRC_Calc_Data(
uint8_t dataValue,
uint16_t crcValue)
uint16_t CRC_Calc_Data(uint8_t dataValue, uint16_t crcValue)
{
return ((crcValue >> 8) ^ DataCRC[(crcValue & 0x00FF) ^ dataValue]);
}
#else
/* Accumulate "dataValue" into the CRC in crcValue. */
@@ -132,18 +112,15 @@ uint16_t CRC_Calc_Data(
/* */
/* The ^ operator means exclusive OR. */
/* Note: This function is copied directly from the BACnet standard. */
uint8_t CRC_Calc_Header(
uint8_t dataValue,
uint8_t crcValue)
uint8_t CRC_Calc_Header(uint8_t dataValue, uint8_t crcValue)
{
uint16_t crc;
crc = crcValue ^ dataValue; /* XOR C7..C0 with D7..D0 */
/* Exclusive OR the terms in the table (top down) */
crc = crc ^ (crc << 1) ^ (crc << 2) ^ (crc << 3)
^ (crc << 4) ^ (crc << 5) ^ (crc << 6)
^ (crc << 7);
crc = crc ^ (crc << 1) ^ (crc << 2) ^ (crc << 3) ^ (crc << 4) ^ (crc << 5) ^
(crc << 6) ^ (crc << 7);
/* Combine bits shifted out left hand end */
return (crc & 0xfe) ^ ((crc >> 8) & 1);
@@ -154,18 +131,15 @@ uint8_t CRC_Calc_Header(
/* */
/* The ^ operator means exclusive OR. */
/* Note: This function is copied directly from the BACnet standard. */
uint16_t CRC_Calc_Data(
uint8_t dataValue,
uint16_t crcValue)
uint16_t CRC_Calc_Data(uint8_t dataValue, uint16_t crcValue)
{
uint16_t crcLow;
crcLow = (crcValue & 0xff) ^ dataValue; /* XOR C7..C0 with D7..D0 */
crcLow = (crcValue & 0xff) ^ dataValue; /* XOR C7..C0 with D7..D0 */
/* Exclusive OR the terms in the table (top down) */
return (crcValue >> 8) ^ (crcLow << 8) ^ (crcLow << 3)
^ (crcLow << 12) ^ (crcLow >> 4)
^ (crcLow & 0x0f) ^ ((crcLow & 0x0f) << 7);
return (crcValue >> 8) ^ (crcLow << 8) ^ (crcLow << 3) ^ (crcLow << 12) ^
(crcLow >> 4) ^ (crcLow & 0x0f) ^ ((crcLow & 0x0f) << 7);
}
#endif
@@ -176,8 +150,7 @@ uint16_t CRC_Calc_Data(
#include "bytes.h"
/* test from Annex G 1.0 of BACnet Standard */
void testCRC8(
Test * pTest)
void testCRC8(Test *pTest)
{
uint8_t crc = 0xff; /* accumulates the crc value */
uint8_t frame_crc; /* appended to the end of the frame */
@@ -202,8 +175,7 @@ void testCRC8(
}
/* test from Annex G 2.0 of BACnet Standard */
void testCRC16(
Test * pTest)
void testCRC16(Test *pTest)
{
uint16_t crc = 0xffff;
uint16_t data_crc;
@@ -224,13 +196,12 @@ void testCRC16(
ct_test(pTest, crc == 0xF0B8);
}
void testCRC8CreateTable(
Test * pTest)
void testCRC8CreateTable(Test *pTest)
{
uint8_t crc = 0xff; /* accumulates the crc value */
int i;
(void) pTest;
(void)pTest;
printf("static const uint8_t HeaderCRC[256] =\n");
printf("{\n");
printf(" ");
@@ -247,13 +218,12 @@ void testCRC8CreateTable(
printf("};\n");
}
void testCRC16CreateTable(
Test * pTest)
void testCRC16CreateTable(Test *pTest)
{
uint16_t crc;
int i;
(void) pTest;
(void)pTest;
printf("static const uint16_t DataCRC[256] =\n");
printf("{\n");
printf(" ");
@@ -273,8 +243,7 @@ void testCRC16CreateTable(
#endif
#ifdef TEST_CRC
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -293,7 +262,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
+31 -41
View File
@@ -1,35 +1,33 @@
/**************************************************************************
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include "credential_authentication_factor.h"
#include "bacdcode.h"
int bacapp_encode_credential_authentication_factor(
uint8_t * apdu,
BACNET_CREDENTIAL_AUTHENTICATION_FACTOR * caf)
uint8_t* apdu, BACNET_CREDENTIAL_AUTHENTICATION_FACTOR* caf)
{
int len;
int apdu_len = 0;
@@ -40,9 +38,8 @@ int bacapp_encode_credential_authentication_factor(
else
apdu_len += len;
len =
bacapp_encode_context_authentication_factor(&apdu[apdu_len], 1,
&caf->authentication_factor);
len = bacapp_encode_context_authentication_factor(
&apdu[apdu_len], 1, &caf->authentication_factor);
if (len < 0)
return -1;
else
@@ -52,9 +49,7 @@ int bacapp_encode_credential_authentication_factor(
}
int bacapp_encode_context_credential_authentication_factor(
uint8_t * apdu,
uint8_t tag,
BACNET_CREDENTIAL_AUTHENTICATION_FACTOR * caf)
uint8_t* apdu, uint8_t tag, BACNET_CREDENTIAL_AUTHENTICATION_FACTOR* caf)
{
int len;
int apdu_len = 0;
@@ -69,12 +64,10 @@ int bacapp_encode_context_credential_authentication_factor(
apdu_len += len;
return apdu_len;
}
int bacapp_decode_credential_authentication_factor(
uint8_t * apdu,
BACNET_CREDENTIAL_AUTHENTICATION_FACTOR * caf)
uint8_t* apdu, BACNET_CREDENTIAL_AUTHENTICATION_FACTOR* caf)
{
int len;
int apdu_len = 0;
@@ -89,9 +82,8 @@ int bacapp_decode_credential_authentication_factor(
return -1;
if (decode_is_context_tag(&apdu[apdu_len], 1)) {
len =
bacapp_decode_context_authentication_factor(&apdu[apdu_len], 1,
&caf->authentication_factor);
len = bacapp_decode_context_authentication_factor(
&apdu[apdu_len], 1, &caf->authentication_factor);
if (len < 0)
return -1;
else
@@ -103,9 +95,7 @@ int bacapp_decode_credential_authentication_factor(
}
int bacapp_decode_context_credential_authentication_factor(
uint8_t * apdu,
uint8_t tag,
BACNET_CREDENTIAL_AUTHENTICATION_FACTOR * caf)
uint8_t* apdu, uint8_t tag, BACNET_CREDENTIAL_AUTHENTICATION_FACTOR* caf)
{
int len = 0;
int section_length;
+22 -42
View File
@@ -44,17 +44,19 @@
#include <string.h>
/* Function pointers - point to your datalink */
/** Function template to Initialize the DataLink services at the given interface.
/** Function template to Initialize the DataLink services at the given
interface.
* @ingroup DLTemplates
*
* @note For Linux, ifname is eth0, ath0, arc0, ttyS0, and others.
For Windows, ifname is the COM port or dotted ip address of the interface.
For Windows, ifname is the COM port or dotted ip address of the
interface.
* @param ifname [in] The named interface to use for the network layer.
* @return True if the interface is successfully initialized,
* else False if the initialization fails.
*/
bool(*datalink_init) (char *ifname);
bool (*datalink_init)(char *ifname);
/** Function template to send a packet via the DataLink.
* @ingroup DLTemplates
@@ -65,33 +67,22 @@ bool(*datalink_init) (char *ifname);
* @param pdu_len [in] Number of bytes in the pdu buffer.
* @return Number of bytes sent on success, negative number on failure.
*/
int (
*datalink_send_pdu) (
BACNET_ADDRESS * dest,
BACNET_NPDU_DATA * npdu_data,
uint8_t * pdu,
unsigned pdu_len);
int (*datalink_send_pdu)(BACNET_ADDRESS *dest, BACNET_NPDU_DATA *npdu_data,
uint8_t *pdu, unsigned pdu_len);
uint16_t(*datalink_receive) (BACNET_ADDRESS * src, uint8_t * pdu,
uint16_t max_pdu, unsigned timeout);
uint16_t (*datalink_receive)(BACNET_ADDRESS *src, uint8_t *pdu,
uint16_t max_pdu, unsigned timeout);
/** Function template to close the DataLink services and perform any cleanup.
* @ingroup DLTemplates
*/
void (
*datalink_cleanup) (
void);
void (*datalink_cleanup)(void);
void (
*datalink_get_broadcast_address) (
BACNET_ADDRESS * dest);
void (*datalink_get_broadcast_address)(BACNET_ADDRESS *dest);
void (
*datalink_get_my_address) (
BACNET_ADDRESS * my_address);
void (*datalink_get_my_address)(BACNET_ADDRESS *my_address);
void datalink_set(
char *datalink_string)
void datalink_set(char *datalink_string)
{
if (strcasecmp("bip", datalink_string) == 0) {
datalink_init = bip_init;
@@ -147,46 +138,35 @@ void datalink_set(
#endif
#if defined(BACDL_NONE)
int datalink_send_pdu(
BACNET_ADDRESS * dest,
BACNET_NPDU_DATA * npdu_data,
uint8_t * pdu,
unsigned pdu_len)
int datalink_send_pdu(BACNET_ADDRESS *dest, BACNET_NPDU_DATA *npdu_data,
uint8_t *pdu, unsigned pdu_len)
{
return 0;
}
uint16_t datalink_receive(
BACNET_ADDRESS * src,
uint8_t * pdu,
uint16_t max_pdu,
unsigned timeout)
uint16_t datalink_receive(BACNET_ADDRESS *src, uint8_t *pdu, uint16_t max_pdu,
unsigned timeout)
{
return 0;
}
void datalink_cleanup(
void)
void datalink_cleanup(void)
{
}
void datalink_get_broadcast_address(
BACNET_ADDRESS * dest)
void datalink_get_broadcast_address(BACNET_ADDRESS *dest)
{
}
void datalink_get_my_address(
BACNET_ADDRESS * my_address)
void datalink_get_my_address(BACNET_ADDRESS *my_address)
{
}
void datalink_set_interface(
char *ifname)
void datalink_set_interface(char *ifname)
{
}
void datalink_set(
char *datalink_string)
void datalink_set(char *datalink_string)
{
}
#endif
+127 -257
View File
@@ -60,8 +60,7 @@
time or date may be interpreted as "any" or "don't care"
*/
bool datetime_is_leap_year(
uint16_t year)
bool datetime_is_leap_year(uint16_t year)
{
if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0))
return (true);
@@ -69,13 +68,11 @@ bool datetime_is_leap_year(
return (false);
}
uint8_t datetime_month_days(
uint16_t year,
uint8_t month)
uint8_t datetime_month_days(uint16_t year, uint8_t month)
{
/* note: start with a zero in the first element to save us from a
month - 1 calculation in the lookup */
int month_days[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int month_days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
/* return value */
uint8_t days = 0;
@@ -83,34 +80,29 @@ uint8_t datetime_month_days(
if ((month == 2) && datetime_is_leap_year(year)) {
days = 29;
} else if (month >= 1 && month <= 12) {
days = (uint8_t) month_days[month];
days = (uint8_t)month_days[month];
}
return days;
}
bool datetime_ymd_is_valid(
uint16_t year,
uint8_t month,
uint8_t day)
bool datetime_ymd_is_valid(uint16_t year, uint8_t month, uint8_t day)
{
bool status = false; /* true if value date */
uint8_t monthdays = 0; /* days in a month */
bool status = false; /* true if value date */
uint8_t monthdays = 0; /* days in a month */
monthdays = datetime_month_days(year, month);
if ((year >= BACNET_EPOCH_YEAR) && (monthdays > 0) &&
(day >= 1) && (day <= monthdays)) {
if ((year >= BACNET_EPOCH_YEAR) && (monthdays > 0) && (day >= 1) &&
(day <= monthdays)) {
status = true;
}
return status;
}
bool datetime_date_is_valid(
BACNET_DATE * bdate)
bool datetime_date_is_valid(BACNET_DATE *bdate)
{
bool status = false; /* true if value date */
bool status = false; /* true if value date */
if (bdate) {
status = datetime_ymd_is_valid(bdate->year, bdate->month, bdate->day);
@@ -119,10 +111,7 @@ bool datetime_date_is_valid(
return status;
}
static uint32_t day_of_year(
uint16_t year,
uint8_t month,
uint8_t day)
static uint32_t day_of_year(uint16_t year, uint8_t month, uint8_t day)
{
uint32_t days = 0; /* return value */
uint8_t months = 0; /* loop counter for months */
@@ -137,21 +126,18 @@ static uint32_t day_of_year(
return (days);
}
static void day_of_year_into_md(
uint32_t days,
uint16_t year,
uint8_t * pMonth,
uint8_t * pDay)
static void day_of_year_into_md(uint32_t days, uint16_t year, uint8_t *pMonth,
uint8_t *pDay)
{
uint8_t month = 1;
uint8_t day = 0;
while (days > (uint32_t) datetime_month_days(year, month)) {
while (days > (uint32_t)datetime_month_days(year, month)) {
days -= datetime_month_days(year, month);
month++;
}
day = (uint8_t) (day + days);
day = (uint8_t)(day + days);
if (pMonth) {
*pMonth = month;
@@ -163,10 +149,8 @@ static void day_of_year_into_md(
return;
}
void datetime_day_of_year_into_date(
uint32_t days,
uint16_t year,
BACNET_DATE *bdate)
void datetime_day_of_year_into_date(uint32_t days, uint16_t year,
BACNET_DATE *bdate)
{
uint8_t month = 0;
uint8_t day = 0;
@@ -175,8 +159,7 @@ void datetime_day_of_year_into_date(
datetime_set_date(bdate, year, month, day);
}
uint32_t datetime_day_of_year(
BACNET_DATE *bdate)
uint32_t datetime_day_of_year(BACNET_DATE *bdate)
{
uint32_t days = 0;
@@ -187,10 +170,7 @@ uint32_t datetime_day_of_year(
return days;
}
static uint32_t days_since_epoch(
uint16_t year,
uint8_t month,
uint8_t day)
static uint32_t days_since_epoch(uint16_t year, uint8_t month, uint8_t day)
{
uint32_t days = 0; /* return value */
uint16_t years = 0; /* loop counter for years */
@@ -209,8 +189,7 @@ static uint32_t days_since_epoch(
return (days);
}
uint32_t datetime_days_since_epoch(
BACNET_DATE * bdate)
uint32_t datetime_days_since_epoch(BACNET_DATE *bdate)
{
uint32_t days = 0;
@@ -221,11 +200,8 @@ uint32_t datetime_days_since_epoch(
return days;
}
static void days_since_epoch_into_ymd(
uint32_t days,
uint16_t * pYear,
uint8_t * pMonth,
uint8_t * pDay)
static void days_since_epoch_into_ymd(uint32_t days, uint16_t *pYear,
uint8_t *pMonth, uint8_t *pDay)
{
uint16_t year = BACNET_EPOCH_YEAR;
uint8_t month = 1;
@@ -240,12 +216,12 @@ static void days_since_epoch_into_ymd(
year++;
}
while (days >= (uint32_t) datetime_month_days(year, month)) {
while (days >= (uint32_t)datetime_month_days(year, month)) {
days -= datetime_month_days(year, month);
month++;
}
day = (uint8_t) (day + days);
day = (uint8_t)(day + days);
if (pYear)
*pYear = year;
@@ -257,9 +233,7 @@ static void days_since_epoch_into_ymd(
return;
}
void datetime_days_since_epoch_into_date(
uint32_t days,
BACNET_DATE * bdate)
void datetime_days_since_epoch_into_date(uint32_t days, BACNET_DATE *bdate)
{
uint16_t year = 0;
uint8_t month = 0;
@@ -271,10 +245,7 @@ void datetime_days_since_epoch_into_date(
/* Jan 1, 1900 is a Monday */
/* wday 1=Monday...7=Sunday */
uint8_t datetime_day_of_week(
uint16_t year,
uint8_t month,
uint8_t day)
uint8_t datetime_day_of_week(uint16_t year, uint8_t month, uint8_t day)
{
uint8_t dow = (uint8_t)BACNET_EPOCH_DOW;
@@ -283,8 +254,7 @@ uint8_t datetime_day_of_week(
return dow;
}
bool datetime_time_is_valid(
BACNET_TIME * btime)
bool datetime_time_is_valid(BACNET_TIME *btime)
{
bool status = false;
@@ -306,29 +276,24 @@ bool datetime_time_is_valid(
*
* @return true if the date and time are valid
*/
bool datetime_is_valid(
BACNET_DATE * bdate,
BACNET_TIME * btime)
bool datetime_is_valid(BACNET_DATE *bdate, BACNET_TIME *btime)
{
return datetime_date_is_valid(bdate) && datetime_time_is_valid(btime);
}
/* if the date1 is the same as date2, return is 0
if date1 is after date2, returns positive
if date1 is before date2, returns negative */
int datetime_compare_date(
BACNET_DATE * date1,
BACNET_DATE * date2)
int datetime_compare_date(BACNET_DATE *date1, BACNET_DATE *date2)
{
int diff = 0;
if (date1 && date2) {
diff = (int) date1->year - (int) date2->year;
diff = (int)date1->year - (int)date2->year;
if (diff == 0) {
diff = (int) date1->month - (int) date2->month;
diff = (int)date1->month - (int)date2->month;
if (diff == 0) {
diff = (int) date1->day - (int) date2->day;
diff = (int)date1->day - (int)date2->day;
}
}
}
@@ -339,20 +304,18 @@ int datetime_compare_date(
/* if the time1 is the same as time2, return is 0
if time1 is after time2, returns positive
if time1 is before time2, returns negative */
int datetime_compare_time(
BACNET_TIME * time1,
BACNET_TIME * time2)
int datetime_compare_time(BACNET_TIME *time1, BACNET_TIME *time2)
{
int diff = 0;
if (time1 && time2) {
diff = (int) time1->hour - (int) time2->hour;
diff = (int)time1->hour - (int)time2->hour;
if (diff == 0) {
diff = (int) time1->min - (int) time2->min;
diff = (int)time1->min - (int)time2->min;
if (diff == 0) {
diff = (int) time1->sec - (int) time2->sec;
diff = (int)time1->sec - (int)time2->sec;
if (diff == 0) {
diff = (int) time1->hundredths - (int) time2->hundredths;
diff = (int)time1->hundredths - (int)time2->hundredths;
}
}
}
@@ -364,9 +327,7 @@ int datetime_compare_time(
/* if the datetime1 is the same as datetime2, return is 0
if datetime1 is before datetime2, returns negative
if datetime1 is after datetime2, returns positive */
int datetime_compare(
BACNET_DATE_TIME * datetime1,
BACNET_DATE_TIME * datetime2)
int datetime_compare(BACNET_DATE_TIME *datetime1, BACNET_DATE_TIME *datetime2)
{
int diff = 0;
@@ -378,9 +339,7 @@ int datetime_compare(
return diff;
}
int datetime_wildcard_compare_date(
BACNET_DATE * date1,
BACNET_DATE * date2)
int datetime_wildcard_compare_date(BACNET_DATE *date1, BACNET_DATE *date2)
{
int diff = 0;
@@ -404,9 +363,7 @@ int datetime_wildcard_compare_date(
return diff;
}
int datetime_wildcard_compare_time(
BACNET_TIME * time1,
BACNET_TIME * time2)
int datetime_wildcard_compare_time(BACNET_TIME *time1, BACNET_TIME *time2)
{
int diff = 0;
@@ -435,27 +392,21 @@ int datetime_wildcard_compare_time(
return diff;
}
int datetime_wildcard_compare(
BACNET_DATE_TIME * datetime1,
BACNET_DATE_TIME * datetime2)
int datetime_wildcard_compare(BACNET_DATE_TIME *datetime1,
BACNET_DATE_TIME *datetime2)
{
int diff = 0;
diff = datetime_wildcard_compare_date(
&datetime1->date,
&datetime2->date);
diff = datetime_wildcard_compare_date(&datetime1->date, &datetime2->date);
if (diff == 0) {
diff = datetime_wildcard_compare_time(
&datetime1->time,
&datetime2->time);
diff =
datetime_wildcard_compare_time(&datetime1->time, &datetime2->time);
}
return diff;
}
void datetime_copy_date(
BACNET_DATE * dest_date,
BACNET_DATE * src_date)
void datetime_copy_date(BACNET_DATE *dest_date, BACNET_DATE *src_date)
{
if (dest_date && src_date) {
dest_date->year = src_date->year;
@@ -465,9 +416,7 @@ void datetime_copy_date(
}
}
void datetime_copy_time(
BACNET_TIME * dest_time,
BACNET_TIME * src_time)
void datetime_copy_time(BACNET_TIME *dest_time, BACNET_TIME *src_time)
{
if (dest_time && src_time) {
dest_time->hour = src_time->hour;
@@ -477,19 +426,15 @@ void datetime_copy_time(
}
}
void datetime_copy(
BACNET_DATE_TIME * dest_datetime,
BACNET_DATE_TIME * src_datetime)
void datetime_copy(BACNET_DATE_TIME *dest_datetime,
BACNET_DATE_TIME *src_datetime)
{
datetime_copy_time(&dest_datetime->time, &src_datetime->time);
datetime_copy_date(&dest_datetime->date, &src_datetime->date);
}
void datetime_set_date(
BACNET_DATE * bdate,
uint16_t year,
uint8_t month,
uint8_t day)
void datetime_set_date(BACNET_DATE *bdate, uint16_t year, uint8_t month,
uint8_t day)
{
if (bdate) {
bdate->year = year;
@@ -499,12 +444,8 @@ void datetime_set_date(
}
}
void datetime_set_time(
BACNET_TIME * btime,
uint8_t hour,
uint8_t minute,
uint8_t seconds,
uint8_t hundredths)
void datetime_set_time(BACNET_TIME *btime, uint8_t hour, uint8_t minute,
uint8_t seconds, uint8_t hundredths)
{
if (btime) {
btime->hour = hour;
@@ -514,10 +455,8 @@ void datetime_set_time(
}
}
void datetime_set(
BACNET_DATE_TIME * bdatetime,
BACNET_DATE * bdate,
BACNET_TIME * btime)
void datetime_set(BACNET_DATE_TIME *bdatetime, BACNET_DATE *bdate,
BACNET_TIME *btime)
{
if (bdate && btime && bdatetime) {
bdatetime->time.hour = btime->hour;
@@ -531,15 +470,9 @@ void datetime_set(
}
}
void datetime_set_values(
BACNET_DATE_TIME * bdatetime,
uint16_t year,
uint8_t month,
uint8_t day,
uint8_t hour,
uint8_t minute,
uint8_t seconds,
uint8_t hundredths)
void datetime_set_values(BACNET_DATE_TIME *bdatetime, uint16_t year,
uint8_t month, uint8_t day, uint8_t hour,
uint8_t minute, uint8_t seconds, uint8_t hundredths)
{
if (bdatetime) {
bdatetime->date.year = year;
@@ -553,33 +486,27 @@ void datetime_set_values(
}
}
static uint32_t seconds_since_midnight(
uint8_t hours,
uint8_t minutes,
uint8_t seconds)
static uint32_t seconds_since_midnight(uint8_t hours, uint8_t minutes,
uint8_t seconds)
{
return ((hours * 60 * 60) + (minutes * 60) + seconds);
}
static uint16_t minutes_since_midnight(
uint8_t hours,
uint8_t minutes)
static uint16_t minutes_since_midnight(uint8_t hours, uint8_t minutes)
{
return ((hours * 60) + minutes);
}
static void seconds_since_midnight_into_hms(
uint32_t seconds,
uint8_t * pHours,
uint8_t * pMinutes,
uint8_t * pSeconds)
static void seconds_since_midnight_into_hms(uint32_t seconds, uint8_t *pHours,
uint8_t *pMinutes,
uint8_t *pSeconds)
{
uint8_t hour = 0;
uint8_t minute = 0;
hour = (uint8_t) (seconds / (60 * 60));
hour = (uint8_t)(seconds / (60 * 60));
seconds -= (hour * 60 * 60);
minute = (uint8_t) (seconds / 60);
minute = (uint8_t)(seconds / 60);
seconds -= (minute * 60);
if (pHours)
@@ -587,7 +514,7 @@ static void seconds_since_midnight_into_hms(
if (pMinutes)
*pMinutes = minute;
if (pSeconds)
*pSeconds = (uint8_t) seconds;
*pSeconds = (uint8_t)seconds;
}
/** Calculates the number of seconds since midnight
@@ -596,16 +523,12 @@ static void seconds_since_midnight_into_hms(
*
* @return seconds since midnight
*/
uint32_t datetime_seconds_since_midnight(
BACNET_TIME * btime)
uint32_t datetime_seconds_since_midnight(BACNET_TIME *btime)
{
uint32_t seconds = 0;
if (btime) {
seconds = seconds_since_midnight(
btime->hour,
btime->min,
btime->sec);
seconds = seconds_since_midnight(btime->hour, btime->min, btime->sec);
}
return seconds;
@@ -617,15 +540,12 @@ uint32_t datetime_seconds_since_midnight(
*
* @return minutes since midnight
*/
uint16_t datetime_minutes_since_midnight(
BACNET_TIME * btime)
uint16_t datetime_minutes_since_midnight(BACNET_TIME *btime)
{
uint32_t minutes = 0;
if (btime) {
minutes = minutes_since_midnight(
btime->hour,
btime->min);
minutes = minutes_since_midnight(btime->hour, btime->min);
}
return minutes;
@@ -636,9 +556,7 @@ uint16_t datetime_minutes_since_midnight(
* @param bdatetime [in] the starting date and time
* @param minutes [in] number of minutes to add or subtract from the time
*/
void datetime_add_minutes(
BACNET_DATE_TIME * bdatetime,
int32_t minutes)
void datetime_add_minutes(BACNET_DATE_TIME *bdatetime, int32_t minutes)
{
uint32_t bdatetime_minutes = 0;
uint32_t bdatetime_days = 0;
@@ -647,7 +565,8 @@ void datetime_add_minutes(
/* convert bdatetime to seconds and days */
bdatetime_minutes =
seconds_since_midnight(bdatetime->time.hour, bdatetime->time.min,
bdatetime->time.sec) / 60;
bdatetime->time.sec) /
60;
bdatetime_days = datetime_days_since_epoch(&bdatetime->date);
/* more minutes than in a day? */
@@ -678,13 +597,13 @@ void datetime_add_minutes(
/* convert bdatetime from seconds and days */
seconds_since_midnight_into_hms(bdatetime_minutes * 60,
&bdatetime->time.hour, &bdatetime->time.min, NULL);
&bdatetime->time.hour, &bdatetime->time.min,
NULL);
datetime_days_since_epoch_into_date(bdatetime_days, &bdatetime->date);
}
/* Returns true if year is a wildcard */
bool datetime_wildcard_year(
BACNET_DATE *bdate)
bool datetime_wildcard_year(BACNET_DATE *bdate)
{
bool wildcard_present = false;
@@ -698,8 +617,7 @@ bool datetime_wildcard_year(
}
/* Sets the year as a wildcard */
void datetime_wildcard_year_set(
BACNET_DATE *bdate)
void datetime_wildcard_year_set(BACNET_DATE *bdate)
{
if (bdate) {
bdate->year = BACNET_EPOCH_YEAR + 0xFF;
@@ -707,8 +625,7 @@ void datetime_wildcard_year_set(
}
/* Returns true if month is a wildcard */
bool datetime_wildcard_month(
BACNET_DATE *bdate)
bool datetime_wildcard_month(BACNET_DATE *bdate)
{
bool wildcard_present = false;
@@ -722,8 +639,7 @@ bool datetime_wildcard_month(
}
/* Sets the month as a wildcard */
void datetime_wildcard_month_set(
BACNET_DATE *bdate)
void datetime_wildcard_month_set(BACNET_DATE *bdate)
{
if (bdate) {
bdate->month = 0xFF;
@@ -731,8 +647,7 @@ void datetime_wildcard_month_set(
}
/* Returns true if day is a wildcard */
bool datetime_wildcard_day(
BACNET_DATE *bdate)
bool datetime_wildcard_day(BACNET_DATE *bdate)
{
bool wildcard_present = false;
@@ -746,8 +661,7 @@ bool datetime_wildcard_day(
}
/* Sets the day as a wildcard */
void datetime_wildcard_day_set(
BACNET_DATE *bdate)
void datetime_wildcard_day_set(BACNET_DATE *bdate)
{
if (bdate) {
bdate->day = 0xFF;
@@ -755,8 +669,7 @@ void datetime_wildcard_day_set(
}
/* Returns true if weekday is a wildcard */
bool datetime_wildcard_weekday(
BACNET_DATE *bdate)
bool datetime_wildcard_weekday(BACNET_DATE *bdate)
{
bool wildcard_present = false;
@@ -770,8 +683,7 @@ bool datetime_wildcard_weekday(
}
/* Sets the weekday as a wildcard */
void datetime_wildcard_weekday_set(
BACNET_DATE *bdate)
void datetime_wildcard_weekday_set(BACNET_DATE *bdate)
{
if (bdate) {
bdate->wday = 0xFF;
@@ -779,8 +691,7 @@ void datetime_wildcard_weekday_set(
}
/* Returns true if hour is a wildcard */
bool datetime_wildcard_hour(
BACNET_TIME *btime)
bool datetime_wildcard_hour(BACNET_TIME *btime)
{
bool wildcard_present = false;
@@ -794,8 +705,7 @@ bool datetime_wildcard_hour(
}
/* Sets the hour as a wildcard */
void datetime_wildcard_hour_set(
BACNET_TIME *btime)
void datetime_wildcard_hour_set(BACNET_TIME *btime)
{
if (btime) {
btime->hour = 0xFF;
@@ -803,8 +713,7 @@ void datetime_wildcard_hour_set(
}
/* Returns true if minute is a wildcard */
bool datetime_wildcard_minute(
BACNET_TIME *btime)
bool datetime_wildcard_minute(BACNET_TIME *btime)
{
bool wildcard_present = false;
@@ -818,8 +727,7 @@ bool datetime_wildcard_minute(
}
/* Sets the minute as a wildcard */
void datetime_wildcard_minute_set(
BACNET_TIME *btime)
void datetime_wildcard_minute_set(BACNET_TIME *btime)
{
if (btime) {
btime->min = 0xFF;
@@ -827,8 +735,7 @@ void datetime_wildcard_minute_set(
}
/* Returns true if seconds is wildcard */
bool datetime_wildcard_second(
BACNET_TIME *btime)
bool datetime_wildcard_second(BACNET_TIME *btime)
{
bool wildcard_present = false;
@@ -842,8 +749,7 @@ bool datetime_wildcard_second(
}
/* Sets the seconds as a wildcard */
void datetime_wildcard_second_set(
BACNET_TIME *btime)
void datetime_wildcard_second_set(BACNET_TIME *btime)
{
if (btime) {
btime->sec = 0xFF;
@@ -851,8 +757,7 @@ void datetime_wildcard_second_set(
}
/* Returns true if hundredths is a wildcard */
bool datetime_wildcard_hundredths(
BACNET_TIME *btime)
bool datetime_wildcard_hundredths(BACNET_TIME *btime)
{
bool wildcard_present = false;
@@ -866,16 +771,14 @@ bool datetime_wildcard_hundredths(
}
/* Sets the hundredths as a wildcard */
void datetime_wildcard_hundredths_set(
BACNET_TIME *btime)
void datetime_wildcard_hundredths_set(BACNET_TIME *btime)
{
if (btime) {
btime->hundredths = 0xFF;
}
}
bool datetime_wildcard(
BACNET_DATE_TIME * bdatetime)
bool datetime_wildcard(BACNET_DATE_TIME *bdatetime)
{
bool wildcard_present = false;
@@ -899,8 +802,7 @@ bool datetime_wildcard(
* on it's own. Also checks for special day and month values. Used in
* trendlog object.
*/
bool datetime_wildcard_present(
BACNET_DATE_TIME * bdatetime)
bool datetime_wildcard_present(BACNET_DATE_TIME *bdatetime)
{
bool wildcard_present = false;
@@ -918,8 +820,7 @@ bool datetime_wildcard_present(
return wildcard_present;
}
void datetime_date_wildcard_set(
BACNET_DATE * bdate)
void datetime_date_wildcard_set(BACNET_DATE *bdate)
{
if (bdate) {
bdate->year = BACNET_EPOCH_YEAR + 0xFF;
@@ -929,8 +830,7 @@ void datetime_date_wildcard_set(
}
}
void datetime_time_wildcard_set(
BACNET_TIME * btime)
void datetime_time_wildcard_set(BACNET_TIME *btime)
{
if (btime) {
btime->hour = 0xFF;
@@ -940,8 +840,7 @@ void datetime_time_wildcard_set(
}
}
void datetime_wildcard_set(
BACNET_DATE_TIME * bdatetime)
void datetime_wildcard_set(BACNET_DATE_TIME *bdatetime)
{
if (bdatetime) {
datetime_date_wildcard_set(&bdatetime->date);
@@ -949,14 +848,11 @@ void datetime_wildcard_set(
}
}
int bacapp_encode_datetime(
uint8_t * apdu,
BACNET_DATE_TIME * value)
int bacapp_encode_datetime(uint8_t *apdu, BACNET_DATE_TIME *value)
{
int len = 0;
int apdu_len = 0;
if (apdu && value) {
len = encode_application_date(&apdu[0], &value->date);
apdu_len += len;
@@ -967,16 +863,12 @@ int bacapp_encode_datetime(
return apdu_len;
}
int bacapp_encode_context_datetime(
uint8_t * apdu,
uint8_t tag_number,
BACNET_DATE_TIME * value)
int bacapp_encode_context_datetime(uint8_t *apdu, uint8_t tag_number,
BACNET_DATE_TIME *value)
{
int len = 0;
int apdu_len = 0;
if (apdu && value) {
len = encode_opening_tag(&apdu[apdu_len], tag_number);
apdu_len += len;
@@ -990,21 +882,19 @@ int bacapp_encode_context_datetime(
return apdu_len;
}
int bacapp_decode_datetime(
uint8_t * apdu,
BACNET_DATE_TIME * value)
int bacapp_decode_datetime(uint8_t *apdu, BACNET_DATE_TIME *value)
{
int len = 0;
int section_len;
if (-1 == (section_len =
decode_application_date(&apdu[len], &value->date))) {
if (-1 ==
(section_len = decode_application_date(&apdu[len], &value->date))) {
return -1;
}
len += section_len;
if (-1 == (section_len =
decode_application_time(&apdu[len], &value->time))) {
if (-1 ==
(section_len = decode_application_time(&apdu[len], &value->time))) {
return -1;
}
@@ -1013,10 +903,8 @@ int bacapp_decode_datetime(
return len;
}
int bacapp_decode_context_datetime(
uint8_t * apdu,
uint8_t tag_number,
BACNET_DATE_TIME * value)
int bacapp_decode_context_datetime(uint8_t *apdu, uint8_t tag_number,
BACNET_DATE_TIME *value)
{
int apdu_len = 0;
int len;
@@ -1046,8 +934,7 @@ int bacapp_decode_context_datetime(
#include <string.h>
#include "ctest.h"
static void testBACnetDateTimeWildcard(
Test * pTest)
static void testBACnetDateTimeWildcard(Test *pTest)
{
BACNET_DATE_TIME bdatetime;
bool status = false;
@@ -1061,8 +948,7 @@ static void testBACnetDateTimeWildcard(
ct_test(pTest, status == true);
}
static void testBACnetDateTimeAdd(
Test * pTest)
static void testBACnetDateTimeAdd(Test *pTest)
{
BACNET_DATE_TIME bdatetime, test_bdatetime;
uint32_t minutes = 0;
@@ -1105,8 +991,7 @@ static void testBACnetDateTimeAdd(
ct_test(pTest, diff == 0);
}
static void testBACnetDateTimeSeconds(
Test * pTest)
static void testBACnetDateTimeSeconds(Test *pTest)
{
uint8_t hour = 0, minute = 0, second = 0;
uint8_t test_hour = 0, test_minute = 0, test_second = 0;
@@ -1117,18 +1002,16 @@ static void testBACnetDateTimeSeconds(
for (second = 0; second < 60; second += 17) {
seconds = seconds_since_midnight(hour, minute, second);
seconds_since_midnight_into_hms(seconds, &test_hour,
&test_minute, &test_second);
&test_minute, &test_second);
test_seconds =
seconds_since_midnight(test_hour, test_minute,
test_second);
seconds_since_midnight(test_hour, test_minute, test_second);
ct_test(pTest, seconds == test_seconds);
}
}
}
}
static void testBACnetDate(
Test * pTest)
static void testBACnetDate(Test *pTest)
{
BACNET_DATE bdate1, bdate2;
int diff = 0;
@@ -1189,8 +1072,7 @@ static void testBACnetDate(
return;
}
static void testBACnetTime(
Test * pTest)
static void testBACnetTime(Test *pTest)
{
BACNET_TIME btime1, btime2;
int diff = 0;
@@ -1239,8 +1121,7 @@ static void testBACnetTime(
return;
}
static void testBACnetDateTime(
Test * pTest)
static void testBACnetDateTime(Test *pTest)
{
BACNET_DATE_TIME bdatetime1, bdatetime2;
BACNET_DATE bdate;
@@ -1303,12 +1184,10 @@ static void testBACnetDateTime(
diff = datetime_compare(&bdatetime1, &bdatetime2);
ct_test(pTest, diff > 0);
return;
}
static void testWildcardDateTime(
Test * pTest)
static void testWildcardDateTime(Test *pTest)
{
BACNET_DATE_TIME bdatetime1, bdatetime2;
BACNET_DATE bdate;
@@ -1330,8 +1209,7 @@ static void testWildcardDateTime(
return;
}
static void testDayOfYear(
Test * pTest)
static void testDayOfYear(Test *pTest)
{
uint32_t days = 0;
uint8_t month = 0, test_month = 0;
@@ -1368,8 +1246,7 @@ static void testDayOfYear(
}
}
static void testDateEpoch(
Test * pTest)
static void testDateEpoch(Test *pTest)
{
uint32_t days = 0;
uint16_t year = 0, test_year = 0;
@@ -1383,13 +1260,12 @@ static void testDateEpoch(
ct_test(pTest, month == 1);
ct_test(pTest, day == 1);
for (year = BACNET_EPOCH_YEAR; year < (BACNET_EPOCH_YEAR+0xFF); year++) {
for (year = BACNET_EPOCH_YEAR; year < (BACNET_EPOCH_YEAR + 0xFF); year++) {
for (month = 1; month <= 12; month++) {
for (day = 1; day <= datetime_month_days(year, month); day++) {
days = days_since_epoch(year, month, day);
days_since_epoch_into_ymd(days,
&test_year, &test_month, &test_day);
days_since_epoch_into_ymd(days, &test_year, &test_month,
&test_day);
ct_test(pTest, year == test_year);
ct_test(pTest, month == test_month);
ct_test(pTest, day == test_day);
@@ -1398,8 +1274,7 @@ static void testDateEpoch(
}
}
static void testBACnetDayOfWeek(
Test * pTest)
static void testBACnetDayOfWeek(Test *pTest)
{
uint8_t dow = 0;
@@ -1427,8 +1302,7 @@ static void testBACnetDayOfWeek(
ct_test(pTest, dow == 3);
}
static void testDatetimeCodec(
Test * pTest)
static void testDatetimeCodec(Test *pTest)
{
uint8_t apdu[MAX_APDU];
BACNET_DATE_TIME datetimeIn;
@@ -1460,11 +1334,9 @@ static void testDatetimeCodec(
ct_test(pTest, datetimeIn.time.min == datetimeOut.time.min);
ct_test(pTest, datetimeIn.time.sec == datetimeOut.time.sec);
ct_test(pTest, datetimeIn.time.hundredths == datetimeOut.time.hundredths);
}
void testDateTime(
Test * pTest)
void testDateTime(Test *pTest)
{
bool rc;
@@ -1494,8 +1366,7 @@ void testDateTime(
}
#ifdef TEST_DATE_TIME
int main(
void)
int main(void)
{
Test *pTest;
@@ -1503,12 +1374,11 @@ int main(
testDateTime(pTest);
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
}
#endif /* TEST_DATE_TIME */
#endif /* TEST */
+46 -69
View File
@@ -49,14 +49,12 @@ static BACNET_COMMUNICATION_ENABLE_DISABLE DCC_Enable_Disable =
COMMUNICATION_ENABLE;
/* password is optionally supported */
BACNET_COMMUNICATION_ENABLE_DISABLE dcc_enable_status(
void)
BACNET_COMMUNICATION_ENABLE_DISABLE dcc_enable_status(void)
{
return DCC_Enable_Disable;
}
bool dcc_communication_enabled(
void)
bool dcc_communication_enabled(void)
{
return (DCC_Enable_Disable == COMMUNICATION_ENABLE);
}
@@ -64,8 +62,7 @@ bool dcc_communication_enabled(
/* When network communications are completely disabled,
only DeviceCommunicationControl and ReinitializeDevice APDUs
shall be processed and no messages shall be initiated.*/
bool dcc_communication_disabled(
void)
bool dcc_communication_disabled(void)
{
return (DCC_Enable_Disable == COMMUNICATION_DISABLE);
}
@@ -79,23 +76,20 @@ bool dcc_communication_disabled(
for any Who-Is request that is received if and only if
the Who-Is request does not contain an address range or
the device is included in the address range. */
bool dcc_communication_initiation_disabled(
void)
bool dcc_communication_initiation_disabled(void)
{
return (DCC_Enable_Disable == COMMUNICATION_DISABLE_INITIATION);
}
/* note: 0 indicates either expired, or infinite duration */
uint32_t dcc_duration_seconds(
void)
uint32_t dcc_duration_seconds(void)
{
return DCC_Time_Duration_Seconds;
}
/* called every second or so. If more than one second,
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 > seconds)
@@ -108,9 +102,8 @@ void dcc_timer_seconds(
}
}
bool dcc_set_status_duration(
BACNET_COMMUNICATION_ENABLE_DISABLE status,
uint16_t minutes)
bool dcc_set_status_duration(BACNET_COMMUNICATION_ENABLE_DISABLE status,
uint16_t minutes)
{
bool valid = false;
@@ -130,15 +123,13 @@ bool dcc_set_status_duration(
#if BACNET_SVC_DCC_A
/* encode service */
int dcc_encode_apdu(
uint8_t * apdu,
uint8_t invoke_id,
uint16_t timeDuration, /* 0=optional */
BACNET_COMMUNICATION_ENABLE_DISABLE enable_disable,
BACNET_CHARACTER_STRING * password)
{ /* NULL=optional */
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
int dcc_encode_apdu(uint8_t *apdu, uint8_t invoke_id,
uint16_t timeDuration, /* 0=optional */
BACNET_COMMUNICATION_ENABLE_DISABLE enable_disable,
BACNET_CHARACTER_STRING *password)
{ /* NULL=optional */
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) {
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
@@ -157,8 +148,7 @@ int dcc_encode_apdu(
/* optional password */
if (password) {
/* 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;
}
}
@@ -169,11 +159,9 @@ int dcc_encode_apdu(
/* decode the service request only */
int dcc_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
uint16_t * timeDuration,
BACNET_COMMUNICATION_ENABLE_DISABLE * enable_disable,
BACNET_CHARACTER_STRING * password)
uint8_t *apdu, unsigned apdu_len, uint16_t *timeDuration,
BACNET_COMMUNICATION_ENABLE_DISABLE *enable_disable,
BACNET_CHARACTER_STRING *password)
{
unsigned len = 0;
uint8_t tag_number = 0;
@@ -186,12 +174,11 @@ int dcc_decode_service_request(
* But if not included, take it as indefinite,
* which we return as "very large" */
if (decode_is_context_tag(&apdu[len], 0)) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_unsigned(&apdu[len], len_value_type, &value32);
if (timeDuration) {
*timeDuration = (uint16_t) value32;
*timeDuration = (uint16_t)value32;
}
} else if (timeDuration) {
/* zero indicates infinite duration and
@@ -202,21 +189,19 @@ int dcc_decode_service_request(
if (!decode_is_context_tag(&apdu[len], 1)) {
return -1;
}
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_enumerated(&apdu[len], len_value_type, &value32);
if (enable_disable) {
*enable_disable = (BACNET_COMMUNICATION_ENABLE_DISABLE) value32;
*enable_disable = (BACNET_COMMUNICATION_ENABLE_DISABLE)value32;
}
/* Tag 2: password --optional-- */
if (len < apdu_len) {
if (!decode_is_context_tag(&apdu[len], 2)) {
return -1;
}
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len +=
decode_character_string(&apdu[len], len_value_type, password);
} else if (password) {
@@ -224,7 +209,7 @@ int dcc_decode_service_request(
}
}
return (int) len;
return (int)len;
}
#ifdef TEST
@@ -232,13 +217,10 @@ int dcc_decode_service_request(
#include <string.h>
#include "ctest.h"
int dcc_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
uint8_t * invoke_id,
uint16_t * timeDuration,
BACNET_COMMUNICATION_ENABLE_DISABLE * enable_disable,
BACNET_CHARACTER_STRING * password)
int dcc_decode_apdu(uint8_t *apdu, unsigned apdu_len, uint8_t *invoke_id,
uint16_t *timeDuration,
BACNET_COMMUNICATION_ENABLE_DISABLE *enable_disable,
BACNET_CHARACTER_STRING *password)
{
int len = 0;
unsigned offset = 0;
@@ -249,7 +231,7 @@ int dcc_decode_apdu(
if (apdu[0] != PDU_TYPE_CONFIRMED_SERVICE_REQUEST)
return -1;
/* apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU); */
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
if (apdu[3] != SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL)
return -1;
offset = 4;
@@ -257,20 +239,18 @@ int dcc_decode_apdu(
if (apdu_len > offset) {
len =
dcc_decode_service_request(&apdu[offset], apdu_len - offset,
timeDuration, enable_disable, password);
timeDuration, enable_disable, password);
}
return len;
}
void test_DeviceCommunicationControlData(
Test * pTest,
uint8_t invoke_id,
uint16_t timeDuration,
Test *pTest, uint8_t invoke_id, uint16_t timeDuration,
BACNET_COMMUNICATION_ENABLE_DISABLE enable_disable,
BACNET_CHARACTER_STRING * password)
BACNET_CHARACTER_STRING *password)
{
uint8_t apdu[480] = { 0 };
uint8_t apdu[480] = {0};
int len = 0;
int apdu_len = 0;
uint8_t test_invoke_id = 0;
@@ -278,15 +258,14 @@ void test_DeviceCommunicationControlData(
BACNET_COMMUNICATION_ENABLE_DISABLE test_enable_disable;
BACNET_CHARACTER_STRING test_password;
len =
dcc_encode_apdu(&apdu[0], invoke_id, timeDuration, enable_disable,
password);
len = dcc_encode_apdu(&apdu[0], invoke_id, timeDuration, enable_disable,
password);
ct_test(pTest, len != 0);
apdu_len = len;
len =
dcc_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_timeDuration, &test_enable_disable, &test_password);
dcc_decode_apdu(&apdu[0], apdu_len, &test_invoke_id, &test_timeDuration,
&test_enable_disable, &test_password);
ct_test(pTest, len != -1);
ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest, test_timeDuration == timeDuration);
@@ -294,8 +273,7 @@ void test_DeviceCommunicationControlData(
ct_test(pTest, characterstring_same(&test_password, password));
}
void test_DeviceCommunicationControl(
Test * pTest)
void test_DeviceCommunicationControl(Test *pTest)
{
uint8_t invoke_id = 128;
uint16_t timeDuration = 0;
@@ -306,19 +284,18 @@ void test_DeviceCommunicationControl(
enable_disable = COMMUNICATION_DISABLE_INITIATION;
characterstring_init_ansi(&password, "John 3:16");
test_DeviceCommunicationControlData(pTest, invoke_id, timeDuration,
enable_disable, &password);
enable_disable, &password);
timeDuration = 12345;
enable_disable = COMMUNICATION_DISABLE;
test_DeviceCommunicationControlData(pTest, invoke_id, timeDuration,
enable_disable, NULL);
enable_disable, NULL);
return;
}
#ifdef TEST_DEVICE_COMMUNICATION_CONTROL
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -330,7 +307,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+6 -10
View File
@@ -32,19 +32,17 @@
-------------------------------------------
####COPYRIGHTEND####*/
#include <stdint.h> /* for standard integer types uint8_t etc. */
#include <stdbool.h> /* for the standard bool type. */
#include <stdio.h> /* Standard I/O */
#include <stdlib.h> /* Standard Library */
#include <stdint.h> /* for standard integer types uint8_t etc. */
#include <stdbool.h> /* for the standard bool type. */
#include <stdio.h> /* Standard I/O */
#include <stdlib.h> /* Standard Library */
#include <stdarg.h>
#include "debug.h"
/** @file debug.c Debug print function */
#if DEBUG_ENABLED
void debug_printf(
const char *format,
...)
void debug_printf(const char *format, ...)
{
va_list ap;
@@ -56,9 +54,7 @@ void debug_printf(
return;
}
#else
void debug_printf(
const char *format,
...)
void debug_printf(const char *format, ...)
{
format = format;
}
+505 -578
View File
File diff suppressed because it is too large Load Diff
+201 -222
View File
@@ -1,110 +1,109 @@
/**
* @file
* @author Steve Karg
* @date 2004
* @brief Generic interrupt safe FIFO library for deeply embedded system.
*
* @section LICENSE
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to:
* The Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*
* As a special exception, if other files instantiate templates or
* use macros or inline functions from this file, or you compile
* this file and link it with other works to produce a work based
* on this file, this file does not by itself cause the resulting
* work to be covered by the GNU General Public License. However
* the source code for this file must still be made available in
* accordance with section (3) of the GNU General Public License.
*
* This exception does not invalidate any other reasons why a work
* based on this file might be covered by the GNU General Public
* License.
*
* @section DESCRIPTION
*
* Generic interrupt safe FIFO library for deeply embedded system
* This library only uses a byte sized chunk for a data element.
* It uses a data store whose size is a power of 2 (8, 16, 32, 64, ...)
* and doesn't waste any data bytes. It has very low overhead, and
* utilizes modulo for indexing the data in the data store.
*
* To use this library, first declare a data store, sized for a power of 2:
* {@code
* static volatile uint8_t data_store[64];
* }
*
* Then declare the FIFO tracking structure:
* {@code
* static FIFO_BUFFER queue;
* }
*
* Initialize the queue with the data store:
* {@code
* FIFO_Init(&queue, data_store, sizeof(data_store));
* }
*
* Then begin to use the FIFO queue by giving it data, retreiving data,
* and checking the FIFO queue to see if it is empty or full:
* {@code
* uint8_t in_data = 0;
* uint8_t out_data = 0;
* uint8_t add_data[5] = {0};
* uint8_t pull_data[5] = {0};
* unsigned count = 0;
* bool status = false;
*
* status = FIFO_Put(&queue, in_data);
* if (!FIFO_Empty(&queue)) {
* out_data = FIFO_Get(&queue);
* }
* if (FIFO_Available(&queue, sizeof(add_data))) {
* status = FIFO_Add(&queue, add_data, sizeof(add_data));
* }
* count = FIFO_Count(&queue);
* if (count == sizeof(add_data)) {
* count = FIFO_Pull(&queue, &pull_data[0], sizeof(pull_data));
* }
*
* }
*
* Normally the FIFO is used by a producer, such as in interrupt service
* routine, which places data into the queue using FIFO_Put(), and a consumer,
* such as a main loop handler, which pulls data from the queue by first
* checking the queue for data using FIFO_Empty(), and then pulling data from
* the queue using FIFO_Get().
*
*/
* @file
* @author Steve Karg
* @date 2004
* @brief Generic interrupt safe FIFO library for deeply embedded system.
*
* @section LICENSE
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to:
* The Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*
* As a special exception, if other files instantiate templates or
* use macros or inline functions from this file, or you compile
* this file and link it with other works to produce a work based
* on this file, this file does not by itself cause the resulting
* work to be covered by the GNU General Public License. However
* the source code for this file must still be made available in
* accordance with section (3) of the GNU General Public License.
*
* This exception does not invalidate any other reasons why a work
* based on this file might be covered by the GNU General Public
* License.
*
* @section DESCRIPTION
*
* Generic interrupt safe FIFO library for deeply embedded system
* This library only uses a byte sized chunk for a data element.
* It uses a data store whose size is a power of 2 (8, 16, 32, 64, ...)
* and doesn't waste any data bytes. It has very low overhead, and
* utilizes modulo for indexing the data in the data store.
*
* To use this library, first declare a data store, sized for a power of 2:
* {@code
* static volatile uint8_t data_store[64];
* }
*
* Then declare the FIFO tracking structure:
* {@code
* static FIFO_BUFFER queue;
* }
*
* Initialize the queue with the data store:
* {@code
* FIFO_Init(&queue, data_store, sizeof(data_store));
* }
*
* Then begin to use the FIFO queue by giving it data, retreiving data,
* and checking the FIFO queue to see if it is empty or full:
* {@code
* uint8_t in_data = 0;
* uint8_t out_data = 0;
* uint8_t add_data[5] = {0};
* uint8_t pull_data[5] = {0};
* unsigned count = 0;
* bool status = false;
*
* status = FIFO_Put(&queue, in_data);
* if (!FIFO_Empty(&queue)) {
* out_data = FIFO_Get(&queue);
* }
* if (FIFO_Available(&queue, sizeof(add_data))) {
* status = FIFO_Add(&queue, add_data, sizeof(add_data));
* }
* count = FIFO_Count(&queue);
* if (count == sizeof(add_data)) {
* count = FIFO_Pull(&queue, &pull_data[0], sizeof(pull_data));
* }
*
* }
*
* Normally the FIFO is used by a producer, such as in interrupt service
* routine, which places data into the queue using FIFO_Put(), and a consumer,
* such as a main loop handler, which pulls data from the queue by first
* checking the queue for data using FIFO_Empty(), and then pulling data from
* the queue using FIFO_Get().
*
*/
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include "fifo.h"
/**
* Returns the number of bytes in the FIFO
*
* @param b - pointer to FIFO_BUFFER structure
*
* @return Number of bytes in the FIFO
*/
unsigned FIFO_Count(
FIFO_BUFFER const *b)
* Returns the number of bytes in the FIFO
*
* @param b - pointer to FIFO_BUFFER structure
*
* @return Number of bytes in the FIFO
*/
unsigned FIFO_Count(FIFO_BUFFER const *b)
{
unsigned head, tail; /* used to avoid volatile decision */
unsigned head, tail; /* used to avoid volatile decision */
if (b) {
head = b->head;
@@ -116,57 +115,52 @@ unsigned FIFO_Count(
}
/**
* Returns the full status of the FIFO
*
* @param b - pointer to FIFO_BUFFER structure
*
* @return true if the FIFO is full, false if it is not.
*/
bool FIFO_Full(
FIFO_BUFFER const *b)
* Returns the full status of the FIFO
*
* @param b - pointer to FIFO_BUFFER structure
*
* @return true if the FIFO is full, false if it is not.
*/
bool FIFO_Full(FIFO_BUFFER const *b)
{
return (b ? (FIFO_Count(b) == b->buffer_len) : true);
}
/**
* Tests to see if space is available in the FIFO
*
* @param b - pointer to FIFO_BUFFER structure
* @param count [in] - number of bytes tested for availability
*
* @return true if the number of bytes sought is available
*/
bool FIFO_Available(
FIFO_BUFFER const *b,
unsigned count)
* Tests to see if space is available in the FIFO
*
* @param b - pointer to FIFO_BUFFER structure
* @param count [in] - number of bytes tested for availability
*
* @return true if the number of bytes sought is available
*/
bool FIFO_Available(FIFO_BUFFER const *b, unsigned count)
{
return (b ? (count <= (b->buffer_len - FIFO_Count(b))) : false);
}
/**
* Returns the empty status of the FIFO
*
* @param b - pointer to FIFO_BUFFER structure
* @return true if the FIFO is empty, false if it is not.
*/
bool FIFO_Empty(
FIFO_BUFFER const *b)
* Returns the empty status of the FIFO
*
* @param b - pointer to FIFO_BUFFER structure
* @return true if the FIFO is empty, false if it is not.
*/
bool FIFO_Empty(FIFO_BUFFER const *b)
{
return (b ? (FIFO_Count(b) == 0) : true);
}
/**
* Peeks at the data from the front of the FIFO without removing it.
* Use FIFO_Empty() or FIFO_Available() function to see if there is
* data to retrieve since this function doesn't return a flag indicating
* success or failure.
*
* @param b - pointer to FIFO_BUFFER structure
*
* @return byte of data, or zero if nothing in the list
*/
uint8_t FIFO_Peek(
FIFO_BUFFER const *b)
* Peeks at the data from the front of the FIFO without removing it.
* Use FIFO_Empty() or FIFO_Available() function to see if there is
* data to retrieve since this function doesn't return a flag indicating
* success or failure.
*
* @param b - pointer to FIFO_BUFFER structure
*
* @return byte of data, or zero if nothing in the list
*/
uint8_t FIFO_Peek(FIFO_BUFFER const *b)
{
unsigned index;
@@ -179,17 +173,16 @@ uint8_t FIFO_Peek(
}
/**
* Gets a byte from the front of the FIFO, and removes it.
* Use FIFO_Empty() or FIFO_Available() function to see if there is
* data to retrieve since this function doesn't return a flag indicating
* success or failure.
*
* @param b - pointer to FIFO_BUFFER structure
*
* @return the data
*/
uint8_t FIFO_Get(
FIFO_BUFFER * b)
* Gets a byte from the front of the FIFO, and removes it.
* Use FIFO_Empty() or FIFO_Available() function to see if there is
* data to retrieve since this function doesn't return a flag indicating
* success or failure.
*
* @param b - pointer to FIFO_BUFFER structure
*
* @return the data
*/
uint8_t FIFO_Get(FIFO_BUFFER *b)
{
uint8_t data_byte = 0;
unsigned index;
@@ -203,20 +196,17 @@ uint8_t FIFO_Get(
}
/**
* Pulls one or more bytes from the front of the FIFO, and removes them
* from the FIFO. If less bytes are available, only the available bytes
* are retrieved.
*
* @param b - pointer to FIFO_BUFFER structure
* @param buffer [out] - buffer to hold the pulled bytes
* @param length [in] - number of bytes to pull from the FIFO
*
* @return the number of bytes actually pulled from the FIFO
*/
unsigned FIFO_Pull(
FIFO_BUFFER * b,
uint8_t * buffer,
unsigned length)
* Pulls one or more bytes from the front of the FIFO, and removes them
* from the FIFO. If less bytes are available, only the available bytes
* are retrieved.
*
* @param b - pointer to FIFO_BUFFER structure
* @param buffer [out] - buffer to hold the pulled bytes
* @param length [in] - number of bytes to pull from the FIFO
*
* @return the number of bytes actually pulled from the FIFO
*/
unsigned FIFO_Pull(FIFO_BUFFER *b, uint8_t *buffer, unsigned length)
{
unsigned count;
uint8_t data_byte;
@@ -246,18 +236,16 @@ unsigned FIFO_Pull(
}
/**
* Adds a byte of data to the FIFO
*
* @param b - pointer to FIFO_BUFFER structure
* @param data_byte [in] - data to put into the FIFO
*
* @return true on successful add, false if not added
*/
bool FIFO_Put(
FIFO_BUFFER * b,
uint8_t data_byte)
* Adds a byte of data to the FIFO
*
* @param b - pointer to FIFO_BUFFER structure
* @param data_byte [in] - data to put into the FIFO
*
* @return true on successful add, false if not added
*/
bool FIFO_Put(FIFO_BUFFER *b, uint8_t data_byte)
{
bool status = false; /* return value */
bool status = false; /* return value */
unsigned index;
if (b) {
@@ -274,20 +262,17 @@ bool FIFO_Put(
}
/**
* Adds one or more bytes of data to the FIFO
*
* @param b - pointer to FIFO_BUFFER structure
* @param buffer [out] - data bytes to add to the FIFO
* @param count [in] - number of bytes to add to the FIFO
*
* @return true if space available and added, false if not added
*/
bool FIFO_Add(
FIFO_BUFFER * b,
uint8_t * buffer,
unsigned count)
* Adds one or more bytes of data to the FIFO
*
* @param b - pointer to FIFO_BUFFER structure
* @param buffer [out] - data bytes to add to the FIFO
* @param count [in] - number of bytes to add to the FIFO
*
* @return true if space available and added, false if not added
*/
bool FIFO_Add(FIFO_BUFFER *b, uint8_t *buffer, unsigned count)
{
bool status = false; /* return value */
bool status = false; /* return value */
unsigned index;
/* limit the buffer to prevent overwriting */
@@ -306,16 +291,15 @@ bool FIFO_Add(
}
/**
* Flushes any data in the FIFO buffer
*
* @param b - pointer to FIFO_BUFFER structure
*
* @return none
*/
void FIFO_Flush(
FIFO_BUFFER * b)
* Flushes any data in the FIFO buffer
*
* @param b - pointer to FIFO_BUFFER structure
*
* @return none
*/
void FIFO_Flush(FIFO_BUFFER *b)
{
unsigned head; /* used to avoid volatile decision */
unsigned head; /* used to avoid volatile decision */
if (b) {
head = b->head;
@@ -324,18 +308,15 @@ void FIFO_Flush(
}
/**
* Initializes the FIFO buffer with a data store
*
* @param b - pointer to FIFO_BUFFER structure
* @param buffer [in] - data bytes used to store bytes used by the FIFO
* @param buffer_len [in] - size of the buffer in bytes - must be power of 2.
*
* @return none
*/
void FIFO_Init(
FIFO_BUFFER * b,
volatile uint8_t * buffer,
unsigned buffer_len)
* Initializes the FIFO buffer with a data store
*
* @param b - pointer to FIFO_BUFFER structure
* @param buffer [in] - data bytes used to store bytes used by the FIFO
* @param buffer_len [in] - size of the buffer in bytes - must be power of 2.
*
* @return none
*/
void FIFO_Init(FIFO_BUFFER *b, volatile uint8_t *buffer, unsigned buffer_len)
{
if (b && buffer && buffer_len) {
b->head = 0;
@@ -354,19 +335,18 @@ void FIFO_Init(
#include "ctest.h"
/**
* Unit Test for the FIFO buffer
*
* @param pTest - test tracking pointer
*/
void testFIFOBuffer(
Test * pTest)
* Unit Test for the FIFO buffer
*
* @param pTest - test tracking pointer
*/
void testFIFOBuffer(Test *pTest)
{
/* FIFO data structure */
FIFO_BUFFER test_buffer = { 0 };
FIFO_BUFFER test_buffer = {0};
/* FIFO data store. Note: size must be a power of two! */
volatile uint8_t data_store[64] = { 0 };
uint8_t add_data[40] = { "RoseSteveLouPatRachelJessicaDaniAmyHerb" };
uint8_t test_add_data[40] = { 0 };
volatile uint8_t data_store[64] = {0};
uint8_t add_data[40] = {"RoseSteveLouPatRachelJessicaDaniAmyHerb"};
uint8_t test_add_data[40] = {0};
uint8_t test_data = 0;
unsigned index = 0;
unsigned count = 0;
@@ -474,12 +454,11 @@ void testFIFOBuffer(
#ifdef TEST_FIFO_BUFFER
/**
* Main program entry for Unit Test
*
* @return returns 0 on success, and non-zero on fail.
*/
int main(
void)
* Main program entry for Unit Test
*
* @return returns 0 on success, and non-zero on fail.
*/
int main(void)
{
Test *pTest;
bool rc;
@@ -492,7 +471,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
+6 -9
View File
@@ -37,10 +37,9 @@
/** @file filename.c Function for filename manipulation */
char *filename_remove_path(
const char *filename_in)
char *filename_remove_path(const char *filename_in)
{
char *filename_out = (char *) filename_in;
char *filename_out = (char *)filename_in;
/* allow the device ID to be set */
if (filename_in) {
@@ -53,7 +52,7 @@ char *filename_remove_path(
filename_out++;
} else {
/* no slash in filename */
filename_out = (char *) filename_in;
filename_out = (char *)filename_in;
}
}
@@ -66,8 +65,7 @@ char *filename_remove_path(
#include "ctest.h"
void testFilename(
Test * pTest)
void testFilename(Test *pTest)
{
char *data1 = "c:\\Joshua\\run";
char *data2 = "/home/Anna/run";
@@ -91,8 +89,7 @@ void testFilename(
}
#ifdef TEST_FILENAME
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -105,7 +102,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
+61 -73
View File
@@ -1,41 +1,41 @@
/**
* @file
* @author Krzysztof Malorny <malornykrzysztof@gmail.com>
* @date 2011
* @brief GetAlarmSummary service encoding and decoding
*
* @section LICENSE
*
* Copyright (C) 2011 Krzysztof Malorny <malornykrzysztof@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* @section DESCRIPTION
*
* The GetAlarmSummary service is used by a client BACnet-user
* to obtain a summary of "active alarms." The term "active alarm" refers
* to BACnet standard objects that have an Event_State property whose value
* is not equal to NORMAL and a Notify_Type property whose value is ALARM.
* The GetEnrollmentSummary service provides a more sophisticated approach
* with various kinds of filters
*/
* @file
* @author Krzysztof Malorny <malornykrzysztof@gmail.com>
* @date 2011
* @brief GetAlarmSummary service encoding and decoding
*
* @section LICENSE
*
* Copyright (C) 2011 Krzysztof Malorny <malornykrzysztof@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* @section DESCRIPTION
*
* The GetAlarmSummary service is used by a client BACnet-user
* to obtain a summary of "active alarms." The term "active alarm" refers
* to BACnet standard objects that have an Event_State property whose value
* is not equal to NORMAL and a Notify_Type property whose value is ALARM.
* The GetEnrollmentSummary service provides a more sophisticated approach
* with various kinds of filters
*/
#include <assert.h>
#include "bacdcode.h"
@@ -43,10 +43,8 @@
#include "npdu.h"
/* encode service */
int get_alarm_summary_encode_apdu(
uint8_t * apdu,
uint8_t invoke_id
) {
int get_alarm_summary_encode_apdu(uint8_t* apdu, uint8_t invoke_id)
{
int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) {
@@ -67,15 +65,13 @@ int get_alarm_summary_encode_apdu(
*
* @return number of bytes encoded
*/
int get_alarm_summary_ack_encode_apdu_init(
uint8_t * apdu,
uint8_t invoke_id)
int get_alarm_summary_ack_encode_apdu_init(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) {
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_GET_ALARM_SUMMARY;
apdu_len = 3;
}
@@ -92,28 +88,24 @@ int get_alarm_summary_ack_encode_apdu_init(
* @return number of bytes encoded, or BACNET_STATUS_ERROR if an error.
*/
int get_alarm_summary_ack_encode_apdu_data(
uint8_t * apdu,
size_t max_apdu,
BACNET_GET_ALARM_SUMMARY_DATA * get_alarm_data)
uint8_t* apdu, size_t max_apdu,
BACNET_GET_ALARM_SUMMARY_DATA* get_alarm_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) {
apdu_len = BACNET_STATUS_ERROR;
} else if (max_apdu >= 10) {
/* tag 0 - Object Identifier */
apdu_len +=
encode_application_object_id(&apdu[apdu_len],
(int) get_alarm_data->objectIdentifier.type,
apdu_len += encode_application_object_id(
&apdu[apdu_len], (int)get_alarm_data->objectIdentifier.type,
get_alarm_data->objectIdentifier.instance);
/* tag 1 - Alarm State */
apdu_len +=
encode_application_enumerated(&apdu[apdu_len],
get_alarm_data->alarmState);
apdu_len += encode_application_enumerated(&apdu[apdu_len],
get_alarm_data->alarmState);
/* tag 2 - Acknowledged Transitions */
apdu_len +=
encode_application_bitstring(&apdu[apdu_len],
&get_alarm_data->acknowledgedTransitions);
apdu_len += encode_application_bitstring(
&apdu[apdu_len], &get_alarm_data->acknowledgedTransitions);
} else {
apdu_len = BACNET_STATUS_ABORT;
}
@@ -130,39 +122,35 @@ int get_alarm_summary_ack_encode_apdu_data(
* @return number of bytes decoded, or BACNET_STATUS_ERROR if an error.
*/
int get_alarm_summary_ack_decode_apdu_data(
uint8_t * apdu,
size_t max_apdu,
BACNET_GET_ALARM_SUMMARY_DATA * get_alarm_data)
uint8_t* apdu, size_t max_apdu,
BACNET_GET_ALARM_SUMMARY_DATA* get_alarm_data)
{
int apdu_len = 0; /* total length of the apdu, return value */
int apdu_len = 0; /* total length of the apdu, return value */
BACNET_APPLICATION_DATA_VALUE value;
if (!apdu) {
apdu_len = BACNET_STATUS_ERROR;
} else if (max_apdu >= 10) {
/* tag 0 - Object Identifier */
apdu_len +=
bacapp_decode_application_data(&apdu[apdu_len],
(unsigned int)(max_apdu - apdu_len), &value);
apdu_len += bacapp_decode_application_data(
&apdu[apdu_len], (unsigned int)(max_apdu - apdu_len), &value);
if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) {
get_alarm_data->objectIdentifier = value.type.Object_Id;
} else {
return BACNET_STATUS_ERROR;
}
/* tag 1 - Alarm State */
apdu_len +=
bacapp_decode_application_data(&apdu[apdu_len],
(unsigned int)(max_apdu - apdu_len), &value);
apdu_len += bacapp_decode_application_data(
&apdu[apdu_len], (unsigned int)(max_apdu - apdu_len), &value);
if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) {
get_alarm_data->alarmState =
(BACNET_EVENT_STATE) value.type.Enumerated;
(BACNET_EVENT_STATE)value.type.Enumerated;
} else {
return BACNET_STATUS_ERROR;
}
/* tag 2 - Acknowledged Transitions */
apdu_len +=
bacapp_decode_application_data(&apdu[apdu_len],
(unsigned int)(max_apdu - apdu_len), &value);
apdu_len += bacapp_decode_application_data(
&apdu[apdu_len], (unsigned int)(max_apdu - apdu_len), &value);
if (value.tag == BACNET_APPLICATION_TAG_BIT_STRING) {
get_alarm_data->acknowledgedTransitions = value.type.Bit_String;
} else {
+116 -168
View File
@@ -40,13 +40,11 @@
/** @file getevent.c Encode/Decode GetEvent services */
/* encode service */
int getevent_encode_apdu(
uint8_t * apdu,
uint8_t invoke_id,
BACNET_OBJECT_ID * lastReceivedObjectIdentifier)
int getevent_encode_apdu(uint8_t *apdu, uint8_t invoke_id,
BACNET_OBJECT_ID *lastReceivedObjectIdentifier)
{
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) {
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
@@ -56,9 +54,8 @@ int getevent_encode_apdu(
apdu_len = 4;
/* encode optional parameter */
if (lastReceivedObjectIdentifier) {
len =
encode_context_object_id(&apdu[apdu_len], 0,
(int) lastReceivedObjectIdentifier->type,
len = encode_context_object_id(
&apdu[apdu_len], 0, (int)lastReceivedObjectIdentifier->type,
lastReceivedObjectIdentifier->instance);
apdu_len += len;
}
@@ -69,9 +66,8 @@ int getevent_encode_apdu(
/* decode the service request only */
int getevent_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
BACNET_OBJECT_ID * lastReceivedObjectIdentifier)
uint8_t *apdu, unsigned apdu_len,
BACNET_OBJECT_ID *lastReceivedObjectIdentifier)
{
unsigned len = 0;
@@ -80,24 +76,21 @@ int getevent_decode_service_request(
/* Tag 0: Object ID - optional */
if (!decode_is_context_tag(&apdu[len++], 0))
return -1;
len +=
decode_object_id(&apdu[len], &lastReceivedObjectIdentifier->type,
&lastReceivedObjectIdentifier->instance);
len += decode_object_id(&apdu[len], &lastReceivedObjectIdentifier->type,
&lastReceivedObjectIdentifier->instance);
}
return (int) len;
return (int)len;
}
int getevent_ack_encode_apdu_init(
uint8_t * apdu,
size_t max_apdu,
uint8_t invoke_id)
int getevent_ack_encode_apdu_init(uint8_t *apdu, size_t max_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 && (max_apdu >= 4)) {
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_GET_EVENT_INFORMATION;
apdu_len = 3;
/* service ack follows */
@@ -109,13 +102,12 @@ int getevent_ack_encode_apdu_init(
}
int getevent_ack_encode_apdu_data(
uint8_t * apdu,
size_t max_apdu,
BACNET_GET_EVENT_INFORMATION_DATA * get_event_data)
uint8_t *apdu, size_t max_apdu,
BACNET_GET_EVENT_INFORMATION_DATA *get_event_data)
{
int apdu_len = 0; /* total length of the apdu, return value */
int apdu_len = 0; /* total length of the apdu, return value */
BACNET_GET_EVENT_INFORMATION_DATA *event_data;
unsigned i = 0; /* counter */
unsigned i = 0; /* counter */
/* unused parameter */
max_apdu = max_apdu;
@@ -123,40 +115,33 @@ int getevent_ack_encode_apdu_data(
event_data = get_event_data;
while (event_data) {
/* Tag 0: objectIdentifier */
apdu_len +=
encode_context_object_id(&apdu[apdu_len], 0,
(int) event_data->objectIdentifier.type,
apdu_len += encode_context_object_id(
&apdu[apdu_len], 0, (int)event_data->objectIdentifier.type,
event_data->objectIdentifier.instance);
/* Tag 1: eventState */
apdu_len +=
encode_context_enumerated(&apdu[apdu_len], 1,
event_data->eventState);
apdu_len += encode_context_enumerated(&apdu[apdu_len], 1,
event_data->eventState);
/* Tag 2: acknowledgedTransitions */
apdu_len +=
encode_context_bitstring(&apdu[apdu_len], 2,
&event_data->acknowledgedTransitions);
apdu_len += encode_context_bitstring(
&apdu[apdu_len], 2, &event_data->acknowledgedTransitions);
/* Tag 3: eventTimeStamps */
apdu_len += encode_opening_tag(&apdu[apdu_len], 3);
for (i = 0; i < 3; i++) {
apdu_len +=
bacapp_encode_timestamp(&apdu[apdu_len],
&event_data->eventTimeStamps[i]);
apdu_len += bacapp_encode_timestamp(
&apdu[apdu_len], &event_data->eventTimeStamps[i]);
}
apdu_len += encode_closing_tag(&apdu[apdu_len], 3);
/* Tag 4: notifyType */
apdu_len +=
encode_context_enumerated(&apdu[apdu_len], 4,
event_data->notifyType);
apdu_len += encode_context_enumerated(&apdu[apdu_len], 4,
event_data->notifyType);
/* Tag 5: eventEnable */
apdu_len +=
encode_context_bitstring(&apdu[apdu_len], 5,
&event_data->eventEnable);
apdu_len += encode_context_bitstring(&apdu[apdu_len], 5,
&event_data->eventEnable);
/* Tag 6: eventPriorities */
apdu_len += encode_opening_tag(&apdu[apdu_len], 6);
for (i = 0; i < 3; i++) {
apdu_len +=
encode_application_unsigned(&apdu[apdu_len],
event_data->eventPriorities[i]);
apdu_len += encode_application_unsigned(
&apdu[apdu_len], event_data->eventPriorities[i]);
}
apdu_len += encode_closing_tag(&apdu[apdu_len], 6);
event_data = event_data->next;
@@ -166,12 +151,10 @@ int getevent_ack_encode_apdu_data(
return apdu_len;
}
int getevent_ack_encode_apdu_end(
uint8_t * apdu,
size_t max_apdu,
bool moreEvents)
int getevent_ack_encode_apdu_end(uint8_t *apdu, size_t max_apdu,
bool moreEvents)
{
int apdu_len = 0; /* total length of the apdu, return value */
int apdu_len = 0; /* total length of the apdu, return value */
/* unused parameter */
max_apdu = max_apdu;
@@ -184,17 +167,15 @@ int getevent_ack_encode_apdu_end(
}
int getevent_ack_decode_service_request(
uint8_t * apdu,
int apdu_len, /* total length of the apdu */
BACNET_GET_EVENT_INFORMATION_DATA * get_event_data,
bool * moreEvents)
uint8_t *apdu, int apdu_len, /* total length of the apdu */
BACNET_GET_EVENT_INFORMATION_DATA *get_event_data, bool *moreEvents)
{
uint8_t tag_number = 0;
uint32_t len_value = 0;
int len = 0; /* total length of decodes */
uint32_t enum_value = 0; /* for decoding */
int len = 0; /* total length of decodes */
uint32_t enum_value = 0; /* for decoding */
BACNET_GET_EVENT_INFORMATION_DATA *event_data;
unsigned i = 0; /* counter */
unsigned i = 0; /* counter */
/* FIXME: check apdu_len against the len during decode */
event_data = get_event_data;
@@ -206,21 +187,18 @@ int getevent_ack_decode_service_request(
while (event_data) {
/* Tag 0: objectIdentifier */
if (decode_is_context_tag(&apdu[len], 0)) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len +=
decode_object_id(&apdu[len],
&event_data->objectIdentifier.type,
&event_data->objectIdentifier.instance);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_object_id(&apdu[len],
&event_data->objectIdentifier.type,
&event_data->objectIdentifier.instance);
} else {
return -1;
}
/* Tag 1: eventState */
if (decode_is_context_tag(&apdu[len], 1)) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_enumerated(&apdu[len], len_value, &enum_value);
event_data->eventState = enum_value;
} else {
@@ -228,40 +206,34 @@ int getevent_ack_decode_service_request(
}
/* Tag 2: acknowledgedTransitions */
if (decode_is_context_tag(&apdu[len], 2)) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len +=
decode_bitstring(&apdu[len], len_value,
&event_data->acknowledgedTransitions);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_bitstring(&apdu[len], len_value,
&event_data->acknowledgedTransitions);
} else {
return -1;
}
/* Tag 3: eventTimeStamps */
if (decode_is_opening_tag_number(&apdu[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);
for (i = 0; i < 3; i++) {
len +=
bacapp_decode_timestamp(&apdu[len],
&event_data->eventTimeStamps[i]);
len += bacapp_decode_timestamp(
&apdu[len], &event_data->eventTimeStamps[i]);
}
} else {
return -1;
}
if (decode_is_closing_tag_number(&apdu[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);
} else {
return -1;
}
/* Tag 4: notifyType */
if (decode_is_context_tag(&apdu[len], 4)) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_enumerated(&apdu[len], len_value, &enum_value);
event_data->notifyType = enum_value;
} else {
@@ -269,50 +241,42 @@ int getevent_ack_decode_service_request(
}
/* Tag 5: eventEnable */
if (decode_is_context_tag(&apdu[len], 5)) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len +=
decode_bitstring(&apdu[len], len_value,
&event_data->eventEnable);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_bitstring(&apdu[len], len_value,
&event_data->eventEnable);
} else {
return -1;
}
/* Tag 6: eventPriorities */
if (decode_is_opening_tag_number(&apdu[len], 6)) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
for (i = 0; i < 3; i++) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len +=
decode_unsigned(&apdu[len], len_value,
&event_data->eventPriorities[i]);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_unsigned(&apdu[len], len_value,
&event_data->eventPriorities[i]);
}
} else {
return -1;
}
if (decode_is_closing_tag_number(&apdu[len], 6)) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
} else {
return -1;
}
if (decode_is_closing_tag_number(&apdu[len], 0)) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
event_data->next = NULL;
}
event_data = event_data->next;
}
if (decode_is_context_tag(&apdu[len], 1)) {
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 (len_value == 1)
*moreEvents = decode_context_boolean(&apdu[len++]);
else
@@ -330,11 +294,8 @@ int getevent_ack_decode_service_request(
#include <string.h>
#include "ctest.h"
int getevent_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
uint8_t * invoke_id,
BACNET_OBJECT_ID * lastReceivedObjectIdentifier)
int getevent_decode_apdu(uint8_t *apdu, unsigned apdu_len, uint8_t *invoke_id,
BACNET_OBJECT_ID *lastReceivedObjectIdentifier)
{
int len = 0;
unsigned offset = 0;
@@ -345,26 +306,24 @@ int getevent_decode_apdu(
if (apdu[0] != PDU_TYPE_CONFIRMED_SERVICE_REQUEST)
return -1;
/* apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU); */
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
if (apdu[3] != SERVICE_CONFIRMED_GET_EVENT_INFORMATION)
return -1;
offset = 4;
if (apdu_len > offset) {
len =
getevent_decode_service_request(&apdu[offset], apdu_len - offset,
lastReceivedObjectIdentifier);
len = getevent_decode_service_request(&apdu[offset], apdu_len - offset,
lastReceivedObjectIdentifier);
}
return len;
}
int getevent_ack_decode_apdu(
uint8_t * apdu,
int apdu_len, /* total length of the apdu */
uint8_t * invoke_id,
BACNET_GET_EVENT_INFORMATION_DATA * get_event_data,
bool * moreEvents)
int getevent_ack_decode_apdu(uint8_t *apdu,
int apdu_len, /* total length of the apdu */
uint8_t *invoke_id,
BACNET_GET_EVENT_INFORMATION_DATA *get_event_data,
bool *moreEvents)
{
int len = 0;
int offset = 0;
@@ -379,18 +338,16 @@ int getevent_ack_decode_apdu(
return -1;
offset = 3;
if (apdu_len > offset) {
len =
getevent_ack_decode_service_request(&apdu[offset],
apdu_len - offset, get_event_data, moreEvents);
len = getevent_ack_decode_service_request(
&apdu[offset], apdu_len - offset, get_event_data, moreEvents);
}
return len;
}
void testGetEventInformationAck(
Test * pTest)
void testGetEventInformationAck(Test *pTest)
{
uint8_t apdu[480] = { 0 };
uint8_t apdu[480] = {0};
int len = 0;
int apdu_len = 0;
uint8_t invoke_id = 1;
@@ -406,11 +363,11 @@ void testGetEventInformationAck(
event_data.eventState = EVENT_STATE_NORMAL;
bitstring_init(&event_data.acknowledgedTransitions);
bitstring_set_bit(&event_data.acknowledgedTransitions,
TRANSITION_TO_OFFNORMAL, false);
TRANSITION_TO_OFFNORMAL, false);
bitstring_set_bit(&event_data.acknowledgedTransitions, TRANSITION_TO_FAULT,
false);
bitstring_set_bit(&event_data.acknowledgedTransitions,
TRANSITION_TO_NORMAL, false);
false);
bitstring_set_bit(&event_data.acknowledgedTransitions, TRANSITION_TO_NORMAL,
false);
for (i = 0; i < 3; i++) {
event_data.eventTimeStamps[i].tag = TIME_STAMP_SEQUENCE;
event_data.eventTimeStamps[i].value.sequenceNum = 0;
@@ -429,37 +386,33 @@ void testGetEventInformationAck(
ct_test(pTest, len != 0);
ct_test(pTest, len != -1);
apdu_len = len;
len =
getevent_ack_encode_apdu_data(&apdu[apdu_len], sizeof(apdu) - apdu_len,
&event_data);
len = getevent_ack_encode_apdu_data(&apdu[apdu_len],
sizeof(apdu) - apdu_len, &event_data);
ct_test(pTest, len != 0);
ct_test(pTest, len != -1);
apdu_len += len;
len =
getevent_ack_encode_apdu_end(&apdu[apdu_len], sizeof(apdu) - apdu_len,
moreEvents);
len = getevent_ack_encode_apdu_end(&apdu[apdu_len], sizeof(apdu) - apdu_len,
moreEvents);
ct_test(pTest, len != 0);
ct_test(pTest, len != -1);
apdu_len += len;
len = getevent_ack_decode_apdu(&apdu[0], apdu_len, /* total length of the apdu */
len = getevent_ack_decode_apdu(
&apdu[0], apdu_len, /* total length of the apdu */
&test_invoke_id, &test_event_data, &test_moreEvents);
ct_test(pTest, len != -1);
ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest,
event_data.objectIdentifier.type ==
test_event_data.objectIdentifier.type);
ct_test(pTest,
event_data.objectIdentifier.instance ==
test_event_data.objectIdentifier.instance);
ct_test(pTest, event_data.objectIdentifier.type ==
test_event_data.objectIdentifier.type);
ct_test(pTest, event_data.objectIdentifier.instance ==
test_event_data.objectIdentifier.instance);
ct_test(pTest, event_data.eventState == test_event_data.eventState);
}
void testGetEventInformation(
Test * pTest)
void testGetEventInformation(Test *pTest)
{
uint8_t apdu[480] = { 0 };
uint8_t apdu[480] = {0};
int len = 0;
int apdu_len = 0;
uint8_t invoke_id = 128;
@@ -469,30 +422,25 @@ void testGetEventInformation(
lastReceivedObjectIdentifier.type = OBJECT_BINARY_INPUT;
lastReceivedObjectIdentifier.instance = 12345;
len =
getevent_encode_apdu(&apdu[0], invoke_id,
&lastReceivedObjectIdentifier);
len = getevent_encode_apdu(&apdu[0], invoke_id,
&lastReceivedObjectIdentifier);
ct_test(pTest, len != 0);
apdu_len = len;
len =
getevent_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_lastReceivedObjectIdentifier);
len = getevent_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_lastReceivedObjectIdentifier);
ct_test(pTest, len != -1);
ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest,
test_lastReceivedObjectIdentifier.type ==
lastReceivedObjectIdentifier.type);
ct_test(pTest,
test_lastReceivedObjectIdentifier.instance ==
lastReceivedObjectIdentifier.instance);
ct_test(pTest, test_lastReceivedObjectIdentifier.type ==
lastReceivedObjectIdentifier.type);
ct_test(pTest, test_lastReceivedObjectIdentifier.instance ==
lastReceivedObjectIdentifier.instance);
return;
}
#ifdef TEST_GET_EVENT_INFORMATION
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -506,7 +454,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+33 -55
View File
@@ -43,29 +43,23 @@
/** @file iam.c Encode/Decode I-Am service */
/* encode I-Am service */
int iam_encode_apdu(
uint8_t * apdu,
uint32_t device_id,
unsigned max_apdu,
int segmentation,
uint16_t vendor_id)
int iam_encode_apdu(uint8_t *apdu, uint32_t device_id, unsigned max_apdu,
int segmentation, uint16_t vendor_id)
{
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) {
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;
len =
encode_application_object_id(&apdu[apdu_len], OBJECT_DEVICE,
device_id);
len = encode_application_object_id(&apdu[apdu_len], OBJECT_DEVICE,
device_id);
apdu_len += len;
len = encode_application_unsigned(&apdu[apdu_len], max_apdu);
apdu_len += len;
len =
encode_application_enumerated(&apdu[apdu_len],
(uint32_t) segmentation);
len = encode_application_enumerated(&apdu[apdu_len],
(uint32_t)segmentation);
apdu_len += len;
len = encode_application_unsigned(&apdu[apdu_len], vendor_id);
apdu_len += len;
@@ -74,24 +68,20 @@ int iam_encode_apdu(
return apdu_len;
}
int iam_decode_service_request(
uint8_t * apdu,
uint32_t * pDevice_id,
unsigned *pMax_apdu,
int *pSegmentation,
uint16_t * pVendor_id)
int iam_decode_service_request(uint8_t *apdu, uint32_t *pDevice_id,
unsigned *pMax_apdu, int *pSegmentation,
uint16_t *pVendor_id)
{
int len = 0;
int apdu_len = 0; /* total length of the apdu, return value */
uint16_t object_type = 0; /* should be a Device Object */
int apdu_len = 0; /* total length of the apdu, return value */
uint16_t object_type = 0; /* should be a Device Object */
uint32_t object_instance = 0;
uint8_t tag_number = 0;
uint32_t len_value = 0;
uint32_t decoded_value = 0;
/* 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;
if (tag_number != BACNET_APPLICATION_TAG_OBJECT_ID)
return -1;
@@ -102,18 +92,16 @@ int iam_decode_service_request(
if (pDevice_id)
*pDevice_id = object_instance;
/* 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;
if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT)
return -1;
len = decode_unsigned(&apdu[apdu_len], len_value, &decoded_value);
apdu_len += len;
if (pMax_apdu)
*pMax_apdu = (unsigned) decoded_value;
*pMax_apdu = (unsigned)decoded_value;
/* 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;
if (tag_number != BACNET_APPLICATION_TAG_ENUMERATED)
return -1;
@@ -122,10 +110,9 @@ int iam_decode_service_request(
if (decoded_value >= MAX_BACNET_SEGMENTATION)
return -1;
if (pSegmentation)
*pSegmentation = (int) decoded_value;
*pSegmentation = (int)decoded_value;
/* 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;
if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT)
return -1;
@@ -134,7 +121,7 @@ int iam_decode_service_request(
if (decoded_value > 0xFFFF)
return -1;
if (pVendor_id)
*pVendor_id = (uint16_t) decoded_value;
*pVendor_id = (uint16_t)decoded_value;
return apdu_len;
}
@@ -144,14 +131,10 @@ int iam_decode_service_request(
#include <string.h>
#include "ctest.h"
int iam_decode_apdu(
uint8_t * apdu,
uint32_t * pDevice_id,
unsigned *pMax_apdu,
int *pSegmentation,
uint16_t * pVendor_id)
int iam_decode_apdu(uint8_t *apdu, uint32_t *pDevice_id, unsigned *pMax_apdu,
int *pSegmentation, uint16_t *pVendor_id)
{
int apdu_len = 0; /* total length of the apdu, return value */
int apdu_len = 0; /* total length of the apdu, return value */
/* valid data? */
if (!apdu)
@@ -161,17 +144,15 @@ int iam_decode_apdu(
return -1;
if (apdu[1] != SERVICE_UNCONFIRMED_I_AM)
return -1;
apdu_len =
iam_decode_service_request(&apdu[2], pDevice_id, pMax_apdu,
pSegmentation, pVendor_id);
apdu_len = iam_decode_service_request(&apdu[2], pDevice_id, pMax_apdu,
pSegmentation, pVendor_id);
return apdu_len;
}
void testIAm(
Test * pTest)
void testIAm(Test *pTest)
{
uint8_t apdu[480] = { 0 };
uint8_t apdu[480] = {0};
int len = 0;
uint32_t device_id = 42;
unsigned max_apdu = 480;
@@ -183,13 +164,11 @@ void testIAm(
uint16_t test_vendor_id = 0;
len =
iam_encode_apdu(&apdu[0], device_id, max_apdu, segmentation,
vendor_id);
iam_encode_apdu(&apdu[0], device_id, max_apdu, segmentation, vendor_id);
ct_test(pTest, len != 0);
len =
iam_decode_apdu(&apdu[0], &test_device_id, &test_max_apdu,
&test_segmentation, &test_vendor_id);
len = iam_decode_apdu(&apdu[0], &test_device_id, &test_max_apdu,
&test_segmentation, &test_vendor_id);
ct_test(pTest, len != -1);
ct_test(pTest, test_device_id == device_id);
@@ -199,8 +178,7 @@ void testIAm(
}
#ifdef TEST_IAM
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -212,7 +190,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+38 -55
View File
@@ -39,31 +39,28 @@
/** @file ihave.c Encode/Decode I-Have service */
int ihave_encode_apdu(
uint8_t * apdu,
BACNET_I_HAVE_DATA * data)
int ihave_encode_apdu(uint8_t *apdu, BACNET_I_HAVE_DATA *data)
{
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
if (apdu && data) {
apdu[0] = PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST;
apdu[1] = SERVICE_UNCONFIRMED_I_HAVE;
apdu_len = 2;
/* deviceIdentifier */
len =
encode_application_object_id(&apdu[apdu_len],
(int) data->device_id.type, data->device_id.instance);
len = encode_application_object_id(&apdu[apdu_len],
(int)data->device_id.type,
data->device_id.instance);
apdu_len += len;
/* objectIdentifier */
len =
encode_application_object_id(&apdu[apdu_len],
(int) data->object_id.type, data->object_id.instance);
len = encode_application_object_id(&apdu[apdu_len],
(int)data->object_id.type,
data->object_id.instance);
apdu_len += len;
/* objectName */
len =
encode_application_character_string(&apdu[apdu_len],
&data->object_name);
len = encode_application_character_string(&apdu[apdu_len],
&data->object_name);
apdu_len += len;
}
@@ -73,44 +70,36 @@ int ihave_encode_apdu(
#if BACNET_SVC_I_HAVE_A
/* decode the service request only */
int ihave_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
BACNET_I_HAVE_DATA * data)
int ihave_decode_service_request(uint8_t *apdu, unsigned apdu_len,
BACNET_I_HAVE_DATA *data)
{
int len = 0;
uint8_t tag_number = 0;
uint32_t len_value = 0;
uint16_t decoded_type = 0; /* for decoding */
uint16_t decoded_type = 0; /* for decoding */
if (apdu_len && data) {
/* deviceIdentifier */
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 == BACNET_APPLICATION_TAG_OBJECT_ID) {
len +=
decode_object_id(&apdu[len], &decoded_type,
&data->device_id.instance);
len += decode_object_id(&apdu[len], &decoded_type,
&data->device_id.instance);
data->device_id.type = decoded_type;
} else
return -1;
/* objectIdentifier */
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 == BACNET_APPLICATION_TAG_OBJECT_ID) {
len +=
decode_object_id(&apdu[len], &decoded_type,
&data->object_id.instance);
len += decode_object_id(&apdu[len], &decoded_type,
&data->object_id.instance);
data->object_id.type = decoded_type;
} else
return -1;
/* objectName */
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 == BACNET_APPLICATION_TAG_CHARACTER_STRING) {
len +=
decode_character_string(&apdu[len], len_value,
&data->object_name);
len += decode_character_string(&apdu[len], len_value,
&data->object_name);
} else
return -1;
} else
@@ -119,10 +108,8 @@ int ihave_decode_service_request(
return len;
}
int ihave_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
BACNET_I_HAVE_DATA * data)
int ihave_decode_apdu(uint8_t *apdu, unsigned apdu_len,
BACNET_I_HAVE_DATA *data)
{
int len = 0;
@@ -144,11 +131,9 @@ int ihave_decode_apdu(
#include <string.h>
#include "ctest.h"
void testIHaveData(
Test * pTest,
BACNET_I_HAVE_DATA * data)
void testIHaveData(Test *pTest, BACNET_I_HAVE_DATA *data)
{
uint8_t apdu[480] = { 0 };
uint8_t apdu[480] = {0};
int len = 0;
int apdu_len = 0;
BACNET_I_HAVE_DATA test_data;
@@ -163,26 +148,25 @@ void testIHaveData(
ct_test(pTest, test_data.device_id.instance == data->device_id.instance);
ct_test(pTest, test_data.object_id.type == data->object_id.type);
ct_test(pTest, test_data.object_id.instance == data->object_id.instance);
ct_test(pTest, characterstring_same(&test_data.object_name,
&data->object_name));
ct_test(pTest,
characterstring_same(&test_data.object_name, &data->object_name));
}
void testIHave(
Test * pTest)
void testIHave(Test *pTest)
{
BACNET_I_HAVE_DATA data;
characterstring_init_ansi(&data.object_name, "Patricia - my love!");
data.device_id.type = OBJECT_DEVICE;
for (data.device_id.instance = 1;
data.device_id.instance <= BACNET_MAX_INSTANCE;
data.device_id.instance <<= 1) {
data.device_id.instance <= BACNET_MAX_INSTANCE;
data.device_id.instance <<= 1) {
for (data.object_id.type = OBJECT_ANALOG_INPUT;
data.object_id.type < MAX_BACNET_OBJECT_TYPE;
data.object_id.type++) {
data.object_id.type < MAX_BACNET_OBJECT_TYPE;
data.object_id.type++) {
for (data.object_id.instance = 1;
data.object_id.instance <= BACNET_MAX_INSTANCE;
data.object_id.instance <<= 1) {
data.object_id.instance <= BACNET_MAX_INSTANCE;
data.object_id.instance <<= 1) {
testIHaveData(pTest, &data);
}
}
@@ -190,8 +174,7 @@ void testIHave(
}
#ifdef TEST_I_HAVE
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -203,7 +186,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+34 -58
View File
@@ -13,9 +13,9 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to
along with this program; if not, write to
The Free Software Foundation, Inc.
59 Temple Place - Suite 330
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA.
As a special exception, if other files instantiate templates or
@@ -39,32 +39,28 @@
#if !defined(__BORLANDC__) && !defined(_MSC_VER)
#include <ctype.h>
int stricmp(
const char *s1,
const char *s2)
int stricmp(const char *s1, const char *s2)
{
unsigned char c1, c2;
do {
c1 = (unsigned char) *s1;
c2 = (unsigned char) *s2;
c1 = (unsigned char) tolower(c1);
c2 = (unsigned char) tolower(c2);
c1 = (unsigned char)*s1;
c2 = (unsigned char)*s2;
c1 = (unsigned char)tolower(c1);
c2 = (unsigned char)tolower(c2);
s1++;
s2++;
} while ((c1 == c2) && (c1 != '\0'));
return (int) c1 - c2;
return (int)c1 - c2;
}
#endif
#if defined(_MSC_VER)
#define stricmp _stricmp
#endif
bool indtext_by_string(
INDTEXT_DATA * data_list,
const char *search_name,
unsigned *found_index)
bool indtext_by_string(INDTEXT_DATA *data_list, const char *search_name,
unsigned *found_index)
{
bool found = false;
unsigned index = 0;
@@ -87,10 +83,8 @@ bool indtext_by_string(
}
/* case insensitive version */
bool indtext_by_istring(
INDTEXT_DATA * data_list,
const char *search_name,
unsigned *found_index)
bool indtext_by_istring(INDTEXT_DATA *data_list, const char *search_name,
unsigned *found_index)
{
bool found = false;
unsigned index = 0;
@@ -112,10 +106,9 @@ bool indtext_by_istring(
return found;
}
unsigned indtext_by_string_default(
INDTEXT_DATA * data_list,
const char *search_name,
unsigned default_index)
unsigned indtext_by_string_default(INDTEXT_DATA *data_list,
const char *search_name,
unsigned default_index)
{
unsigned index = 0;
@@ -125,10 +118,9 @@ unsigned indtext_by_string_default(
return index;
}
unsigned indtext_by_istring_default(
INDTEXT_DATA * data_list,
const char *search_name,
unsigned default_index)
unsigned indtext_by_istring_default(INDTEXT_DATA *data_list,
const char *search_name,
unsigned default_index)
{
unsigned index = 0;
@@ -138,10 +130,8 @@ unsigned indtext_by_istring_default(
return index;
}
const char *indtext_by_index_default(
INDTEXT_DATA * data_list,
unsigned index,
const char *default_string)
const char *indtext_by_index_default(INDTEXT_DATA *data_list, unsigned index,
const char *default_string)
{
const char *pString = NULL;
@@ -159,29 +149,22 @@ const char *indtext_by_index_default(
}
const char *indtext_by_index_split_default(
INDTEXT_DATA * data_list,
unsigned index,
unsigned split_index,
const char *before_split_default_name,
const char *default_name)
INDTEXT_DATA *data_list, unsigned index, unsigned split_index,
const char *before_split_default_name, const char *default_name)
{
if (index < split_index)
return indtext_by_index_default(data_list, index,
before_split_default_name);
before_split_default_name);
else
return indtext_by_index_default(data_list, index, default_name);
}
const char *indtext_by_index(
INDTEXT_DATA * data_list,
unsigned index)
const char *indtext_by_index(INDTEXT_DATA *data_list, unsigned index)
{
return indtext_by_index_default(data_list, index, NULL);
}
unsigned indtext_count(
INDTEXT_DATA * data_list)
unsigned indtext_count(INDTEXT_DATA *data_list)
{
unsigned count = 0; /* return value */
@@ -198,17 +181,11 @@ unsigned indtext_count(
#include <assert.h>
#include "ctest.h"
static INDTEXT_DATA data_list[] = {
{1, "Joshua"},
{2, "Mary"},
{3, "Anna"},
{4, "Christopher"},
{5, "Patricia"},
{0, NULL}
};
static INDTEXT_DATA data_list[] = {{1, "Joshua"}, {2, "Mary"},
{3, "Anna"}, {4, "Christopher"},
{5, "Patricia"}, {0, NULL}};
void testIndexText(
Test * pTest)
void testIndexText(Test *pTest)
{
unsigned i; /*counter */
const char *pString;
@@ -224,7 +201,7 @@ void testIndexText(
ct_test(pTest, valid == true);
ct_test(pTest, index == i);
ct_test(pTest, index == indtext_by_string_default(data_list,
pString, index));
pString, index));
}
}
ct_test(pTest, indtext_count(data_list) == count);
@@ -238,14 +215,13 @@ void testIndexText(
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);
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
#ifdef TEST_INDEX_TEXT
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -258,7 +234,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
+10 -13
View File
@@ -13,9 +13,9 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to
along with this program; if not, write to
The Free Software Foundation, Inc.
59 Temple Place - Suite 330
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA.
As a special exception, if other files instantiate templates or
@@ -44,8 +44,7 @@
#include "ctest.h"
/* test the encode and decode macros */
void testKeys(
Test * pTest)
void testKeys(Test *pTest)
{
int type, id;
int decoded_type, decoded_id;
@@ -65,12 +64,11 @@ void testKeys(
}
/* test the encode and decode macros */
void testKeySample(
Test * pTest)
void testKeySample(Test *pTest)
{
int type, id;
int type_list[] = { 0, 1, KEY_TYPE_MAX / 2, KEY_TYPE_MAX - 1, -1 };
int id_list[] = { 0, 1, KEY_ID_MAX / 2, KEY_ID_MAX - 1, -1 };
int type_list[] = {0, 1, KEY_TYPE_MAX / 2, KEY_TYPE_MAX - 1, -1};
int id_list[] = {0, 1, KEY_ID_MAX / 2, KEY_ID_MAX - 1, -1};
int type_index = 0;
int id_index = 0;
int decoded_type, decoded_id;
@@ -96,22 +94,21 @@ void testKeySample(
}
#ifdef TEST_KEY
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
pTest = ct_create("key", NULL);
/* add the individual tests */
/* rc = ct_addTestFunction(pTest, testKeys); */
/* assert(rc); */
/* rc = ct_addTestFunction(pTest, testKeys); */
/* assert(rc); */
rc = ct_addTestFunction(pTest, testKeySample);
assert(rc);
/* run all the tests */
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
/* completed testing - cleanup */
ct_destroy(pTest);
+56 -103
View File
@@ -42,7 +42,7 @@
#include <stdlib.h>
#include "keylist.h" /* check for valid prototypes */
#include "keylist.h" /* check for valid prototypes */
#ifndef FALSE
#define FALSE 0
@@ -57,15 +57,13 @@
/******************************************************************** */
/* grab memory for a node */
static struct Keylist_Node *NodeCreate(
void)
static struct Keylist_Node *NodeCreate(void)
{
return calloc(1, sizeof(struct Keylist_Node));
}
/* grab memory for a list */
static struct Keylist *KeylistCreate(
void)
static struct Keylist *KeylistCreate(void)
{
return calloc(1, sizeof(struct Keylist));
}
@@ -73,13 +71,12 @@ static struct Keylist *KeylistCreate(
/* check to see if the array is big enough for an addition */
/* or is too big when we are deleting and we can shrink */
/* returns TRUE if success, FALSE if failed */
static int CheckArraySize(
OS_Keylist list)
static int CheckArraySize(OS_Keylist list)
{
int new_size = 0; /* set it up so that no size change is the default */
const int chunk = 8; /* minimum number of nodes to allocate memory for */
struct Keylist_Node **new_array; /* new array of nodes, if needed */
int i; /* counter */
int new_size = 0; /* set it up so that no size change is the default */
const int chunk = 8; /* minimum number of nodes to allocate memory for */
struct Keylist_Node **new_array; /* new array of nodes, if needed */
int i; /* counter */
if (!list)
return FALSE;
@@ -91,9 +88,8 @@ static int CheckArraySize(
else if ((list->size > chunk) && (list->count < (list->size - chunk)))
new_size = list->size - chunk;
if (new_size) {
/* Allocate more room for node pointer array */
new_array = calloc((size_t) new_size, sizeof(new_array));
new_array = calloc((size_t)new_size, sizeof(new_array));
/* See if we got the memory we wanted */
if (!new_array)
@@ -112,24 +108,21 @@ static int CheckArraySize(
return TRUE;
}
/* find the index of the key that we are looking for */
/* since it is sorted, we can optimize the search */
/* returns TRUE if found, and FALSE not found */
/* returns the found key and the index where it was found in parameters */
/* If the key is not found, the nearest index from the bottom will be returned, */
/* If the key is not found, the nearest index from the bottom will be returned,
*/
/* allowing the ability to find where an key should go into the list. */
static int FindIndex(
OS_Keylist list,
KEY key,
int *pIndex)
static int FindIndex(OS_Keylist list, KEY key, int *pIndex)
{
struct Keylist_Node *node; /* holds the new node */
int left = 0; /* the left branch of tree, beginning of list */
int right = 0; /* the right branch on the tree, end of list */
int index = 0; /* our current search place in the array */
KEY current_key = 0; /* place holder for current node key */
int status = FALSE; /* return value */
struct Keylist_Node *node; /* holds the new node */
int left = 0; /* the left branch of tree, beginning of list */
int right = 0; /* the right branch on the tree, end of list */
int index = 0; /* our current search place in the array */
KEY current_key = 0; /* place holder for current node key */
int status = FALSE; /* return value */
if (!list || !list->array || !list->count) {
*pIndex = 0;
return (FALSE);
@@ -137,7 +130,6 @@ static int FindIndex(
right = list->count - 1;
/* assume that the list is sorted */
do {
/* A binary search */
index = (left + right) / 2;
node = list->array[index];
@@ -149,15 +141,13 @@ static int FindIndex(
else
left = index + 1;
}
while ((key != current_key) && (left <= right));
} while ((key != current_key) && (left <= right));
if (key == current_key) {
status = TRUE;
*pIndex = index;
}
else {
/* where the index should be */
if (key > current_key)
*pIndex = index + 1;
@@ -168,24 +158,20 @@ static int FindIndex(
return (status);
}
/******************************************************************** */
/* list data functions */
/******************************************************************** */
/* inserts a node into its sorted position */
int Keylist_Data_Add(
OS_Keylist list,
KEY key,
void *data)
int Keylist_Data_Add(OS_Keylist list, KEY key, void *data)
{
struct Keylist_Node *node; /* holds the new node */
int index = -1; /* return value */
int i; /* counts through the array */
struct Keylist_Node *node; /* holds the new node */
int index = -1; /* return value */
int i; /* counts through the array */
if (list && CheckArraySize(list)) {
/* figure out where to put the new node */
if (list->count) {
(void) FindIndex(list, key, &index);
(void)FindIndex(list, key, &index);
/* Add to the beginning of the list */
if (index < 0)
index = 0;
@@ -218,9 +204,7 @@ int Keylist_Data_Add(
/* deletes a node specified by its index */
/* returns the data from the node */
void *Keylist_Data_Delete_By_Index(
OS_Keylist list,
int index)
void *Keylist_Data_Delete_By_Index(OS_Keylist list, int index)
{
struct Keylist_Node *node;
void *data = NULL;
@@ -233,17 +217,15 @@ void *Keylist_Data_Delete_By_Index(
/* move the nodes to account for the deleted one */
if (list->count == 1) {
/* There is no node shifting to do */
}
/* We are the last one */
else if (index == (list->count - 1)) {
/* There is no node shifting to do */
}
/* Move all the nodes down one */
else {
int i; /* counter */
int i; /* counter */
int count = list->count - 1;
for (i = index; i < count; i++) {
list->array[i] = list->array[i + 1];
@@ -254,20 +236,17 @@ void *Keylist_Data_Delete_By_Index(
free(node);
/* potentially reduce the size of the array */
(void) CheckArraySize(list);
(void)CheckArraySize(list);
}
return (data);
}
/* deletes a node specified by its key */
/* returns the data from the node */
void *Keylist_Data_Delete(
OS_Keylist list,
KEY key)
void *Keylist_Data_Delete(OS_Keylist list, KEY key)
{
void *data = NULL; /* return value */
int index; /* where the node is in the array */
void *data = NULL; /* return value */
int index; /* where the node is in the array */
if (list) {
if (FindIndex(list, key, &index))
@@ -278,11 +257,10 @@ void *Keylist_Data_Delete(
}
/* returns the data from last node, and removes it from the list */
void *Keylist_Data_Pop(
OS_Keylist list)
void *Keylist_Data_Pop(OS_Keylist list)
{
void *data = NULL; /* return value */
int index; /* position in the array */
void *data = NULL; /* return value */
int index; /* position in the array */
if (list && list->count) {
index = list->count - 1;
@@ -293,12 +271,10 @@ void *Keylist_Data_Pop(
}
/* returns the data from the node specified by key */
void *Keylist_Data(
OS_Keylist list,
KEY key)
void *Keylist_Data(OS_Keylist list, KEY key)
{
struct Keylist_Node *node = NULL;
int index = 0; /* used to look up the index of node */
int index = 0; /* used to look up the index of node */
if (list && list->array && list->count) {
if (FindIndex(list, key, &index))
@@ -309,11 +285,9 @@ void *Keylist_Data(
}
/* returns the index from the node specified by key */
int Keylist_Index(
OS_Keylist list,
KEY key)
int Keylist_Index(OS_Keylist list, KEY key)
{
int index = -1; /* used to look up the index of node */
int index = -1; /* used to look up the index of node */
if (list && list->array && list->count) {
if (!FindIndex(list, key, &index)) {
@@ -324,11 +298,8 @@ int Keylist_Index(
return index;
}
/* returns the data specified by index */
void *Keylist_Data_Index(
OS_Keylist list,
int index)
void *Keylist_Data_Index(OS_Keylist list, int index)
{
struct Keylist_Node *node = NULL;
@@ -340,11 +311,9 @@ void *Keylist_Data_Index(
}
/* return the key at the given index */
KEY Keylist_Key(
OS_Keylist list,
int index)
KEY Keylist_Key(OS_Keylist list, int index)
{
KEY key = 0; /* return value */
KEY key = 0; /* return value */
struct Keylist_Node *node;
if (list && list->array && list->count && (index >= 0) &&
@@ -358,9 +327,7 @@ KEY Keylist_Key(
}
/* returns the next empty key from the list */
KEY Keylist_Next_Empty_Key(
OS_Keylist list,
KEY key)
KEY Keylist_Next_Empty_Key(OS_Keylist list, KEY key)
{
int index;
@@ -376,8 +343,7 @@ KEY Keylist_Next_Empty_Key(
}
/* return the number of nodes in this list */
int Keylist_Count(
OS_Keylist list)
int Keylist_Count(OS_Keylist list)
{
return list->count;
}
@@ -387,8 +353,7 @@ int Keylist_Count(
/******************************************************************** */
/* returns head of the list or NULL on failure. */
OS_Keylist Keylist_Create(
void)
OS_Keylist Keylist_Create(void)
{
struct Keylist *list;
@@ -400,13 +365,12 @@ OS_Keylist Keylist_Create(
}
/* delete specified list */
void Keylist_Delete(
OS_Keylist list)
{ /* list number to be deleted */
void Keylist_Delete(OS_Keylist list)
{ /* list number to be deleted */
if (list) {
/* clean out the list */
while (list->count) {
(void) Keylist_Data_Delete_By_Index(list, 0);
(void)Keylist_Data_Delete_By_Index(list, 0);
}
if (list->array)
free(list->array);
@@ -423,8 +387,7 @@ void Keylist_Delete(
#include "ctest.h"
/* test the FIFO */
static void testKeyListFIFO(
Test * pTest)
static void testKeyListFIFO(Test *pTest)
{
OS_Keylist list;
KEY key;
@@ -467,8 +430,7 @@ static void testKeyListFIFO(
}
/* test the FILO */
static void testKeyListFILO(
Test * pTest)
static void testKeyListFILO(Test *pTest)
{
OS_Keylist list;
KEY key;
@@ -514,8 +476,7 @@ static void testKeyListFILO(
return;
}
static void testKeyListDataKey(
Test * pTest)
static void testKeyListDataKey(Test *pTest)
{
OS_Keylist list;
KEY key;
@@ -587,16 +548,14 @@ static void testKeyListDataKey(
/* cleanup */
do {
data = Keylist_Data_Pop(list);
}
while (data);
} while (data);
Keylist_Delete(list);
return;
}
static void testKeyListDataIndex(
Test * pTest)
static void testKeyListDataIndex(Test *pTest)
{
OS_Keylist list;
KEY key;
@@ -617,7 +576,6 @@ static void testKeyListDataIndex(
index = Keylist_Data_Add(list, key, data3);
ct_test(pTest, index == 0);
ct_test(pTest, Keylist_Count(list) == 3);
/* look at the data */
@@ -658,8 +616,7 @@ static void testKeyListDataIndex(
/* cleanup */
do {
data = Keylist_Data_Pop(list);
}
while (data);
} while (data);
Keylist_Delete(list);
@@ -667,8 +624,7 @@ static void testKeyListDataIndex(
}
/* test access of a lot of entries */
static void testKeyListLarge(
Test * pTest)
static void testKeyListLarge(Test *pTest)
{
int data1 = 42;
int *data;
@@ -683,7 +639,6 @@ static void testKeyListLarge(
for (key = 0; key < num_keys; key++) {
index = Keylist_Data_Add(list, key, &data1);
}
for (key = 0; key < num_keys; key++) {
data = Keylist_Data(list, key);
@@ -699,8 +654,7 @@ static void testKeyListLarge(
}
/* test access of a lot of entries */
void testKeyList(
Test * pTest)
void testKeyList(Test *pTest)
{
bool rc;
@@ -718,8 +672,7 @@ void testKeyList(
}
#ifdef TEST_KEYLIST
int main(
void)
int main(void)
{
Test *pTest;
@@ -727,7 +680,7 @@ int main(
testKeyList(pTest);
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
+38 -66
View File
@@ -42,7 +42,6 @@
/** @file lighting.c Manipulate BACnet lighting command values */
/**
* Encodes into bytes from the lighting-command structure
*
@@ -51,45 +50,37 @@
*
* @return number of bytes encoded, or 0 if unable to encode.
*/
int lighting_command_encode(
uint8_t * apdu,
BACNET_LIGHTING_COMMAND * data)
int lighting_command_encode(uint8_t *apdu, BACNET_LIGHTING_COMMAND *data)
{
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* total length of the apdu, return value */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* total length of the apdu, return value */
if (apdu) {
len = encode_context_enumerated(&apdu[apdu_len], 0,
data->operation);
len = encode_context_enumerated(&apdu[apdu_len], 0, data->operation);
apdu_len += len;
/* optional target-level */
if (data->use_target_level) {
len = encode_context_real(&apdu[apdu_len], 1,
data->target_level);
len = encode_context_real(&apdu[apdu_len], 1, data->target_level);
apdu_len += len;
}
/* optional ramp-rate */
if (data->use_ramp_rate) {
len = encode_context_real(&apdu[apdu_len], 2,
data->ramp_rate);
len = encode_context_real(&apdu[apdu_len], 2, data->ramp_rate);
apdu_len += len;
}
/* optional step increment */
if (data->use_step_increment) {
len = encode_context_real(&apdu[apdu_len], 3,
data->step_increment);
len = encode_context_real(&apdu[apdu_len], 3, data->step_increment);
apdu_len += len;
}
/* optional fade time */
if (data->use_fade_time) {
len = encode_context_unsigned(&apdu[apdu_len], 4,
data->fade_time);
len = encode_context_unsigned(&apdu[apdu_len], 4, data->fade_time);
apdu_len += len;
}
/* optional priority */
if (data->use_priority) {
len = encode_context_unsigned(&apdu[apdu_len], 5,
data->priority);
len = encode_context_unsigned(&apdu[apdu_len], 5, data->priority);
apdu_len += len;
}
}
@@ -107,10 +98,8 @@ int lighting_command_encode(
*
* @return number of bytes encoded, or 0 if unable to encode.
*/
int lighting_command_encode_context(
uint8_t * apdu,
uint8_t tag_number,
BACNET_LIGHTING_COMMAND * value)
int lighting_command_encode_context(uint8_t *apdu, uint8_t tag_number,
BACNET_LIGHTING_COMMAND *value)
{
int apdu_len = 0;
@@ -130,10 +119,8 @@ int lighting_command_encode_context(
*
* @return number of bytes encoded
*/
int lighting_command_decode(
uint8_t * apdu,
unsigned apdu_max_len,
BACNET_LIGHTING_COMMAND * data)
int lighting_command_decode(uint8_t *apdu, unsigned apdu_max_len,
BACNET_LIGHTING_COMMAND *data)
{
int len = 0;
int apdu_len = 0;
@@ -148,9 +135,8 @@ int lighting_command_decode(
/* Tag 0: operation */
if (!decode_is_context_tag(&apdu[apdu_len], 0))
return BACNET_STATUS_ERROR;
len =
decode_tag_number_and_value(&apdu[apdu_len], &tag_number,
&len_value_type);
len = decode_tag_number_and_value(&apdu[apdu_len], &tag_number,
&len_value_type);
apdu_len += len;
len =
decode_enumerated(&apdu[apdu_len], len_value_type, &unsigned_value);
@@ -160,9 +146,8 @@ int lighting_command_decode(
apdu_len += len;
/* Tag 1: target-level - OPTIONAL */
if (decode_is_context_tag(&apdu[apdu_len], 1)) {
len =
decode_tag_number_and_value(&apdu[apdu_len], &tag_number,
&len_value_type);
len = decode_tag_number_and_value(&apdu[apdu_len], &tag_number,
&len_value_type);
apdu_len += len;
len = decode_real(&apdu[apdu_len], &real_value);
data->target_level = real_value;
@@ -173,9 +158,8 @@ int lighting_command_decode(
}
/* Tag 2: ramp-rate - OPTIONAL */
if (decode_is_context_tag(&apdu[apdu_len], 2)) {
len =
decode_tag_number_and_value(&apdu[apdu_len], &tag_number,
&len_value_type);
len = decode_tag_number_and_value(&apdu[apdu_len], &tag_number,
&len_value_type);
apdu_len += len;
len = decode_real(&apdu[apdu_len], &real_value);
data->ramp_rate = real_value;
@@ -185,9 +169,8 @@ int lighting_command_decode(
}
/* Tag 3: step-increment - OPTIONAL */
if (decode_is_context_tag(&apdu[apdu_len], 3)) {
len =
decode_tag_number_and_value(&apdu[apdu_len], &tag_number,
&len_value_type);
len = decode_tag_number_and_value(&apdu[apdu_len], &tag_number,
&len_value_type);
apdu_len += len;
len = decode_real(&apdu[apdu_len], &real_value);
data->step_increment = real_value;
@@ -197,12 +180,11 @@ int lighting_command_decode(
}
/* Tag 4: fade-time - OPTIONAL */
if (decode_is_context_tag(&apdu[apdu_len], 4)) {
len =
decode_tag_number_and_value(&apdu[apdu_len], &tag_number,
&len_value_type);
len = decode_tag_number_and_value(&apdu[apdu_len], &tag_number,
&len_value_type);
apdu_len += len;
len = decode_unsigned(&apdu[apdu_len], len_value_type,
&unsigned_value);
&unsigned_value);
data->fade_time = unsigned_value;
data->use_fade_time = true;
} else {
@@ -210,12 +192,11 @@ int lighting_command_decode(
}
/* Tag 5: priority - OPTIONAL */
if (decode_is_context_tag(&apdu[apdu_len], 4)) {
len =
decode_tag_number_and_value(&apdu[apdu_len], &tag_number,
&len_value_type);
len = decode_tag_number_and_value(&apdu[apdu_len], &tag_number,
&len_value_type);
apdu_len += len;
len = decode_unsigned(&apdu[apdu_len], len_value_type,
&unsigned_value);
&unsigned_value);
data->priority = unsigned_value;
data->use_priority = true;
} else {
@@ -234,9 +215,8 @@ int lighting_command_decode(
*
* @return true if copy succeeded
*/
bool lighting_command_copy(
BACNET_LIGHTING_COMMAND * dst,
BACNET_LIGHTING_COMMAND * src)
bool lighting_command_copy(BACNET_LIGHTING_COMMAND *dst,
BACNET_LIGHTING_COMMAND *src)
{
bool status = false;
@@ -266,9 +246,8 @@ bool lighting_command_copy(
*
* @return true if lighting-commands are the same for values in-use
*/
bool lighting_command_same(
BACNET_LIGHTING_COMMAND * dst,
BACNET_LIGHTING_COMMAND * src)
bool lighting_command_same(BACNET_LIGHTING_COMMAND *dst,
BACNET_LIGHTING_COMMAND *src)
{
bool status = false;
@@ -284,20 +263,17 @@ bool lighting_command_same(
(dst->target_level != src->target_level)) {
status = false;
}
if ((dst->use_ramp_rate) &&
(dst->ramp_rate != src->ramp_rate)) {
if ((dst->use_ramp_rate) && (dst->ramp_rate != src->ramp_rate)) {
status = false;
}
if ((dst->use_step_increment) &&
(dst->step_increment != src->step_increment)) {
status = false;
}
if ((dst->use_fade_time) &&
(dst->fade_time != src->fade_time)) {
if ((dst->use_fade_time) && (dst->fade_time != src->fade_time)) {
status = false;
}
if ((dst->use_priority) &&
(dst->priority != src->priority)) {
if ((dst->use_priority) && (dst->priority != src->priority)) {
status = false;
}
}
@@ -311,9 +287,7 @@ bool lighting_command_same(
#include <string.h>
#include "ctest.h"
void testBACnetLightingCommand(
Test * pTest,
BACNET_LIGHTING_COMMAND *data)
void testBACnetLightingCommand(Test *pTest, BACNET_LIGHTING_COMMAND *data)
{
bool status = false;
BACNET_LIGHTING_COMMAND test_data;
@@ -335,8 +309,7 @@ void testBACnetLightingCommand(
status = lighting_command_same(&test_data, data);
}
void testBACnetLightingCommandAll(
Test * pTest)
void testBACnetLightingCommandAll(Test *pTest)
{
BACNET_LIGHTING_COMMAND data;
@@ -362,8 +335,7 @@ void testBACnetLightingCommandAll(
}
#ifdef TEST_LIGHTING_COMMAND
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -375,7 +347,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+30 -44
View File
@@ -37,13 +37,10 @@
/** @file lso.c BACnet Life Safety Operation encode/decode */
int lso_encode_apdu(
uint8_t * apdu,
uint8_t invoke_id,
BACNET_LSO_DATA * data)
int lso_encode_apdu(uint8_t *apdu, uint8_t invoke_id, BACNET_LSO_DATA *data)
{
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
if (apdu && data) {
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
@@ -55,9 +52,8 @@ int lso_encode_apdu(
len = encode_context_unsigned(&apdu[apdu_len], 0, data->processId);
apdu_len += len;
/* tag 1 - requestingSource */
len =
encode_context_character_string(&apdu[apdu_len], 1,
&data->requestingSrc);
len = encode_context_character_string(&apdu[apdu_len], 1,
&data->requestingSrc);
apdu_len += len;
/*
Operation
@@ -68,9 +64,9 @@ int lso_encode_apdu(
Object ID
*/
len =
encode_context_object_id(&apdu[apdu_len], 3,
(int) data->targetObject.type, data->targetObject.instance);
len = encode_context_object_id(&apdu[apdu_len], 3,
(int)data->targetObject.type,
data->targetObject.instance);
apdu_len += len;
}
@@ -78,48 +74,43 @@ int lso_encode_apdu(
return apdu_len;
}
int lso_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
BACNET_LSO_DATA * data)
int lso_decode_service_request(uint8_t *apdu, unsigned apdu_len,
BACNET_LSO_DATA *data)
{
int len = 0; /* return value */
int section_length = 0; /* length returned from decoding */
uint32_t operation = 0; /* handles decoded value */
int len = 0; /* return value */
int section_length = 0; /* length returned from decoding */
uint32_t operation = 0; /* handles decoded value */
/* check for value pointers */
if (apdu_len && data) {
/* Tag 0: Object ID */
if ((section_length =
decode_context_unsigned(&apdu[len], 0,
&data->processId)) == -1) {
if ((section_length = decode_context_unsigned(
&apdu[len], 0, &data->processId)) == -1) {
return -1;
}
len += section_length;
if ((section_length = decode_context_character_string(
&apdu[len], 1, &data->requestingSrc)) == -1) {
return -1;
}
len += section_length;
if ((section_length =
decode_context_character_string(&apdu[len], 1,
&data->requestingSrc)) == -1) {
decode_context_enumerated(&apdu[len], 2, &operation)) == -1) {
return -1;
}
len += section_length;
if ((section_length =
decode_context_enumerated(&apdu[len], 2, &operation)) == -1) {
return -1;
}
data->operation = (BACNET_LIFE_SAFETY_OPERATION) operation;
data->operation = (BACNET_LIFE_SAFETY_OPERATION)operation;
len += section_length;
/*
** This is an optional parameter, so dont fail if it doesnt exist
*/
if (decode_is_context_tag(&apdu[len], 3)) {
if ((section_length =
decode_context_object_id(&apdu[len], 3,
&data->targetObject.type,
&data->targetObject.instance)) == -1) {
if ((section_length = decode_context_object_id(
&apdu[len], 3, &data->targetObject.type,
&data->targetObject.instance)) == -1) {
return -1;
}
len += section_length;
@@ -128,7 +119,6 @@ int lso_decode_service_request(
data->targetObject.instance = 0;
}
return len;
}
return 0;
@@ -140,8 +130,7 @@ int lso_decode_service_request(
#include "ctest.h"
#include "bacapp.h"
void testLSO(
Test * pTest)
void testLSO(Test *pTest)
{
uint8_t apdu[1000];
int len;
@@ -151,7 +140,6 @@ void testLSO(
memset(&rxdata, 0, sizeof(rxdata));
characterstring_init_ansi(&data.requestingSrc, "foobar");
data.operation = LIFE_SAFETY_OP_RESET;
data.processId = 0x1234;
@@ -167,13 +155,11 @@ void testLSO(
ct_test(pTest, data.targetObject.instance == rxdata.targetObject.instance);
ct_test(pTest, data.targetObject.type == rxdata.targetObject.type);
ct_test(pTest, memcmp(data.requestingSrc.value, rxdata.requestingSrc.value,
rxdata.requestingSrc.length) == 0);
rxdata.requestingSrc.length) == 0);
}
#ifdef TEST_LSO
int main(
int argc,
char *argv[])
int main(int argc, char *argv[])
{
Test *pTest;
bool rc;
@@ -185,7 +171,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+89 -102
View File
@@ -1,87 +1,79 @@
/**
* @file
* @author Steve Karg
* @date 2008
* @section LICENSE
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to:
* The Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*
* As a special exception, if other files instantiate templates or
* use macros or inline functions from this file, or you compile
* this file and link it with other works to produce a work based
* on this file, this file does not by itself cause the resulting
* work to be covered by the GNU General Public License. However
* the source code for this file must still be made available in
* accordance with section (3) of the GNU General Public License.
*
* This exception does not invalidate any other reasons why a work
* based on this file might be covered by the GNU General Public
* License.
*
* @section DESCRIPTION
*
* Memory copy functions for deeply embedded system. The functions
* are used with a buffer, the buffer offset, the sizeof the buffer,
* and the number of bytes to copy to the buffer.
*/
* @file
* @author Steve Karg
* @date 2008
* @section LICENSE
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to:
* The Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*
* As a special exception, if other files instantiate templates or
* use macros or inline functions from this file, or you compile
* this file and link it with other works to produce a work based
* on this file, this file does not by itself cause the resulting
* work to be covered by the GNU General Public License. However
* the source code for this file must still be made available in
* accordance with section (3) of the GNU General Public License.
*
* This exception does not invalidate any other reasons why a work
* based on this file might be covered by the GNU General Public
* License.
*
* @section DESCRIPTION
*
* Memory copy functions for deeply embedded system. The functions
* are used with a buffer, the buffer offset, the sizeof the buffer,
* and the number of bytes to copy to the buffer.
*/
#include <stddef.h>
#include "memcopy.h"
#include <string.h>
/**
* Tests to see if the number of bytes is available from an offset
* given the maximum sizeof a buffer.
*
* @param offset - offset into a buffer
* @param max - maximum sizeof a buffer
* @param len - number of bytes to add to the buffer starting at offset.
*
* @return True if there is enough space to copy len bytes.
*/
bool memcopylen(
size_t offset,
size_t max,
size_t len)
* Tests to see if the number of bytes is available from an offset
* given the maximum sizeof a buffer.
*
* @param offset - offset into a buffer
* @param max - maximum sizeof a buffer
* @param len - number of bytes to add to the buffer starting at offset.
*
* @return True if there is enough space to copy len bytes.
*/
bool memcopylen(size_t offset, size_t max, size_t len)
{
return ((offset + len) <= max);
}
#if defined (MEMCOPY_SIMPLE)
#if defined(MEMCOPY_SIMPLE)
/**
* Copy len bytes from src to offset of dest if there is enough space
* in a buffer of max bytes.
*
* @param dest - pointer to the destination buffer
* @param src - pointer to the source buffer
* @param offset - offset into the destination buffer
* @param max - maximum sizeof the destination buffer
* @param len - number of bytes to add to the destination buffer
* starting at offset.
*
* @return returns zero if there is not enough space, or returns
* the number of bytes copied.
*/
size_t memcopy(
void *dest,
void *src,
size_t offset,
size_t len,
size_t max)
* Copy len bytes from src to offset of dest if there is enough space
* in a buffer of max bytes.
*
* @param dest - pointer to the destination buffer
* @param src - pointer to the source buffer
* @param offset - offset into the destination buffer
* @param max - maximum sizeof the destination buffer
* @param len - number of bytes to add to the destination buffer
* starting at offset.
*
* @return returns zero if there is not enough space, or returns
* the number of bytes copied.
*/
size_t memcopy(void *dest, void *src, size_t offset, size_t len, size_t max)
{
size_t i;
size_t copy_len = 0;
@@ -100,28 +92,26 @@ size_t memcopy(
}
#else
/**
* Copy len bytes from src to offset of dest if there is enough space
* in a buffer of max bytes.
*
* @param dest - pointer to the destination buffer
* @param src - pointer to the source buffer
* @param offset - offset into the destination buffer
* @param max - maximum sizeof the destination buffer
* @param len - number of bytes to add to the destination buffer
* starting at offset.
*
* @return returns zero if there is not enough space, or returns
* the number of bytes copied.
*/
size_t memcopy(
void *dest,
void *src,
size_t offset, /* where in dest to put the data */
size_t len, /* amount of data to copy */
size_t max)
{ /* total size of destination */
* Copy len bytes from src to offset of dest if there is enough space
* in a buffer of max bytes.
*
* @param dest - pointer to the destination buffer
* @param src - pointer to the source buffer
* @param offset - offset into the destination buffer
* @param max - maximum sizeof the destination buffer
* @param len - number of bytes to add to the destination buffer
* starting at offset.
*
* @return returns zero if there is not enough space, or returns
* the number of bytes copied.
*/
size_t memcopy(void *dest, void *src,
size_t offset, /* where in dest to put the data */
size_t len, /* amount of data to copy */
size_t max)
{ /* total size of destination */
if (memcopylen(offset, max, len)) {
memcpy(&((char *) dest)[offset], src, len);
memcpy(&((char *)dest)[offset], src, len);
return (len);
}
@@ -135,8 +125,7 @@ size_t memcopy(
#include "ctest.h"
void test_memcopy(
Test * pTest)
void test_memcopy(Test *pTest)
{
char *data1 = "Joshua";
char *data2 = "Anna";
@@ -149,15 +138,13 @@ void test_memcopy(
ct_test(pTest, memcmp(&buffer[0], &data1[0], len) == 0);
len = memcopy(&buffer[0], &data2[0], len, sizeof(data2), sizeof(buffer));
ct_test(pTest, len == sizeof(data2));
len =
memcopy(&buffer[0], &big_buffer[0], 1, sizeof(big_buffer),
sizeof(buffer));
len = memcopy(&buffer[0], &big_buffer[0], 1, sizeof(big_buffer),
sizeof(buffer));
ct_test(pTest, len == 0);
}
#ifdef TEST_MEM_COPY
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -170,7 +157,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
+323 -318
View File
File diff suppressed because it is too large Load Diff
+9 -14
View File
@@ -44,11 +44,9 @@ static INDTEXT_DATA mstp_receive_state_text[] = {
{MSTP_RECEIVE_STATE_PREAMBLE, "PREAMBLE"},
{MSTP_RECEIVE_STATE_HEADER, "HEADER"},
{MSTP_RECEIVE_STATE_DATA, "DATA"},
{0, NULL}
};
{0, NULL}};
const char *mstptext_receive_state(
unsigned index)
const char *mstptext_receive_state(unsigned index)
{
return indtext_by_index_default(mstp_receive_state_text, index, "unknown");
}
@@ -63,11 +61,9 @@ static INDTEXT_DATA mstp_master_state_text[] = {
{MSTP_MASTER_STATE_NO_TOKEN, "NO_TOKEN"},
{MSTP_MASTER_STATE_POLL_FOR_MASTER, "POLL_FOR_MASTER"},
{MSTP_MASTER_STATE_ANSWER_DATA_REQUEST, "ANSWER_DATA_REQUEST"},
{0, NULL}
};
{0, NULL}};
const char *mstptext_master_state(
unsigned index)
const char *mstptext_master_state(unsigned index)
{
return indtext_by_index_default(mstp_master_state_text, index, "unknown");
}
@@ -80,14 +76,13 @@ static INDTEXT_DATA mstp_frame_type_text[] = {
{FRAME_TYPE_TEST_RESPONSE, "TEST_RESPONSE"},
{FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY, "BACNET_DATA_EXPECTING_REPLY"},
{FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY,
"BACNET_DATA_NOT_EXPECTING_REPLY"},
"BACNET_DATA_NOT_EXPECTING_REPLY"},
{FRAME_TYPE_REPLY_POSTPONED, "REPLY_POSTPONED"},
{0, NULL}
};
{0, NULL}};
const char *mstptext_frame_type(
unsigned index)
const char *mstptext_frame_type(unsigned index)
{
return indtext_by_index_split_default(mstp_frame_type_text, index,
FRAME_TYPE_PROPRIETARY_MIN, "UNKNOWN", "PROPRIETARY");
FRAME_TYPE_PROPRIETARY_MIN, "UNKNOWN",
"PROPRIETARY");
}
+62 -75
View File
@@ -47,9 +47,7 @@
* @param dest [out] The 'to' structure
* @param src [in] The 'from' structure
*/
void npdu_copy_data(
BACNET_NPDU_DATA * dest,
BACNET_NPDU_DATA * src)
void npdu_copy_data(BACNET_NPDU_DATA *dest, BACNET_NPDU_DATA *src)
{
if (dest && src) {
dest->protocol_version = src->protocol_version;
@@ -102,7 +100,6 @@ ABORT.request Yes No Yes No
ABORT.indication Yes Yes Yes No
*/
/** Encode the NPDU portion of a message to be sent, based on the npdu_data
* and associated data.
* If this is to be a Network Layer Control Message, there are probably
@@ -110,9 +107,9 @@ ABORT.indication Yes Yes Yes No
* The Network Layer Protocol Control Information byte is described
* in section 6.2.2 of the BACnet standard.
* @param npdu [out] Buffer which will hold the encoded NPDU header bytes.
* The size isn't given, but it must be at least 2 bytes
* for the simplest case, and should always be at least 24
* bytes to accommodate the maximal case (all fields loaded).
* The size isn't given, but it must be at
* least 2 bytes for the simplest case, and should always be at least 24 bytes
* to accommodate the maximal case (all fields loaded).
* @param dest [in] The routing destination information if the message must
* be routed to reach its destination.
* If dest->net and dest->len are 0, there is no
@@ -129,15 +126,11 @@ ABORT.indication Yes Yes Yes No
* NPDU section.
* If 0 or negative, there were problems with the data or encoding.
*/
int npdu_encode_pdu(
uint8_t * npdu,
BACNET_ADDRESS * dest,
BACNET_ADDRESS * src,
BACNET_NPDU_DATA * npdu_data)
int npdu_encode_pdu(uint8_t *npdu, BACNET_ADDRESS *dest, BACNET_ADDRESS *src,
BACNET_NPDU_DATA *npdu_data)
{
int len = 0; /* return value - number of octets loaded in this function */
uint8_t i = 0; /* counter */
int len = 0; /* return value - number of octets loaded in this function */
uint8_t i = 0; /* counter */
if (npdu && npdu_data) {
/* protocol version */
@@ -194,7 +187,7 @@ int npdu_encode_pdu(
}
}
}
if (src && src->net && src->len) { /* Only insert if valid */
if (src && src->net && src->len) { /* Only insert if valid */
len += encode_unsigned16(&npdu[len], src->net);
npdu[len++] = src->len;
/* SLEN = 0 denotes broadcast MAC SADR and SADR field is absent */
@@ -264,22 +257,23 @@ is expected for the service being issued.
* @see npdu_encode_npdu_network if you need to set a network layer msg.
*
* @param npdu_data [out] Returns a filled-out structure with information
* provided by the other arguments and good defaults.
* provided by the other arguments and
* good defaults.
* @param data_expecting_reply [in] True if message should have a reply.
* @param priority [in] One of the 4 priorities defined in section 6.2.2,
* like B'11' = Life Safety message
*/
void npdu_encode_npdu_data(
BACNET_NPDU_DATA * npdu_data,
bool data_expecting_reply,
BACNET_MESSAGE_PRIORITY priority)
void npdu_encode_npdu_data(BACNET_NPDU_DATA *npdu_data,
bool data_expecting_reply,
BACNET_MESSAGE_PRIORITY priority)
{
if (npdu_data) {
npdu_data->data_expecting_reply = data_expecting_reply;
npdu_data->protocol_version = BACNET_PROTOCOL_VERSION;
npdu_data->network_layer_message = false; /* false if APDU */
npdu_data->network_message_type = NETWORK_MESSAGE_INVALID; /* optional */
npdu_data->vendor_id = 0; /* optional, if net message type is > 0x80 */
npdu_data->network_layer_message = false; /* false if APDU */
npdu_data->network_message_type =
NETWORK_MESSAGE_INVALID; /* optional */
npdu_data->vendor_id = 0; /* optional, if net message type is > 0x80 */
npdu_data->priority = priority;
npdu_data->hop_count = HOP_COUNT_DEFAULT;
}
@@ -288,7 +282,8 @@ void npdu_encode_npdu_data(
/** Decode the NPDU portion of a received message, particularly the NCPI byte.
* The Network Layer Protocol Control Information byte is described
* in section 6.2.2 of the BACnet standard.
* @param npdu [in] Buffer holding the received NPDU header bytes (must be at least 2)
* @param npdu [in] Buffer holding the received NPDU header bytes (must be at
* least 2)
* @param dest [out] Returned with routing destination information if the NPDU
* has any and if this points to non-null storage for it.
* If dest->net and dest->len are 0 on return, there is no
@@ -300,20 +295,18 @@ void npdu_encode_npdu_data(
* This src describes the original source of the message when
* it had to be routed to reach this BACnet Device.
* @param npdu_data [out] Returns a filled-out structure with information
* decoded from the NCPI and other NPDU bytes.
* decoded from the NCPI and other NPDU
* bytes.
* @return On success, returns the number of bytes which were decoded from the
* NPDU section; if this is a network layer message, there may be more
* bytes left in the NPDU; if not a network msg, the APDU follows.
* If 0 or negative, there were problems with the data or arguments.
* NPDU section; if this is a network layer message, there may
* be more bytes left in the NPDU; if not a network msg, the APDU follows. If 0
* or negative, there were problems with the data or arguments.
*/
int npdu_decode(
uint8_t * npdu,
BACNET_ADDRESS * dest,
BACNET_ADDRESS * src,
BACNET_NPDU_DATA * npdu_data)
int npdu_decode(uint8_t *npdu, BACNET_ADDRESS *dest, BACNET_ADDRESS *src,
BACNET_NPDU_DATA *npdu_data)
{
int len = 0; /* return value - number of octets loaded in this function */
uint8_t i = 0; /* counter */
int len = 0; /* return value - number of octets loaded in this function */
uint8_t i = 0; /* counter */
uint16_t src_net = 0;
uint16_t dest_net = 0;
uint8_t slen = 0;
@@ -345,7 +338,7 @@ int npdu_decode(
/* B'10' = Critical Equipment message */
/* B'01' = Urgent message */
/* B'00' = Normal message */
npdu_data->priority = (BACNET_MESSAGE_PRIORITY) (npdu[1] & 0x03);
npdu_data->priority = (BACNET_MESSAGE_PRIORITY)(npdu[1] & 0x03);
/* set the offset to where the optional stuff starts */
len = 2;
/*Bit 5: Destination specifier where: */
@@ -431,7 +424,7 @@ int npdu_decode(
/* Message Type field is present. */
if (npdu_data->network_layer_message) {
npdu_data->network_message_type =
(BACNET_NETWORK_MESSAGE_TYPE) npdu[len++];
(BACNET_NETWORK_MESSAGE_TYPE)npdu[len++];
/* Message Type field contains a value in the range 0x80 - 0xFF, */
/* then a Vendor ID field shall be present */
if (npdu_data->network_message_type >= 0x80)
@@ -451,23 +444,22 @@ int npdu_decode(
#include <string.h>
#include "ctest.h"
void testNPDU2(
Test * pTest)
void testNPDU2(Test *pTest)
{
uint8_t pdu[480] = { 0 };
BACNET_ADDRESS dest = { 0 };
BACNET_ADDRESS src = { 0 };
BACNET_ADDRESS npdu_dest = { 0 };
BACNET_ADDRESS npdu_src = { 0 };
uint8_t pdu[480] = {0};
BACNET_ADDRESS dest = {0};
BACNET_ADDRESS src = {0};
BACNET_ADDRESS npdu_dest = {0};
BACNET_ADDRESS npdu_src = {0};
int len = 0;
bool data_expecting_reply = true;
BACNET_MESSAGE_PRIORITY priority = MESSAGE_PRIORITY_NORMAL;
BACNET_NPDU_DATA npdu_data = { 0 };
int i = 0; /* counter */
BACNET_NPDU_DATA npdu_data = {0};
int i = 0; /* counter */
int npdu_len = 0;
bool network_layer_message = false; /* false if APDU */
BACNET_NETWORK_MESSAGE_TYPE network_message_type = 0; /* optional */
uint16_t vendor_id = 0; /* optional, if net message type is > 0x80 */
bool network_layer_message = false; /* false if APDU */
BACNET_NETWORK_MESSAGE_TYPE network_message_type = 0; /* optional */
uint16_t vendor_id = 0; /* optional, if net message type is > 0x80 */
dest.mac_len = 6;
for (i = 0; i < dest.mac_len; i++) {
@@ -516,23 +508,22 @@ void testNPDU2(
}
}
void testNPDU1(
Test * pTest)
void testNPDU1(Test *pTest)
{
uint8_t pdu[480] = { 0 };
BACNET_ADDRESS dest = { 0 };
BACNET_ADDRESS src = { 0 };
BACNET_ADDRESS npdu_dest = { 0 };
BACNET_ADDRESS npdu_src = { 0 };
uint8_t pdu[480] = {0};
BACNET_ADDRESS dest = {0};
BACNET_ADDRESS src = {0};
BACNET_ADDRESS npdu_dest = {0};
BACNET_ADDRESS npdu_src = {0};
int len = 0;
bool data_expecting_reply = false;
BACNET_MESSAGE_PRIORITY priority = MESSAGE_PRIORITY_NORMAL;
BACNET_NPDU_DATA npdu_data = { 0 };
int i = 0; /* counter */
BACNET_NPDU_DATA npdu_data = {0};
int i = 0; /* counter */
int npdu_len = 0;
bool network_layer_message = false; /* false if APDU */
BACNET_NETWORK_MESSAGE_TYPE network_message_type = 0; /* optional */
uint16_t vendor_id = 0; /* optional, if net message type is > 0x80 */
bool network_layer_message = false; /* false if APDU */
BACNET_NETWORK_MESSAGE_TYPE network_message_type = 0; /* optional */
uint16_t vendor_id = 0; /* optional, if net message type is > 0x80 */
/* mac_len = 0 if global address */
dest.mac_len = 0;
@@ -574,24 +565,20 @@ void testNPDU1(
#ifdef TEST_NPDU
/* dummy stub for testing */
void tsm_free_invoke_id(
uint8_t invokeID)
void tsm_free_invoke_id(uint8_t invokeID)
{
(void) invokeID;
(void)invokeID;
}
void iam_handler(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src)
void iam_handler(uint8_t *service_request, uint16_t service_len,
BACNET_ADDRESS *src)
{
(void) service_request;
(void) service_len;
(void) src;
(void)service_request;
(void)service_len;
(void)src;
}
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -605,7 +592,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+222 -403
View File
@@ -49,11 +49,7 @@
/* note: the PROP_PROPERTY_LIST is NOT included in these lists, on purpose */
static const int Default_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
-1
};
PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE, -1};
static const int Device_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
@@ -76,8 +72,7 @@ static const int Device_Properties_Required[] = {
PROP_NUMBER_OF_APDU_RETRIES,
PROP_DEVICE_ADDRESS_BINDING,
PROP_DATABASE_REVISION,
-1
};
-1};
static const int Device_Properties_Optional[] = {
PROP_LOCATION,
@@ -114,22 +109,19 @@ static const int Device_Properties_Optional[] = {
PROP_ALIGN_INTERVALS,
PROP_INTERVAL_OFFSET,
PROP_PROFILE_NAME,
-1
};
-1};
static const int Accumulator_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_SCALE,
PROP_UNITS,
PROP_MAX_PRES_VALUE,
-1
};
static const int Accumulator_Properties_Required[] = {PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_SCALE,
PROP_UNITS,
PROP_MAX_PRES_VALUE,
-1};
static const int Accumulator_Properties_Optional[] = {
PROP_DESCRIPTION,
@@ -155,20 +147,12 @@ static const int Accumulator_Properties_Optional[] = {
PROP_EVENT_MESSAGE_TEXTS,
PROP_RELIABILITY_EVALUATION_INHIBIT,
PROP_PROFILE_NAME,
-1
};
-1};
static const int Analog_Input_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_UNITS,
-1
};
PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE, PROP_STATUS_FLAGS, PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE, PROP_UNITS, -1};
static const int Analog_Input_Properties_Optional[] = {
PROP_DESCRIPTION,
@@ -192,22 +176,19 @@ static const int Analog_Input_Properties_Optional[] = {
PROP_EVENT_MESSAGE_TEXTS,
PROP_RELIABILITY_EVALUATION_INHIBIT,
PROP_PROFILE_NAME,
-1
};
-1};
static const int Analog_Output_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_UNITS,
PROP_PRIORITY_ARRAY,
PROP_RELINQUISH_DEFAULT,
-1
};
static const int Analog_Output_Properties_Required[] = {PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_UNITS,
PROP_PRIORITY_ARRAY,
PROP_RELINQUISH_DEFAULT,
-1};
static const int Analog_Output_Properties_Optional[] = {
PROP_DESCRIPTION,
@@ -230,20 +211,12 @@ static const int Analog_Output_Properties_Optional[] = {
PROP_EVENT_MESSAGE_TEXTS,
PROP_RELIABILITY_EVALUATION_INHIBIT,
PROP_PROFILE_NAME,
-1
};
-1};
static const int Analog_Value_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_UNITS,
-1
};
PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE, PROP_STATUS_FLAGS, PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE, PROP_UNITS, -1};
static const int Analog_Value_Properties_Optional[] = {
PROP_DESCRIPTION,
@@ -264,22 +237,19 @@ static const int Analog_Value_Properties_Optional[] = {
PROP_EVENT_MESSAGE_TEXTS,
PROP_RELIABILITY_EVALUATION_INHIBIT,
PROP_PROFILE_NAME,
-1
};
-1};
static const int Averaging_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_MINIMUM_VALUE,
PROP_AVERAGE_VALUE,
PROP_MAXIMUM_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_UNITS,
-1
};
static const int Averaging_Properties_Required[] = {PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_MINIMUM_VALUE,
PROP_AVERAGE_VALUE,
PROP_MAXIMUM_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_UNITS,
-1};
static const int Averaging_Properties_Optional[] = {
PROP_PROFILE_NAME,
@@ -292,20 +262,12 @@ static const int Averaging_Properties_Optional[] = {
PROP_OBJECT_PROPERTY_REFERENCE,
PROP_WINDOW_INTERVAL,
PROP_WINDOW_SAMPLES,
-1
};
-1};
static const int Binary_Input_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_POLARITY,
-1
};
PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE, PROP_STATUS_FLAGS, PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE, PROP_POLARITY, -1};
static const int Binary_Input_Properties_Optional[] = {
PROP_DESCRIPTION,
@@ -328,22 +290,19 @@ static const int Binary_Input_Properties_Optional[] = {
PROP_EVENT_MESSAGE_TEXTS,
PROP_RELIABILITY_EVALUATION_INHIBIT,
PROP_PROFILE_NAME,
-1
};
-1};
static const int Binary_Output_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_POLARITY,
PROP_PRIORITY_ARRAY,
PROP_RELINQUISH_DEFAULT,
-1
};
static const int Binary_Output_Properties_Required[] = {PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_POLARITY,
PROP_PRIORITY_ARRAY,
PROP_RELINQUISH_DEFAULT,
-1};
static const int Binary_Output_Properties_Optional[] = {
PROP_DESCRIPTION,
@@ -368,19 +327,13 @@ static const int Binary_Output_Properties_Optional[] = {
PROP_EVENT_MESSAGE_TEXTS,
PROP_RELIABILITY_EVALUATION_INHIBIT,
PROP_PROFILE_NAME,
-1
};
-1};
static const int Binary_Value_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
-1
};
PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME,
PROP_OBJECT_TYPE, PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS, PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE, -1};
static const int Binary_Value_Properties_Optional[] = {
PROP_DESCRIPTION,
@@ -406,23 +359,14 @@ static const int Binary_Value_Properties_Optional[] = {
PROP_EVENT_MESSAGE_TEXTS,
PROP_RELIABILITY_EVALUATION_INHIBIT,
PROP_PROFILE_NAME,
-1
};
-1};
static const int Calendar_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_DATE_LIST,
-1
};
PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE, PROP_DATE_LIST, -1};
static const int Calendar_Properties_Optional[] = {
PROP_DESCRIPTION,
PROP_PROFILE_NAME,
-1
};
static const int Calendar_Properties_Optional[] = {PROP_DESCRIPTION,
PROP_PROFILE_NAME, -1};
static const int Channel_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
@@ -436,8 +380,7 @@ static const int Channel_Properties_Required[] = {
PROP_LIST_OF_OBJECT_PROPERTY_REFERENCES,
PROP_CHANNEL_NUMBER,
PROP_CONTROL_GROUPS,
-1
};
-1};
static const int Channel_Properties_Optional[] = {
PROP_DESCRIPTION,
@@ -455,56 +398,34 @@ static const int Channel_Properties_Optional[] = {
PROP_EVENT_MESSAGE_TEXTS_CONFIG,
PROP_RELIABILITY_EVALUATION_INHIBIT,
PROP_PROFILE_NAME,
-1
};
-1};
static const int Command_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_IN_PROCESS,
PROP_ALL_WRITES_SUCCESSFUL,
PROP_ACTION,
-1
};
static const int Command_Properties_Required[] = {PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_IN_PROCESS,
PROP_ALL_WRITES_SUCCESSFUL,
PROP_ACTION,
-1};
static const int Command_Properties_Optional[] = {
PROP_DESCRIPTION,
PROP_ACTION_TEXT,
PROP_PROFILE_NAME,
-1
};
PROP_DESCRIPTION, PROP_ACTION_TEXT, PROP_PROFILE_NAME, -1};
static const int CharacterString_Value_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
-1
};
PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE, PROP_STATUS_FLAGS, -1};
static const int CharacterString_Value_Properties_Optional[] = {
PROP_DESCRIPTION,
PROP_EVENT_STATE,
PROP_RELIABILITY,
PROP_OUT_OF_SERVICE,
PROP_PRIORITY_ARRAY,
PROP_RELINQUISH_DEFAULT,
PROP_TIME_DELAY,
PROP_NOTIFICATION_CLASS,
PROP_ALARM_VALUES,
PROP_FAULT_VALUES,
PROP_EVENT_ENABLE,
PROP_ACKED_TRANSITIONS,
PROP_NOTIFY_TYPE,
PROP_EVENT_TIME_STAMPS,
PROP_EVENT_MESSAGE_TEXTS,
PROP_RELIABILITY_EVALUATION_INHIBIT,
PROP_PROFILE_NAME,
-1
};
PROP_DESCRIPTION, PROP_EVENT_STATE,
PROP_RELIABILITY, PROP_OUT_OF_SERVICE,
PROP_PRIORITY_ARRAY, PROP_RELINQUISH_DEFAULT,
PROP_TIME_DELAY, PROP_NOTIFICATION_CLASS,
PROP_ALARM_VALUES, PROP_FAULT_VALUES,
PROP_EVENT_ENABLE, PROP_ACKED_TRANSITIONS,
PROP_NOTIFY_TYPE, PROP_EVENT_TIME_STAMPS,
PROP_EVENT_MESSAGE_TEXTS, PROP_RELIABILITY_EVALUATION_INHIBIT,
PROP_PROFILE_NAME, -1};
static const int Lighting_Output_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
@@ -525,8 +446,7 @@ static const int Lighting_Output_Properties_Required[] = {
PROP_PRIORITY_ARRAY,
PROP_RELINQUISH_DEFAULT,
PROP_LIGHTING_COMMAND_DEFAULT_PRIORITY,
-1
};
-1};
static const int Lighting_Output_Properties_Optional[] = {
PROP_DESCRIPTION,
@@ -540,8 +460,7 @@ static const int Lighting_Output_Properties_Optional[] = {
PROP_COV_INCREMENT,
PROP_RELIABILITY_EVALUATION_INHIBIT,
PROP_PROFILE_NAME,
-1
};
-1};
static const int Load_Control_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
@@ -559,42 +478,25 @@ static const int Load_Control_Properties_Required[] = {
PROP_ACTUAL_SHED_LEVEL,
PROP_SHED_LEVELS,
PROP_SHED_LEVEL_DESCRIPTIONS,
-1
};
-1};
static const int Load_Control_Properties_Optional[] = {
PROP_DESCRIPTION,
PROP_STATE_DESCRIPTION,
PROP_RELIABILITY,
PROP_FULL_DUTY_BASELINE,
PROP_NOTIFICATION_CLASS,
PROP_TIME_DELAY,
PROP_EVENT_ENABLE,
PROP_ACKED_TRANSITIONS,
PROP_NOTIFY_TYPE,
PROP_EVENT_TIME_STAMPS,
PROP_EVENT_MESSAGE_TEXTS,
PROP_RELIABILITY_EVALUATION_INHIBIT,
PROP_PROFILE_NAME,
-1
};
PROP_DESCRIPTION, PROP_STATE_DESCRIPTION,
PROP_RELIABILITY, PROP_FULL_DUTY_BASELINE,
PROP_NOTIFICATION_CLASS, PROP_TIME_DELAY,
PROP_EVENT_ENABLE, PROP_ACKED_TRANSITIONS,
PROP_NOTIFY_TYPE, PROP_EVENT_TIME_STAMPS,
PROP_EVENT_MESSAGE_TEXTS, PROP_RELIABILITY_EVALUATION_INHIBIT,
PROP_PROFILE_NAME, -1};
static const int Life_Safety_Point_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_TRACKING_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_RELIABILITY,
PROP_MODE,
PROP_ACCEPTED_MODES,
PROP_SILENCED,
PROP_OPERATION_EXPECTED,
-1
};
PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME,
PROP_OBJECT_TYPE, PROP_PRESENT_VALUE,
PROP_TRACKING_VALUE, PROP_STATUS_FLAGS,
PROP_EVENT_STATE, PROP_OUT_OF_SERVICE,
PROP_RELIABILITY, PROP_MODE,
PROP_ACCEPTED_MODES, PROP_SILENCED,
PROP_OPERATION_EXPECTED, -1};
static const int Life_Safety_Point_Properties_Optional[] = {
PROP_DESCRIPTION,
@@ -615,39 +517,22 @@ static const int Life_Safety_Point_Properties_Optional[] = {
PROP_MEMBER_OF,
PROP_RELIABILITY_EVALUATION_INHIBIT,
PROP_PROFILE_NAME,
-1
};
-1};
static const int Multistate_Input_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_NUMBER_OF_STATES,
-1
};
PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE, PROP_STATUS_FLAGS, PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE, PROP_NUMBER_OF_STATES, -1};
static const int Multistate_Input_Properties_Optional[] = {
PROP_DESCRIPTION,
PROP_DEVICE_TYPE,
PROP_RELIABILITY,
PROP_STATE_TEXT,
PROP_TIME_DELAY,
PROP_NOTIFICATION_CLASS,
PROP_ALARM_VALUES,
PROP_FAULT_VALUES,
PROP_EVENT_ENABLE,
PROP_ACKED_TRANSITIONS,
PROP_NOTIFY_TYPE,
PROP_EVENT_TIME_STAMPS,
PROP_EVENT_MESSAGE_TEXTS,
PROP_RELIABILITY_EVALUATION_INHIBIT,
PROP_PROFILE_NAME,
-1
};
PROP_DESCRIPTION, PROP_DEVICE_TYPE,
PROP_RELIABILITY, PROP_STATE_TEXT,
PROP_TIME_DELAY, PROP_NOTIFICATION_CLASS,
PROP_ALARM_VALUES, PROP_FAULT_VALUES,
PROP_EVENT_ENABLE, PROP_ACKED_TRANSITIONS,
PROP_NOTIFY_TYPE, PROP_EVENT_TIME_STAMPS,
PROP_EVENT_MESSAGE_TEXTS, PROP_RELIABILITY_EVALUATION_INHIBIT,
PROP_PROFILE_NAME, -1};
static const int Multistate_Output_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
@@ -660,8 +545,7 @@ static const int Multistate_Output_Properties_Required[] = {
PROP_NUMBER_OF_STATES,
PROP_PRIORITY_ARRAY,
PROP_RELINQUISH_DEFAULT,
-1
};
-1};
static const int Multistate_Output_Properties_Optional[] = {
PROP_DESCRIPTION,
@@ -678,20 +562,12 @@ static const int Multistate_Output_Properties_Optional[] = {
PROP_EVENT_MESSAGE_TEXTS,
PROP_RELIABILITY_EVALUATION_INHIBIT,
PROP_PROFILE_NAME,
-1
};
-1};
static const int Multistate_Value_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_NUMBER_OF_STATES,
-1
};
PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE, PROP_STATUS_FLAGS, PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE, PROP_NUMBER_OF_STATES, -1};
static const int Multistate_Value_Properties_Optional[] = {
PROP_DESCRIPTION,
@@ -710,41 +586,30 @@ static const int Multistate_Value_Properties_Optional[] = {
PROP_EVENT_MESSAGE_TEXTS,
PROP_RELIABILITY_EVALUATION_INHIBIT,
PROP_PROFILE_NAME,
-1
};
-1};
static const int Notification_Class_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_NOTIFICATION_CLASS,
PROP_PRIORITY,
PROP_ACK_REQUIRED,
PROP_RECIPIENT_LIST,
-1
};
PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME,
PROP_OBJECT_TYPE, PROP_NOTIFICATION_CLASS,
PROP_PRIORITY, PROP_ACK_REQUIRED,
PROP_RECIPIENT_LIST, -1};
static const int Notification_Class_Properties_Optional[] = {
PROP_DESCRIPTION,
PROP_PROFILE_NAME,
-1
};
PROP_DESCRIPTION, PROP_PROFILE_NAME, -1};
static const int Trend_Log_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_ENABLE,
PROP_STOP_WHEN_FULL,
PROP_BUFFER_SIZE,
PROP_LOG_BUFFER,
PROP_RECORD_COUNT,
PROP_TOTAL_RECORD_COUNT,
PROP_EVENT_STATE,
PROP_LOGGING_TYPE,
PROP_STATUS_FLAGS,
-1
};
static const int Trend_Log_Properties_Required[] = {PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_ENABLE,
PROP_STOP_WHEN_FULL,
PROP_BUFFER_SIZE,
PROP_LOG_BUFFER,
PROP_RECORD_COUNT,
PROP_TOTAL_RECORD_COUNT,
PROP_EVENT_STATE,
PROP_LOGGING_TYPE,
PROP_STATUS_FLAGS,
-1};
static const int Trend_Log_Properties_Optional[] = {
PROP_DESCRIPTION,
@@ -769,39 +634,30 @@ static const int Trend_Log_Properties_Optional[] = {
PROP_RELIABILITY,
PROP_RELIABILITY_EVALUATION_INHIBIT,
PROP_PROFILE_NAME,
-1
};
-1};
static const int File_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_FILE_TYPE,
PROP_FILE_SIZE,
PROP_MODIFICATION_DATE,
PROP_ARCHIVE,
PROP_READ_ONLY,
PROP_FILE_ACCESS_METHOD,
-1
};
static const int File_Properties_Required[] = {PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_FILE_TYPE,
PROP_FILE_SIZE,
PROP_MODIFICATION_DATE,
PROP_ARCHIVE,
PROP_READ_ONLY,
PROP_FILE_ACCESS_METHOD,
-1};
static const int File_Properties_Optional[] = {
PROP_DESCRIPTION,
PROP_RECORD_COUNT,
PROP_PROFILE_NAME,
-1
};
PROP_DESCRIPTION, PROP_RECORD_COUNT, PROP_PROFILE_NAME, -1};
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Integer_Value_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_UNITS,
-1
};
static const int Integer_Value_Properties_Required[] = {PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_UNITS,
-1};
static const int Integer_Value_Properties_Optional[] = {
PROP_DESCRIPTION,
@@ -832,8 +688,7 @@ static const int Integer_Value_Properties_Optional[] = {
PROP_MAX_PRES_VALUE,
PROP_RESOLUTION,
PROP_PROFILE_NAME,
-1
};
-1};
/**
* Function that returns the list of all Optional properties
@@ -844,10 +699,9 @@ static const int Integer_Value_Properties_Optional[] = {
* type 'int' that contain BACnet object properties for the given object
* type.
*/
const int * property_list_optional(
BACNET_OBJECT_TYPE object_type)
const int *property_list_optional(BACNET_OBJECT_TYPE object_type)
{
const int * pList = NULL;
const int *pList = NULL;
switch (object_type) {
case OBJECT_DEVICE:
@@ -887,8 +741,7 @@ const int * property_list_optional(
pList = Command_Properties_Optional;
break;
case OBJECT_CHARACTERSTRING_VALUE:
pList =
CharacterString_Value_Properties_Optional;
pList = CharacterString_Value_Properties_Optional;
break;
case OBJECT_LIGHTING_OUTPUT:
pList = Lighting_Output_Properties_Optional;
@@ -897,24 +750,19 @@ const int * property_list_optional(
pList = Load_Control_Properties_Optional;
break;
case OBJECT_LIFE_SAFETY_POINT:
pList =
Life_Safety_Point_Properties_Optional;
pList = Life_Safety_Point_Properties_Optional;
break;
case OBJECT_MULTI_STATE_INPUT:
pList =
Multistate_Input_Properties_Optional;
pList = Multistate_Input_Properties_Optional;
break;
case OBJECT_MULTI_STATE_OUTPUT:
pList =
Multistate_Output_Properties_Optional;
pList = Multistate_Output_Properties_Optional;
break;
case OBJECT_MULTI_STATE_VALUE:
pList =
Multistate_Value_Properties_Optional;
pList = Multistate_Value_Properties_Optional;
break;
case OBJECT_NOTIFICATION_CLASS:
pList =
Notification_Class_Properties_Optional;
pList = Notification_Class_Properties_Optional;
break;
case OBJECT_TRENDLOG:
pList = Trend_Log_Properties_Optional;
@@ -941,10 +789,9 @@ const int * property_list_optional(
* type 'int' that contain BACnet object properties for the given object
* type.
*/
const int * property_list_required(
BACNET_OBJECT_TYPE object_type)
const int *property_list_required(BACNET_OBJECT_TYPE object_type)
{
const int * pList = NULL;
const int *pList = NULL;
switch (object_type) {
case OBJECT_DEVICE:
@@ -984,8 +831,7 @@ const int * property_list_required(
pList = Command_Properties_Required;
break;
case OBJECT_CHARACTERSTRING_VALUE:
pList =
CharacterString_Value_Properties_Required;
pList = CharacterString_Value_Properties_Required;
break;
case OBJECT_LOAD_CONTROL:
pList = Load_Control_Properties_Required;
@@ -994,24 +840,19 @@ const int * property_list_required(
pList = Lighting_Output_Properties_Required;
break;
case OBJECT_LIFE_SAFETY_POINT:
pList =
Life_Safety_Point_Properties_Required;
pList = Life_Safety_Point_Properties_Required;
break;
case OBJECT_MULTI_STATE_INPUT:
pList =
Multistate_Input_Properties_Required;
pList = Multistate_Input_Properties_Required;
break;
case OBJECT_MULTI_STATE_OUTPUT:
pList =
Multistate_Output_Properties_Required;
pList = Multistate_Output_Properties_Required;
break;
case OBJECT_MULTI_STATE_VALUE:
pList =
Multistate_Value_Properties_Required;
pList = Multistate_Value_Properties_Required;
break;
case OBJECT_NOTIFICATION_CLASS:
pList =
Notification_Class_Properties_Required;
pList = Notification_Class_Properties_Required;
break;
case OBJECT_TRENDLOG:
pList = Trend_Log_Properties_Required;
@@ -1039,9 +880,8 @@ const int * property_list_required(
* type 'int' that contain BACnet object properties for the given object
* type.
*/
void property_list_special(
BACNET_OBJECT_TYPE object_type,
struct special_property_list_t *pPropertyList)
void property_list_special(BACNET_OBJECT_TYPE object_type,
struct special_property_list_t *pPropertyList)
{
if (pPropertyList == NULL) {
return;
@@ -1060,13 +900,12 @@ void property_list_special(
}
BACNET_PROPERTY_ID property_list_special_property(
BACNET_OBJECT_TYPE object_type,
BACNET_PROPERTY_ID special_property,
BACNET_OBJECT_TYPE object_type, BACNET_PROPERTY_ID special_property,
unsigned index)
{
int property = -1; /* return value */
int property = -1; /* return value */
unsigned required, optional, proprietary;
struct special_property_list_t PropertyList = { {0} };
struct special_property_list_t PropertyList = {{0}};
property_list_special(object_type, &PropertyList);
required = PropertyList.Required.count;
@@ -1102,21 +941,19 @@ BACNET_PROPERTY_ID property_list_special_property(
}
}
return (BACNET_PROPERTY_ID) property;
return (BACNET_PROPERTY_ID)property;
}
unsigned property_list_special_count(
BACNET_OBJECT_TYPE object_type,
BACNET_PROPERTY_ID special_property)
unsigned property_list_special_count(BACNET_OBJECT_TYPE object_type,
BACNET_PROPERTY_ID special_property)
{
unsigned count = 0; /* return value */
struct special_property_list_t PropertyList = { {0} };
struct special_property_list_t PropertyList = {{0}};
property_list_special(object_type, &PropertyList);
if (special_property == PROP_ALL) {
count =
PropertyList.Required.count + PropertyList.Optional.count +
PropertyList.Proprietary.count;
count = PropertyList.Required.count + PropertyList.Optional.count +
PropertyList.Proprietary.count;
} else if (special_property == PROP_REQUIRED) {
count = PropertyList.Required.count;
} else if (special_property == PROP_OPTIONAL) {
@@ -1133,8 +970,7 @@ unsigned property_list_special_count(
* @param pList - array of type 'int' that is a list of BACnet object
* properties, terminated by a '-1' value.
*/
unsigned property_list_count(
const int *pList)
unsigned property_list_count(const int *pList)
{
unsigned property_count = 0;
@@ -1156,9 +992,7 @@ unsigned property_list_count(
*
* @return true if object_property is a member of the property list
*/
bool property_list_member(
const int *pList,
int object_property)
bool property_list_member(const int *pList, int object_property)
{
bool status = false;
@@ -1185,13 +1019,11 @@ bool property_list_member(
* @return number of APDU bytes in the response, or
* BACNET_STATUS_ERROR on error.
*/
int property_list_encode(
BACNET_READ_PROPERTY_DATA * rpdata,
const int *pListRequired,
const int *pListOptional,
const int *pListProprietary)
int property_list_encode(BACNET_READ_PROPERTY_DATA *rpdata,
const int *pListRequired, const int *pListOptional,
const int *pListProprietary)
{
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
uint8_t *apdu = NULL;
int max_apdu_len = 0;
uint32_t count = 0;
@@ -1220,10 +1052,10 @@ int property_list_encode(
case PROP_PROPERTY_LIST:
if (rpdata->array_index == 0) {
/* Array element zero is the number of elements in the array */
apdu_len =
encode_application_unsigned(&apdu[0], count);
apdu_len = encode_application_unsigned(&apdu[0], count);
} else if (rpdata->array_index == BACNET_ARRAY_ALL) {
/* if no index was specified, then try to encode the entire list */
/* if no index was specified, then try to encode the entire list
*/
/* into one packet. */
if (required_count > 3) {
for (i = 0; i < required_count; i++) {
@@ -1232,9 +1064,8 @@ int property_list_encode(
(pListRequired[i] == PROP_OBJECT_NAME)) {
continue;
} else {
len =
encode_application_enumerated(&apdu[apdu_len],
(uint32_t)pListRequired[i]);
len = encode_application_enumerated(
&apdu[apdu_len], (uint32_t)pListRequired[i]);
}
/* add it if we have room */
if ((apdu_len + len) < max_apdu_len) {
@@ -1249,9 +1080,8 @@ int property_list_encode(
}
if (optional_count) {
for (i = 0; i < optional_count; i++) {
len =
encode_application_enumerated(&apdu[apdu_len],
(uint32_t)pListOptional[i]);
len = encode_application_enumerated(
&apdu[apdu_len], (uint32_t)pListOptional[i]);
/* add it if we have room */
if ((apdu_len + len) < max_apdu_len) {
apdu_len += len;
@@ -1265,9 +1095,8 @@ int property_list_encode(
}
if (proprietary_count) {
for (i = 0; i < proprietary_count; i++) {
len =
encode_application_enumerated(&apdu[apdu_len],
(uint32_t)pListProprietary[i]);
len = encode_application_enumerated(
&apdu[apdu_len], (uint32_t)pListProprietary[i]);
/* add it if we have room */
if ((apdu_len + len) < max_apdu_len) {
apdu_len += len;
@@ -1343,8 +1172,7 @@ int property_list_encode(
#include <string.h>
#include "ctest.h"
void testPropList(
Test * pTest)
void testPropList(Test *pTest)
{
unsigned i = 0, j = 0;
unsigned count = 0;
@@ -1352,17 +1180,15 @@ void testPropList(
unsigned object_id = 0, object_name = 0, object_type = 0;
struct special_property_list_t property_list = {0};
for (i = 0; i < OBJECT_PROPRIETARY_MIN; i++) {
count = property_list_special_count((BACNET_OBJECT_TYPE) i, PROP_ALL);
count = property_list_special_count((BACNET_OBJECT_TYPE)i, PROP_ALL);
ct_test(pTest, count >= 3);
object_id = 0;
object_name = 0;
object_type = 0;
for (j = 0; j < count; j++) {
property =
property_list_special_property((BACNET_OBJECT_TYPE) i,
PROP_ALL, j);
property = property_list_special_property((BACNET_OBJECT_TYPE)i,
PROP_ALL, j);
if (property == PROP_OBJECT_TYPE) {
object_type++;
}
@@ -1377,25 +1203,18 @@ void testPropList(
ct_test(pTest, object_id == 1);
ct_test(pTest, object_name == 1);
/* test member function */
property_list_special((BACNET_OBJECT_TYPE) i, &property_list);
ct_test(pTest,
property_list_member(
property_list.Required.pList,
PROP_OBJECT_TYPE));
ct_test(pTest,
property_list_member(
property_list.Required.pList,
PROP_OBJECT_IDENTIFIER));
ct_test(pTest,
property_list_member(
property_list.Required.pList,
PROP_OBJECT_NAME));
property_list_special((BACNET_OBJECT_TYPE)i, &property_list);
ct_test(pTest, property_list_member(property_list.Required.pList,
PROP_OBJECT_TYPE));
ct_test(pTest, property_list_member(property_list.Required.pList,
PROP_OBJECT_IDENTIFIER));
ct_test(pTest, property_list_member(property_list.Required.pList,
PROP_OBJECT_NAME));
}
}
#ifdef TEST_PROPLIST
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -1407,7 +1226,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+151 -197
View File
@@ -40,30 +40,26 @@
/** @file ptransfer.c Encode/Decode Private Transfer data */
/* encode service */
static int pt_encode_apdu(
uint8_t * apdu,
uint16_t max_apdu,
BACNET_PRIVATE_TRANSFER_DATA * private_data)
static int pt_encode_apdu(uint8_t *apdu, uint16_t max_apdu,
BACNET_PRIVATE_TRANSFER_DATA *private_data)
{
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
/*
Unconfirmed/ConfirmedPrivateTransfer-Request ::= SEQUENCE {
vendorID [0] Unsigned,
serviceNumber [1] Unsigned,
serviceParameters [2] ABSTRACT-SYNTAX.&Type OPTIONAL
}
*/
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
/*
Unconfirmed/ConfirmedPrivateTransfer-Request ::= SEQUENCE {
vendorID [0] Unsigned,
serviceNumber [1] Unsigned,
serviceParameters [2] ABSTRACT-SYNTAX.&Type OPTIONAL
}
*/
/* unused parameter */
max_apdu = max_apdu;
if (apdu) {
len =
encode_context_unsigned(&apdu[apdu_len], 0,
private_data->vendorID);
encode_context_unsigned(&apdu[apdu_len], 0, private_data->vendorID);
apdu_len += len;
len =
encode_context_unsigned(&apdu[apdu_len], 1,
private_data->serviceNumber);
len = encode_context_unsigned(&apdu[apdu_len], 1,
private_data->serviceNumber);
apdu_len += len;
len = encode_opening_tag(&apdu[apdu_len], 2);
apdu_len += len;
@@ -78,12 +74,10 @@ static int pt_encode_apdu(
return apdu_len;
}
int ptransfer_encode_apdu(
uint8_t * apdu,
uint8_t invoke_id,
BACNET_PRIVATE_TRANSFER_DATA * private_data)
int ptransfer_encode_apdu(uint8_t *apdu, uint8_t invoke_id,
BACNET_PRIVATE_TRANSFER_DATA *private_data)
{
int apdu_len = 0; /* total length of the apdu, return value */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0;
if (apdu) {
@@ -92,29 +86,26 @@ int ptransfer_encode_apdu(
apdu[2] = invoke_id;
apdu[3] = SERVICE_CONFIRMED_PRIVATE_TRANSFER;
apdu_len = 4;
len =
pt_encode_apdu(&apdu[apdu_len], (uint16_t) (MAX_APDU - apdu_len),
private_data);
len = pt_encode_apdu(&apdu[apdu_len], (uint16_t)(MAX_APDU - apdu_len),
private_data);
apdu_len += len;
}
return apdu_len;
}
int uptransfer_encode_apdu(
uint8_t * apdu,
BACNET_PRIVATE_TRANSFER_DATA * private_data)
int uptransfer_encode_apdu(uint8_t *apdu,
BACNET_PRIVATE_TRANSFER_DATA *private_data)
{
int apdu_len = 0; /* total length of the apdu, return value */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0;
if (apdu) {
apdu[0] = PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST;
apdu[1] = SERVICE_UNCONFIRMED_PRIVATE_TRANSFER;
apdu_len = 2;
len =
pt_encode_apdu(&apdu[apdu_len], (uint16_t) (MAX_APDU - apdu_len),
private_data);
len = pt_encode_apdu(&apdu[apdu_len], (uint16_t)(MAX_APDU - apdu_len),
private_data);
apdu_len += len;
}
@@ -122,10 +113,8 @@ int uptransfer_encode_apdu(
}
/* decode the service request only */
int ptransfer_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
BACNET_PRIVATE_TRANSFER_DATA * private_data)
int ptransfer_decode_service_request(uint8_t *apdu, unsigned apdu_len,
BACNET_PRIVATE_TRANSFER_DATA *private_data)
{
int len = 0; /* return value */
int decode_len = 0; /* return value */
@@ -139,7 +128,7 @@ int ptransfer_decode_service_request(
return -1;
}
len = decode_len;
private_data->vendorID = (uint16_t) unsigned_value;
private_data->vendorID = (uint16_t)unsigned_value;
/* Tag 1: serviceNumber */
decode_len = decode_context_unsigned(&apdu[len], 1, &unsigned_value);
if (decode_len < 0) {
@@ -154,9 +143,9 @@ int ptransfer_decode_service_request(
/* don't decode the serviceParameters here */
private_data->serviceParameters = &apdu[len];
private_data->serviceParametersLen =
(int) apdu_len - len - 1 /*closing tag */ ;
(int)apdu_len - len - 1 /*closing tag */;
/* len includes the data and the closing tag */
len = (int) apdu_len;
len = (int)apdu_len;
} else {
return -1;
}
@@ -165,15 +154,13 @@ int ptransfer_decode_service_request(
return len;
}
int ptransfer_error_encode_apdu(
uint8_t * apdu,
uint8_t invoke_id,
BACNET_ERROR_CLASS error_class,
BACNET_ERROR_CODE error_code,
BACNET_PRIVATE_TRANSFER_DATA * private_data)
int ptransfer_error_encode_apdu(uint8_t *apdu, uint8_t invoke_id,
BACNET_ERROR_CLASS error_class,
BACNET_ERROR_CODE error_code,
BACNET_PRIVATE_TRANSFER_DATA *private_data)
{
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* length of the part of the encoding */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* length of the part of the encoding */
if (apdu) {
apdu[0] = PDU_TYPE_ERROR;
@@ -181,14 +168,14 @@ int ptransfer_error_encode_apdu(
apdu[2] = SERVICE_CONFIRMED_PRIVATE_TRANSFER;
apdu_len = 3;
/* service parameters */
/*
ConfirmedPrivateTransfer-Error ::= SEQUENCE {
errorType [0] Error,
vendorID [1] Unsigned,
serviceNumber [2] Unsigned,
errorParameters [3] ABSTRACT-SYNTAX.&Type OPTIONAL
}
*/
/*
ConfirmedPrivateTransfer-Error ::= SEQUENCE {
errorType [0] Error,
vendorID [1] Unsigned,
serviceNumber [2] Unsigned,
errorParameters [3] ABSTRACT-SYNTAX.&Type OPTIONAL
}
*/
len = encode_opening_tag(&apdu[apdu_len], 0);
apdu_len += len;
len = encode_application_enumerated(&apdu[apdu_len], error_class);
@@ -198,12 +185,10 @@ int ptransfer_error_encode_apdu(
len = encode_closing_tag(&apdu[apdu_len], 0);
apdu_len += len;
len =
encode_context_unsigned(&apdu[apdu_len], 1,
private_data->vendorID);
encode_context_unsigned(&apdu[apdu_len], 1, private_data->vendorID);
apdu_len += len;
len =
encode_context_unsigned(&apdu[apdu_len], 2,
private_data->serviceNumber);
len = encode_context_unsigned(&apdu[apdu_len], 2,
private_data->serviceNumber);
apdu_len += len;
len = encode_opening_tag(&apdu[apdu_len], 3);
apdu_len += len;
@@ -220,11 +205,8 @@ int ptransfer_error_encode_apdu(
/* decode the service request only */
int ptransfer_error_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code,
BACNET_PRIVATE_TRANSFER_DATA * private_data)
uint8_t *apdu, unsigned apdu_len, BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code, BACNET_PRIVATE_TRANSFER_DATA *private_data)
{
int len = 0; /* return value */
int decode_len = 0; /* return value */
@@ -239,9 +221,8 @@ int ptransfer_error_decode_service_request(
/* a tag number of 0 is not extended so only one octet */
len++;
/* error class */
decode_len =
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
decode_len = decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_len;
if (tag_number != BACNET_APPLICATION_TAG_ENUMERATED) {
return 0;
@@ -250,12 +231,11 @@ int ptransfer_error_decode_service_request(
decode_enumerated(&apdu[len], len_value_type, &unsigned_value);
len += decode_len;
if (error_class) {
*error_class = (BACNET_ERROR_CLASS) unsigned_value;
*error_class = (BACNET_ERROR_CLASS)unsigned_value;
}
/* error code */
decode_len =
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
decode_len = decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_len;
if (tag_number != BACNET_APPLICATION_TAG_ENUMERATED) {
return 0;
@@ -264,7 +244,7 @@ int ptransfer_error_decode_service_request(
decode_enumerated(&apdu[len], len_value_type, &unsigned_value);
len += decode_len;
if (error_code) {
*error_code = (BACNET_ERROR_CODE) unsigned_value;
*error_code = (BACNET_ERROR_CODE)unsigned_value;
}
if (decode_is_closing_tag_number(&apdu[len], 0)) {
/* a tag number of 0 is not extended so only one octet */
@@ -279,7 +259,7 @@ int ptransfer_error_decode_service_request(
return -1;
}
len += decode_len;
private_data->vendorID = (uint16_t) unsigned_value;
private_data->vendorID = (uint16_t)unsigned_value;
/* Tag 2: serviceNumber */
decode_len = decode_context_unsigned(&apdu[len], 2, &unsigned_value);
if (decode_len < 0) {
@@ -294,7 +274,7 @@ int ptransfer_error_decode_service_request(
/* don't decode the serviceParameters here */
private_data->serviceParameters = &apdu[len];
private_data->serviceParametersLen =
(int) apdu_len - len - 1 /*closing tag */ ;
(int)apdu_len - len - 1 /*closing tag */;
} else {
return -1;
}
@@ -304,34 +284,30 @@ int ptransfer_error_decode_service_request(
return len;
}
int ptransfer_ack_encode_apdu(
uint8_t * apdu,
uint8_t invoke_id,
BACNET_PRIVATE_TRANSFER_DATA * private_data)
int ptransfer_ack_encode_apdu(uint8_t *apdu, uint8_t invoke_id,
BACNET_PRIVATE_TRANSFER_DATA *private_data)
{
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) {
apdu[0] = PDU_TYPE_COMPLEX_ACK; /* complex ACK service */
apdu[1] = invoke_id; /* original invoke id from request */
apdu[2] = SERVICE_CONFIRMED_PRIVATE_TRANSFER; /* service choice */
apdu[1] = invoke_id; /* original invoke id from request */
apdu[2] = SERVICE_CONFIRMED_PRIVATE_TRANSFER; /* service choice */
apdu_len = 3;
/* service ack follows */
/*
ConfirmedPrivateTransfer-ACK ::= SEQUENCE {
vendorID [0] Unsigned,
serviceNumber [1] Unsigned,
resultBlock [2] ABSTRACT-SYNTAX.&Type OPTIONAL
}
*/
/*
ConfirmedPrivateTransfer-ACK ::= SEQUENCE {
vendorID [0] Unsigned,
serviceNumber [1] Unsigned,
resultBlock [2] ABSTRACT-SYNTAX.&Type OPTIONAL
}
*/
len =
encode_context_unsigned(&apdu[apdu_len], 0,
private_data->vendorID);
encode_context_unsigned(&apdu[apdu_len], 0, private_data->vendorID);
apdu_len += len;
len =
encode_context_unsigned(&apdu[apdu_len], 1,
private_data->serviceNumber);
len = encode_context_unsigned(&apdu[apdu_len], 1,
private_data->serviceNumber);
apdu_len += len;
len = encode_opening_tag(&apdu[apdu_len], 2);
apdu_len += len;
@@ -349,18 +325,14 @@ int ptransfer_ack_encode_apdu(
/* ptransfer_ack_decode_service_request() is the same as
ptransfer_decode_service_request */
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
#include "bacapp.h"
int ptransfer_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
uint8_t * invoke_id,
BACNET_PRIVATE_TRANSFER_DATA * private_data)
int ptransfer_decode_apdu(uint8_t *apdu, unsigned apdu_len, uint8_t *invoke_id,
BACNET_PRIVATE_TRANSFER_DATA *private_data)
{
int len = 0;
unsigned offset = 0;
@@ -378,18 +350,15 @@ int ptransfer_decode_apdu(
offset = 4;
if (apdu_len > offset) {
len =
ptransfer_decode_service_request(&apdu[offset], apdu_len - offset,
private_data);
len = ptransfer_decode_service_request(&apdu[offset], apdu_len - offset,
private_data);
}
return len;
}
int uptransfer_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
BACNET_PRIVATE_TRANSFER_DATA * private_data)
int uptransfer_decode_apdu(uint8_t *apdu, unsigned apdu_len,
BACNET_PRIVATE_TRANSFER_DATA *private_data)
{
int len = 0;
unsigned offset = 0;
@@ -406,19 +375,17 @@ int uptransfer_decode_apdu(
}
offset = 2;
if (apdu_len > offset) {
len =
ptransfer_decode_service_request(&apdu[offset], apdu_len - offset,
private_data);
len = ptransfer_decode_service_request(&apdu[offset], apdu_len - offset,
private_data);
}
return len;
}
int ptransfer_ack_decode_apdu(
uint8_t * apdu,
int apdu_len, /* total length of the apdu */
uint8_t * invoke_id,
BACNET_PRIVATE_TRANSFER_DATA * private_data)
int ptransfer_ack_decode_apdu(uint8_t *apdu,
int apdu_len, /* total length of the apdu */
uint8_t *invoke_id,
BACNET_PRIVATE_TRANSFER_DATA *private_data)
{
int len = 0;
int offset = 0;
@@ -433,21 +400,19 @@ int ptransfer_ack_decode_apdu(
return -1;
offset = 3;
if (apdu_len > offset) {
len =
ptransfer_decode_service_request(&apdu[offset], apdu_len - offset,
private_data);
len = ptransfer_decode_service_request(&apdu[offset], apdu_len - offset,
private_data);
}
return len;
}
int ptransfer_error_decode_apdu(
uint8_t * apdu,
int apdu_len, /* total length of the apdu */
uint8_t * invoke_id,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code,
BACNET_PRIVATE_TRANSFER_DATA * private_data)
int ptransfer_error_decode_apdu(uint8_t *apdu,
int apdu_len, /* total length of the apdu */
uint8_t *invoke_id,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code,
BACNET_PRIVATE_TRANSFER_DATA *private_data)
{
int len = 0;
int offset = 0;
@@ -462,27 +427,26 @@ int ptransfer_error_decode_apdu(
return -1;
offset = 3;
if (apdu_len > offset) {
len =
ptransfer_error_decode_service_request(&apdu[offset],
apdu_len - offset, error_class, error_code, private_data);
len = ptransfer_error_decode_service_request(
&apdu[offset], apdu_len - offset, error_class, error_code,
private_data);
}
return len;
}
void test_Private_Transfer_Ack(
Test * pTest)
void test_Private_Transfer_Ack(Test *pTest)
{
uint8_t apdu[480] = { 0 };
uint8_t apdu[480] = {0};
int len = 0;
int apdu_len = 0;
uint8_t invoke_id = 128;
uint8_t test_invoke_id = 0;
BACNET_PRIVATE_TRANSFER_DATA private_data;
BACNET_PRIVATE_TRANSFER_DATA test_data;
uint8_t test_value[480] = { 0 };
uint8_t test_value[480] = {0};
int private_data_len = 0;
char private_data_chunk[33] = { "00112233445566778899AABBCCDDEEFF" };
char private_data_chunk[33] = {"00112233445566778899AABBCCDDEEFF"};
BACNET_APPLICATION_DATA_VALUE data_value;
BACNET_APPLICATION_DATA_VALUE test_data_value;
bool status = false;
@@ -490,9 +454,8 @@ void test_Private_Transfer_Ack(
private_data.vendorID = BACNET_VENDOR_ID;
private_data.serviceNumber = 1;
status =
bacapp_parse_application_data(BACNET_APPLICATION_TAG_OCTET_STRING,
&private_data_chunk[0], &data_value);
status = bacapp_parse_application_data(BACNET_APPLICATION_TAG_OCTET_STRING,
&private_data_chunk[0], &data_value);
ct_test(pTest, status == true);
private_data_len =
bacapp_encode_application_data(&test_value[0], &data_value);
@@ -500,30 +463,27 @@ void test_Private_Transfer_Ack(
private_data.serviceParameters = &test_value[0];
private_data.serviceParametersLen = private_data_len;
len = ptransfer_ack_encode_apdu(&apdu[0], invoke_id, &private_data);
ct_test(pTest, len != 0);
ct_test(pTest, len != -1);
apdu_len = len;
len =
ptransfer_ack_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_data);
len = ptransfer_ack_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_data);
ct_test(pTest, len != -1);
ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest, test_data.vendorID == private_data.vendorID);
ct_test(pTest, test_data.serviceNumber == private_data.serviceNumber);
ct_test(pTest,
test_data.serviceParametersLen == private_data.serviceParametersLen);
len =
bacapp_decode_application_data(test_data.serviceParameters,
test_data.serviceParametersLen, &test_data_value);
ct_test(pTest, test_data.serviceParametersLen ==
private_data.serviceParametersLen);
len = bacapp_decode_application_data(test_data.serviceParameters,
test_data.serviceParametersLen,
&test_data_value);
ct_test(pTest, bacapp_same_value(&data_value, &test_data_value) == true);
}
void test_Private_Transfer_Error(
Test * pTest)
void test_Private_Transfer_Error(Test *pTest)
{
uint8_t apdu[480] = { 0 };
uint8_t apdu[480] = {0};
int len = 0;
int apdu_len = 0;
uint8_t invoke_id = 128;
@@ -534,9 +494,9 @@ void test_Private_Transfer_Error(
BACNET_ERROR_CODE test_error_code = 0;
BACNET_PRIVATE_TRANSFER_DATA private_data;
BACNET_PRIVATE_TRANSFER_DATA test_data;
uint8_t test_value[480] = { 0 };
uint8_t test_value[480] = {0};
int private_data_len = 0;
char private_data_chunk[33] = { "00112233445566778899AABBCCDDEEFF" };
char private_data_chunk[33] = {"00112233445566778899AABBCCDDEEFF"};
BACNET_APPLICATION_DATA_VALUE data_value;
BACNET_APPLICATION_DATA_VALUE test_data_value;
bool status = false;
@@ -544,61 +504,57 @@ void test_Private_Transfer_Error(
private_data.vendorID = BACNET_VENDOR_ID;
private_data.serviceNumber = 1;
status =
bacapp_parse_application_data(BACNET_APPLICATION_TAG_OCTET_STRING,
&private_data_chunk[0], &data_value);
status = bacapp_parse_application_data(BACNET_APPLICATION_TAG_OCTET_STRING,
&private_data_chunk[0], &data_value);
ct_test(pTest, status == true);
private_data_len =
bacapp_encode_application_data(&test_value[0], &data_value);
private_data.serviceParameters = &test_value[0];
private_data.serviceParametersLen = private_data_len;
len =
ptransfer_error_encode_apdu(&apdu[0], invoke_id, error_class,
error_code, &private_data);
len = ptransfer_error_encode_apdu(&apdu[0], invoke_id, error_class,
error_code, &private_data);
ct_test(pTest, len != 0);
ct_test(pTest, len != -1);
apdu_len = len;
len =
ptransfer_error_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_error_class, &test_error_code, &test_data);
len = ptransfer_error_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_error_class, &test_error_code,
&test_data);
ct_test(pTest, len != -1);
ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest, test_data.vendorID == private_data.vendorID);
ct_test(pTest, test_data.serviceNumber == private_data.serviceNumber);
ct_test(pTest, test_error_class == error_class);
ct_test(pTest, test_error_code == error_code);
ct_test(pTest,
test_data.serviceParametersLen == private_data.serviceParametersLen);
len =
bacapp_decode_application_data(test_data.serviceParameters,
test_data.serviceParametersLen, &test_data_value);
ct_test(pTest, test_data.serviceParametersLen ==
private_data.serviceParametersLen);
len = bacapp_decode_application_data(test_data.serviceParameters,
test_data.serviceParametersLen,
&test_data_value);
ct_test(pTest, bacapp_same_value(&data_value, &test_data_value) == true);
}
void test_Private_Transfer_Request(
Test * pTest)
void test_Private_Transfer_Request(Test *pTest)
{
uint8_t apdu[480] = { 0 };
uint8_t test_value[480] = { 0 };
uint8_t apdu[480] = {0};
uint8_t test_value[480] = {0};
int len = 0;
int apdu_len = 0;
uint8_t invoke_id = 128;
uint8_t test_invoke_id = 0;
int private_data_len = 0;
char private_data_chunk[33] = { "00112233445566778899AABBCCDDEEFF" };
BACNET_APPLICATION_DATA_VALUE data_value = { 0 };
BACNET_APPLICATION_DATA_VALUE test_data_value = { 0 };
BACNET_PRIVATE_TRANSFER_DATA private_data = { 0 };
BACNET_PRIVATE_TRANSFER_DATA test_data = { 0 };
char private_data_chunk[33] = {"00112233445566778899AABBCCDDEEFF"};
BACNET_APPLICATION_DATA_VALUE data_value = {0};
BACNET_APPLICATION_DATA_VALUE test_data_value = {0};
BACNET_PRIVATE_TRANSFER_DATA private_data = {0};
BACNET_PRIVATE_TRANSFER_DATA test_data = {0};
bool status = false;
private_data.vendorID = BACNET_VENDOR_ID;
private_data.serviceNumber = 1;
status =
bacapp_parse_application_data(BACNET_APPLICATION_TAG_OCTET_STRING,
&private_data_chunk[0], &data_value);
status = bacapp_parse_application_data(BACNET_APPLICATION_TAG_OCTET_STRING,
&private_data_chunk[0], &data_value);
ct_test(pTest, status == true);
private_data_len =
bacapp_encode_application_data(&test_value[0], &data_value);
@@ -613,25 +569,24 @@ void test_Private_Transfer_Request(
ct_test(pTest, len != -1);
ct_test(pTest, test_data.vendorID == private_data.vendorID);
ct_test(pTest, test_data.serviceNumber == private_data.serviceNumber);
ct_test(pTest,
test_data.serviceParametersLen == private_data.serviceParametersLen);
len =
bacapp_decode_application_data(test_data.serviceParameters,
test_data.serviceParametersLen, &test_data_value);
ct_test(pTest, test_data.serviceParametersLen ==
private_data.serviceParametersLen);
len = bacapp_decode_application_data(test_data.serviceParameters,
test_data.serviceParametersLen,
&test_data_value);
ct_test(pTest, bacapp_same_value(&data_value, &test_data_value) == true);
return;
}
void test_Unconfirmed_Private_Transfer_Request(
Test * pTest)
void test_Unconfirmed_Private_Transfer_Request(Test *pTest)
{
uint8_t apdu[480] = { 0 };
uint8_t test_value[480] = { 0 };
uint8_t apdu[480] = {0};
uint8_t test_value[480] = {0};
int len = 0;
int apdu_len = 0;
int private_data_len = 0;
char private_data_chunk[32] = { "I Love You, Patricia!" };
char private_data_chunk[32] = {"I Love You, Patricia!"};
BACNET_APPLICATION_DATA_VALUE data_value;
BACNET_APPLICATION_DATA_VALUE test_data_value;
BACNET_PRIVATE_TRANSFER_DATA private_data;
@@ -643,7 +598,7 @@ void test_Unconfirmed_Private_Transfer_Request(
status =
bacapp_parse_application_data(BACNET_APPLICATION_TAG_CHARACTER_STRING,
&private_data_chunk[0], &data_value);
&private_data_chunk[0], &data_value);
ct_test(pTest, status == true);
private_data_len =
bacapp_encode_application_data(&test_value[0], &data_value);
@@ -657,19 +612,18 @@ void test_Unconfirmed_Private_Transfer_Request(
ct_test(pTest, len != -1);
ct_test(pTest, test_data.vendorID == private_data.vendorID);
ct_test(pTest, test_data.serviceNumber == private_data.serviceNumber);
ct_test(pTest,
test_data.serviceParametersLen == private_data.serviceParametersLen);
len =
bacapp_decode_application_data(test_data.serviceParameters,
test_data.serviceParametersLen, &test_data_value);
ct_test(pTest, test_data.serviceParametersLen ==
private_data.serviceParametersLen);
len = bacapp_decode_application_data(test_data.serviceParameters,
test_data.serviceParametersLen,
&test_data_value);
ct_test(pTest, bacapp_same_value(&data_value, &test_data_value) == true);
return;
}
#ifdef TEST_PRIVATE_TRANSFER
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -687,7 +641,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+27 -41
View File
@@ -40,14 +40,12 @@
/** @file rd.c Encode/Decode Reinitialize Device APDUs */
#if BACNET_SVC_RD_A
/* encode service */
int rd_encode_apdu(
uint8_t * apdu,
uint8_t invoke_id,
BACNET_REINITIALIZED_STATE state,
BACNET_CHARACTER_STRING * password)
int rd_encode_apdu(uint8_t *apdu, uint8_t invoke_id,
BACNET_REINITIALIZED_STATE state,
BACNET_CHARACTER_STRING *password)
{
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) {
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
@@ -60,8 +58,7 @@ int rd_encode_apdu(
/* optional password */
if (password) {
/* FIXME: must be at least 1 character, limited to 20 characters */
len =
encode_context_character_string(&apdu[apdu_len], 1, password);
len = encode_context_character_string(&apdu[apdu_len], 1, password);
apdu_len += len;
}
}
@@ -71,11 +68,9 @@ int rd_encode_apdu(
#endif
/* decode the service request only */
int rd_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
BACNET_REINITIALIZED_STATE * state,
BACNET_CHARACTER_STRING * password)
int rd_decode_service_request(uint8_t *apdu, unsigned apdu_len,
BACNET_REINITIALIZED_STATE *state,
BACNET_CHARACTER_STRING *password)
{
unsigned len = 0;
uint8_t tag_number = 0;
@@ -87,25 +82,23 @@ int rd_decode_service_request(
/* Tag 0: reinitializedStateOfDevice */
if (!decode_is_context_tag(&apdu[len], 0))
return -1;
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_enumerated(&apdu[len], len_value_type, &value);
if (state)
*state = (BACNET_REINITIALIZED_STATE) value;
*state = (BACNET_REINITIALIZED_STATE)value;
/* Tag 1: password - optional */
if (len < apdu_len) {
if (!decode_is_context_tag(&apdu[len], 1))
return -1;
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len +=
decode_character_string(&apdu[len], len_value_type, password);
}
}
return (int) len;
return (int)len;
}
#ifdef TEST
@@ -113,12 +106,9 @@ int rd_decode_service_request(
#include <string.h>
#include "ctest.h"
int rd_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
uint8_t * invoke_id,
BACNET_REINITIALIZED_STATE * state,
BACNET_CHARACTER_STRING * password)
int rd_decode_apdu(uint8_t *apdu, unsigned apdu_len, uint8_t *invoke_id,
BACNET_REINITIALIZED_STATE *state,
BACNET_CHARACTER_STRING *password)
{
int len = 0;
unsigned offset = 0;
@@ -129,24 +119,22 @@ int rd_decode_apdu(
if (apdu[0] != PDU_TYPE_CONFIRMED_SERVICE_REQUEST)
return -1;
/* apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU); */
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
if (apdu[3] != SERVICE_CONFIRMED_REINITIALIZE_DEVICE)
return -1;
offset = 4;
if (apdu_len > offset) {
len =
rd_decode_service_request(&apdu[offset], apdu_len - offset, state,
password);
len = rd_decode_service_request(&apdu[offset], apdu_len - offset, state,
password);
}
return len;
}
void test_ReinitializeDevice(
Test * pTest)
void test_ReinitializeDevice(Test *pTest)
{
uint8_t apdu[480] = { 0 };
uint8_t apdu[480] = {0};
int len = 0;
int apdu_len = 0;
uint8_t invoke_id = 128;
@@ -162,9 +150,8 @@ void test_ReinitializeDevice(
ct_test(pTest, len != 0);
apdu_len = len;
len =
rd_decode_apdu(&apdu[0], apdu_len, &test_invoke_id, &test_state,
&test_password);
len = rd_decode_apdu(&apdu[0], apdu_len, &test_invoke_id, &test_state,
&test_password);
ct_test(pTest, len != -1);
ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest, test_state == state);
@@ -174,8 +161,7 @@ void test_ReinitializeDevice(
}
#ifdef TEST_REINITIALIZE_DEVICE
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -187,7 +173,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+141 -170
View File
@@ -43,10 +43,8 @@
* ReadRange-Request ::= SEQUENCE {
* objectIdentifier [0] BACnetObjectIdentifier,
* propertyIdentifier [1] BACnetPropertyIdentifier,
* propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
* range CHOICE {
* byPosition [3] SEQUENCE {
* referenceIndex Unsigned,
* propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array
* datatype range CHOICE { byPosition [3] SEQUENCE { referenceIndex Unsigned,
* count INTEGER
* },
* -- context tag 4 is deprecated
@@ -67,12 +65,10 @@
* Build a ReadRange request packet. *
*****************************************************************************/
int rr_encode_apdu(
uint8_t * apdu,
uint8_t invoke_id,
BACNET_READ_RANGE_DATA * rrdata)
int rr_encode_apdu(uint8_t* apdu, uint8_t invoke_id,
BACNET_READ_RANGE_DATA* rrdata)
{
int apdu_len = 0; /* total length of the apdu, return value */
int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) {
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
@@ -81,29 +77,26 @@ int rr_encode_apdu(
apdu[3] = SERVICE_CONFIRMED_READ_RANGE; /* service choice */
apdu_len = 4;
apdu_len +=
encode_context_object_id(&apdu[apdu_len], 0, rrdata->object_type,
rrdata->object_instance);
apdu_len +=
encode_context_enumerated(&apdu[apdu_len], 1,
rrdata->object_property);
apdu_len += encode_context_object_id(
&apdu[apdu_len], 0, rrdata->object_type, rrdata->object_instance);
apdu_len += encode_context_enumerated(&apdu[apdu_len], 1,
rrdata->object_property);
/* optional array index */
if (rrdata->array_index != BACNET_ARRAY_ALL) {
apdu_len +=
encode_context_unsigned(&apdu[apdu_len], 2,
rrdata->array_index);
apdu_len += encode_context_unsigned(&apdu[apdu_len], 2,
rrdata->array_index);
}
/* Build the appropriate (optional) range parameter based on the request type */
/* Build the appropriate (optional) range parameter based on the request
* type */
switch (rrdata->RequestType) {
case RR_BY_POSITION:
apdu_len += encode_opening_tag(&apdu[apdu_len], 3);
apdu_len +=
encode_application_unsigned(&apdu[apdu_len],
rrdata->Range.RefIndex);
apdu_len += encode_application_unsigned(&apdu[apdu_len],
rrdata->Range.RefIndex);
apdu_len +=
encode_application_signed(&apdu[apdu_len], rrdata->Count);
apdu_len += encode_closing_tag(&apdu[apdu_len], 3);
@@ -111,9 +104,8 @@ int rr_encode_apdu(
case RR_BY_SEQUENCE:
apdu_len += encode_opening_tag(&apdu[apdu_len], 6);
apdu_len +=
encode_application_unsigned(&apdu[apdu_len],
rrdata->Range.RefSeqNum);
apdu_len += encode_application_unsigned(
&apdu[apdu_len], rrdata->Range.RefSeqNum);
apdu_len +=
encode_application_signed(&apdu[apdu_len], rrdata->Count);
apdu_len += encode_closing_tag(&apdu[apdu_len], 6);
@@ -121,18 +113,17 @@ int rr_encode_apdu(
case RR_BY_TIME:
apdu_len += encode_opening_tag(&apdu[apdu_len], 7);
apdu_len +=
encode_application_date(&apdu[apdu_len],
&rrdata->Range.RefTime.date);
apdu_len +=
encode_application_time(&apdu[apdu_len],
&rrdata->Range.RefTime.time);
apdu_len += encode_application_date(
&apdu[apdu_len], &rrdata->Range.RefTime.date);
apdu_len += encode_application_time(
&apdu[apdu_len], &rrdata->Range.RefTime.time);
apdu_len +=
encode_application_signed(&apdu[apdu_len], rrdata->Count);
apdu_len += encode_closing_tag(&apdu[apdu_len], 7);
break;
case RR_READ_ALL: /* to attempt a read of the whole array or list, omit the range parameter */
case RR_READ_ALL: /* to attempt a read of the whole array or list,
omit the range parameter */
break;
default:
@@ -147,16 +138,14 @@ int rr_encode_apdu(
* Decode the received ReadRange request *
*****************************************************************************/
int rr_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
BACNET_READ_RANGE_DATA * rrdata)
int rr_decode_service_request(uint8_t* apdu, unsigned apdu_len,
BACNET_READ_RANGE_DATA* rrdata)
{
unsigned len = 0;
unsigned TagLen = 0;
uint8_t tag_number = 0;
uint32_t len_value_type = 0;
uint16_t type = 0; /* for decoding */
uint16_t type = 0; /* for decoding */
uint32_t UnsignedTemp;
/* check for value pointers */
@@ -165,129 +154,118 @@ int rr_decode_service_request(
if (!decode_is_context_tag(&apdu[len++], 0))
return -1;
len += decode_object_id(&apdu[len], &type, &rrdata->object_instance);
rrdata->object_type = (BACNET_OBJECT_TYPE) type;
rrdata->object_type = (BACNET_OBJECT_TYPE)type;
/* Tag 1: Property ID */
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
if (tag_number != 1)
return -1;
len += decode_enumerated(&apdu[len], len_value_type, &UnsignedTemp);
rrdata->object_property = (BACNET_PROPERTY_ID) UnsignedTemp;
rrdata->object_property = (BACNET_PROPERTY_ID)UnsignedTemp;
rrdata->Overhead = RR_OVERHEAD; /* Start with the fixed overhead */
/* Tag 2: Optional Array Index - set to ALL if not present */
rrdata->array_index = BACNET_ARRAY_ALL; /* Assuming this is the most common outcome... */
rrdata->array_index =
BACNET_ARRAY_ALL; /* Assuming this is the most common outcome... */
if (len < apdu_len) {
TagLen =
(unsigned) decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
TagLen = (unsigned)decode_tag_number_and_value(
&apdu[len], &tag_number, &len_value_type);
if (tag_number == 2) {
len += TagLen;
len +=
decode_unsigned(&apdu[len], len_value_type, &UnsignedTemp);
rrdata->array_index = UnsignedTemp;
rrdata->Overhead += RR_INDEX_OVERHEAD; /* Allow for this in the response */
rrdata->Overhead +=
RR_INDEX_OVERHEAD; /* Allow for this in the response */
}
}
/* And/or optional range selection- Tags 3, 6 and 7 */
rrdata->RequestType = RR_READ_ALL; /* Assume the worst to cut out explicit checking later */
rrdata->RequestType = RR_READ_ALL; /* Assume the worst to cut out
explicit checking later */
if (len < apdu_len) {
/*
* Note: We pick up the opening tag and then decode the parameter types we recognise.
* We deal with the count and the closing tag in each case statement even though it
* might appear that we could do them after the switch statement as common elements.
* This is so that if we receive a tag we don't recognise, we don't try to decode it
* blindly and make a mess of it.
* Note: We pick up the opening tag and then decode the parameter
* types we recognise. We deal with the count and the closing tag in
* each case statement even though it might appear that we could do
* them after the switch statement as common elements. This is so
* that if we receive a tag we don't recognise, we don't try to
* decode it blindly and make a mess of it.
*/
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
switch (tag_number) {
case 3: /* ReadRange by position */
case 3: /* ReadRange by position */
rrdata->RequestType = RR_BY_POSITION;
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len +=
decode_unsigned(&apdu[len], len_value_type,
&rrdata->Range.RefIndex);
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len +=
decode_signed(&apdu[len], len_value_type,
&rrdata->Count);
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_unsigned(&apdu[len], len_value_type,
&rrdata->Range.RefIndex);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_signed(&apdu[len], len_value_type,
&rrdata->Count);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
break;
case 6: /* ReadRange by sequence number */
case 6: /* ReadRange by sequence number */
rrdata->RequestType = RR_BY_SEQUENCE;
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len +=
decode_unsigned(&apdu[len], len_value_type,
&rrdata->Range.RefSeqNum);
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len +=
decode_signed(&apdu[len], len_value_type,
&rrdata->Count);
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
rrdata->Overhead += RR_1ST_SEQ_OVERHEAD; /* Allow for this in the response */
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_unsigned(&apdu[len], len_value_type,
&rrdata->Range.RefSeqNum);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_signed(&apdu[len], len_value_type,
&rrdata->Count);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
rrdata->Overhead +=
RR_1ST_SEQ_OVERHEAD; /* Allow for this in the response
*/
break;
case 7: /* ReadRange by time stamp */
case 7: /* ReadRange by time stamp */
rrdata->RequestType = RR_BY_TIME;
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len +=
decode_date(&apdu[len], &rrdata->Range.RefTime.date);
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len +=
decode_bacnet_time(&apdu[len],
&rrdata->Range.RefTime.time);
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len +=
decode_signed(&apdu[len], len_value_type,
&rrdata->Count);
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
rrdata->Overhead += RR_1ST_SEQ_OVERHEAD; /* Allow for this in the response */
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_date(&apdu[len], &rrdata->Range.RefTime.date);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_bacnet_time(&apdu[len],
&rrdata->Range.RefTime.time);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_signed(&apdu[len], len_value_type,
&rrdata->Count);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
rrdata->Overhead +=
RR_1ST_SEQ_OVERHEAD; /* Allow for this in the response
*/
break;
default: /* If we don't recognise the tag then we do nothing here and try to return
* all elements of the array */
default: /* If we don't recognise the tag then we do nothing
* here and try to return all elements of the array */
break;
}
}
}
return (int) len;
return (int)len;
}
/*
* ReadRange-ACK ::= SEQUENCE {
* objectIdentifier [0] BACnetObjectIdentifier,
* propertyIdentifier [1] BACnetPropertyIdentifier,
* propertyArrayIndex [2] Unsigned OPTIONAL , -- used only with array datatype
* resultFlags [3] BACnetResultFlags,
* itemCount [4] Unsigned,
* itemData [5] SEQUENCE OF ABSTRACT-SYNTAX.&TYPE,
* firstSequenceNumber [6] Unsigned32 OPTIONAL -- used only if 'Item Count' > 0 and the request was either of
* -- type 'By Sequence Number' or 'By Time'
* propertyArrayIndex [2] Unsigned OPTIONAL , -- used only with
* array datatype resultFlags [3] BACnetResultFlags, itemCount [4]
* Unsigned, itemData [5] SEQUENCE OF ABSTRACT-SYNTAX.&TYPE,
* firstSequenceNumber [6] Unsigned32 OPTIONAL -- used only if 'Item Count'
* > 0 and the request was either of
* -- type 'By Sequence Number'
* or 'By Time'
* }
*/
@@ -295,31 +273,26 @@ int rr_decode_service_request(
* Build a ReadRange response packet *
*****************************************************************************/
int rr_ack_encode_apdu(
uint8_t * apdu,
uint8_t invoke_id,
BACNET_READ_RANGE_DATA * rrdata)
int rr_ack_encode_apdu(uint8_t* apdu, uint8_t invoke_id,
BACNET_READ_RANGE_DATA* rrdata)
{
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) {
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_RANGE; /* service choice */
apdu_len = 3;
/* service ack follows */
apdu_len +=
encode_context_object_id(&apdu[apdu_len], 0, rrdata->object_type,
rrdata->object_instance);
apdu_len +=
encode_context_enumerated(&apdu[apdu_len], 1,
rrdata->object_property);
apdu_len += encode_context_object_id(
&apdu[apdu_len], 0, rrdata->object_type, rrdata->object_instance);
apdu_len += encode_context_enumerated(&apdu[apdu_len], 1,
rrdata->object_property);
/* context 2 array index is optional */
if (rrdata->array_index != BACNET_ARRAY_ALL) {
apdu_len +=
encode_context_unsigned(&apdu[apdu_len], 2,
rrdata->array_index);
apdu_len += encode_context_unsigned(&apdu[apdu_len], 2,
rrdata->array_index);
}
/* Context 3 BACnet Result Flags */
apdu_len +=
@@ -327,8 +300,9 @@ int rr_ack_encode_apdu(
/* Context 4 Item Count */
apdu_len +=
encode_context_unsigned(&apdu[apdu_len], 4, rrdata->ItemCount);
/* Context 5 Property list - reading the standard it looks like an empty list still
* requires an opening and closing tag as the tagged parameter is not optional
/* Context 5 Property list - reading the standard it looks like an empty
* list still requires an opening and closing tag as the tagged
* parameter is not optional
*/
apdu_len += encode_opening_tag(&apdu[apdu_len], 5);
if (rrdata->ItemCount != 0) {
@@ -338,12 +312,12 @@ int rr_ack_encode_apdu(
}
apdu_len += encode_closing_tag(&apdu[apdu_len], 5);
if ((rrdata->ItemCount != 0) && (rrdata->RequestType != RR_BY_POSITION)
&& (rrdata->RequestType != RR_READ_ALL)) {
if ((rrdata->ItemCount != 0) &&
(rrdata->RequestType != RR_BY_POSITION) &&
(rrdata->RequestType != RR_READ_ALL)) {
/* Context 6 Sequence number of first item */
apdu_len +=
encode_context_unsigned(&apdu[apdu_len], 6,
rrdata->FirstSequence);
apdu_len += encode_context_unsigned(&apdu[apdu_len], 6,
rrdata->FirstSequence);
}
}
@@ -354,19 +328,18 @@ int rr_ack_encode_apdu(
* Decode the received ReadRange response *
*****************************************************************************/
int rr_ack_decode_service_request(
uint8_t * apdu,
int apdu_len, /* total length of the apdu */
BACNET_READ_RANGE_DATA * rrdata)
int rr_ack_decode_service_request(uint8_t* apdu,
int apdu_len, /* total length of the apdu */
BACNET_READ_RANGE_DATA* rrdata)
{
uint8_t tag_number = 0;
uint32_t len_value_type = 0;
int tag_len = 0; /* length of tag decode */
int len = 0; /* total length of decodes */
int tag_len = 0; /* length of tag decode */
int len = 0; /* total length of decodes */
int start_len;
uint16_t object = 0; /* object type */
uint32_t property = 0; /* for decoding */
uint32_t array_value = 0; /* for decoding */
uint16_t object = 0; /* object type */
uint32_t property = 0; /* for decoding */
uint32_t array_value = 0; /* for decoding */
/* FIXME: check apdu_len against the len during decode */
/* Tag 0: Object ID */
@@ -374,7 +347,7 @@ int rr_ack_decode_service_request(
return -1;
len = 1;
len += decode_object_id(&apdu[len], &object, &rrdata->object_instance);
rrdata->object_type = (BACNET_OBJECT_TYPE) object;
rrdata->object_type = (BACNET_OBJECT_TYPE)object;
/* Tag 1: Property ID */
len +=
@@ -382,7 +355,7 @@ int rr_ack_decode_service_request(
if (tag_number != 1)
return -1;
len += decode_enumerated(&apdu[len], len_value_type, &property);
rrdata->object_property = (BACNET_PROPERTY_ID) property;
rrdata->object_property = (BACNET_PROPERTY_ID)property;
/* Tag 2: Optional Array Index */
tag_len =
@@ -411,44 +384,42 @@ int rr_ack_decode_service_request(
len += decode_unsigned(&apdu[len], len_value_type, &rrdata->ItemCount);
if (decode_is_opening_tag_number(&apdu[len], 5)) {
len++; /* a tag number of 5 is not extended so only one octet */
/* Setup the start position and length of the data returned from the request
* don't decode the application tag number or its data here */
len++; /* a tag number of 5 is not extended so only one octet */
/* Setup the start position and length of the data returned from the
* request don't decode the application tag number or its data here */
rrdata->application_data = &apdu[len];
start_len = len;
while (len < apdu_len) {
if (IS_CONTEXT_SPECIFIC(apdu[len]) &&
(decode_is_closing_tag_number(&apdu[len], 5))) {
rrdata->application_data_len = len - start_len;
len++; /* Step over single byte closing tag */
len++; /* Step over single byte closing tag */
break;
} else {
/* Don't care about tag number, just skipping over anyway */
len +=
decode_tag_number_and_value(&apdu[len], NULL,
&len_value_type);
len += len_value_type; /* Skip over data value as well */
if (len >= apdu_len) /* APDU is exhausted so we have failed to find closing tag */
len += decode_tag_number_and_value(&apdu[len], NULL,
&len_value_type);
len += len_value_type; /* Skip over data value as well */
if (len >= apdu_len) /* APDU is exhausted so we have failed to
find closing tag */
return (-1);
}
}
} else {
return -1;
}
if (len < apdu_len) { /* Still something left to look at? */
if (len < apdu_len) { /* Still something left to look at? */
/* Tag 6: Item count */
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
if (tag_number != 6)
return -1;
len +=
decode_unsigned(&apdu[len], len_value_type,
&rrdata->FirstSequence);
decode_unsigned(&apdu[len], len_value_type, &rrdata->FirstSequence);
}
len = apdu_len; /* There should be nothing left to see here */
len = apdu_len; /* There should be nothing left to see here */
return len;
}
+26 -46
View File
@@ -39,15 +39,13 @@
/** @file reject.c Encode/Decode Reject APDUs */
/* Helper function to avoid needing additional entries in service data structures
* when passing back reject status.
* Convert from error code to reject code.
* Anything not defined gets converted to REJECT_REASON_OTHER.
* Will need reworking if it is required to return proprietary reject codes.
/* Helper function to avoid needing additional entries in service data
* structures when passing back reject status. Convert from error code to reject
* code. Anything not defined gets converted to REJECT_REASON_OTHER. Will need
* reworking if it is required to return proprietary reject codes.
*/
BACNET_REJECT_REASON reject_convert_error_code(
BACNET_ERROR_CODE error_code)
BACNET_REJECT_REASON reject_convert_error_code(BACNET_ERROR_CODE error_code)
{
BACNET_REJECT_REASON reject_code = REJECT_REASON_OTHER;
@@ -92,12 +90,9 @@ BACNET_REJECT_REASON reject_convert_error_code(
}
/* encode service */
int reject_encode_apdu(
uint8_t * apdu,
uint8_t invoke_id,
uint8_t reject_reason)
int reject_encode_apdu(uint8_t *apdu, 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) {
apdu[0] = PDU_TYPE_REJECT;
@@ -111,11 +106,8 @@ int reject_encode_apdu(
#if !BACNET_SVC_SERVER
/* decode the service request only */
int reject_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
uint8_t * invoke_id,
uint8_t * reject_reason)
int reject_decode_service_request(uint8_t *apdu, unsigned apdu_len,
uint8_t *invoke_id, uint8_t *reject_reason)
{
int len = 0;
@@ -136,11 +128,8 @@ int reject_decode_service_request(
#include "ctest.h"
/* decode the whole APDU - mainly used for unit testing */
int reject_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
uint8_t * invoke_id,
uint8_t * reject_reason)
int reject_decode_apdu(uint8_t *apdu, unsigned apdu_len, uint8_t *invoke_id,
uint8_t *reject_reason)
{
int len = 0;
@@ -151,19 +140,17 @@ int reject_decode_apdu(
if (apdu[0] != PDU_TYPE_REJECT)
return -1;
if (apdu_len > 1) {
len =
reject_decode_service_request(&apdu[1], apdu_len - 1,
invoke_id, reject_reason);
len = reject_decode_service_request(&apdu[1], apdu_len - 1,
invoke_id, reject_reason);
}
}
return len;
}
void testReject(
Test * pTest)
void testReject(Test *pTest)
{
uint8_t apdu[480] = { 0 };
uint8_t apdu[480] = {0};
int len = 0;
int apdu_len = 0;
uint8_t invoke_id = 0;
@@ -175,41 +162,35 @@ void testReject(
ct_test(pTest, len != 0);
apdu_len = len;
len =
reject_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_reject_reason);
len = reject_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_reject_reason);
ct_test(pTest, len != -1);
ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest, test_reject_reason == reject_reason);
/* change type to get negative response */
apdu[0] = PDU_TYPE_ABORT;
len =
reject_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_reject_reason);
len = reject_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_reject_reason);
ct_test(pTest, len == -1);
/* test NULL APDU */
len =
reject_decode_apdu(NULL, apdu_len, &test_invoke_id,
&test_reject_reason);
len = reject_decode_apdu(NULL, apdu_len, &test_invoke_id,
&test_reject_reason);
ct_test(pTest, len == -1);
/* force a zero length */
len =
reject_decode_apdu(&apdu[0], 0, &test_invoke_id, &test_reject_reason);
len = reject_decode_apdu(&apdu[0], 0, &test_invoke_id, &test_reject_reason);
ct_test(pTest, len == 0);
/* check them all... */
for (invoke_id = 0; invoke_id < 255; invoke_id++) {
for (reject_reason = 0; reject_reason < 255; reject_reason++) {
len = reject_encode_apdu(&apdu[0], invoke_id, reject_reason);
apdu_len = len;
ct_test(pTest, len != 0);
len =
reject_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_reject_reason);
len = reject_decode_apdu(&apdu[0], apdu_len, &test_invoke_id,
&test_reject_reason);
ct_test(pTest, len != -1);
ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest, test_reject_reason == reject_reason);
@@ -218,8 +199,7 @@ void testReject(
}
#ifdef TEST_REJECT
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -231,7 +211,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+284 -301
View File
@@ -1,66 +1,66 @@
/**
* @file
* @author Steve Karg
* @date 2004
* @brief Generic ring buffer library for deeply embedded system.
*
* @section LICENSE
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to:
* The Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*
* As a special exception, if other files instantiate templates or
* use macros or inline functions from this file, or you compile
* this file and link it with other works to produce a work based
* on this file, this file does not by itself cause the resulting
* work to be covered by the GNU General Public License. However
* the source code for this file must still be made available in
* accordance with section (3) of the GNU General Public License.
*
* This exception does not invalidate any other reasons why a work
* based on this file might be covered by the GNU General Public
* License.
*
* @section DESCRIPTION
*
* Generic ring buffer library for deeply embedded system.
* It uses a data store whose size is a power of 2 (8, 16, 32, 64, ...)
* and doesn't waste any data bytes. It has very low overhead, and
* utilizes modulo for indexing the data in the data store.
* It uses separate variables for consumer and producer so it can
* be used in multithreaded environment.
*
* See the unit tests for usage examples.
*
*/
* @file
* @author Steve Karg
* @date 2004
* @brief Generic ring buffer library for deeply embedded system.
*
* @section LICENSE
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to:
* The Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*
* As a special exception, if other files instantiate templates or
* use macros or inline functions from this file, or you compile
* this file and link it with other works to produce a work based
* on this file, this file does not by itself cause the resulting
* work to be covered by the GNU General Public License. However
* the source code for this file must still be made available in
* accordance with section (3) of the GNU General Public License.
*
* This exception does not invalidate any other reasons why a work
* based on this file might be covered by the GNU General Public
* License.
*
* @section DESCRIPTION
*
* Generic ring buffer library for deeply embedded system.
* It uses a data store whose size is a power of 2 (8, 16, 32, 64, ...)
* and doesn't waste any data bytes. It has very low overhead, and
* utilizes modulo for indexing the data in the data store.
* It uses separate variables for consumer and producer so it can
* be used in multithreaded environment.
*
* See the unit tests for usage examples.
*
*/
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include "ringbuf.h"
/**
* Returns the number of elements in the ring buffer
*
* @param b - pointer to RING_BUFFER structure
* @return Number of elements in the ring buffer
*/
* Returns the number of elements in the ring buffer
*
* @param b - pointer to RING_BUFFER structure
* @return Number of elements in the ring buffer
*/
unsigned Ringbuf_Count(RING_BUFFER const *b)
{
unsigned head, tail; /* used to avoid volatile decision */
unsigned head, tail; /* used to avoid volatile decision */
if (b) {
head = b->head;
@@ -72,32 +72,32 @@ unsigned Ringbuf_Count(RING_BUFFER const *b)
}
/**
* Returns the empty/full status of the ring buffer
*
* @param b - pointer to RING_BUFFER structure
* @return true if the ring buffer is full, false if it is not.
*/
* Returns the empty/full status of the ring buffer
*
* @param b - pointer to RING_BUFFER structure
* @return true if the ring buffer is full, false if it is not.
*/
bool Ringbuf_Full(RING_BUFFER const *b)
{
return (b ? (Ringbuf_Count(b) == b->element_count) : true);
}
/**
* Returns the empty/full status of the ring buffer
*
* @param b - pointer to RING_BUFFER structure
* @return true if the ring buffer is empty, false if it is not.
*/
* Returns the empty/full status of the ring buffer
*
* @param b - pointer to RING_BUFFER structure
* @return true if the ring buffer is empty, false if it is not.
*/
bool Ringbuf_Empty(RING_BUFFER const *b)
{
return (b ? (Ringbuf_Count(b) == 0) : true);
}
/**
* Updates the depth tracking in the ring buffer
*
* @param b - pointer to RING_BUFFER structure
*/
* Updates the depth tracking in the ring buffer
*
* @param b - pointer to RING_BUFFER structure
*/
static void Ringbuf_Depth_Update(RING_BUFFER *b)
{
unsigned count;
@@ -111,11 +111,11 @@ static void Ringbuf_Depth_Update(RING_BUFFER *b)
}
/**
* Updates the depth tracking in the ring buffer
*
* @param b - pointer to RING_BUFFER structure
* @return largest number of items that have been in the ring buffer
*/
* Updates the depth tracking in the ring buffer
*
* @param b - pointer to RING_BUFFER structure
* @return largest number of items that have been in the ring buffer
*/
unsigned Ringbuf_Depth(RING_BUFFER const *b)
{
unsigned depth = 0;
@@ -128,11 +128,11 @@ unsigned Ringbuf_Depth(RING_BUFFER const *b)
}
/**
* Resets the depth tracking in the ring buffer
*
* @param b - pointer to RING_BUFFER structure
* @return largest number of items that have been in the ring buffer
*/
* Resets the depth tracking in the ring buffer
*
* @param b - pointer to RING_BUFFER structure
* @return largest number of items that have been in the ring buffer
*/
unsigned Ringbuf_Depth_Reset(RING_BUFFER *b)
{
unsigned depth = 0;
@@ -146,11 +146,11 @@ unsigned Ringbuf_Depth_Reset(RING_BUFFER *b)
}
/**
* Gets the capacity of the ring buffer (number of possible elements)
*
* @param b - pointer to RING_BUFFER structure
* @return largest number of items that have been in the ring buffer
*/
* Gets the capacity of the ring buffer (number of possible elements)
*
* @param b - pointer to RING_BUFFER structure
* @return largest number of items that have been in the ring buffer
*/
unsigned Ringbuf_Size(RING_BUFFER const *b)
{
unsigned count = 0;
@@ -163,14 +163,14 @@ unsigned Ringbuf_Size(RING_BUFFER const *b)
}
/**
* Looks at the data from the head of the list without removing it
*
* @param b - pointer to RING_BUFFER structure
* @return pointer to the data, or NULL if nothing in the list
*/
* Looks at the data from the head of the list without removing it
*
* @param b - pointer to RING_BUFFER structure
* @return pointer to the data, or NULL if nothing in the list
*/
volatile uint8_t *Ringbuf_Peek(RING_BUFFER const *b)
{
volatile uint8_t *data_element = NULL; /* return value */
volatile uint8_t *data_element = NULL; /* return value */
if (!Ringbuf_Empty(b)) {
data_element = b->buffer;
@@ -181,28 +181,27 @@ volatile uint8_t *Ringbuf_Peek(RING_BUFFER const *b)
}
/**
* Looks at the data from the next element of the list without removing it
*
* @param b - pointer to RING_BUFFER structure
* @param data_element - find the next element from this one
* @return pointer to the data, or NULL if nothing in the list
*/
volatile uint8_t *Ringbuf_Peek_Next(RING_BUFFER const *b,
uint8_t * data_element)
* Looks at the data from the next element of the list without removing it
*
* @param b - pointer to RING_BUFFER structure
* @param data_element - find the next element from this one
* @return pointer to the data, or NULL if nothing in the list
*/
volatile uint8_t *Ringbuf_Peek_Next(RING_BUFFER const *b, uint8_t *data_element)
{
unsigned index; /* list index */
unsigned index; /* list index */
volatile uint8_t *this_element;
volatile uint8_t *next_element = NULL; /* return value */
volatile uint8_t *next_element = NULL; /* return value */
if (!Ringbuf_Empty(b) && data_element != NULL) {
/* Use (b->head-1) here to avoid walking off end of ring */
for (index = b->tail; index < b->head-1; index++) {
for (index = b->tail; index < b->head - 1; index++) {
/* Find the specified data_element */
this_element = b->buffer +
((index % b->element_count) * b->element_size);
this_element =
b->buffer + ((index % b->element_count) * b->element_size);
if (data_element == this_element) {
/* Found the current element, get the next one on the list */
next_element = b->buffer +
(((index+1) % b->element_count) * b->element_size);
next_element = b->buffer + (((index + 1) % b->element_count) *
b->element_size);
break;
}
}
@@ -212,18 +211,17 @@ volatile uint8_t *Ringbuf_Peek_Next(RING_BUFFER const *b,
}
/**
* Copy the data from the front of the list, and removes it
*
* @param b - pointer to RING_BUFFER structure
* @param data_element - element of data that is loaded with data from ring
* @return true if data was copied, false if list is empty
*/
bool Ringbuf_Pop(RING_BUFFER * b,
uint8_t * data_element)
* Copy the data from the front of the list, and removes it
*
* @param b - pointer to RING_BUFFER structure
* @param data_element - element of data that is loaded with data from ring
* @return true if data was copied, false if list is empty
*/
bool Ringbuf_Pop(RING_BUFFER *b, uint8_t *data_element)
{
bool status = false; /* return value */
bool status = false; /* return value */
volatile uint8_t *ring_data = NULL; /* used to help point ring data */
unsigned i; /* loop counter */
unsigned i; /* loop counter */
if (!Ringbuf_Empty(b)) {
ring_data = b->buffer;
@@ -241,29 +239,28 @@ bool Ringbuf_Pop(RING_BUFFER * b,
}
/**
* Copy the data from the specified element, and removes it and moves other
* elements up the list
*
* @param b - pointer to RING_BUFFER structure
* @param this_element - element to find
* @param data_element - element of data that is loaded with data from ring
* @return true if data was copied, false if list is empty
*/
bool Ringbuf_Pop_Element(RING_BUFFER * b,
uint8_t * this_element,
uint8_t * data_element)
* Copy the data from the specified element, and removes it and moves other
* elements up the list
*
* @param b - pointer to RING_BUFFER structure
* @param this_element - element to find
* @param data_element - element of data that is loaded with data from ring
* @return true if data was copied, false if list is empty
*/
bool Ringbuf_Pop_Element(RING_BUFFER *b, uint8_t *this_element,
uint8_t *data_element)
{
bool status = false; /* return value */
bool status = false; /* return value */
volatile uint8_t *ring_data = NULL; /* used to help point ring data */
volatile uint8_t *prev_data;
unsigned index; /* list index */
unsigned this_index = b->head; /* index of element to remove */
unsigned i; /* loop counter */
unsigned index; /* list index */
unsigned this_index = b->head; /* index of element to remove */
unsigned i; /* loop counter */
if (!Ringbuf_Empty(b) && this_element != NULL) {
for (index = b->tail; index < b->head; index++) {
/* Find the specified data_element */
ring_data = b->buffer +
((index % b->element_count) * b->element_size);
ring_data =
b->buffer + ((index % b->element_count) * b->element_size);
if (this_element == ring_data) {
/* Found the specified element, copy the data if required */
this_index = index;
@@ -277,12 +274,12 @@ bool Ringbuf_Pop_Element(RING_BUFFER * b,
}
if (this_index < b->head) {
/* Found a match, move elements up the list to fill the gap */
for ( index = this_index; index > b->tail; index--) {
for (index = this_index; index > b->tail; index--) {
/* Get pointers to current and previous data_elements */
ring_data = b->buffer +
((index % b->element_count) * b->element_size);
prev_data = b->buffer +
(((index-1) % b->element_count) * b->element_size);
ring_data =
b->buffer + ((index % b->element_count) * b->element_size);
prev_data = b->buffer + (((index - 1) % b->element_count) *
b->element_size);
for (i = 0; i < b->element_size; i++) {
ring_data[i] = prev_data[i];
}
@@ -296,18 +293,17 @@ bool Ringbuf_Pop_Element(RING_BUFFER * b,
}
/**
* Adds an element of data to the ring buffer
*
* @param b - pointer to RING_BUFFER structure
* @param data_element - one element that is copied to the ring buffer
* @return true on succesful add, false if not added
*/
bool Ringbuf_Put(RING_BUFFER * b,
uint8_t * data_element)
* Adds an element of data to the ring buffer
*
* @param b - pointer to RING_BUFFER structure
* @param data_element - one element that is copied to the ring buffer
* @return true on succesful add, false if not added
*/
bool Ringbuf_Put(RING_BUFFER *b, uint8_t *data_element)
{
bool status = false; /* return value */
bool status = false; /* return value */
volatile uint8_t *ring_data = NULL; /* used to help point ring data */
unsigned i; /* loop counter */
unsigned i; /* loop counter */
if (b && data_element) {
/* limit the amount of elements that we accept */
@@ -327,22 +323,21 @@ bool Ringbuf_Put(RING_BUFFER * b,
}
/**
* Adds an element of data to the front of the ring buffer
*
* Note that this function moves the tail on add instead of head,
* so this function cannot be used if you are keeping producer and
* consumer as separate processes (i.e. interrupt handlers)
*
* @param b - pointer to RING_BUFFER structure
* @param data_element - one element to copy to the front of the ring
* @return true on succesful add, false if not added
*/
bool Ringbuf_Put_Front(RING_BUFFER * b,
uint8_t * data_element)
* Adds an element of data to the front of the ring buffer
*
* Note that this function moves the tail on add instead of head,
* so this function cannot be used if you are keeping producer and
* consumer as separate processes (i.e. interrupt handlers)
*
* @param b - pointer to RING_BUFFER structure
* @param data_element - one element to copy to the front of the ring
* @return true on succesful add, false if not added
*/
bool Ringbuf_Put_Front(RING_BUFFER *b, uint8_t *data_element)
{
bool status = false; /* return value */
bool status = false; /* return value */
volatile uint8_t *ring_data = NULL; /* used to help point ring data */
unsigned i = 0; /* loop counter */
unsigned i = 0; /* loop counter */
if (b && data_element) {
/* limit the amount of elements that we accept */
@@ -363,13 +358,13 @@ bool Ringbuf_Put_Front(RING_BUFFER * b,
}
/**
* Gets a pointer to the next free data element of the buffer
* without adding it to the ring.
*
* @param b - pointer to RING_BUFFER structure
* @return pointer to the next data element, or NULL if the list is full
*/
volatile uint8_t *Ringbuf_Data_Peek(RING_BUFFER * b)
* Gets a pointer to the next free data element of the buffer
* without adding it to the ring.
*
* @param b - pointer to RING_BUFFER structure
* @return pointer to the next data element, or NULL if the list is full
*/
volatile uint8_t *Ringbuf_Data_Peek(RING_BUFFER *b)
{
volatile uint8_t *ring_data = NULL; /* used to help point ring data */
@@ -385,15 +380,15 @@ volatile uint8_t *Ringbuf_Data_Peek(RING_BUFFER * b)
}
/**
* Adds the previously peeked element of data to the end of the
* ring buffer.
*
* @param b - pointer to RING_BUFFER structure
* @param data_element - pointer to the peeked data element
* @return true if the buffer has space and the data element points to the
* same memory previously peeked.
*/
bool Ringbuf_Data_Put(RING_BUFFER * b, volatile uint8_t *data_element)
* Adds the previously peeked element of data to the end of the
* ring buffer.
*
* @param b - pointer to RING_BUFFER structure
* @param data_element - pointer to the peeked data element
* @return true if the buffer has space and the data element points to the
* same memory previously peeked.
*/
bool Ringbuf_Data_Put(RING_BUFFER *b, volatile uint8_t *data_element)
{
bool status = false;
volatile uint8_t *ring_data = NULL; /* used to help point ring data */
@@ -416,33 +411,31 @@ bool Ringbuf_Data_Put(RING_BUFFER * b, volatile uint8_t *data_element)
}
/**
* Test that the parameter is a power of two.
*
* @param x unsigned integer value to be tested
*
* @return true if the parameter is a power of 2
*/
static bool isPowerOfTwo (unsigned int x)
* Test that the parameter is a power of two.
*
* @param x unsigned integer value to be tested
*
* @return true if the parameter is a power of 2
*/
static bool isPowerOfTwo(unsigned int x)
{
/* First x in the below expression is for the case when x is 0 */
return x && (!(x&(x-1)));
return x && (!(x & (x - 1)));
}
/**
* Configures the ring buffer data buffer. Note that the element_count
* parameter must be a power of two.
*
* @param b - pointer to RING_BUFFER structure
* @param buffer - pointer to a data buffer that is used to store the ring data
* @param element_size - size of one element in the data block
* @param element_count - number elements in the data block
*
* @return true if ring buffer was initialized
*/
bool Ringbuf_Init(RING_BUFFER * b,
volatile uint8_t * buffer,
unsigned element_size,
unsigned element_count)
* Configures the ring buffer data buffer. Note that the element_count
* parameter must be a power of two.
*
* @param b - pointer to RING_BUFFER structure
* @param buffer - pointer to a data buffer that is used to store the ring data
* @param element_size - size of one element in the data block
* @param element_count - number elements in the data block
*
* @return true if ring buffer was initialized
*/
bool Ringbuf_Init(RING_BUFFER *b, volatile uint8_t *buffer,
unsigned element_size, unsigned element_count)
{
bool status = false;
@@ -467,19 +460,17 @@ bool Ringbuf_Init(RING_BUFFER * b,
#include "ctest.h"
/**
* Unit Test for the ring buffer
*
* @param pTest - test tracking pointer
* @param test_buffer - pointer to RING_BUFFER structure
* @param data_element - one data element
* @param element_size - size of one data element
* @param element_count - number of data elements in the store
*/
static void testRingAroundBuffer(Test * pTest,
RING_BUFFER * test_buffer,
uint8_t * data_element,
unsigned element_size,
unsigned element_count)
* Unit Test for the ring buffer
*
* @param pTest - test tracking pointer
* @param test_buffer - pointer to RING_BUFFER structure
* @param data_element - one data element
* @param element_size - size of one data element
* @param element_count - number of data elements in the store
*/
static void testRingAroundBuffer(Test *pTest, RING_BUFFER *test_buffer,
uint8_t *data_element, unsigned element_size,
unsigned element_count)
{
volatile uint8_t *test_data;
unsigned index;
@@ -492,7 +483,7 @@ static void testRingAroundBuffer(Test * pTest,
/* test the ring around the buffer */
for (index = 0; index < element_count; index++) {
for (count = 1; count < 4; count++) {
value = (index * count)%255;
value = (index * count) % 255;
for (data_index = 0; data_index < element_size; data_index++) {
data_element[data_index] = value;
}
@@ -501,7 +492,7 @@ static void testRingAroundBuffer(Test * pTest,
ct_test(pTest, Ringbuf_Count(test_buffer) == count);
}
for (count = 1; count < 4; count++) {
value = (index * count)%255;
value = (index * count) % 255;
test_data = Ringbuf_Peek(test_buffer);
ct_test(pTest, test_data);
if (test_data) {
@@ -517,19 +508,16 @@ static void testRingAroundBuffer(Test * pTest,
}
/**
* Unit Test for the ring buffer
*
* @param pTest - test tracking pointer
* @param data_store - buffer to store elements
* @param data_element - one data element
* @param element_size - size of one data element
* @param element_count - number of data elements in the store
*/
static bool testRingBuf(Test * pTest,
uint8_t * data_store,
uint8_t * data_element,
unsigned element_size,
unsigned element_count)
* Unit Test for the ring buffer
*
* @param pTest - test tracking pointer
* @param data_store - buffer to store elements
* @param data_element - one data element
* @param element_size - size of one data element
* @param element_count - number of data elements in the store
*/
static bool testRingBuf(Test *pTest, uint8_t *data_store, uint8_t *data_element,
unsigned element_size, unsigned element_count)
{
RING_BUFFER test_buffer;
volatile uint8_t *test_data;
@@ -537,8 +525,8 @@ static bool testRingBuf(Test * pTest,
unsigned data_index;
bool status;
status = Ringbuf_Init(&test_buffer, data_store,
element_size, element_count);
status =
Ringbuf_Init(&test_buffer, data_store, element_size, element_count);
if (!status) {
return false;
}
@@ -558,7 +546,7 @@ static bool testRingBuf(Test * pTest,
ct_test(pTest, test_data[data_index] == data_element[data_index]);
}
ct_test(pTest, !Ringbuf_Empty(&test_buffer));
(void) Ringbuf_Pop(&test_buffer, NULL);
(void)Ringbuf_Pop(&test_buffer, NULL);
ct_test(pTest, Ringbuf_Empty(&test_buffer));
ct_test(pTest, Ringbuf_Depth(&test_buffer) == 1);
@@ -570,7 +558,7 @@ static bool testRingBuf(Test * pTest,
status = Ringbuf_Put(&test_buffer, data_element);
ct_test(pTest, status == true);
ct_test(pTest, !Ringbuf_Empty(&test_buffer));
ct_test(pTest, Ringbuf_Depth(&test_buffer) == (index+1));
ct_test(pTest, Ringbuf_Depth(&test_buffer) == (index + 1));
}
ct_test(pTest, Ringbuf_Depth(&test_buffer) == element_count);
/* verify actions on full buffer */
@@ -593,7 +581,7 @@ static bool testRingBuf(Test * pTest,
ct_test(pTest, test_data[data_index] == index);
}
}
(void) Ringbuf_Pop(&test_buffer, NULL);
(void)Ringbuf_Pop(&test_buffer, NULL);
}
ct_test(pTest, Ringbuf_Empty(&test_buffer));
ct_test(pTest, Ringbuf_Depth(&test_buffer) == element_count);
@@ -601,102 +589,97 @@ static bool testRingBuf(Test * pTest,
ct_test(pTest, Ringbuf_Depth(&test_buffer) == 0);
testRingAroundBuffer(pTest, &test_buffer, data_element, element_size,
element_count);
element_count);
/* adjust the internal index of Ringbuf to test unsigned wrapping */
test_buffer.head = UINT_MAX - 1;
test_buffer.tail = UINT_MAX - 1;
testRingAroundBuffer(pTest, &test_buffer, data_element, element_size,
element_count);
element_count);
return true;
}
/**
* Unit Test for the ring buffer with 16 data elements
*
* @param pTest - test tracking pointer
*/
void testRingBufSizeSmall(Test * pTest)
* Unit Test for the ring buffer with 16 data elements
*
* @param pTest - test tracking pointer
*/
void testRingBufSizeSmall(Test *pTest)
{
bool status;
uint8_t data_element[5];
uint8_t data_store[sizeof(data_element) * NEXT_POWER_OF_2(16)];
status = testRingBuf(pTest, data_store, data_element,
sizeof(data_element),
sizeof(data_store) / sizeof(data_element));
status = testRingBuf(pTest, data_store, data_element, sizeof(data_element),
sizeof(data_store) / sizeof(data_element));
ct_test(pTest, status);
}
/**
* Unit Test for the ring buffer with 32 data elements
*
* @param pTest - test tracking pointer
*/
void testRingBufSizeLarge(Test * pTest)
* Unit Test for the ring buffer with 32 data elements
*
* @param pTest - test tracking pointer
*/
void testRingBufSizeLarge(Test *pTest)
{
bool status;
uint8_t data_element[16];
uint8_t data_store[sizeof(data_element) * NEXT_POWER_OF_2(99)];
status = testRingBuf(pTest, data_store, data_element,
sizeof(data_element),
sizeof(data_store) / sizeof(data_element));
status = testRingBuf(pTest, data_store, data_element, sizeof(data_element),
sizeof(data_store) / sizeof(data_element));
ct_test(pTest, status);
}
/**
* Unit Test for the ring buffer with 32 data elements
*
* @param pTest - test tracking pointer
*/
void testRingBufSizeInvalid(Test * pTest)
* Unit Test for the ring buffer with 32 data elements
*
* @param pTest - test tracking pointer
*/
void testRingBufSizeInvalid(Test *pTest)
{
bool status;
uint8_t data_element[16];
uint8_t data_store[sizeof(data_element) * 99];
status = testRingBuf(pTest, data_store, data_element,
sizeof(data_element),
sizeof(data_store) / sizeof(data_element));
ct_test(pTest, status==false);
status = testRingBuf(pTest, data_store, data_element, sizeof(data_element),
sizeof(data_store) / sizeof(data_element));
ct_test(pTest, status == false);
}
void testRingBufPowerOfTwo(Test * pTest)
void testRingBufPowerOfTwo(Test *pTest)
{
ct_test(pTest, NEXT_POWER_OF_2(3)==4);
ct_test(pTest, NEXT_POWER_OF_2(100)==128);
ct_test(pTest, NEXT_POWER_OF_2(127)==128);
ct_test(pTest, NEXT_POWER_OF_2(128)==128);
ct_test(pTest, NEXT_POWER_OF_2(129)==256);
ct_test(pTest, NEXT_POWER_OF_2(300)==512);
ct_test(pTest, NEXT_POWER_OF_2(500)==512);
ct_test(pTest, NEXT_POWER_OF_2(3) == 4);
ct_test(pTest, NEXT_POWER_OF_2(100) == 128);
ct_test(pTest, NEXT_POWER_OF_2(127) == 128);
ct_test(pTest, NEXT_POWER_OF_2(128) == 128);
ct_test(pTest, NEXT_POWER_OF_2(129) == 256);
ct_test(pTest, NEXT_POWER_OF_2(300) == 512);
ct_test(pTest, NEXT_POWER_OF_2(500) == 512);
}
/**
* Unit Test for the ring buffer peek/pop next element
*
* @param pTest - test tracking pointer
* @param data_store - buffer to store elements
* @param data_element - one data element
* @param element_size - size of one data element
* @param element_count - number of data elements in the store
*/
static bool testRingBufNextElement(Test * pTest,
uint8_t * data_store,
uint8_t * data_element,
unsigned element_size,
unsigned element_count)
* Unit Test for the ring buffer peek/pop next element
*
* @param pTest - test tracking pointer
* @param data_store - buffer to store elements
* @param data_element - one data element
* @param element_size - size of one data element
* @param element_count - number of data elements in the store
*/
static bool testRingBufNextElement(Test *pTest, uint8_t *data_store,
uint8_t *data_element, unsigned element_size,
unsigned element_count)
{
RING_BUFFER test_buffer;
volatile uint8_t *test_data;
unsigned index;
unsigned data_index;
bool status;
status = Ringbuf_Init(&test_buffer, data_store,
element_size, element_count);
status =
Ringbuf_Init(&test_buffer, data_store, element_size, element_count);
if (!status) {
return false;
}
@@ -716,7 +699,7 @@ static bool testRingBufNextElement(Test * pTest,
ct_test(pTest, test_data[data_index] == data_element[data_index]);
}
ct_test(pTest, !Ringbuf_Empty(&test_buffer));
(void) Ringbuf_Pop(&test_buffer, NULL);
(void)Ringbuf_Pop(&test_buffer, NULL);
ct_test(pTest, Ringbuf_Empty(&test_buffer));
ct_test(pTest, Ringbuf_Depth(&test_buffer) == 1);
@@ -728,7 +711,7 @@ static bool testRingBufNextElement(Test * pTest,
status = Ringbuf_Put(&test_buffer, data_element);
ct_test(pTest, status == true);
ct_test(pTest, !Ringbuf_Empty(&test_buffer));
ct_test(pTest, Ringbuf_Depth(&test_buffer) == (index+1));
ct_test(pTest, Ringbuf_Depth(&test_buffer) == (index + 1));
}
ct_test(pTest, Ringbuf_Depth(&test_buffer) == element_count);
ct_test(pTest, Ringbuf_Count(&test_buffer) == element_count);
@@ -753,54 +736,54 @@ static bool testRingBufNextElement(Test * pTest,
/* Walk through ring buffer and pop alternate elements */
test_data = Ringbuf_Peek(&test_buffer);
ct_test(pTest, test_data);
for (index = 1; index < element_count/2; index++) {
for (index = 1; index < element_count / 2; index++) {
test_data = Ringbuf_Peek_Next(&test_buffer, (uint8_t *)test_data);
ct_test(pTest, test_data);
(void) Ringbuf_Pop_Element(&test_buffer, (uint8_t *)test_data, NULL);
(void)Ringbuf_Pop_Element(&test_buffer, (uint8_t *)test_data, NULL);
test_data = Ringbuf_Peek_Next(&test_buffer, (uint8_t *)test_data);
}
ct_test(pTest, Ringbuf_Count(&test_buffer) == element_count/2+1);
ct_test(pTest, Ringbuf_Count(&test_buffer) == element_count / 2 + 1);
/* Walk through ring buffer and check data */
test_data = Ringbuf_Peek(&test_buffer);
ct_test(pTest, test_data);
for (index = 0; index < element_count/2; index++) {
for (index = 0; index < element_count / 2; index++) {
if (test_data) {
for (data_index = 0; data_index < element_size; data_index++) {
ct_test(pTest, test_data[data_index] == index*2);
ct_test(pTest, test_data[data_index] == index * 2);
}
}
test_data = Ringbuf_Peek_Next(&test_buffer, (uint8_t *)test_data);
ct_test(pTest, test_data);
}
ct_test(pTest, Ringbuf_Count(&test_buffer) == element_count/2+1);
ct_test(pTest, Ringbuf_Count(&test_buffer) == element_count / 2 + 1);
return true;
}
/**
* Unit Test for the ring buffer with 16 data elements
*
* @param pTest - test tracking pointer
*/
void testRingBufNextElementSizeSmall(Test * pTest)
* Unit Test for the ring buffer with 16 data elements
*
* @param pTest - test tracking pointer
*/
void testRingBufNextElementSizeSmall(Test *pTest)
{
bool status;
uint8_t data_element[5];
uint8_t data_store[sizeof(data_element) * NEXT_POWER_OF_2(16)];
status = testRingBufNextElement(pTest, data_store, data_element,
sizeof(data_element),
sizeof(data_store) / sizeof(data_element));
sizeof(data_element),
sizeof(data_store) / sizeof(data_element));
ct_test(pTest, status);
}
#ifdef TEST_RING_BUFFER
/**
* Main program entry for Unit Test
*
* @return returns 0 on success, and non-zero on fail.
*/
* Main program entry for Unit Test
*
* @return returns 0 on success, and non-zero on fail.
*/
int main(void)
{
Test *pTest;
@@ -822,7 +805,7 @@ int main(void)
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
+75 -105
View File
@@ -41,41 +41,37 @@
#if BACNET_SVC_RP_A
/* encode service */
int rp_encode_apdu(
uint8_t * apdu,
uint8_t invoke_id,
BACNET_READ_PROPERTY_DATA * rpdata)
int rp_encode_apdu(uint8_t *apdu, uint8_t invoke_id,
BACNET_READ_PROPERTY_DATA *rpdata)
{
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) {
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU);
apdu[2] = invoke_id;
apdu[3] = SERVICE_CONFIRMED_READ_PROPERTY; /* service choice */
apdu[3] = SERVICE_CONFIRMED_READ_PROPERTY; /* service choice */
apdu_len = 4;
if (rpdata->object_type <= BACNET_MAX_OBJECT) {
/* check bounds so that we could create malformed
messages for testing */
len =
encode_context_object_id(&apdu[apdu_len], 0,
rpdata->object_type, rpdata->object_instance);
len = encode_context_object_id(&apdu[apdu_len], 0,
rpdata->object_type,
rpdata->object_instance);
apdu_len += len;
}
if (rpdata->object_property <= MAX_BACNET_PROPERTY_ID) {
/* check bounds so that we could create malformed
messages for testing */
len =
encode_context_enumerated(&apdu[apdu_len], 1,
rpdata->object_property);
len = encode_context_enumerated(&apdu[apdu_len], 1,
rpdata->object_property);
apdu_len += len;
}
/* optional array index */
if (rpdata->array_index != BACNET_ARRAY_ALL) {
len =
encode_context_unsigned(&apdu[apdu_len], 2,
rpdata->array_index);
len = encode_context_unsigned(&apdu[apdu_len], 2,
rpdata->array_index);
apdu_len += len;
}
}
@@ -85,17 +81,15 @@ int rp_encode_apdu(
#endif
/* decode the service request only */
int rp_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
BACNET_READ_PROPERTY_DATA * rpdata)
int rp_decode_service_request(uint8_t *apdu, unsigned apdu_len,
BACNET_READ_PROPERTY_DATA *rpdata)
{
unsigned len = 0;
uint8_t tag_number = 0;
uint32_t len_value_type = 0;
uint16_t type = 0; /* for decoding */
uint32_t property = 0; /* for decoding */
uint32_t array_value = 0; /* for decoding */
uint16_t type = 0; /* for decoding */
uint32_t property = 0; /* for decoding */
uint32_t array_value = 0; /* for decoding */
/* check for value pointers */
if (rpdata) {
@@ -112,22 +106,20 @@ int rp_decode_service_request(
return BACNET_STATUS_REJECT;
}
len += decode_object_id(&apdu[len], &type, &rpdata->object_instance);
rpdata->object_type = (BACNET_OBJECT_TYPE) type;
rpdata->object_type = (BACNET_OBJECT_TYPE)type;
/* Tag 1: Property ID */
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
if (tag_number != 1) {
rpdata->error_code = ERROR_CODE_REJECT_INVALID_TAG;
return BACNET_STATUS_REJECT;
}
len += decode_enumerated(&apdu[len], len_value_type, &property);
rpdata->object_property = (BACNET_PROPERTY_ID) property;
rpdata->object_property = (BACNET_PROPERTY_ID)property;
/* Tag 2: Optional Array Index */
if (len < apdu_len) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
if ((tag_number == 2) && (len < apdu_len)) {
len +=
decode_unsigned(&apdu[len], len_value_type, &array_value);
@@ -148,38 +140,33 @@ int rp_decode_service_request(
return BACNET_STATUS_REJECT;
}
return (int) len;
return (int)len;
}
/* alternate method to encode the ack without extra buffer */
int rp_ack_encode_apdu_init(
uint8_t * apdu,
uint8_t invoke_id,
BACNET_READ_PROPERTY_DATA * rpdata)
int rp_ack_encode_apdu_init(uint8_t *apdu, uint8_t invoke_id,
BACNET_READ_PROPERTY_DATA *rpdata)
{
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) {
apdu[0] = PDU_TYPE_COMPLEX_ACK; /* complex ACK service */
apdu[1] = invoke_id; /* original invoke id from request */
apdu[2] = SERVICE_CONFIRMED_READ_PROPERTY; /* service choice */
apdu[1] = invoke_id; /* original invoke id from request */
apdu[2] = SERVICE_CONFIRMED_READ_PROPERTY; /* service choice */
apdu_len = 3;
/* service ack follows */
len =
encode_context_object_id(&apdu[apdu_len], 0, rpdata->object_type,
rpdata->object_instance);
len = encode_context_object_id(&apdu[apdu_len], 0, rpdata->object_type,
rpdata->object_instance);
apdu_len += len;
len =
encode_context_enumerated(&apdu[apdu_len], 1,
rpdata->object_property);
len = encode_context_enumerated(&apdu[apdu_len], 1,
rpdata->object_property);
apdu_len += len;
/* context 2 array index is optional */
if (rpdata->array_index != BACNET_ARRAY_ALL) {
len =
encode_context_unsigned(&apdu[apdu_len], 2,
rpdata->array_index);
len = encode_context_unsigned(&apdu[apdu_len], 2,
rpdata->array_index);
apdu_len += len;
}
len = encode_opening_tag(&apdu[apdu_len], 3);
@@ -190,10 +177,9 @@ int rp_ack_encode_apdu_init(
}
/* note: encode the application tagged data yourself */
int rp_ack_encode_apdu_object_property_end(
uint8_t * apdu)
int rp_ack_encode_apdu_object_property_end(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) {
apdu_len = encode_closing_tag(&apdu[0], 3);
@@ -202,13 +188,11 @@ int rp_ack_encode_apdu_object_property_end(
return apdu_len;
}
int rp_ack_encode_apdu(
uint8_t * apdu,
uint8_t invoke_id,
BACNET_READ_PROPERTY_DATA * rpdata)
int rp_ack_encode_apdu(uint8_t *apdu, uint8_t invoke_id,
BACNET_READ_PROPERTY_DATA *rpdata)
{
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) {
/* Do the initial encoding */
@@ -223,7 +207,6 @@ int rp_ack_encode_apdu(
return apdu_len;
}
#if BACNET_SVC_RP_A
/** Decode the ReadProperty reply and store the result for one Property in a
* BACNET_READ_PROPERTY_DATA structure.
@@ -236,18 +219,17 @@ int rp_ack_encode_apdu(
* @return Number of decoded bytes (could be less than apdu_len),
* or -1 on decoding error.
*/
int rp_ack_decode_service_request(
uint8_t * apdu,
int apdu_len, /* total length of the apdu */
BACNET_READ_PROPERTY_DATA * rpdata)
int rp_ack_decode_service_request(uint8_t *apdu,
int apdu_len, /* total length of the apdu */
BACNET_READ_PROPERTY_DATA *rpdata)
{
uint8_t tag_number = 0;
uint32_t len_value_type = 0;
int tag_len = 0; /* length of tag decode */
int len = 0; /* total length of decodes */
uint16_t object = 0; /* object type */
uint32_t property = 0; /* for decoding */
uint32_t array_value = 0; /* for decoding */
int tag_len = 0; /* length of tag decode */
int len = 0; /* total length of decodes */
uint16_t object = 0; /* object type */
uint32_t property = 0; /* for decoding */
uint32_t array_value = 0; /* for decoding */
/* FIXME: check apdu_len against the len during decode */
/* Tag 0: Object ID */
@@ -255,14 +237,14 @@ int rp_ack_decode_service_request(
return -1;
len = 1;
len += decode_object_id(&apdu[len], &object, &rpdata->object_instance);
rpdata->object_type = (BACNET_OBJECT_TYPE) object;
rpdata->object_type = (BACNET_OBJECT_TYPE)object;
/* Tag 1: Property ID */
len +=
decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type);
if (tag_number != 1)
return -1;
len += decode_enumerated(&apdu[len], len_value_type, &property);
rpdata->object_property = (BACNET_PROPERTY_ID) property;
rpdata->object_property = (BACNET_PROPERTY_ID)property;
/* Tag 2: Optional Array Index */
tag_len =
decode_tag_number_and_value(&apdu[len], &tag_number, &len_value_type);
@@ -278,7 +260,7 @@ int rp_ack_decode_service_request(
len++;
/* don't decode the application tag number or its data here */
rpdata->application_data = &apdu[len];
rpdata->application_data_len = apdu_len - len - 1 /*closing tag */ ;
rpdata->application_data_len = apdu_len - len - 1 /*closing tag */;
/* len includes the data and the closing tag */
len = apdu_len;
} else {
@@ -294,11 +276,8 @@ int rp_ack_decode_service_request(
#include <string.h>
#include "ctest.h"
int rp_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
uint8_t * invoke_id,
BACNET_READ_PROPERTY_DATA * rpdata)
int rp_decode_apdu(uint8_t *apdu, unsigned apdu_len, uint8_t *invoke_id,
BACNET_READ_PROPERTY_DATA *rpdata)
{
int len = 0;
unsigned offset = 0;
@@ -309,25 +288,22 @@ int rp_decode_apdu(
if (apdu[0] != PDU_TYPE_CONFIRMED_SERVICE_REQUEST)
return -1;
/* apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU); */
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
if (apdu[3] != SERVICE_CONFIRMED_READ_PROPERTY)
return -1;
offset = 4;
if (apdu_len > offset) {
len =
rp_decode_service_request(&apdu[offset], apdu_len - offset,
rpdata);
rp_decode_service_request(&apdu[offset], apdu_len - offset, rpdata);
}
return len;
}
int rp_ack_decode_apdu(
uint8_t * apdu,
int apdu_len, /* total length of the apdu */
uint8_t * invoke_id,
BACNET_READ_PROPERTY_DATA * rpdata)
int rp_ack_decode_apdu(uint8_t *apdu,
int apdu_len, /* total length of the apdu */
uint8_t *invoke_id, BACNET_READ_PROPERTY_DATA *rpdata)
{
int len = 0;
int offset = 0;
@@ -342,19 +318,17 @@ int rp_ack_decode_apdu(
return -1;
offset = 3;
if (apdu_len > offset) {
len =
rp_ack_decode_service_request(&apdu[offset], apdu_len - offset,
rpdata);
len = rp_ack_decode_service_request(&apdu[offset], apdu_len - offset,
rpdata);
}
return len;
}
void testReadPropertyAck(
Test * pTest)
void testReadPropertyAck(Test *pTest)
{
uint8_t apdu[480] = { 0 };
uint8_t apdu2[480] = { 0 };
uint8_t apdu[480] = {0};
uint8_t apdu2[480] = {0};
int len = 0;
int apdu_len = 0;
uint8_t invoke_id = 1;
@@ -370,17 +344,16 @@ void testReadPropertyAck(
rpdata.object_property = PROP_OBJECT_IDENTIFIER;
rpdata.array_index = BACNET_ARRAY_ALL;
rpdata.application_data_len =
encode_bacnet_object_id(&apdu2[0], rpdata.object_type,
rpdata.object_instance);
rpdata.application_data_len = encode_bacnet_object_id(
&apdu2[0], rpdata.object_type, rpdata.object_instance);
rpdata.application_data = &apdu2[0];
len = rp_ack_encode_apdu(&apdu[0], invoke_id, &rpdata);
ct_test(pTest, len != 0);
ct_test(pTest, len != -1);
apdu_len = len;
len = rp_ack_decode_apdu(&apdu[0], apdu_len, /* total length of the apdu */
&test_invoke_id, &test_data);
len = rp_ack_decode_apdu(&apdu[0], apdu_len, /* total length of the apdu */
&test_invoke_id, &test_data);
ct_test(pTest, len != -1);
ct_test(pTest, test_invoke_id == invoke_id);
@@ -389,22 +362,20 @@ void testReadPropertyAck(
ct_test(pTest, test_data.object_property == rpdata.object_property);
ct_test(pTest, test_data.array_index == rpdata.array_index);
ct_test(pTest,
test_data.application_data_len == rpdata.application_data_len);
test_data.application_data_len == rpdata.application_data_len);
/* since object property == object_id, decode the application data using
the appropriate decode function */
len =
decode_object_id(test_data.application_data, &object,
&object_instance);
decode_object_id(test_data.application_data, &object, &object_instance);
object_type = object;
ct_test(pTest, object_type == rpdata.object_type);
ct_test(pTest, object_instance == rpdata.object_instance);
}
void testReadProperty(
Test * pTest)
void testReadProperty(Test *pTest)
{
uint8_t apdu[480] = { 0 };
uint8_t apdu[480] = {0};
int len = 0;
int apdu_len = 0;
uint8_t invoke_id = 128;
@@ -431,8 +402,7 @@ void testReadProperty(
}
#ifdef TEST_READ_PROPERTY
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -446,7 +416,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+228 -299
View File
@@ -44,11 +44,9 @@
#if BACNET_SVC_RPM_A
/* encode the initial portion of the service */
int rpm_encode_apdu_init(
uint8_t * apdu,
uint8_t invoke_id)
int rpm_encode_apdu_init(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) {
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
@@ -61,17 +59,14 @@ int rpm_encode_apdu_init(
return apdu_len;
}
int rpm_encode_apdu_object_begin(
uint8_t * apdu,
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance)
int rpm_encode_apdu_object_begin(uint8_t *apdu, 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) {
apdu_len =
encode_context_object_id(&apdu[0], 0, object_type,
object_instance);
encode_context_object_id(&apdu[0], 0, object_type, object_instance);
/* Tag 1: sequence of ReadAccessSpecification */
apdu_len += encode_opening_tag(&apdu[apdu_len], 1);
}
@@ -79,12 +74,11 @@ int rpm_encode_apdu_object_begin(
return apdu_len;
}
int rpm_encode_apdu_object_property(
uint8_t * apdu,
BACNET_PROPERTY_ID object_property,
uint32_t array_index)
int rpm_encode_apdu_object_property(uint8_t *apdu,
BACNET_PROPERTY_ID object_property,
uint32_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) {
apdu_len = encode_context_enumerated(&apdu[0], 0, object_property);
@@ -97,10 +91,9 @@ int rpm_encode_apdu_object_property(
return apdu_len;
}
int rpm_encode_apdu_object_end(
uint8_t * apdu)
int rpm_encode_apdu_object_end(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) {
apdu_len = encode_closing_tag(&apdu[0], 1);
@@ -117,22 +110,18 @@ int rpm_encode_apdu_object_end(
* @param read_access_data [in] The RPM data to be requested.
* @return Length of encoded bytes, or 0 on failure.
*/
int rpm_encode_apdu(
uint8_t * apdu,
size_t max_apdu,
uint8_t invoke_id,
BACNET_READ_ACCESS_DATA * read_access_data)
int rpm_encode_apdu(uint8_t *apdu, size_t max_apdu, uint8_t invoke_id,
BACNET_READ_ACCESS_DATA *read_access_data)
{
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* length of the data */
BACNET_READ_ACCESS_DATA *rpm_object; /* current object */
uint8_t apdu_temp[16]; /* temp for data before copy */
BACNET_PROPERTY_REFERENCE *rpm_property; /* current property */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* length of the data */
BACNET_READ_ACCESS_DATA *rpm_object; /* current object */
uint8_t apdu_temp[16]; /* temp for data before copy */
BACNET_PROPERTY_REFERENCE *rpm_property; /* current property */
len = rpm_encode_apdu_init(&apdu_temp[0], invoke_id);
len =
(int) memcopy(&apdu[0], &apdu_temp[0], (size_t) apdu_len, (size_t) len,
(size_t) max_apdu);
len = (int)memcopy(&apdu[0], &apdu_temp[0], (size_t)apdu_len, (size_t)len,
(size_t)max_apdu);
if (len == 0) {
return 0;
}
@@ -141,19 +130,17 @@ int rpm_encode_apdu(
while (rpm_object) {
len =
encode_context_object_id(&apdu_temp[0], 0, rpm_object->object_type,
rpm_object->object_instance);
len =
(int) memcopy(&apdu[0], &apdu_temp[0], (size_t) apdu_len,
(size_t) len, (size_t) max_apdu);
rpm_object->object_instance);
len = (int)memcopy(&apdu[0], &apdu_temp[0], (size_t)apdu_len,
(size_t)len, (size_t)max_apdu);
if (len == 0) {
return 0;
}
apdu_len += len;
/* Tag 1: sequence of ReadAccessSpecification */
len = encode_opening_tag(&apdu_temp[0], 1);
len =
(int) memcopy(&apdu[0], &apdu_temp[0], (size_t) apdu_len,
(size_t) len, (size_t) max_apdu);
len = (int)memcopy(&apdu[0], &apdu_temp[0], (size_t)apdu_len,
(size_t)len, (size_t)max_apdu);
if (len == 0) {
return 0;
}
@@ -161,24 +148,20 @@ int rpm_encode_apdu(
rpm_property = rpm_object->listOfProperties;
while (rpm_property) {
/* stuff as many properties into it as APDU length will allow */
len =
encode_context_enumerated(&apdu_temp[0], 0,
rpm_property->propertyIdentifier);
len =
(int) memcopy(&apdu[0], &apdu_temp[0], (size_t) apdu_len,
(size_t) len, (size_t) max_apdu);
len = encode_context_enumerated(&apdu_temp[0], 0,
rpm_property->propertyIdentifier);
len = (int)memcopy(&apdu[0], &apdu_temp[0], (size_t)apdu_len,
(size_t)len, (size_t)max_apdu);
if (len == 0) {
return 0;
}
apdu_len += len;
/* optional array index */
if (rpm_property->propertyArrayIndex != BACNET_ARRAY_ALL) {
len =
encode_context_unsigned(&apdu_temp[0], 1,
rpm_property->propertyArrayIndex);
len =
(int) memcopy(&apdu[0], &apdu_temp[0], (size_t) apdu_len,
(size_t) len, (size_t) max_apdu);
len = encode_context_unsigned(&apdu_temp[0], 1,
rpm_property->propertyArrayIndex);
len = (int)memcopy(&apdu[0], &apdu_temp[0], (size_t)apdu_len,
(size_t)len, (size_t)max_apdu);
if (len == 0) {
return 0;
}
@@ -187,9 +170,8 @@ int rpm_encode_apdu(
rpm_property = rpm_property->next;
}
len = encode_closing_tag(&apdu_temp[0], 1);
len =
(int) memcopy(&apdu[0], &apdu_temp[0], (size_t) apdu_len,
(size_t) len, (size_t) max_apdu);
len = (int)memcopy(&apdu[0], &apdu_temp[0], (size_t)apdu_len,
(size_t)len, (size_t)max_apdu);
if (len == 0) {
return 0;
}
@@ -205,17 +187,15 @@ int rpm_encode_apdu(
/* decode the object portion of the service request only. Bails out if
* tags are wrong or missing/incomplete
*/
int rpm_decode_object_id(
uint8_t * apdu,
unsigned apdu_len,
BACNET_RPM_DATA * rpmdata)
int rpm_decode_object_id(uint8_t *apdu, unsigned apdu_len,
BACNET_RPM_DATA *rpmdata)
{
unsigned len = 0;
uint16_t type = 0; /* for decoding */
uint16_t type = 0; /* for decoding */
/* check for value pointers */
if (apdu && apdu_len && rpmdata) {
if (apdu_len < 5) { /* Must be at least 2 tags and an object id */
if (apdu_len < 5) { /* Must be at least 2 tags and an object id */
rpmdata->error_code = ERROR_CODE_REJECT_MISSING_REQUIRED_PARAMETER;
return BACNET_STATUS_REJECT;
}
@@ -225,23 +205,21 @@ int rpm_decode_object_id(
return BACNET_STATUS_REJECT;
}
len += decode_object_id(&apdu[len], &type, &rpmdata->object_instance);
rpmdata->object_type = (BACNET_OBJECT_TYPE) type;
rpmdata->object_type = (BACNET_OBJECT_TYPE)type;
/* Tag 1: sequence of ReadAccessSpecification */
if (!decode_is_opening_tag_number(&apdu[len], 1)) {
rpmdata->error_code = ERROR_CODE_REJECT_INVALID_TAG;
return BACNET_STATUS_REJECT;
}
len++; /* opening tag is only one octet */
len++; /* opening tag is only one octet */
}
return (int) len;
return (int)len;
}
int rpm_decode_object_end(
uint8_t * apdu,
unsigned apdu_len)
int rpm_decode_object_end(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 (decode_is_closing_tag_number(apdu, 1) == true)
@@ -259,17 +237,15 @@ int rpm_decode_object_end(
-- if omitted with an array the entire array is referenced
}
*/
int rpm_decode_object_property(
uint8_t * apdu,
unsigned apdu_len,
BACNET_RPM_DATA * rpmdata)
int rpm_decode_object_property(uint8_t *apdu, unsigned apdu_len,
BACNET_RPM_DATA *rpmdata)
{
unsigned len = 0;
unsigned option_len = 0;
uint8_t tag_number = 0;
uint32_t len_value_type = 0;
uint32_t property = 0; /* for decoding */
uint32_t array_value = 0; /* for decoding */
uint32_t property = 0; /* for decoding */
uint32_t array_value = 0; /* for decoding */
/* check for valid pointers */
if (apdu && apdu_len && rpmdata) {
@@ -279,9 +255,8 @@ int rpm_decode_object_property(
return BACNET_STATUS_REJECT;
}
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
if (tag_number != 0) {
rpmdata->error_code = ERROR_CODE_REJECT_INVALID_TAG;
return BACNET_STATUS_REJECT;
@@ -292,14 +267,13 @@ int rpm_decode_object_property(
return BACNET_STATUS_REJECT;
}
len += decode_enumerated(&apdu[len], len_value_type, &property);
rpmdata->object_property = (BACNET_PROPERTY_ID) property;
rpmdata->object_property = (BACNET_PROPERTY_ID)property;
/* Assume most probable outcome */
rpmdata->array_index = BACNET_ARRAY_ALL;
/* Tag 1: Optional propertyArrayIndex */
if (IS_CONTEXT_SPECIFIC(apdu[len]) && !IS_CLOSING_TAG(apdu[len])) {
option_len =
(unsigned) decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
option_len = (unsigned)decode_tag_number_and_value(
&apdu[len], &tag_number, &len_value_type);
if (tag_number == 1) {
len += option_len;
/* Should be at least the unsigned array index + 1 tag left */
@@ -315,18 +289,16 @@ int rpm_decode_object_property(
}
}
return (int) len;
return (int)len;
}
int rpm_ack_encode_apdu_init(
uint8_t * apdu,
uint8_t invoke_id)
int rpm_ack_encode_apdu_init(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) {
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_PROP_MULTIPLE; /* service choice */
apdu_len = 3;
}
@@ -334,17 +306,14 @@ int rpm_ack_encode_apdu_init(
return apdu_len;
}
int rpm_ack_encode_apdu_object_begin(
uint8_t * apdu,
BACNET_RPM_DATA * rpmdata)
int rpm_ack_encode_apdu_object_begin(uint8_t *apdu, BACNET_RPM_DATA *rpmdata)
{
int apdu_len = 0; /* total length of the apdu, return value */
int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) {
/* Tag 0: objectIdentifier */
apdu_len =
encode_context_object_id(&apdu[0], 0, rpmdata->object_type,
rpmdata->object_instance);
apdu_len = encode_context_object_id(&apdu[0], 0, rpmdata->object_type,
rpmdata->object_instance);
/* Tag 1: listOfResults */
apdu_len += encode_opening_tag(&apdu[apdu_len], 1);
}
@@ -352,12 +321,11 @@ int rpm_ack_encode_apdu_object_begin(
return apdu_len;
}
int rpm_ack_encode_apdu_object_property(
uint8_t * apdu,
BACNET_PROPERTY_ID object_property,
uint32_t array_index)
int rpm_ack_encode_apdu_object_property(uint8_t *apdu,
BACNET_PROPERTY_ID object_property,
uint32_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) {
/* Tag 2: propertyIdentifier */
@@ -371,20 +339,20 @@ int rpm_ack_encode_apdu_object_property(
return apdu_len;
}
int rpm_ack_encode_apdu_object_property_value(
uint8_t * apdu,
uint8_t * application_data,
unsigned application_data_len)
int rpm_ack_encode_apdu_object_property_value(uint8_t *apdu,
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;
if (apdu) {
/* Tag 4: propertyValue */
apdu_len += encode_opening_tag(&apdu[apdu_len], 4);
if (application_data == &apdu[apdu_len]) { /* Is Data already in place? */
apdu_len += application_data_len; /* Yes, step over data */
} else { /* No, copy data in */
if (application_data ==
&apdu[apdu_len]) { /* Is Data already in place? */
apdu_len += application_data_len; /* Yes, step over data */
} else { /* No, copy data in */
for (len = 0; len < application_data_len; len++) {
apdu[apdu_len++] = application_data[len];
}
@@ -395,18 +363,16 @@ int rpm_ack_encode_apdu_object_property_value(
return apdu_len;
}
int rpm_ack_encode_apdu_object_property_error(
uint8_t * apdu,
BACNET_ERROR_CLASS error_class,
BACNET_ERROR_CODE error_code)
int rpm_ack_encode_apdu_object_property_error(uint8_t *apdu,
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) {
/* Tag 5: propertyAccessError */
apdu_len += encode_opening_tag(&apdu[apdu_len], 5);
apdu_len +=
encode_application_enumerated(&apdu[apdu_len], error_class);
apdu_len += encode_application_enumerated(&apdu[apdu_len], error_class);
apdu_len += encode_application_enumerated(&apdu[apdu_len], error_code);
apdu_len += encode_closing_tag(&apdu[apdu_len], 5);
}
@@ -414,10 +380,9 @@ int rpm_ack_encode_apdu_object_property_error(
return apdu_len;
}
int rpm_ack_encode_apdu_object_end(
uint8_t * apdu)
int rpm_ack_encode_apdu_object_end(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) {
apdu_len = encode_closing_tag(&apdu[0], 1);
@@ -429,14 +394,12 @@ int rpm_ack_encode_apdu_object_end(
#if BACNET_SVC_RPM_A
/* decode the object portion of the service request only */
int rpm_ack_decode_object_id(
uint8_t * apdu,
unsigned apdu_len,
BACNET_OBJECT_TYPE * object_type,
uint32_t * object_instance)
int rpm_ack_decode_object_id(uint8_t *apdu, unsigned apdu_len,
BACNET_OBJECT_TYPE *object_type,
uint32_t *object_instance)
{
unsigned len = 0;
uint16_t type = 0; /* for decoding */
uint16_t type = 0; /* for decoding */
/* check for value pointers */
if (apdu && apdu_len && object_type && object_instance) {
@@ -445,22 +408,20 @@ int rpm_ack_decode_object_id(
return -1;
len += decode_object_id(&apdu[len], &type, object_instance);
if (object_type)
*object_type = (BACNET_OBJECT_TYPE) type;
*object_type = (BACNET_OBJECT_TYPE)type;
/* Tag 1: listOfResults */
if (!decode_is_opening_tag_number(&apdu[len], 1))
return -1;
len++; /* opening tag is only one octet */
len++; /* opening tag is only one octet */
}
return (int) len;
return (int)len;
}
/* is this the end of the list of this objects properties values? */
int rpm_ack_decode_object_end(
uint8_t * apdu,
unsigned apdu_len)
int rpm_ack_decode_object_end(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 (decode_is_closing_tag_number(apdu, 1))
@@ -470,38 +431,34 @@ int rpm_ack_decode_object_end(
return len;
}
int rpm_ack_decode_object_property(
uint8_t * apdu,
unsigned apdu_len,
BACNET_PROPERTY_ID * object_property,
uint32_t * array_index)
int rpm_ack_decode_object_property(uint8_t *apdu, unsigned apdu_len,
BACNET_PROPERTY_ID *object_property,
uint32_t *array_index)
{
unsigned len = 0;
unsigned tag_len = 0;
uint8_t tag_number = 0;
uint32_t len_value_type = 0;
uint32_t property = 0; /* for decoding */
uint32_t array_value = 0; /* for decoding */
uint32_t property = 0; /* for decoding */
uint32_t array_value = 0; /* for decoding */
/* check for valid pointers */
if (apdu && apdu_len && object_property && array_index) {
/* Tag 2: propertyIdentifier */
if (!IS_CONTEXT_SPECIFIC(apdu[len]))
return -1;
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
if (tag_number != 2)
return -1;
len += decode_enumerated(&apdu[len], len_value_type, &property);
if (object_property)
*object_property = (BACNET_PROPERTY_ID) property;
*object_property = (BACNET_PROPERTY_ID)property;
/* Tag 3: Optional propertyArrayIndex */
if ((len < apdu_len) && IS_CONTEXT_SPECIFIC(apdu[len]) &&
(!IS_CLOSING_TAG(apdu[len]))) {
tag_len =
(unsigned) decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
tag_len = (unsigned)decode_tag_number_and_value(
&apdu[len], &tag_number, &len_value_type);
if (tag_number == 3) {
len += tag_len;
len +=
@@ -515,7 +472,7 @@ int rpm_ack_decode_object_property(
}
}
return (int) len;
return (int)len;
}
#endif
@@ -525,12 +482,10 @@ int rpm_ack_decode_object_property(
#include <string.h>
#include "ctest.h"
int rpm_ack_decode_apdu(
uint8_t * apdu,
int apdu_len, /* total length of the apdu */
uint8_t * invoke_id,
uint8_t ** service_request,
unsigned *service_request_len)
int rpm_ack_decode_apdu(uint8_t *apdu,
int apdu_len, /* total length of the apdu */
uint8_t *invoke_id, uint8_t **service_request,
unsigned *service_request_len)
{
int offset = 0;
@@ -553,12 +508,8 @@ int rpm_ack_decode_apdu(
return offset;
}
int rpm_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
uint8_t * invoke_id,
uint8_t ** service_request,
unsigned *service_request_len)
int rpm_decode_apdu(uint8_t *apdu, unsigned apdu_len, uint8_t *invoke_id,
uint8_t **service_request, unsigned *service_request_len)
{
unsigned offset = 0;
@@ -568,7 +519,7 @@ int rpm_decode_apdu(
if (apdu[0] != PDU_TYPE_CONFIRMED_SERVICE_REQUEST)
return -1;
/* apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU); */
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
if (apdu[3] != SERVICE_CONFIRMED_READ_PROP_MULTIPLE)
return -1;
offset = 4;
@@ -583,10 +534,9 @@ int rpm_decode_apdu(
return offset;
}
void testReadPropertyMultiple(
Test * pTest)
void testReadPropertyMultiple(Test *pTest)
{
uint8_t apdu[480] = { 0 };
uint8_t apdu[480] = {0};
int len = 0;
int test_len = 0;
int apdu_len = 0;
@@ -601,38 +551,37 @@ void testReadPropertyMultiple(
rpmdata.object_property = PROP_OBJECT_IDENTIFIER;
rpmdata.array_index = 0;
/* build the RPM - try to make it easy for the Application Layer development */
/* IDEA: similar construction, but pass apdu, apdu_len pointer, size of apdu to
let the called function handle the out of space problem that these get into
by returning a boolean of success/failure.
It almost needs to use the keylist library or something similar.
Also check case of storing a backoff point (i.e. save enough room for object_end) */
/* build the RPM - try to make it easy for the Application Layer development
*/
/* IDEA: similar construction, but pass apdu, apdu_len pointer, size of apdu
to let the called function handle the out of space problem that these get
into by returning a boolean of success/failure. It almost needs to use
the keylist library or something similar. Also check case of storing a
backoff point (i.e. save enough room for object_end) */
apdu_len = rpm_encode_apdu_init(&apdu[0], invoke_id);
/* each object has a beginning and an end */
apdu_len +=
rpm_encode_apdu_object_begin(&apdu[apdu_len], OBJECT_DEVICE, 123);
/* then stuff as many properties into it as APDU length will allow */
apdu_len +=
rpm_encode_apdu_object_property(&apdu[apdu_len],
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL);
apdu_len +=
rpm_encode_apdu_object_property(&apdu[apdu_len], PROP_OBJECT_NAME,
BACNET_ARRAY_ALL);
apdu_len += rpm_encode_apdu_object_property(
&apdu[apdu_len], PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL);
apdu_len += rpm_encode_apdu_object_property(
&apdu[apdu_len], PROP_OBJECT_NAME, BACNET_ARRAY_ALL);
apdu_len += rpm_encode_apdu_object_end(&apdu[apdu_len]);
/* each object has a beginning and an end */
apdu_len +=
rpm_encode_apdu_object_begin(&apdu[apdu_len], OBJECT_ANALOG_INPUT, 33);
apdu_len +=
rpm_encode_apdu_object_property(&apdu[apdu_len],
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL);
apdu_len +=
rpm_encode_apdu_object_property(&apdu[apdu_len], PROP_ALL,
BACNET_ARRAY_ALL);
apdu_len += rpm_encode_apdu_object_property(
&apdu[apdu_len], PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL);
apdu_len += rpm_encode_apdu_object_property(&apdu[apdu_len], PROP_ALL,
BACNET_ARRAY_ALL);
apdu_len += rpm_encode_apdu_object_end(&apdu[apdu_len]);
ct_test(pTest, apdu_len != 0);
test_len = rpm_decode_apdu(&apdu[0], apdu_len, &test_invoke_id, &service_request, /* will point to the service request in the apdu */
test_len = rpm_decode_apdu(
&apdu[0], apdu_len, &test_invoke_id,
&service_request, /* will point to the service request in the apdu */
&service_request_len);
ct_test(pTest, test_len != -1);
ct_test(pTest, test_invoke_id == invoke_id);
@@ -646,71 +595,61 @@ void testReadPropertyMultiple(
ct_test(pTest, rpmdata.object_instance == 123);
len = test_len;
/* decode the object property portion of the service request */
test_len =
rpm_decode_object_property(&service_request[len],
service_request_len - len, &rpmdata);
test_len = rpm_decode_object_property(&service_request[len],
service_request_len - len, &rpmdata);
ct_test(pTest, test_len > 0);
ct_test(pTest, rpmdata.object_property == PROP_OBJECT_IDENTIFIER);
ct_test(pTest, rpmdata.array_index == BACNET_ARRAY_ALL);
len += test_len;
test_len =
rpm_decode_object_property(&service_request[len],
service_request_len - len, &rpmdata);
test_len = rpm_decode_object_property(&service_request[len],
service_request_len - len, &rpmdata);
ct_test(pTest, test_len > 0);
ct_test(pTest, rpmdata.object_property == PROP_OBJECT_NAME);
ct_test(pTest, rpmdata.array_index == BACNET_ARRAY_ALL);
len += test_len;
/* try again - we should fail */
test_len =
rpm_decode_object_property(&service_request[len],
service_request_len - len, &rpmdata);
test_len = rpm_decode_object_property(&service_request[len],
service_request_len - len, &rpmdata);
ct_test(pTest, test_len < 0);
/* is it the end of this object? */
test_len =
rpm_decode_object_end(&service_request[len],
service_request_len - len);
rpm_decode_object_end(&service_request[len], service_request_len - len);
ct_test(pTest, test_len == 1);
len += test_len;
/* try to decode an object id */
test_len =
rpm_decode_object_id(&service_request[len], service_request_len - len,
&rpmdata);
test_len = rpm_decode_object_id(&service_request[len],
service_request_len - len, &rpmdata);
ct_test(pTest, test_len > 0);
ct_test(pTest, rpmdata.object_type == OBJECT_ANALOG_INPUT);
ct_test(pTest, rpmdata.object_instance == 33);
len += test_len;
/* decode the object property portion of the service request only */
test_len =
rpm_decode_object_property(&service_request[len],
service_request_len - len, &rpmdata);
test_len = rpm_decode_object_property(&service_request[len],
service_request_len - len, &rpmdata);
ct_test(pTest, test_len > 0);
ct_test(pTest, rpmdata.object_property == PROP_OBJECT_IDENTIFIER);
ct_test(pTest, rpmdata.array_index == BACNET_ARRAY_ALL);
len += test_len;
test_len =
rpm_decode_object_property(&service_request[len],
service_request_len - len, &rpmdata);
test_len = rpm_decode_object_property(&service_request[len],
service_request_len - len, &rpmdata);
ct_test(pTest, test_len > 0);
ct_test(pTest, rpmdata.object_property == PROP_ALL);
ct_test(pTest, rpmdata.array_index == BACNET_ARRAY_ALL);
len += test_len;
test_len =
rpm_decode_object_property(&service_request[len],
service_request_len - len, &rpmdata);
test_len = rpm_decode_object_property(&service_request[len],
service_request_len - len, &rpmdata);
ct_test(pTest, test_len < 0);
/* got an error -1, is it the end of this object? */
test_len =
rpm_decode_object_end(&service_request[len],
service_request_len - len);
rpm_decode_object_end(&service_request[len], service_request_len - len);
ct_test(pTest, test_len == 1);
len += test_len;
ct_test(pTest, len == service_request_len);
}
void testReadPropertyMultipleAck(
Test * pTest)
void testReadPropertyMultipleAck(Test *pTest)
{
uint8_t apdu[480] = { 0 };
uint8_t apdu[480] = {0};
int len = 0;
int test_len = 0;
int apdu_len = 0;
@@ -722,9 +661,9 @@ void testReadPropertyMultipleAck(
uint32_t object_instance = 0;
BACNET_PROPERTY_ID object_property = PROP_OBJECT_IDENTIFIER;
uint32_t array_index = 0;
BACNET_APPLICATION_DATA_VALUE application_data[4] = { {0} };
BACNET_APPLICATION_DATA_VALUE test_application_data = { 0 };
uint8_t application_data_buffer[MAX_APDU] = { 0 };
BACNET_APPLICATION_DATA_VALUE application_data[4] = {{0}};
BACNET_APPLICATION_DATA_VALUE test_application_data = {0};
uint8_t application_data_buffer[MAX_APDU] = {0};
int application_data_buffer_len = 0;
BACNET_ERROR_CLASS error_class;
BACNET_ERROR_CODE error_code;
@@ -745,32 +684,28 @@ void testReadPropertyMultipleAck(
rpmdata.object_instance = 123;
apdu_len += rpm_ack_encode_apdu_object_begin(&apdu[apdu_len], &rpmdata);
/* reply property */
apdu_len +=
rpm_ack_encode_apdu_object_property(&apdu[apdu_len],
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL);
apdu_len += rpm_ack_encode_apdu_object_property(
&apdu[apdu_len], PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL);
/* reply value */
application_data[0].tag = BACNET_APPLICATION_TAG_OBJECT_ID;
application_data[0].type.Object_Id.type = OBJECT_DEVICE;
application_data[0].type.Object_Id.instance = 123;
application_data_buffer_len =
bacapp_encode_application_data(&application_data_buffer[0],
&application_data[0]);
apdu_len +=
rpm_ack_encode_apdu_object_property_value(&apdu[apdu_len],
&application_data_buffer[0], application_data_buffer_len);
application_data_buffer_len = bacapp_encode_application_data(
&application_data_buffer[0], &application_data[0]);
apdu_len += rpm_ack_encode_apdu_object_property_value(
&apdu[apdu_len], &application_data_buffer[0],
application_data_buffer_len);
/* reply property */
apdu_len +=
rpm_ack_encode_apdu_object_property(&apdu[apdu_len], PROP_OBJECT_TYPE,
BACNET_ARRAY_ALL);
apdu_len += rpm_ack_encode_apdu_object_property(
&apdu[apdu_len], PROP_OBJECT_TYPE, BACNET_ARRAY_ALL);
/* reply value */
application_data[1].tag = BACNET_APPLICATION_TAG_ENUMERATED;
application_data[1].type.Enumerated = OBJECT_DEVICE;
application_data_buffer_len =
bacapp_encode_application_data(&application_data_buffer[0],
&application_data[1]);
apdu_len +=
rpm_ack_encode_apdu_object_property_value(&apdu[apdu_len],
&application_data_buffer[0], application_data_buffer_len);
application_data_buffer_len = bacapp_encode_application_data(
&application_data_buffer[0], &application_data[1]);
apdu_len += rpm_ack_encode_apdu_object_property_value(
&apdu[apdu_len], &application_data_buffer[0],
application_data_buffer_len);
/* object end */
apdu_len += rpm_ack_encode_apdu_object_end(&apdu[apdu_len]);
@@ -779,49 +714,46 @@ void testReadPropertyMultipleAck(
rpmdata.object_instance = 33;
apdu_len += rpm_ack_encode_apdu_object_begin(&apdu[apdu_len], &rpmdata);
/* reply property */
apdu_len +=
rpm_ack_encode_apdu_object_property(&apdu[apdu_len],
PROP_PRESENT_VALUE, BACNET_ARRAY_ALL);
apdu_len += rpm_ack_encode_apdu_object_property(
&apdu[apdu_len], PROP_PRESENT_VALUE, BACNET_ARRAY_ALL);
/* reply value */
application_data[2].tag = BACNET_APPLICATION_TAG_REAL;
application_data[2].type.Real = 0.0;
application_data_buffer_len =
bacapp_encode_application_data(&application_data_buffer[0],
&application_data[2]);
apdu_len +=
rpm_ack_encode_apdu_object_property_value(&apdu[apdu_len],
&application_data_buffer[0], application_data_buffer_len);
application_data_buffer_len = bacapp_encode_application_data(
&application_data_buffer[0], &application_data[2]);
apdu_len += rpm_ack_encode_apdu_object_property_value(
&apdu[apdu_len], &application_data_buffer[0],
application_data_buffer_len);
/* reply property */
apdu_len +=
rpm_ack_encode_apdu_object_property(&apdu[apdu_len], PROP_DEADBAND,
BACNET_ARRAY_ALL);
apdu_len += rpm_ack_encode_apdu_object_property(
&apdu[apdu_len], PROP_DEADBAND, BACNET_ARRAY_ALL);
/* reply error */
apdu_len +=
rpm_ack_encode_apdu_object_property_error(&apdu[apdu_len],
ERROR_CLASS_PROPERTY, ERROR_CODE_UNKNOWN_PROPERTY);
apdu_len += rpm_ack_encode_apdu_object_property_error(
&apdu[apdu_len], ERROR_CLASS_PROPERTY, ERROR_CODE_UNKNOWN_PROPERTY);
/* object end */
apdu_len += rpm_ack_encode_apdu_object_end(&apdu[apdu_len]);
ct_test(pTest, apdu_len != 0);
/****** decode the packet ******/
test_len = rpm_ack_decode_apdu(&apdu[0], apdu_len, &test_invoke_id, &service_request, /* will point to the service request in the apdu */
/****** decode the packet ******/
test_len = rpm_ack_decode_apdu(
&apdu[0], apdu_len, &test_invoke_id,
&service_request, /* will point to the service request in the apdu */
&service_request_len);
ct_test(pTest, test_len != -1);
ct_test(pTest, test_invoke_id == invoke_id);
ct_test(pTest, service_request != NULL);
ct_test(pTest, service_request_len > 0);
/* the first part should be the first object id */
test_len =
rpm_ack_decode_object_id(service_request, service_request_len,
&object_type, &object_instance);
test_len = rpm_ack_decode_object_id(service_request, service_request_len,
&object_type, &object_instance);
ct_test(pTest, test_len != -1);
ct_test(pTest, object_type == OBJECT_DEVICE);
ct_test(pTest, object_instance == 123);
len = test_len;
/* extract the property */
test_len =
rpm_ack_decode_object_property(&service_request[len],
service_request_len - len, &object_property, &array_index);
test_len = rpm_ack_decode_object_property(&service_request[len],
service_request_len - len,
&object_property, &array_index);
ct_test(pTest, object_property == PROP_OBJECT_IDENTIFIER);
ct_test(pTest, array_index == BACNET_ARRAY_ALL);
len += test_len;
@@ -831,19 +763,19 @@ void testReadPropertyMultipleAck(
/* decode the object property portion of the service request */
/* note: if this was an array, there could have been
more than one element to decode */
test_len =
bacapp_decode_application_data(&service_request[len],
service_request_len - len, &test_application_data);
test_len = bacapp_decode_application_data(&service_request[len],
service_request_len - len,
&test_application_data);
ct_test(pTest, test_len > 0);
ct_test(pTest, bacapp_same_value(&application_data[0],
&test_application_data));
ct_test(pTest,
bacapp_same_value(&application_data[0], &test_application_data));
len += test_len;
ct_test(pTest, decode_is_closing_tag_number(&service_request[len], 4));
len++;
/* see if there is another property */
test_len =
rpm_ack_decode_object_property(&service_request[len],
service_request_len - len, &object_property, &array_index);
test_len = rpm_ack_decode_object_property(&service_request[len],
service_request_len - len,
&object_property, &array_index);
ct_test(pTest, test_len != -1);
ct_test(pTest, object_property == PROP_OBJECT_TYPE);
ct_test(pTest, array_index == BACNET_ARRAY_ALL);
@@ -852,39 +784,38 @@ void testReadPropertyMultipleAck(
ct_test(pTest, decode_is_opening_tag_number(&service_request[len], 4));
len++;
/* decode the object property portion of the service request */
test_len =
bacapp_decode_application_data(&service_request[len],
service_request_len - len, &test_application_data);
test_len = bacapp_decode_application_data(&service_request[len],
service_request_len - len,
&test_application_data);
ct_test(pTest, test_len > 0);
ct_test(pTest, bacapp_same_value(&application_data[1],
&test_application_data));
ct_test(pTest,
bacapp_same_value(&application_data[1], &test_application_data));
len += test_len;
ct_test(pTest, decode_is_closing_tag_number(&service_request[len], 4));
len++;
/* see if there is another property */
/* this time we should fail */
test_len =
rpm_ack_decode_object_property(&service_request[len],
service_request_len - len, &object_property, &array_index);
test_len = rpm_ack_decode_object_property(&service_request[len],
service_request_len - len,
&object_property, &array_index);
ct_test(pTest, test_len == -1);
/* see if it is the end of this object */
test_len =
rpm_ack_decode_object_end(&service_request[len],
service_request_len - len);
test_len = rpm_ack_decode_object_end(&service_request[len],
service_request_len - len);
ct_test(pTest, test_len == 1);
len += test_len;
/* try to decode another object id */
test_len =
rpm_ack_decode_object_id(&service_request[len],
service_request_len - len, &object_type, &object_instance);
test_len = rpm_ack_decode_object_id(&service_request[len],
service_request_len - len, &object_type,
&object_instance);
ct_test(pTest, test_len != -1);
ct_test(pTest, object_type == OBJECT_ANALOG_INPUT);
ct_test(pTest, object_instance == 33);
len += test_len;
/* decode the object property portion of the service request only */
test_len =
rpm_ack_decode_object_property(&service_request[len],
service_request_len - len, &object_property, &array_index);
test_len = rpm_ack_decode_object_property(&service_request[len],
service_request_len - len,
&object_property, &array_index);
ct_test(pTest, test_len != -1);
ct_test(pTest, object_property == PROP_PRESENT_VALUE);
ct_test(pTest, array_index == BACNET_ARRAY_ALL);
@@ -893,19 +824,19 @@ void testReadPropertyMultipleAck(
ct_test(pTest, decode_is_opening_tag_number(&service_request[len], 4));
len++;
/* decode the object property portion of the service request */
test_len =
bacapp_decode_application_data(&service_request[len],
service_request_len - len, &test_application_data);
test_len = bacapp_decode_application_data(&service_request[len],
service_request_len - len,
&test_application_data);
ct_test(pTest, test_len > 0);
ct_test(pTest, bacapp_same_value(&application_data[2],
&test_application_data));
ct_test(pTest,
bacapp_same_value(&application_data[2], &test_application_data));
len += test_len;
ct_test(pTest, decode_is_closing_tag_number(&service_request[len], 4));
len++;
/* see if there is another property */
test_len =
rpm_ack_decode_object_property(&service_request[len],
service_request_len - len, &object_property, &array_index);
test_len = rpm_ack_decode_object_property(&service_request[len],
service_request_len - len,
&object_property, &array_index);
ct_test(pTest, test_len != -1);
ct_test(pTest, object_property == PROP_DEADBAND);
ct_test(pTest, array_index == BACNET_ARRAY_ALL);
@@ -914,9 +845,9 @@ void testReadPropertyMultipleAck(
ct_test(pTest, decode_is_opening_tag_number(&service_request[len], 5));
len++;
/* it was an error reply */
test_len =
bacerror_decode_error_class_and_code(&service_request[len],
service_request_len - len, &error_class, &error_code);
test_len = bacerror_decode_error_class_and_code(&service_request[len],
service_request_len - len,
&error_class, &error_code);
ct_test(pTest, test_len != 0);
ct_test(pTest, error_class == ERROR_CLASS_PROPERTY);
ct_test(pTest, error_code == ERROR_CODE_UNKNOWN_PROPERTY);
@@ -924,27 +855,25 @@ void testReadPropertyMultipleAck(
ct_test(pTest, decode_is_closing_tag_number(&service_request[len], 5));
len++;
/* is there another property? */
test_len =
rpm_ack_decode_object_property(&service_request[len],
service_request_len - len, &object_property, &array_index);
test_len = rpm_ack_decode_object_property(&service_request[len],
service_request_len - len,
&object_property, &array_index);
ct_test(pTest, test_len == -1);
/* got an error -1, is it the end of this object? */
test_len =
rpm_ack_decode_object_end(&service_request[len],
service_request_len - len);
test_len = rpm_ack_decode_object_end(&service_request[len],
service_request_len - len);
ct_test(pTest, test_len == 1);
len += test_len;
/* check for another object */
test_len =
rpm_ack_decode_object_id(&service_request[len],
service_request_len - len, &object_type, &object_instance);
test_len = rpm_ack_decode_object_id(&service_request[len],
service_request_len - len, &object_type,
&object_instance);
ct_test(pTest, test_len == 0);
ct_test(pTest, len == service_request_len);
}
#ifdef TEST_READ_PROPERTY_MULTIPLE
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -958,7 +887,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+25 -35
View File
@@ -42,11 +42,10 @@
#include <stddef.h>
#include "sbuf.h"
void sbuf_init(
STATIC_BUFFER * b, /* static buffer structure */
char *data, /* data block */
unsigned size)
{ /* actual size, in bytes, of the data block or array of data */
void sbuf_init(STATIC_BUFFER *b, /* static buffer structure */
char *data, /* data block */
unsigned size)
{ /* actual size, in bytes, of the data block or array of data */
if (b) {
b->data = data;
b->size = size;
@@ -57,38 +56,33 @@ void sbuf_init(
}
/* returns true if count==0, false if count > 0 */
bool sbuf_empty(
STATIC_BUFFER const *b)
bool sbuf_empty(STATIC_BUFFER const *b)
{
return (b ? (b->count == 0) : false);
}
char *sbuf_data(
STATIC_BUFFER const *b)
char *sbuf_data(STATIC_BUFFER const *b)
{
return (b ? b->data : NULL);
}
unsigned sbuf_size(
STATIC_BUFFER * b)
unsigned sbuf_size(STATIC_BUFFER *b)
{
return (b ? b->size : 0);
}
unsigned sbuf_count(
STATIC_BUFFER * b)
unsigned sbuf_count(STATIC_BUFFER *b)
{
return (b ? b->count : 0);
}
/* returns true if successful, false if not enough room to append data */
bool sbuf_put(
STATIC_BUFFER * b, /* static buffer structure */
unsigned offset, /* where to start */
char *data, /* data to place in buffer */
unsigned data_size)
{ /* how many bytes to add */
bool status = false; /* return value */
bool sbuf_put(STATIC_BUFFER *b, /* static buffer structure */
unsigned offset, /* where to start */
char *data, /* data to place in buffer */
unsigned data_size)
{ /* how many bytes to add */
bool status = false; /* return value */
if (b && b->data) {
if (((offset + data_size) < b->size)) {
@@ -107,11 +101,10 @@ bool sbuf_put(
}
/* returns true if successful, false if not enough room to append data */
bool sbuf_append(
STATIC_BUFFER * b, /* static buffer structure */
char *data, /* data to place in buffer */
unsigned data_size)
{ /* how many bytes to add */
bool sbuf_append(STATIC_BUFFER *b, /* static buffer structure */
char *data, /* data to place in buffer */
unsigned data_size)
{ /* how many bytes to add */
unsigned count = 0;
if (b) {
@@ -122,11 +115,10 @@ bool sbuf_append(
}
/* returns true if successful, false if not enough room to append data */
bool sbuf_truncate(
STATIC_BUFFER * b, /* static buffer structure */
unsigned count)
{ /* total number of bytes in to remove */
bool status = false; /* return value */
bool sbuf_truncate(STATIC_BUFFER *b, /* static buffer structure */
unsigned count)
{ /* total number of bytes in to remove */
bool status = false; /* return value */
if (b) {
if (count < b->size) {
@@ -144,8 +136,7 @@ bool sbuf_truncate(
#include "ctest.h"
void testStaticBuffer(
Test * pTest)
void testStaticBuffer(Test *pTest)
{
STATIC_BUFFER sbuffer;
char *data1 = "Joshua";
@@ -198,8 +189,7 @@ void testStaticBuffer(
}
#ifdef TEST_STATIC_BUFFER
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -212,7 +202,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
+58 -96
View File
@@ -37,9 +37,7 @@
/** @file timestamp.c Encode/Decode BACnet Timestamps */
void bacapp_timestamp_sequence_set(
BACNET_TIMESTAMP * dest,
uint16_t sequenceNum)
void bacapp_timestamp_sequence_set(BACNET_TIMESTAMP *dest, uint16_t sequenceNum)
{
if (dest) {
dest->tag = TIME_STAMP_SEQUENCE;
@@ -47,9 +45,7 @@ void bacapp_timestamp_sequence_set(
}
}
void bacapp_timestamp_time_set(
BACNET_TIMESTAMP * dest,
BACNET_TIME *btime)
void bacapp_timestamp_time_set(BACNET_TIMESTAMP *dest, BACNET_TIME *btime)
{
if (dest && btime) {
dest->tag = TIME_STAMP_TIME;
@@ -57,9 +53,8 @@ void bacapp_timestamp_time_set(
}
}
void bacapp_timestamp_datetime_set(
BACNET_TIMESTAMP * dest,
BACNET_DATE_TIME * bdateTime)
void bacapp_timestamp_datetime_set(BACNET_TIMESTAMP *dest,
BACNET_DATE_TIME *bdateTime)
{
if (dest && bdateTime) {
dest->tag = TIME_STAMP_DATETIME;
@@ -67,9 +62,7 @@ void bacapp_timestamp_datetime_set(
}
}
void bacapp_timestamp_copy(
BACNET_TIMESTAMP * dest,
BACNET_TIMESTAMP * src)
void bacapp_timestamp_copy(BACNET_TIMESTAMP *dest, BACNET_TIMESTAMP *src)
{
if (dest && src) {
dest->tag = src->tag;
@@ -89,11 +82,9 @@ void bacapp_timestamp_copy(
}
}
int bacapp_encode_timestamp(
uint8_t * apdu,
BACNET_TIMESTAMP * value)
int bacapp_encode_timestamp(uint8_t *apdu, BACNET_TIMESTAMP *value)
{
int len = 0; /* length of each encoding */
int len = 0; /* length of each encoding */
if (value && apdu) {
switch (value->tag) {
@@ -102,15 +93,13 @@ int bacapp_encode_timestamp(
break;
case TIME_STAMP_SEQUENCE:
len =
encode_context_unsigned(&apdu[0], 1,
value->value.sequenceNum);
len = encode_context_unsigned(&apdu[0], 1,
value->value.sequenceNum);
break;
case TIME_STAMP_DATETIME:
len =
bacapp_encode_context_datetime(&apdu[0], 2,
&value->value.dateTime);
len = bacapp_encode_context_datetime(&apdu[0], 2,
&value->value.dateTime);
break;
default:
@@ -123,12 +112,10 @@ int bacapp_encode_timestamp(
return len;
}
int bacapp_encode_context_timestamp(
uint8_t * apdu,
uint8_t tag_number,
BACNET_TIMESTAMP * value)
int bacapp_encode_context_timestamp(uint8_t *apdu, uint8_t tag_number,
BACNET_TIMESTAMP *value)
{
int len = 0; /* length of each encoding */
int len = 0; /* length of each encoding */
int apdu_len = 0;
if (value && apdu) {
@@ -142,9 +129,7 @@ int bacapp_encode_context_timestamp(
return apdu_len;
}
int bacapp_decode_timestamp(
uint8_t * apdu,
BACNET_TIMESTAMP * value)
int bacapp_decode_timestamp(uint8_t *apdu, BACNET_TIMESTAMP *value)
{
int len = 0;
int section_len;
@@ -152,18 +137,17 @@ int bacapp_decode_timestamp(
uint32_t sequenceNum;
if (apdu) {
section_len =
decode_tag_number_and_value(&apdu[len], &value->tag,
&len_value_type);
section_len = decode_tag_number_and_value(&apdu[len], &value->tag,
&len_value_type);
if (-1 == section_len) {
return -1;
}
switch (value->tag) {
case TIME_STAMP_TIME:
if ((section_len =
decode_context_bacnet_time(&apdu[len], TIME_STAMP_TIME,
&value->value.time)) == -1) {
if ((section_len = decode_context_bacnet_time(
&apdu[len], TIME_STAMP_TIME, &value->value.time)) ==
-1) {
return -1;
} else {
len += section_len;
@@ -171,14 +155,14 @@ int bacapp_decode_timestamp(
break;
case TIME_STAMP_SEQUENCE:
if ((section_len =
decode_context_unsigned(&apdu[len],
TIME_STAMP_SEQUENCE, &sequenceNum)) == -1) {
if ((section_len = decode_context_unsigned(
&apdu[len], TIME_STAMP_SEQUENCE, &sequenceNum)) ==
-1) {
return -1;
} else {
if (sequenceNum <= 0xffff) {
len += section_len;
value->value.sequenceNum = (uint16_t) sequenceNum;
value->value.sequenceNum = (uint16_t)sequenceNum;
} else {
return -1;
}
@@ -186,10 +170,9 @@ int bacapp_decode_timestamp(
break;
case TIME_STAMP_DATETIME:
if ((section_len =
bacapp_decode_context_datetime(&apdu[len],
TIME_STAMP_DATETIME,
&value->value.dateTime)) == -1) {
if ((section_len = bacapp_decode_context_datetime(
&apdu[len], TIME_STAMP_DATETIME,
&value->value.dateTime)) == -1) {
return -1;
} else {
len += section_len;
@@ -204,15 +187,12 @@ int bacapp_decode_timestamp(
return len;
}
int bacapp_decode_context_timestamp(
uint8_t * apdu,
uint8_t tag_number,
BACNET_TIMESTAMP * value)
int bacapp_decode_context_timestamp(uint8_t *apdu, uint8_t tag_number,
BACNET_TIMESTAMP *value)
{
int len = 0;
int section_len;
if (decode_is_opening_tag_number(&apdu[len], tag_number)) {
len++;
section_len = bacapp_decode_timestamp(&apdu[len], value);
@@ -234,9 +214,7 @@ int bacapp_decode_context_timestamp(
#include <string.h>
#include "ctest.h"
void testTimestampSequence(
Test * pTest)
void testTimestampSequence(Test *pTest)
{
BACNET_TIMESTAMP testTimestampIn;
BACNET_TIMESTAMP testTimestampOut;
@@ -249,19 +227,16 @@ void testTimestampSequence(
memset(&testTimestampOut, 0, sizeof(testTimestampOut));
inLen = bacapp_encode_context_timestamp(buffer, 2, &testTimestampIn);
outLen = bacapp_decode_context_timestamp(buffer, 2, &testTimestampOut);
ct_test(pTest, inLen == outLen);
ct_test(pTest, testTimestampIn.tag == testTimestampOut.tag);
ct_test(pTest,
testTimestampIn.value.sequenceNum ==
testTimestampOut.value.sequenceNum);
ct_test(pTest, testTimestampIn.value.sequenceNum ==
testTimestampOut.value.sequenceNum);
}
void testTimestampTime(
Test * pTest)
void testTimestampTime(Test *pTest)
{
BACNET_TIMESTAMP testTimestampIn;
BACNET_TIMESTAMP testTimestampOut;
@@ -277,25 +252,22 @@ void testTimestampTime(
memset(&testTimestampOut, 0, sizeof(testTimestampOut));
inLen = bacapp_encode_context_timestamp(buffer, 2, &testTimestampIn);
outLen = bacapp_decode_context_timestamp(buffer, 2, &testTimestampOut);
ct_test(pTest, inLen == outLen);
ct_test(pTest, testTimestampIn.tag == testTimestampOut.tag);
ct_test(pTest, testTimestampIn.value.time.hour ==
testTimestampOut.value.time.hour);
ct_test(pTest,
testTimestampIn.value.time.hour == testTimestampOut.value.time.hour);
testTimestampIn.value.time.min == testTimestampOut.value.time.min);
ct_test(pTest,
testTimestampIn.value.time.min == testTimestampOut.value.time.min);
ct_test(pTest,
testTimestampIn.value.time.sec == testTimestampOut.value.time.sec);
ct_test(pTest,
testTimestampIn.value.time.hundredths ==
testTimestampOut.value.time.hundredths);
testTimestampIn.value.time.sec == testTimestampOut.value.time.sec);
ct_test(pTest, testTimestampIn.value.time.hundredths ==
testTimestampOut.value.time.hundredths);
}
void testTimestampTimeDate(
Test * pTest)
void testTimestampTimeDate(Test *pTest)
{
BACNET_TIMESTAMP testTimestampIn;
BACNET_TIMESTAMP testTimestampOut;
@@ -321,38 +293,28 @@ void testTimestampTimeDate(
ct_test(pTest, inLen == outLen);
ct_test(pTest, testTimestampIn.tag == testTimestampOut.tag);
ct_test(pTest,
testTimestampIn.value.dateTime.time.hour ==
testTimestampOut.value.dateTime.time.hour);
ct_test(pTest,
testTimestampIn.value.dateTime.time.min ==
testTimestampOut.value.dateTime.time.min);
ct_test(pTest,
testTimestampIn.value.dateTime.time.sec ==
testTimestampOut.value.dateTime.time.sec);
ct_test(pTest,
testTimestampIn.value.dateTime.time.hundredths ==
testTimestampOut.value.dateTime.time.hundredths);
ct_test(pTest,
testTimestampIn.value.dateTime.date.year ==
testTimestampOut.value.dateTime.date.year);
ct_test(pTest,
testTimestampIn.value.dateTime.date.month ==
testTimestampOut.value.dateTime.date.month);
ct_test(pTest,
testTimestampIn.value.dateTime.date.wday ==
testTimestampOut.value.dateTime.date.wday);
ct_test(pTest,
testTimestampIn.value.dateTime.date.day ==
testTimestampOut.value.dateTime.date.day);
ct_test(pTest, testTimestampIn.value.dateTime.time.hour ==
testTimestampOut.value.dateTime.time.hour);
ct_test(pTest, testTimestampIn.value.dateTime.time.min ==
testTimestampOut.value.dateTime.time.min);
ct_test(pTest, testTimestampIn.value.dateTime.time.sec ==
testTimestampOut.value.dateTime.time.sec);
ct_test(pTest, testTimestampIn.value.dateTime.time.hundredths ==
testTimestampOut.value.dateTime.time.hundredths);
ct_test(pTest, testTimestampIn.value.dateTime.date.year ==
testTimestampOut.value.dateTime.date.year);
ct_test(pTest, testTimestampIn.value.dateTime.date.month ==
testTimestampOut.value.dateTime.date.month);
ct_test(pTest, testTimestampIn.value.dateTime.date.wday ==
testTimestampOut.value.dateTime.date.wday);
ct_test(pTest, testTimestampIn.value.dateTime.date.day ==
testTimestampOut.value.dateTime.date.day);
}
#ifdef TEST_TIME_STAMP
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -370,7 +332,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+93 -141
View File
@@ -41,14 +41,12 @@
/** @file timesync.c Encode/Decode TimeSync APDUs */
#if BACNET_SVC_TS_A
/* encode service */
int timesync_encode_apdu_service(
uint8_t * apdu,
BACNET_UNCONFIRMED_SERVICE service,
BACNET_DATE * my_date,
BACNET_TIME * my_time)
int timesync_encode_apdu_service(uint8_t *apdu,
BACNET_UNCONFIRMED_SERVICE service,
BACNET_DATE *my_date, BACNET_TIME *my_time)
{
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
if (apdu && my_date && my_time) {
apdu[0] = PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST;
@@ -63,31 +61,24 @@ int timesync_encode_apdu_service(
return apdu_len;
}
int timesync_utc_encode_apdu(
uint8_t * apdu,
BACNET_DATE * my_date,
BACNET_TIME * my_time)
int timesync_utc_encode_apdu(uint8_t *apdu, BACNET_DATE *my_date,
BACNET_TIME *my_time)
{
return timesync_encode_apdu_service(apdu,
SERVICE_UNCONFIRMED_UTC_TIME_SYNCHRONIZATION, my_date, my_time);
return timesync_encode_apdu_service(
apdu, SERVICE_UNCONFIRMED_UTC_TIME_SYNCHRONIZATION, my_date, my_time);
}
int timesync_encode_apdu(
uint8_t * apdu,
BACNET_DATE * my_date,
BACNET_TIME * my_time)
int timesync_encode_apdu(uint8_t *apdu, BACNET_DATE *my_date,
BACNET_TIME *my_time)
{
return timesync_encode_apdu_service(apdu,
SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION, my_date, my_time);
return timesync_encode_apdu_service(
apdu, SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION, my_date, my_time);
}
#endif
/* decode the service request only */
int timesync_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
BACNET_DATE * my_date,
BACNET_TIME * my_time)
int timesync_decode_service_request(uint8_t *apdu, unsigned apdu_len,
BACNET_DATE *my_date, BACNET_TIME *my_time)
{
int len = 0;
uint8_t tag_number = 0;
@@ -95,15 +86,13 @@ int timesync_decode_service_request(
if (apdu_len && my_date && my_time) {
/* date */
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 == BACNET_APPLICATION_TAG_DATE) {
len += decode_date(&apdu[len], my_date);
} else
return -1;
/* time */
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 == BACNET_APPLICATION_TAG_TIME) {
len += decode_bacnet_time(&apdu[len], my_time);
} else
@@ -137,10 +126,8 @@ int timesync_decode_service_request(
* @return How many bytes were encoded in the buffer, or
* BACNET_STATUS_ABORT if the response would not fit within the buffer.
*/
int timesync_encode_timesync_recipients(
uint8_t * apdu,
unsigned max_apdu,
BACNET_RECIPIENT_LIST * recipient)
int timesync_encode_timesync_recipients(uint8_t *apdu, unsigned max_apdu,
BACNET_RECIPIENT_LIST *recipient)
{
int len = 0;
int apdu_len = 0;
@@ -152,9 +139,8 @@ int timesync_encode_timesync_recipients(
if (pRecipient->tag == 0) {
if (max_apdu >= (1 + 4)) {
/* CHOICE - device [0] BACnetObjectIdentifier */
len =
encode_context_object_id(&apdu[apdu_len], 0,
(int)pRecipient->type.device.type,
len = encode_context_object_id(
&apdu[apdu_len], 0, (int)pRecipient->type.device.type,
pRecipient->type.device.instance);
apdu_len += len;
} else {
@@ -164,8 +150,7 @@ int timesync_encode_timesync_recipients(
if (pRecipient->type.address.net) {
len = (int)(1 + 3 + 2 + pRecipient->type.address.len + 1);
} else {
len =
(int)(1 + 3 + 2 + pRecipient->type.address.mac_len + 1);
len = (int)(1 + 3 + 2 + pRecipient->type.address.mac_len + 1);
}
if (max_apdu >= (unsigned)len) {
/* CHOICE - address [1] BACnetAddress - opening */
@@ -173,9 +158,8 @@ int timesync_encode_timesync_recipients(
apdu_len += len;
/* network-number Unsigned16, */
/* -- A value of 0 indicates the local network */
len =
encode_application_unsigned(&apdu[apdu_len],
pRecipient->type.address.net);
len = encode_application_unsigned(&apdu[apdu_len],
pRecipient->type.address.net);
apdu_len += len;
/* mac-address OCTET STRING */
/* -- A string of length 0 indicates a broadcast */
@@ -183,16 +167,15 @@ int timesync_encode_timesync_recipients(
octetstring_init(&octet_string, NULL, 0);
} else if (pRecipient->type.address.net) {
octetstring_init(&octet_string,
&pRecipient->type.address.adr[0],
pRecipient->type.address.len);
&pRecipient->type.address.adr[0],
pRecipient->type.address.len);
} else {
octetstring_init(&octet_string,
&pRecipient->type.address.mac[0],
pRecipient->type.address.mac_len);
&pRecipient->type.address.mac[0],
pRecipient->type.address.mac_len);
}
len =
encode_application_octet_string(&apdu[apdu_len],
&octet_string);
len = encode_application_octet_string(&apdu[apdu_len],
&octet_string);
apdu_len += len;
/* CHOICE - address [1] BACnetAddress - closing */
len = encode_closing_tag(&apdu[apdu_len], 1);
@@ -231,10 +214,8 @@ int timesync_encode_timesync_recipients(
* @return How many bytes were decoded from the buffer, or
* BACNET_STATUS_ABORT if there was a problem decoding the buffer
*/
int timesync_decode_timesync_recipients(
uint8_t * apdu,
unsigned max_apdu,
BACNET_RECIPIENT_LIST * recipient)
int timesync_decode_timesync_recipients(uint8_t *apdu, unsigned max_apdu,
BACNET_RECIPIENT_LIST *recipient)
{
int len = 0;
int apdu_len = 0;
@@ -250,10 +231,9 @@ int timesync_decode_timesync_recipients(
/* device [0] BACnetObjectIdentifier */
if (decode_is_context_tag(&apdu[apdu_len], 0)) {
pRecipient->tag = 0;
len =
decode_context_object_id(&apdu[apdu_len], 0,
&pRecipient->type.device.type,
&pRecipient->type.device.instance);
len = decode_context_object_id(&apdu[apdu_len], 0,
&pRecipient->type.device.type,
&pRecipient->type.device.instance);
if (len < 0) {
return BACNET_STATUS_ABORT;
}
@@ -262,22 +242,19 @@ int timesync_decode_timesync_recipients(
apdu_len += 1;
pRecipient->tag = 1;
/* network-number Unsigned16 */
tag_len =
decode_tag_number_and_value(&apdu[apdu_len], &tag_number,
&len_value_type);
tag_len = decode_tag_number_and_value(&apdu[apdu_len], &tag_number,
&len_value_type);
apdu_len += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT) {
return BACNET_STATUS_ABORT;
}
len =
decode_unsigned(&apdu[apdu_len], len_value_type,
&unsigned_value);
len = decode_unsigned(&apdu[apdu_len], len_value_type,
&unsigned_value);
pRecipient->type.address.net = unsigned_value;
apdu_len += len;
/* mac-address OCTET STRING */
tag_len =
decode_tag_number_and_value(&apdu[apdu_len], &tag_number,
&len_value_type);
tag_len = decode_tag_number_and_value(&apdu[apdu_len], &tag_number,
&len_value_type);
apdu_len += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_OCTET_STRING) {
return BACNET_STATUS_ABORT;
@@ -287,12 +264,12 @@ int timesync_decode_timesync_recipients(
if (octetstring_length(&octet_string) == 0) {
/* -- A string of length 0 indicates a broadcast */
} else if (pRecipient->type.address.net) {
pRecipient->type.address.len =
octetstring_copy_value(&pRecipient->type.address.adr[0],
pRecipient->type.address.len = octetstring_copy_value(
&pRecipient->type.address.adr[0],
sizeof(pRecipient->type.address.adr), &octet_string);
} else {
pRecipient->type.address.mac_len =
octetstring_copy_value(&pRecipient->type.address.mac[0],
pRecipient->type.address.mac_len = octetstring_copy_value(
&pRecipient->type.address.mac[0],
sizeof(pRecipient->type.address.mac), &octet_string);
}
} else {
@@ -304,51 +281,42 @@ int timesync_decode_timesync_recipients(
return apdu_len;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
void testTimeSyncRecipientData(
Test * pTest,
BACNET_RECIPIENT_LIST * recipient1,
BACNET_RECIPIENT_LIST * recipient2)
void testTimeSyncRecipientData(Test *pTest, BACNET_RECIPIENT_LIST *recipient1,
BACNET_RECIPIENT_LIST *recipient2)
{
unsigned i = 0;
if (recipient1 && recipient2) {
ct_test(pTest, recipient1->tag == recipient2->tag);
if (recipient1->tag == 0) {
ct_test(pTest,
recipient1->type.device.type == recipient2->type.device.type);
ct_test(pTest,
recipient1->type.device.instance ==
recipient2->type.device.instance);
ct_test(pTest, recipient1->type.device.type ==
recipient2->type.device.type);
ct_test(pTest, recipient1->type.device.instance ==
recipient2->type.device.instance);
} else if (recipient1->tag == 1) {
ct_test(pTest,
recipient1->type.address.net == recipient2->type.address.net);
ct_test(pTest, recipient1->type.address.net ==
recipient2->type.address.net);
if (recipient1->type.address.net == BACNET_BROADCAST_NETWORK) {
ct_test(pTest,
recipient1->type.address.mac_len ==
recipient2->type.address.mac_len);
ct_test(pTest, recipient1->type.address.mac_len ==
recipient2->type.address.mac_len);
} else if (recipient1->type.address.net) {
ct_test(pTest,
recipient1->type.address.len ==
recipient2->type.address.len);
ct_test(pTest, recipient1->type.address.len ==
recipient2->type.address.len);
for (i = 0; i < recipient1->type.address.len; i++) {
ct_test(pTest,
recipient1->type.address.adr[i] ==
recipient2->type.address.adr[i]);
ct_test(pTest, recipient1->type.address.adr[i] ==
recipient2->type.address.adr[i]);
}
} else {
ct_test(pTest,
recipient1->type.address.mac_len ==
recipient2->type.address.mac_len);
ct_test(pTest, recipient1->type.address.mac_len ==
recipient2->type.address.mac_len);
for (i = 0; i < recipient1->type.address.mac_len; i++) {
ct_test(pTest,
recipient1->type.address.mac[i] ==
recipient2->type.address.mac[i]);
ct_test(pTest, recipient1->type.address.mac[i] ==
recipient2->type.address.mac[i]);
}
}
} else {
@@ -357,10 +325,9 @@ void testTimeSyncRecipientData(
}
}
void testTimeSyncRecipient(
Test * pTest)
void testTimeSyncRecipient(Test *pTest)
{
uint8_t apdu[480] = { 0 };
uint8_t apdu[480] = {0};
int len = 0;
BACNET_RECIPIENT_LIST recipient[4];
BACNET_RECIPIENT_LIST test_recipient[4];
@@ -399,25 +366,21 @@ void testTimeSyncRecipient(
recipient[2].type.address.mac[5] = 0xC1;
recipient[2].type.address.mac_len = 6;
/* perform positive test */
len =
timesync_encode_timesync_recipients(&apdu[0], sizeof(apdu),
&recipient[0]);
len = timesync_encode_timesync_recipients(&apdu[0], sizeof(apdu),
&recipient[0]);
ct_test(pTest, len != BACNET_STATUS_ABORT);
ct_test(pTest, len > 0);
len =
timesync_decode_timesync_recipients(&apdu[0], sizeof(apdu),
&test_recipient[0]);
len = timesync_decode_timesync_recipients(&apdu[0], sizeof(apdu),
&test_recipient[0]);
ct_test(pTest, len != BACNET_STATUS_ABORT);
ct_test(pTest, len > 0);
testTimeSyncRecipientData(pTest, &recipient[0], &test_recipient[0]);
}
int timesync_decode_apdu_service(
uint8_t * apdu,
BACNET_UNCONFIRMED_SERVICE service,
unsigned apdu_len,
BACNET_DATE * my_date,
BACNET_TIME * my_time)
int timesync_decode_apdu_service(uint8_t *apdu,
BACNET_UNCONFIRMED_SERVICE service,
unsigned apdu_len, BACNET_DATE *my_date,
BACNET_TIME *my_time)
{
int len = 0;
@@ -430,41 +393,32 @@ int timesync_decode_apdu_service(
return -1;
/* optional limits - must be used as a pair */
if (apdu_len > 2) {
len =
timesync_decode_service_request(&apdu[2], apdu_len - 2, my_date,
my_time);
len = timesync_decode_service_request(&apdu[2], apdu_len - 2, my_date,
my_time);
}
return len;
}
int timesync_utc_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
BACNET_DATE * my_date,
BACNET_TIME * my_time)
int timesync_utc_decode_apdu(uint8_t *apdu, unsigned apdu_len,
BACNET_DATE *my_date, BACNET_TIME *my_time)
{
return timesync_decode_apdu_service(apdu,
SERVICE_UNCONFIRMED_UTC_TIME_SYNCHRONIZATION, apdu_len, my_date,
return timesync_decode_apdu_service(
apdu, SERVICE_UNCONFIRMED_UTC_TIME_SYNCHRONIZATION, apdu_len, my_date,
my_time);
}
int timesync_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
BACNET_DATE * my_date,
BACNET_TIME * my_time)
int timesync_decode_apdu(uint8_t *apdu, unsigned apdu_len, BACNET_DATE *my_date,
BACNET_TIME *my_time)
{
return timesync_decode_apdu_service(apdu,
SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION, apdu_len, my_date, my_time);
return timesync_decode_apdu_service(
apdu, SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION, apdu_len, my_date,
my_time);
}
void testTimeSyncData(
Test * pTest,
BACNET_DATE * my_date,
BACNET_TIME * my_time)
void testTimeSyncData(Test *pTest, BACNET_DATE *my_date, BACNET_TIME *my_time)
{
uint8_t apdu[480] = { 0 };
uint8_t apdu[480] = {0};
int len = 0;
int apdu_len = 0;
BACNET_DATE test_date;
@@ -487,16 +441,15 @@ void testTimeSyncData(
ct_test(pTest, datetime_compare_date(my_date, &test_date) == 0);
}
void testTimeSync(
Test * pTest)
void testTimeSync(Test *pTest)
{
BACNET_DATE bdate;
BACNET_TIME btime;
bdate.year = 2006; /* AD */
bdate.month = 4; /* 1=Jan */
bdate.day = 11; /* 1..31 */
bdate.wday = 1; /* 1=Monday */
bdate.year = 2006; /* AD */
bdate.month = 4; /* 1=Jan */
bdate.day = 11; /* 1..31 */
bdate.wday = 1; /* 1=Monday */
btime.hour = 7;
btime.min = 0;
@@ -507,8 +460,7 @@ void testTimeSync(
}
#ifdef TEST_TIMESYNC
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -520,7 +472,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+52 -71
View File
@@ -66,22 +66,20 @@ static uint8_t Current_Invoke_ID = 1;
static tsm_timeout_function Timeout_Function;
void tsm_set_timeout_handler(
tsm_timeout_function pFunction)
void tsm_set_timeout_handler(tsm_timeout_function pFunction)
{
Timeout_Function = pFunction;
}
/* returns MAX_TSM_TRANSACTIONS if not found */
static uint8_t tsm_find_invokeID_index(
uint8_t invokeID)
static uint8_t tsm_find_invokeID_index(uint8_t invokeID)
{
unsigned i = 0; /* counter */
uint8_t index = MAX_TSM_TRANSACTIONS; /* return value */
unsigned i = 0; /* counter */
uint8_t index = MAX_TSM_TRANSACTIONS; /* return value */
for (i = 0; i < MAX_TSM_TRANSACTIONS; i++) {
if (TSM_List[i].InvokeID == invokeID) {
index = (uint8_t) i;
index = (uint8_t)i;
break;
}
}
@@ -89,15 +87,14 @@ static uint8_t tsm_find_invokeID_index(
return index;
}
static uint8_t tsm_find_first_free_index(
void)
static uint8_t tsm_find_first_free_index(void)
{
unsigned i = 0; /* counter */
uint8_t index = MAX_TSM_TRANSACTIONS; /* return value */
unsigned i = 0; /* counter */
uint8_t index = MAX_TSM_TRANSACTIONS; /* return value */
for (i = 0; i < MAX_TSM_TRANSACTIONS; i++) {
if (TSM_List[i].InvokeID == 0) {
index = (uint8_t) i;
index = (uint8_t)i;
break;
}
}
@@ -105,11 +102,10 @@ static uint8_t tsm_find_first_free_index(
return index;
}
bool tsm_transaction_available(
void)
bool tsm_transaction_available(void)
{
bool status = false; /* return value */
unsigned i = 0; /* counter */
bool status = false; /* return value */
unsigned i = 0; /* counter */
for (i = 0; i < MAX_TSM_TRANSACTIONS; i++) {
if (TSM_List[i].InvokeID == 0) {
@@ -122,11 +118,10 @@ bool tsm_transaction_available(
return status;
}
uint8_t tsm_transaction_idle_count(
void)
uint8_t tsm_transaction_idle_count(void)
{
uint8_t count = 0; /* return value */
unsigned i = 0; /* counter */
uint8_t count = 0; /* return value */
unsigned i = 0; /* counter */
for (i = 0; i < MAX_TSM_TRANSACTIONS; i++) {
if ((TSM_List[i].InvokeID == 0) &&
@@ -141,8 +136,7 @@ uint8_t tsm_transaction_idle_count(
/* sets the invokeID */
void tsm_invokeID_set(
uint8_t invokeID)
void tsm_invokeID_set(uint8_t invokeID)
{
if (invokeID == 0) {
invokeID = 1;
@@ -153,8 +147,7 @@ void tsm_invokeID_set(
/* gets the next free invokeID,
and reserves a spot in the table
returns 0 if none are available */
uint8_t tsm_next_free_invokeID(
void)
uint8_t tsm_next_free_invokeID(void)
{
uint8_t index = 0;
uint8_t invokeID = 0;
@@ -175,7 +168,8 @@ uint8_t tsm_next_free_invokeID(
TSM_List[index].RequestTimer = apdu_timeout();
/* update for the next call or check */
Current_Invoke_ID++;
/* skip zero - we treat that internally as invalid or no free */
/* skip zero - we treat that internally as invalid or no
* free */
if (Current_Invoke_ID == 0) {
Current_Invoke_ID = 1;
}
@@ -195,12 +189,10 @@ uint8_t tsm_next_free_invokeID(
return invokeID;
}
void tsm_set_confirmed_unsegmented_transaction(
uint8_t invokeID,
BACNET_ADDRESS * dest,
BACNET_NPDU_DATA * ndpu_data,
uint8_t * apdu,
uint16_t apdu_len)
void tsm_set_confirmed_unsegmented_transaction(uint8_t invokeID,
BACNET_ADDRESS *dest,
BACNET_NPDU_DATA *ndpu_data,
uint8_t *apdu, uint16_t apdu_len)
{
uint16_t j = 0;
uint8_t index;
@@ -228,12 +220,9 @@ void tsm_set_confirmed_unsegmented_transaction(
/* used to retrieve the transaction payload */
/* if we wanted to find out what we sent (i.e. when we get an ack) */
bool tsm_get_transaction_pdu(
uint8_t invokeID,
BACNET_ADDRESS * dest,
BACNET_NPDU_DATA * ndpu_data,
uint8_t * apdu,
uint16_t * apdu_len)
bool tsm_get_transaction_pdu(uint8_t invokeID, BACNET_ADDRESS *dest,
BACNET_NPDU_DATA *ndpu_data, uint8_t *apdu,
uint16_t *apdu_len)
{
uint16_t j = 0;
uint8_t index;
@@ -243,10 +232,11 @@ bool tsm_get_transaction_pdu(
index = tsm_find_invokeID_index(invokeID);
/* how much checking is needed? state? dest match? just invokeID? */
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 */
/* FIXME: bounds check the pdu_len? */
*apdu_len = (uint16_t) TSM_List[index].apdu_len;
*apdu_len = (uint16_t)TSM_List[index].apdu_len;
for (j = 0; j < *apdu_len; j++) {
apdu[j] = TSM_List[index].apdu[j];
}
@@ -260,10 +250,9 @@ bool tsm_get_transaction_pdu(
}
/* called once a millisecond or slower */
void tsm_timer_milliseconds(
uint16_t milliseconds)
void tsm_timer_milliseconds(uint16_t milliseconds)
{
unsigned i = 0; /* counter */
unsigned i = 0; /* counter */
for (i = 0; i < MAX_TSM_TRANSACTIONS; i++) {
if (TSM_List[i].state == TSM_STATE_AWAIT_CONFIRMATION) {
@@ -276,9 +265,9 @@ void tsm_timer_milliseconds(
if (TSM_List[i].RetryCount < apdu_retries()) {
TSM_List[i].RequestTimer = apdu_timeout();
TSM_List[i].RetryCount++;
datalink_send_pdu(&TSM_List[i].dest,
&TSM_List[i].npdu_data, &TSM_List[i].apdu[0],
TSM_List[i].apdu_len);
datalink_send_pdu(&TSM_List[i].dest, &TSM_List[i].npdu_data,
&TSM_List[i].apdu[0],
TSM_List[i].apdu_len);
} else {
/* note: the invoke id has not been cleared yet
and this indicates a failed message:
@@ -296,8 +285,7 @@ void tsm_timer_milliseconds(
}
/* frees the invokeID and sets its state to IDLE */
void tsm_free_invoke_id(
uint8_t invokeID)
void tsm_free_invoke_id(uint8_t invokeID)
{
uint8_t index;
@@ -309,11 +297,11 @@ void tsm_free_invoke_id(
}
/** Check if the invoke ID has been made free by the Transaction State Machine.
* @param invokeID [in] The invokeID to be checked, normally of last message sent.
* @param invokeID [in] The invokeID to be checked, normally of last message
* sent.
* @return True if it is free (done with), False if still pending in the TSM.
*/
bool tsm_invoke_id_free(
uint8_t invokeID)
bool tsm_invoke_id_free(uint8_t invokeID)
{
bool status = true;
uint8_t index;
@@ -327,12 +315,12 @@ bool tsm_invoke_id_free(
/** See if we failed get a confirmation for the message associated
* with this invoke ID.
* @param invokeID [in] The invokeID to be checked, normally of last message sent.
* @param invokeID [in] The invokeID to be checked, normally of last message
* sent.
* @return True if already failed, False if done or segmented or still waiting
* for a confirmation.
*/
bool tsm_invoke_id_failed(
uint8_t invokeID)
bool tsm_invoke_id_failed(uint8_t invokeID)
{
bool status = false;
uint8_t index;
@@ -348,7 +336,6 @@ bool tsm_invoke_id_failed(
return status;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
@@ -358,37 +345,31 @@ bool tsm_invoke_id_failed(
bool I_Am_Request = true;
/* dummy function stubs */
int datalink_send_pdu(
BACNET_ADDRESS * dest,
BACNET_NPDU_DATA * npdu_data,
uint8_t * pdu,
unsigned pdu_len)
int datalink_send_pdu(BACNET_ADDRESS *dest, BACNET_NPDU_DATA *npdu_data,
uint8_t *pdu, unsigned pdu_len)
{
(void) dest;
(void) npdu_data;
(void) pdu;
(void) pdu_len;
(void)dest;
(void)npdu_data;
(void)pdu;
(void)pdu_len;
return 0;
}
/* dummy function stubs */
void datalink_get_broadcast_address(
BACNET_ADDRESS * dest)
void datalink_get_broadcast_address(BACNET_ADDRESS *dest)
{
(void) dest;
(void)dest;
}
void testTSM(
Test * pTest)
void testTSM(Test *pTest)
{
/* FIXME: add some unit testing... */
return;
}
#ifdef TEST_TSM
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -400,7 +381,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+31 -71
View File
@@ -13,7 +13,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
* Copyright (C) 2008 John Crispin <blogic@openwrt.org>
* Copyright (C) 2008 John Crispin <blogic@openwrt.org>
*/
#include <stdbool.h>
@@ -27,12 +27,8 @@
static struct uci_ptr ptr;
static inline int ucix_get_ptr(
struct uci_context *ctx,
const char *p,
const char *s,
const char *o,
const char *t)
static inline int ucix_get_ptr(struct uci_context *ctx, const char *p,
const char *s, const char *o, const char *t)
{
memset(&ptr, 0, sizeof(ptr));
ptr.package = p;
@@ -42,60 +38,51 @@ static inline int ucix_get_ptr(
return uci_lookup_ptr(ctx, &ptr, NULL, true);
}
struct uci_context *ucix_init(
const char *config_file)
struct uci_context *ucix_init(const char *config_file)
{
struct uci_context *ctx = uci_alloc_context();
/* uci_add_history_path(ctx, "/var/state"); */
/* uci_add_history_path(ctx, "/var/state"); */
uci_add_delta_path(ctx, "/var/state");
if (uci_load(ctx, config_file, NULL) != UCI_OK) {
fprintf(stderr, "%s/%s is missing or corrupt\n", ctx->savedir,
config_file);
config_file);
return NULL;
}
return ctx;
}
struct uci_context *ucix_init_path(
const char *path,
const char *config_file)
struct uci_context *ucix_init_path(const char *path, const char *config_file)
{
struct uci_context *ctx = uci_alloc_context();
if (path)
uci_set_confdir(ctx, path);
if (uci_load(ctx, config_file, NULL) != UCI_OK) {
fprintf(stderr, "%s/%s is missing or corrupt\n", ctx->savedir,
config_file);
config_file);
return NULL;
}
return ctx;
}
void ucix_cleanup(
struct uci_context *ctx)
void ucix_cleanup(struct uci_context *ctx)
{
uci_free_context(ctx);
}
void ucix_save(
struct uci_context *ctx)
void ucix_save(struct uci_context *ctx)
{
uci_set_savedir(ctx, "/tmp/.uci/");
uci_save(ctx, NULL);
}
void ucix_save_state(
struct uci_context *ctx)
void ucix_save_state(struct uci_context *ctx)
{
uci_set_savedir(ctx, "/var/state/");
uci_save(ctx, NULL);
}
const char *ucix_get_option(
struct uci_context *ctx,
const char *p,
const char *s,
const char *o)
const char *ucix_get_option(struct uci_context *ctx, const char *p,
const char *s, const char *o)
{
struct uci_element *e = NULL;
const char *value = NULL;
@@ -125,12 +112,8 @@ const char *ucix_get_option(
return value;
}
int ucix_get_option_int(
struct uci_context *ctx,
const char *p,
const char *s,
const char *o,
int def)
int ucix_get_option_int(struct uci_context *ctx, const char *p, const char *s,
const char *o, int def)
{
const char *tmp = ucix_get_option(ctx, p, s, o);
int ret = def;
@@ -140,80 +123,57 @@ int ucix_get_option_int(
return ret;
}
void ucix_add_section(
struct uci_context *ctx,
const char *p,
const char *s,
const char *t)
void ucix_add_section(struct uci_context *ctx, const char *p, const char *s,
const char *t)
{
if (ucix_get_ptr(ctx, p, s, NULL, t))
return;
uci_set(ctx, &ptr);
}
void ucix_add_option(
struct uci_context *ctx,
const char *p,
const char *s,
const char *o,
const char *t)
void ucix_add_option(struct uci_context *ctx, const char *p, const char *s,
const char *o, const char *t)
{
if (ucix_get_ptr(ctx, p, s, o, (t) ? (t) : ("")))
return;
uci_set(ctx, &ptr);
}
void ucix_add_option_int(
struct uci_context *ctx,
const char *p,
const char *s,
const char *o,
int t)
void ucix_add_option_int(struct uci_context *ctx, const char *p, const char *s,
const char *o, int t)
{
char tmp[64];
snprintf(tmp, 64, "%d", t);
ucix_add_option(ctx, p, s, o, tmp);
}
void ucix_del(
struct uci_context *ctx,
const char *p,
const char *s,
const char *o)
void ucix_del(struct uci_context *ctx, const char *p, const char *s,
const char *o)
{
if (!ucix_get_ptr(ctx, p, s, o, NULL))
uci_delete(ctx, &ptr);
}
void ucix_revert(
struct uci_context *ctx,
const char *p,
const char *s,
const char *o)
void ucix_revert(struct uci_context *ctx, const char *p, const char *s,
const char *o)
{
if (!ucix_get_ptr(ctx, p, s, o, NULL))
uci_revert(ctx, &ptr);
}
void ucix_for_each_section_type(
struct uci_context *ctx,
const char *p,
const char *t,
void (*cb) (const char *,
void *),
void *priv)
void ucix_for_each_section_type(struct uci_context *ctx, const char *p,
const char *t, void (*cb)(const char *, void *),
void *priv)
{
struct uci_element *e;
if (ucix_get_ptr(ctx, p, NULL, NULL, NULL))
return;
uci_foreach_element(&ptr.p->sections, e)
if (!strcmp(t, uci_to_section(e)->type))
uci_foreach_element(&ptr.p->sections,
e) if (!strcmp(t, uci_to_section(e)->type))
cb(e->name, priv);
}
int ucix_commit(
struct uci_context *ctx,
const char *p)
int ucix_commit(struct uci_context *ctx, const char *p)
{
if (ucix_get_ptr(ctx, p, NULL, NULL, NULL))
return 1;
+5 -11
View File
@@ -138,9 +138,7 @@ struct vmac_data *VMAC_Find_By_Key(uint32_t device_id)
*
* @return true if the addresses are different
*/
bool VMAC_Different(
struct vmac_data *vmac1,
struct vmac_data *vmac2)
bool VMAC_Different(struct vmac_data *vmac1, struct vmac_data *vmac2)
{
bool status = false;
unsigned int i = 0;
@@ -171,9 +169,7 @@ bool VMAC_Different(
*
* @return true if the addresses are the same
*/
bool VMAC_Match(
struct vmac_data *vmac1,
struct vmac_data *vmac2)
bool VMAC_Match(struct vmac_data *vmac1, struct vmac_data *vmac2)
{
bool status = false;
unsigned int i = 0;
@@ -268,8 +264,7 @@ void VMAC_Init(void)
#include <string.h>
#include "ctest.h"
void testVMAC(
Test * pTest)
void testVMAC(Test *pTest)
{
uint32_t device_id = 123;
uint32_t test_device_id = 0;
@@ -304,8 +299,7 @@ void testVMAC(
}
#ifdef TEST_VMAC
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -317,7 +311,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+46 -66
View File
@@ -41,38 +41,33 @@
/* encode service - use -1 for limit for unlimited */
int whohas_encode_apdu(
uint8_t * apdu,
BACNET_WHO_HAS_DATA * data)
int whohas_encode_apdu(uint8_t *apdu, BACNET_WHO_HAS_DATA *data)
{
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
if (apdu && data) {
apdu[0] = PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST;
apdu[1] = SERVICE_UNCONFIRMED_WHO_HAS; /* service choice */
apdu[1] = SERVICE_UNCONFIRMED_WHO_HAS; /* service choice */
apdu_len = 2;
/* optional limits - must be used as a pair */
if ((data->low_limit >= 0)
&& (data->low_limit <= BACNET_MAX_INSTANCE)
&& (data->high_limit >= 0)
&& (data->high_limit <= BACNET_MAX_INSTANCE)) {
if ((data->low_limit >= 0) &&
(data->low_limit <= BACNET_MAX_INSTANCE) &&
(data->high_limit >= 0) &&
(data->high_limit <= BACNET_MAX_INSTANCE)) {
len = encode_context_unsigned(&apdu[apdu_len], 0, data->low_limit);
apdu_len += len;
len =
encode_context_unsigned(&apdu[apdu_len], 1, data->high_limit);
len = encode_context_unsigned(&apdu[apdu_len], 1, data->high_limit);
apdu_len += len;
}
if (data->is_object_name) {
len =
encode_context_character_string(&apdu[apdu_len], 3,
&data->object.name);
len = encode_context_character_string(&apdu[apdu_len], 3,
&data->object.name);
apdu_len += len;
} else {
len =
encode_context_object_id(&apdu[apdu_len], 2,
(int) data->object.identifier.type,
data->object.identifier.instance);
len = encode_context_object_id(&apdu[apdu_len], 2,
(int)data->object.identifier.type,
data->object.identifier.instance);
apdu_len += len;
}
}
@@ -81,10 +76,8 @@ int whohas_encode_apdu(
}
/* decode the service request only */
int whohas_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
BACNET_WHO_HAS_DATA * data)
int whohas_decode_service_request(uint8_t *apdu, unsigned apdu_len,
BACNET_WHO_HAS_DATA *data)
{
int len = 0;
uint8_t tag_number = 0;
@@ -95,17 +88,15 @@ int whohas_decode_service_request(
if (apdu_len && data) {
/* optional limits - must be used as a pair */
if (decode_is_context_tag(&apdu[len], 0)) {
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_unsigned(&apdu[len], len_value, &decoded_value);
if (decoded_value <= BACNET_MAX_INSTANCE)
data->low_limit = decoded_value;
if (!decode_is_context_tag(&apdu[len], 1))
return -1;
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_unsigned(&apdu[len], len_value, &decoded_value);
if (decoded_value <= BACNET_MAX_INSTANCE)
data->high_limit = decoded_value;
@@ -116,23 +107,19 @@ int whohas_decode_service_request(
/* object id */
if (decode_is_context_tag(&apdu[len], 2)) {
data->is_object_name = false;
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len +=
decode_object_id(&apdu[len], &decoded_type,
&data->object.identifier.instance);
len += 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.type = decoded_type;
}
/* object name */
else if (decode_is_context_tag(&apdu[len], 3)) {
data->is_object_name = true;
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len +=
decode_character_string(&apdu[len], len_value,
&data->object.name);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_character_string(&apdu[len], len_value,
&data->object.name);
}
/* missing required parameters */
else
@@ -147,10 +134,8 @@ int whohas_decode_service_request(
#include <string.h>
#include "ctest.h"
int whohas_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
BACNET_WHO_HAS_DATA * data)
int whohas_decode_apdu(uint8_t *apdu, unsigned apdu_len,
BACNET_WHO_HAS_DATA *data)
{
int len = 0;
@@ -169,11 +154,9 @@ int whohas_decode_apdu(
return len;
}
void testWhoHasData(
Test * pTest,
BACNET_WHO_HAS_DATA * data)
void testWhoHasData(Test *pTest, BACNET_WHO_HAS_DATA *data)
{
uint8_t apdu[480] = { 0 };
uint8_t apdu[480] = {0};
int len = 0;
int apdu_len = 0;
BACNET_WHO_HAS_DATA test_data;
@@ -189,21 +172,19 @@ void testWhoHasData(
ct_test(pTest, test_data.is_object_name == data->is_object_name);
/* Object ID */
if (data->is_object_name == false) {
ct_test(pTest,
test_data.object.identifier.type == data->object.identifier.type);
ct_test(pTest,
test_data.object.identifier.instance ==
data->object.identifier.instance);
ct_test(pTest, test_data.object.identifier.type ==
data->object.identifier.type);
ct_test(pTest, test_data.object.identifier.instance ==
data->object.identifier.instance);
}
/* Object Name */
else {
ct_test(pTest, characterstring_same(&test_data.object.name,
&data->object.name));
&data->object.name));
}
}
void testWhoHas(
Test * pTest)
void testWhoHas(Test *pTest)
{
BACNET_WHO_HAS_DATA data;
@@ -215,16 +196,16 @@ void testWhoHas(
testWhoHasData(pTest, &data);
for (data.low_limit = 0; 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; data.high_limit <= BACNET_MAX_INSTANCE;
data.high_limit += (BACNET_MAX_INSTANCE / 4)) {
data.high_limit += (BACNET_MAX_INSTANCE / 4)) {
data.is_object_name = false;
for (data.object.identifier.type = OBJECT_ANALOG_INPUT;
data.object.identifier.type < MAX_BACNET_OBJECT_TYPE;
data.object.identifier.type++) {
data.object.identifier.type < MAX_BACNET_OBJECT_TYPE;
data.object.identifier.type++) {
for (data.object.identifier.instance = 1;
data.object.identifier.instance <= BACNET_MAX_INSTANCE;
data.object.identifier.instance <<= 1) {
data.object.identifier.instance <= BACNET_MAX_INSTANCE;
data.object.identifier.instance <<= 1) {
testWhoHasData(pTest, &data);
}
}
@@ -236,8 +217,7 @@ void testWhoHas(
}
#ifdef TEST_WHOHAS
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -249,7 +229,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+29 -43
View File
@@ -40,17 +40,14 @@
/** @file whois.c Encode/Decode Who-Is requests */
/* encode I-Am service - use -1 for limit if you want unlimited */
int whois_encode_apdu(
uint8_t * apdu,
int32_t low_limit,
int32_t high_limit)
int whois_encode_apdu(uint8_t *apdu, int32_t low_limit, int32_t high_limit)
{
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* length of each encoding */
int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) {
apdu[0] = PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST;
apdu[1] = SERVICE_UNCONFIRMED_WHO_IS; /* service choice */
apdu[1] = SERVICE_UNCONFIRMED_WHO_IS; /* service choice */
apdu_len = 2;
/* optional limits - must be used as a pair */
if ((low_limit >= 0) && (low_limit <= BACNET_MAX_INSTANCE) &&
@@ -66,11 +63,8 @@ int whois_encode_apdu(
}
/* decode the service request only */
int whois_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
int32_t * pLow_limit,
int32_t * pHigh_limit)
int whois_decode_service_request(uint8_t *apdu, unsigned apdu_len,
int32_t *pLow_limit, int32_t *pHigh_limit)
{
unsigned int len = 0;
uint8_t tag_number = 0;
@@ -79,8 +73,7 @@ int whois_decode_service_request(
/* optional limits - must be used as a pair */
if (apdu_len) {
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 != 0) {
return BACNET_STATUS_ERROR;
}
@@ -92,13 +85,14 @@ int whois_decode_service_request(
}
}
if (apdu_len > (unsigned)len) {
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) {
return BACNET_STATUS_ERROR;
}
if (apdu_len > (unsigned)len) {
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 (pHigh_limit) {
*pHigh_limit = decoded_value;
@@ -131,11 +125,8 @@ int whois_decode_service_request(
#include <string.h>
#include "ctest.h"
int whois_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
int32_t * pLow_limit,
int32_t * pHigh_limit)
int whois_decode_apdu(uint8_t *apdu, unsigned apdu_len, int32_t *pLow_limit,
int32_t *pHigh_limit)
{
int len = 0;
@@ -144,25 +135,24 @@ int whois_decode_apdu(
}
/* optional limits - must be used as a pair */
if (apdu_len >= 2) {
/* optional checking - most likely was already done prior to this call */
/* optional checking - most likely was already done prior to this call
*/
if (apdu[0] != PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST) {
return BACNET_STATUS_ERROR;
}
if (apdu[1] != SERVICE_UNCONFIRMED_WHO_IS) {
return BACNET_STATUS_ERROR;
}
len =
whois_decode_service_request(&apdu[2], apdu_len - 2, pLow_limit,
pHigh_limit);
len = whois_decode_service_request(&apdu[2], apdu_len - 2, pLow_limit,
pHigh_limit);
}
return len;
}
void testWhoIs(
Test * pTest)
void testWhoIs(Test *pTest)
{
uint8_t apdu[480] = { 0 };
uint8_t apdu[480] = {0};
int len = 0;
int apdu_len = 0;
int32_t low_limit = -1;
@@ -175,24 +165,22 @@ void testWhoIs(
ct_test(pTest, len > 0);
apdu_len = len;
len =
whois_decode_apdu(&apdu[0], apdu_len, &test_low_limit,
&test_high_limit);
len = whois_decode_apdu(&apdu[0], apdu_len, &test_low_limit,
&test_high_limit);
ct_test(pTest, len != BACNET_STATUS_ERROR);
ct_test(pTest, test_low_limit == low_limit);
ct_test(pTest, test_high_limit == high_limit);
/* normal who-is with limits - complete range */
for (low_limit = 0; low_limit <= BACNET_MAX_INSTANCE;
low_limit += (BACNET_MAX_INSTANCE / 4)) {
low_limit += (BACNET_MAX_INSTANCE / 4)) {
for (high_limit = 0; 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);
apdu_len = len;
ct_test(pTest, len > 0);
len =
whois_decode_apdu(&apdu[0], apdu_len, &test_low_limit,
&test_high_limit);
len = whois_decode_apdu(&apdu[0], apdu_len, &test_low_limit,
&test_high_limit);
ct_test(pTest, len != BACNET_STATUS_ERROR);
ct_test(pTest, test_low_limit == low_limit);
ct_test(pTest, test_high_limit == high_limit);
@@ -210,17 +198,15 @@ void testWhoIs(
len = whois_encode_apdu(&apdu[0], low_limit, high_limit);
ct_test(pTest, len > 0);
apdu_len = len;
len =
whois_decode_apdu(&apdu[0], apdu_len, &test_low_limit,
&test_high_limit);
len = whois_decode_apdu(&apdu[0], apdu_len, &test_low_limit,
&test_high_limit);
ct_test(pTest, len != BACNET_STATUS_ERROR);
ct_test(pTest, test_low_limit == low_limit);
ct_test(pTest, test_high_limit == high_limit);
}
#ifdef TEST_WHOIS
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -232,7 +218,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+60 -83
View File
@@ -40,33 +40,28 @@
/** @file wp.c Encode/Decode BACnet Write Property APDUs */
#if BACNET_SVC_WP_A
/* encode service */
int wp_encode_apdu(
uint8_t * apdu,
uint8_t invoke_id,
BACNET_WRITE_PROPERTY_DATA * wpdata)
int wp_encode_apdu(uint8_t *apdu, uint8_t invoke_id,
BACNET_WRITE_PROPERTY_DATA *wpdata)
{
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* total length of the apdu, return value */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* total length of the apdu, return value */
if (apdu) {
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU);
apdu[2] = invoke_id;
apdu[3] = SERVICE_CONFIRMED_WRITE_PROPERTY; /* service choice */
apdu[3] = SERVICE_CONFIRMED_WRITE_PROPERTY; /* service choice */
apdu_len = 4;
len =
encode_context_object_id(&apdu[apdu_len], 0, wpdata->object_type,
wpdata->object_instance);
len = encode_context_object_id(&apdu[apdu_len], 0, wpdata->object_type,
wpdata->object_instance);
apdu_len += len;
len =
encode_context_enumerated(&apdu[apdu_len], 1,
wpdata->object_property);
len = encode_context_enumerated(&apdu[apdu_len], 1,
wpdata->object_property);
apdu_len += len;
/* optional array index; ALL is -1 which is assumed when missing */
if (wpdata->array_index != BACNET_ARRAY_ALL) {
len =
encode_context_unsigned(&apdu[apdu_len], 2,
wpdata->array_index);
len = encode_context_unsigned(&apdu[apdu_len], 2,
wpdata->array_index);
apdu_len += len;
}
/* propertyValue */
@@ -80,8 +75,7 @@ int wp_encode_apdu(
apdu_len += len;
/* optional priority - 0 if not set, 1..16 if set */
if (wpdata->priority != BACNET_NO_PRIORITY) {
len =
encode_context_unsigned(&apdu[apdu_len], 4, wpdata->priority);
len = encode_context_unsigned(&apdu[apdu_len], 4, wpdata->priority);
apdu_len += len;
}
}
@@ -93,19 +87,17 @@ int wp_encode_apdu(
/* decode the service request only */
/* FIXME: there could be various error messages returned
using unique values less than zero */
int wp_decode_service_request(
uint8_t * apdu,
unsigned apdu_len,
BACNET_WRITE_PROPERTY_DATA * wpdata)
int wp_decode_service_request(uint8_t *apdu, unsigned apdu_len,
BACNET_WRITE_PROPERTY_DATA *wpdata)
{
int len = 0;
int tag_len = 0;
uint8_t tag_number = 0;
uint32_t len_value_type = 0;
uint16_t type = 0; /* for decoding */
uint32_t property = 0; /* for decoding */
uint16_t type = 0; /* for decoding */
uint32_t property = 0; /* for decoding */
uint32_t unsigned_value = 0;
int i = 0; /* loop counter */
int i = 0; /* loop counter */
/* check for value pointers */
if (apdu_len && wpdata) {
@@ -113,24 +105,22 @@ int wp_decode_service_request(
if (!decode_is_context_tag(&apdu[len++], 0))
return -1;
len += decode_object_id(&apdu[len], &type, &wpdata->object_instance);
wpdata->object_type = (BACNET_OBJECT_TYPE) type;
wpdata->object_type = (BACNET_OBJECT_TYPE)type;
/* Tag 1: Property ID */
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
if (tag_number != 1)
return -1;
len += decode_enumerated(&apdu[len], len_value_type, &property);
wpdata->object_property = (BACNET_PROPERTY_ID) property;
wpdata->object_property = (BACNET_PROPERTY_ID)property;
/* Tag 2: Optional Array Index */
/* note: decode without incrementing len so we can check for opening tag */
tag_len =
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
/* note: decode without incrementing len so we can check for opening tag
*/
tag_len = decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
if (tag_number == 2) {
len += tag_len;
len +=
decode_unsigned(&apdu[len], len_value_type, &unsigned_value);
len += decode_unsigned(&apdu[len], len_value_type, &unsigned_value);
wpdata->array_index = unsigned_value;
} else
wpdata->array_index = BACNET_ARRAY_ALL;
@@ -138,9 +128,8 @@ int wp_decode_service_request(
if (!decode_is_opening_tag_number(&apdu[len], 3))
return -1;
/* determine the length of the data blob */
wpdata->application_data_len =
bacapp_data_len(&apdu[len], apdu_len - len,
(BACNET_PROPERTY_ID) property);
wpdata->application_data_len = bacapp_data_len(
&apdu[len], apdu_len - len, (BACNET_PROPERTY_ID)property);
/* a tag number of 3 is not extended so only one octet */
len++;
/* copy the data from the APDU */
@@ -155,18 +144,16 @@ int wp_decode_service_request(
len++;
/* Tag 4: optional Priority - assumed MAX if not explicitly set */
wpdata->priority = BACNET_MAX_PRIORITY;
if ((unsigned) len < apdu_len) {
tag_len =
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
if ((unsigned)len < apdu_len) {
tag_len = decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
if (tag_number == 4) {
len += tag_len;
len =
decode_unsigned(&apdu[len], len_value_type,
&unsigned_value);
if ((unsigned_value >= BACNET_MIN_PRIORITY)
&& (unsigned_value <= BACNET_MAX_PRIORITY)) {
wpdata->priority = (uint8_t) unsigned_value;
len = decode_unsigned(&apdu[len], len_value_type,
&unsigned_value);
if ((unsigned_value >= BACNET_MIN_PRIORITY) &&
(unsigned_value <= BACNET_MAX_PRIORITY)) {
wpdata->priority = (uint8_t)unsigned_value;
} else
return -5;
}
@@ -181,11 +168,8 @@ int wp_decode_service_request(
#include <string.h>
#include "ctest.h"
int wp_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
uint8_t * invoke_id,
BACNET_WRITE_PROPERTY_DATA * wpdata)
int wp_decode_apdu(uint8_t *apdu, unsigned apdu_len, uint8_t *invoke_id,
BACNET_WRITE_PROPERTY_DATA *wpdata)
{
int len = 0;
unsigned offset = 0;
@@ -196,28 +180,25 @@ int wp_decode_apdu(
if (apdu[0] != PDU_TYPE_CONFIRMED_SERVICE_REQUEST)
return -1;
/* apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU); */
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
if (apdu[3] != SERVICE_CONFIRMED_WRITE_PROPERTY)
return -1;
offset = 4;
if (apdu_len > offset) {
len =
wp_decode_service_request(&apdu[offset], apdu_len - offset,
wpdata);
wp_decode_service_request(&apdu[offset], apdu_len - offset, wpdata);
}
return len;
}
void testWritePropertyTag(
Test * pTest,
BACNET_APPLICATION_DATA_VALUE * value)
void testWritePropertyTag(Test *pTest, BACNET_APPLICATION_DATA_VALUE *value)
{
BACNET_WRITE_PROPERTY_DATA wpdata = { 0 };
BACNET_WRITE_PROPERTY_DATA test_data = { 0 };
BACNET_WRITE_PROPERTY_DATA wpdata = {0};
BACNET_WRITE_PROPERTY_DATA test_data = {0};
BACNET_APPLICATION_DATA_VALUE test_value;
uint8_t apdu[480] = { 0 };
uint8_t apdu[480] = {0};
int len = 0;
int apdu_len = 0;
uint8_t invoke_id = 128;
@@ -236,9 +217,9 @@ void testWritePropertyTag(
ct_test(pTest, test_data.object_property == wpdata.object_property);
ct_test(pTest, test_data.array_index == wpdata.array_index);
/* decode the application value of the request */
len =
bacapp_decode_application_data(test_data.application_data,
test_data.application_data_len, &test_value);
len = bacapp_decode_application_data(test_data.application_data,
test_data.application_data_len,
&test_value);
ct_test(pTest, test_value.tag == value->tag);
switch (test_value.tag) {
case BACNET_APPLICATION_TAG_NULL:
@@ -248,23 +229,23 @@ void testWritePropertyTag(
break;
case BACNET_APPLICATION_TAG_UNSIGNED_INT:
ct_test(pTest,
test_value.type.Unsigned_Int == value->type.Unsigned_Int);
test_value.type.Unsigned_Int == value->type.Unsigned_Int);
break;
case BACNET_APPLICATION_TAG_SIGNED_INT:
ct_test(pTest,
test_value.type.Signed_Int == value->type.Signed_Int);
test_value.type.Signed_Int == value->type.Signed_Int);
break;
case BACNET_APPLICATION_TAG_REAL:
ct_test(pTest, test_value.type.Real == value->type.Real);
break;
case BACNET_APPLICATION_TAG_ENUMERATED:
ct_test(pTest,
test_value.type.Enumerated == value->type.Enumerated);
test_value.type.Enumerated == value->type.Enumerated);
break;
case BACNET_APPLICATION_TAG_DATE:
ct_test(pTest, test_value.type.Date.year == value->type.Date.year);
ct_test(pTest,
test_value.type.Date.month == value->type.Date.month);
test_value.type.Date.month == value->type.Date.month);
ct_test(pTest, test_value.type.Date.day == value->type.Date.day);
ct_test(pTest, test_value.type.Date.wday == value->type.Date.wday);
break;
@@ -272,24 +253,21 @@ void testWritePropertyTag(
ct_test(pTest, test_value.type.Time.hour == value->type.Time.hour);
ct_test(pTest, test_value.type.Time.min == value->type.Time.min);
ct_test(pTest, test_value.type.Time.sec == value->type.Time.sec);
ct_test(pTest,
test_value.type.Time.hundredths ==
value->type.Time.hundredths);
ct_test(pTest, test_value.type.Time.hundredths ==
value->type.Time.hundredths);
break;
case BACNET_APPLICATION_TAG_OBJECT_ID:
ct_test(pTest,
test_value.type.Object_Id.type == value->type.Object_Id.type);
ct_test(pTest,
test_value.type.Object_Id.instance ==
value->type.Object_Id.instance);
ct_test(pTest, test_value.type.Object_Id.type ==
value->type.Object_Id.type);
ct_test(pTest, test_value.type.Object_Id.instance ==
value->type.Object_Id.instance);
break;
default:
break;
}
}
void testWriteProperty(
Test * pTest)
void testWriteProperty(Test *pTest)
{
BACNET_APPLICATION_DATA_VALUE value;
@@ -366,8 +344,7 @@ void testWriteProperty(
}
#ifdef TEST_WRITE_PROPERTY
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -379,7 +356,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+77 -108
View File
@@ -1,28 +1,28 @@
/**************************************************************************
*
* Copyright (C) 2011 Krzysztof Malorny <malornykrzysztof@gmail.com>
* Contributions by Nikola Jelic 2011 <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2011 Krzysztof Malorny <malornykrzysztof@gmail.com>
* Contributions by Nikola Jelic 2011 <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <stdint.h>
#include "bacapp.h"
#include "bacenum.h"
@@ -49,10 +49,8 @@
* @param data [out] The BACNET_WRITE_PROPERTY_DATA structure
* which will contain the reponse values or error.
*/
int wpm_decode_object_id(
uint8_t * apdu,
uint16_t apdu_len,
BACNET_WRITE_PROPERTY_DATA * wp_data)
int wpm_decode_object_id(uint8_t *apdu, uint16_t apdu_len,
BACNET_WRITE_PROPERTY_DATA *wp_data)
{
uint8_t tag_number = 0;
uint32_t len_value = 0;
@@ -62,14 +60,12 @@ int wpm_decode_object_id(
if (apdu && (apdu_len > 5) && wp_data) {
/* Context tag 0 - Object ID */
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 == 0) && (apdu_len > len)) {
apdu_len -= len;
if (apdu_len >= 4) {
len +=
decode_object_id(&apdu[len], &object_type,
&object_instance);
len += decode_object_id(&apdu[len], &object_type,
&object_instance);
wp_data->object_type = object_type;
wp_data->object_instance = object_instance;
apdu_len -= len;
@@ -93,28 +89,23 @@ int wpm_decode_object_id(
return BACNET_STATUS_REJECT;
}
return (int) len;
return (int)len;
}
int wpm_decode_object_property(
uint8_t * apdu,
uint16_t apdu_len,
BACNET_WRITE_PROPERTY_DATA * wp_data)
int wpm_decode_object_property(uint8_t *apdu, uint16_t apdu_len,
BACNET_WRITE_PROPERTY_DATA *wp_data)
{
uint8_t tag_number = 0;
uint32_t len_value = 0;
uint32_t ulVal = 0;
int len = 0, i = 0;
if ((apdu) && (apdu_len) && (wp_data)) {
wp_data->array_index = BACNET_ARRAY_ALL;
wp_data->priority = BACNET_MAX_PRIORITY;
wp_data->application_data_len = 0;
/* tag 0 - Property Identifier */
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 == 0) {
len += decode_enumerated(&apdu[len], len_value, &ulVal);
wp_data->object_property = ulVal;
@@ -124,22 +115,20 @@ int wpm_decode_object_property(
}
/* tag 1 - Property Array Index - optional */
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) {
len += decode_unsigned(&apdu[len], len_value, &ulVal);
wp_data->array_index = ulVal;
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
}
/* tag 2 - Property Value */
if ((tag_number == 2) && (decode_is_opening_tag(&apdu[len - 1]))) {
len--;
wp_data->application_data_len =
bacapp_data_len(&apdu[len], (unsigned) (apdu_len - len),
wp_data->object_property);
bacapp_data_len(&apdu[len], (unsigned)(apdu_len - len),
wp_data->object_property);
len++;
/* copy application data */
@@ -147,9 +136,8 @@ int wpm_decode_object_property(
wp_data->application_data[i] = apdu[len + i];
}
len += wp_data->application_data_len;
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
/* closing tag 2 */
if ((tag_number != 2) && (decode_is_closing_tag(&apdu[len - 1]))) {
wp_data->error_code = ERROR_CODE_REJECT_INVALID_TAG;
@@ -161,8 +149,7 @@ int wpm_decode_object_property(
}
/* tag 3 - Priority - optional */
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 == 3) {
len += decode_unsigned(&apdu[len], len_value, &ulVal);
wp_data->priority = ulVal;
@@ -177,35 +164,29 @@ int wpm_decode_object_property(
}
/* encode functions */
int wpm_encode_apdu_init(
uint8_t * apdu,
uint8_t invoke_id)
int wpm_encode_apdu_init(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) {
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU);
apdu[2] = invoke_id;
apdu[3] = SERVICE_CONFIRMED_WRITE_PROP_MULTIPLE; /* service choice */
apdu[3] = SERVICE_CONFIRMED_WRITE_PROP_MULTIPLE; /* service choice */
apdu_len = 4;
}
return apdu_len;
}
int wpm_encode_apdu_object_begin(
uint8_t * apdu,
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance)
int wpm_encode_apdu_object_begin(uint8_t *apdu, 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) {
apdu_len =
encode_context_object_id(&apdu[0], 0, object_type,
object_instance);
encode_context_object_id(&apdu[0], 0, object_type, object_instance);
/* Tag 1: sequence of WriteAccessSpecification */
apdu_len += encode_opening_tag(&apdu[apdu_len], 1);
}
@@ -213,10 +194,9 @@ int wpm_encode_apdu_object_begin(
return apdu_len;
}
int wpm_encode_apdu_object_end(
uint8_t * apdu)
int wpm_encode_apdu_object_end(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) {
apdu_len = encode_closing_tag(&apdu[0], 1);
@@ -225,11 +205,10 @@ int wpm_encode_apdu_object_end(
return apdu_len;
}
int wpm_encode_apdu_object_property(
uint8_t * apdu,
BACNET_WRITE_PROPERTY_DATA * wpdata)
int wpm_encode_apdu_object_property(uint8_t *apdu,
BACNET_WRITE_PROPERTY_DATA *wpdata)
{
int apdu_len = 0; /* total length of the apdu, return value */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0;
if (apdu) {
@@ -237,9 +216,8 @@ int wpm_encode_apdu_object_property(
encode_context_enumerated(&apdu[0], 0, wpdata->object_property);
/* optional array index */
if (wpdata->array_index != BACNET_ARRAY_ALL) {
apdu_len +=
encode_context_unsigned(&apdu[apdu_len], 1,
wpdata->array_index);
apdu_len += encode_context_unsigned(&apdu[apdu_len], 1,
wpdata->array_index);
}
apdu_len += encode_opening_tag(&apdu[apdu_len], 2);
for (len = 0; len < wpdata->application_data_len; len++) {
@@ -256,18 +234,17 @@ int wpm_encode_apdu_object_property(
return apdu_len;
}
int wpm_encode_apdu(
uint8_t * apdu,
size_t max_apdu,
uint8_t invoke_id,
BACNET_WRITE_ACCESS_DATA * write_access_data)
int wpm_encode_apdu(uint8_t *apdu, size_t max_apdu, uint8_t invoke_id,
BACNET_WRITE_ACCESS_DATA *write_access_data)
{
int apdu_len = 0;
int len = 0;
BACNET_WRITE_ACCESS_DATA *wpm_object; /* current object */
uint8_t apdu_temp[MAX_APDU]; /* temp for data before copy */
BACNET_PROPERTY_VALUE *wpm_property; /* current property */
BACNET_WRITE_PROPERTY_DATA wpdata; /* for compatibility with wpm_encode_apdu_object_property function */
BACNET_WRITE_ACCESS_DATA *wpm_object; /* current object */
uint8_t apdu_temp[MAX_APDU]; /* temp for data before copy */
BACNET_PROPERTY_VALUE *wpm_property; /* current property */
BACNET_WRITE_PROPERTY_DATA
wpdata; /* for compatibility with wpm_encode_apdu_object_property
function */
if (apdu) {
len = wpm_encode_apdu_init(&apdu[0], invoke_id);
@@ -276,10 +253,9 @@ int wpm_encode_apdu(
wpm_object = write_access_data;
while (wpm_object) {
len =
wpm_encode_apdu_object_begin(&apdu[apdu_len],
wpm_object->object_type, wpm_object->object_instance);
len = wpm_encode_apdu_object_begin(&apdu[apdu_len],
wpm_object->object_type,
wpm_object->object_instance);
apdu_len += len;
wpm_property = wpm_object->listOfProperties;
@@ -288,12 +264,11 @@ int wpm_encode_apdu(
wpdata.object_property = wpm_property->propertyIdentifier;
wpdata.array_index = wpm_property->propertyArrayIndex;
wpdata.priority = wpm_property->priority;
wpdata.application_data_len = bacapp_encode_data(&apdu_temp[0],
&wpm_property->value);
memcpy(&wpdata.application_data[0], &apdu_temp[0],
(size_t)wpdata.application_data_len);
len =
wpm_encode_apdu_object_property(&apdu[apdu_len], &wpdata);
wpdata.application_data_len =
bacapp_encode_data(&apdu_temp[0], &wpm_property->value);
memcpy(&wpdata.application_data[0], &apdu_temp[0],
(size_t)wpdata.application_data_len);
len = wpm_encode_apdu_object_property(&apdu[apdu_len], &wpdata);
apdu_len += len;
wpm_property = wpm_property->next;
@@ -309,9 +284,7 @@ int wpm_encode_apdu(
return apdu_len;
}
int wpm_ack_encode_apdu_init(
uint8_t * apdu,
uint8_t invoke_id)
int wpm_ack_encode_apdu_init(uint8_t *apdu, uint8_t invoke_id)
{
int len = 0;
@@ -324,10 +297,8 @@ int wpm_ack_encode_apdu_init(
return len;
}
int wpm_error_ack_encode_apdu(
uint8_t * apdu,
uint8_t invoke_id,
BACNET_WRITE_PROPERTY_DATA * wp_data)
int wpm_error_ack_encode_apdu(uint8_t *apdu, uint8_t invoke_id,
BACNET_WRITE_PROPERTY_DATA *wp_data)
{
int len = 0;
@@ -342,15 +313,13 @@ int wpm_error_ack_encode_apdu(
len += encode_closing_tag(&apdu[len], 0);
len += encode_opening_tag(&apdu[len], 1);
len +=
encode_context_object_id(&apdu[len], 0, wp_data->object_type,
wp_data->object_instance);
len += encode_context_object_id(&apdu[len], 0, wp_data->object_type,
wp_data->object_instance);
len +=
encode_context_enumerated(&apdu[len], 1, wp_data->object_property);
if (wp_data->array_index != BACNET_ARRAY_ALL)
len +=
encode_context_unsigned(&apdu[len], 2, wp_data->array_index);
len += encode_context_unsigned(&apdu[len], 2, wp_data->array_index);
len += encode_closing_tag(&apdu[len], 1);
}
return len;