added clang format C and H files.
This commit is contained in:
+31
-55
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+320
-600
File diff suppressed because it is too large
Load Diff
+71
-96
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+6
-10
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+354
-567
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+201
-222
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+9
-14
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user