From 1cc71f8d14dd3315ca4a9f5bfffa1368b60614e6 Mon Sep 17 00:00:00 2001 From: skarg Date: Fri, 23 Dec 2005 17:39:36 +0000 Subject: [PATCH] changed the modules to use the new BACNet string types. Modified the device object to handle having the string properties changed via WriteProperty service. Updated the unit tests. Updated the demo objects. --- bacnet-stack/abort.mak | 1 + bacnet-stack/ai.c | 5 +- bacnet-stack/ai.mak | 1 + bacnet-stack/ao.c | 5 +- bacnet-stack/ao.mak | 1 + bacnet-stack/arf.c | 37 +++--- bacnet-stack/arf.h | 6 +- bacnet-stack/arf.mak | 1 + bacnet-stack/awf.c | 39 +++---- bacnet-stack/awf.h | 6 +- bacnet-stack/awf.mak | 1 + bacnet-stack/bacapp.mak | 1 + bacnet-stack/bacdcode.c | 190 ++++++++++++++++-------------- bacnet-stack/bacdcode.h | 18 ++- bacnet-stack/bacdcode.mak | 1 + bacnet-stack/bacerror.mak | 1 + bacnet-stack/bacfile.c | 22 ++-- bacnet-stack/bacstr.c | 148 +++++++++++++++-------- bacnet-stack/bacstr.h | 29 ++++- bacnet-stack/device.c | 195 +++++++++++++++++++++++-------- bacnet-stack/device.h | 15 ++- bacnet-stack/device.mak | 1 + bacnet-stack/handlers.c | 11 +- bacnet-stack/iam.mak | 1 + bacnet-stack/npdu.mak | 1 + bacnet-stack/ports/linux/main.c | 18 +-- bacnet-stack/ports/rtos32/main.c | 16 +-- bacnet-stack/reject.mak | 1 + bacnet-stack/rp.mak | 1 + bacnet-stack/rpm.mak | 1 + bacnet-stack/test.sh | 164 +++++++++++++++----------- bacnet-stack/tsm.c | 19 +-- bacnet-stack/tsm.mak | 10 +- bacnet-stack/whois.mak | 1 + bacnet-stack/wp.mak | 1 + 35 files changed, 580 insertions(+), 389 deletions(-) diff --git a/bacnet-stack/abort.mak b/bacnet-stack/abort.mak index 64d762e1..753540ec 100644 --- a/bacnet-stack/abort.mak +++ b/bacnet-stack/abort.mak @@ -7,6 +7,7 @@ BASEDIR = . CFLAGS = -Wall -I. -Itest -DTEST -DTEST_ABORT -g SRCS = bacdcode.c \ + bacstr.c \ bigend.c \ abort.c \ test/ctest.c diff --git a/bacnet-stack/ai.c b/bacnet-stack/ai.c index 4a965aaa..1e11205f 100644 --- a/bacnet-stack/ai.c +++ b/bacnet-stack/ai.c @@ -71,6 +71,7 @@ int Analog_Input_Encode_Property_APDU( { int apdu_len = 0; // return value BACNET_BIT_STRING bit_string; + BACNET_CHARACTER_STRING char_string; char text_string[32] = {""}; float value = 3.14; @@ -84,7 +85,9 @@ int Analog_Input_Encode_Property_APDU( case PROP_OBJECT_NAME: case PROP_DESCRIPTION: sprintf(text_string,"ANALOG INPUT %u",object_instance); - apdu_len = encode_tagged_character_string(&apdu[0], text_string); + characterstring_init_ansi(&char_string, text_string); + apdu_len = encode_tagged_character_string(&apdu[0], + &char_string); break; case PROP_OBJECT_TYPE: apdu_len = encode_tagged_enumerated(&apdu[0], OBJECT_ANALOG_INPUT); diff --git a/bacnet-stack/ai.mak b/bacnet-stack/ai.mak index 617981f9..6aef7e43 100755 --- a/bacnet-stack/ai.mak +++ b/bacnet-stack/ai.mak @@ -7,6 +7,7 @@ BASEDIR = . CFLAGS = -Wall -I. -Itest -DTEST -DTEST_ANALOG_INPUT -g SRCS = bacdcode.c \ + bacstr.c \ bigend.c \ ai.c \ test/ctest.c diff --git a/bacnet-stack/ao.c b/bacnet-stack/ao.c index 35dbceee..1e17ea24 100644 --- a/bacnet-stack/ao.c +++ b/bacnet-stack/ao.c @@ -152,6 +152,7 @@ int Analog_Output_Encode_Property_APDU( int len = 0; int apdu_len = 0; // return value BACNET_BIT_STRING bit_string; + BACNET_CHARACTER_STRING char_string; char text_string[32] = {""}; float real_value = 1.414; unsigned object_index = 0; @@ -168,7 +169,9 @@ int Analog_Output_Encode_Property_APDU( case PROP_DESCRIPTION: // note: the object name must be unique within this device sprintf(text_string,"ANALOG OUTPUT %u",object_instance); - apdu_len = encode_tagged_character_string(&apdu[0], text_string); + characterstring_init_ansi(&char_string, text_string); + apdu_len = encode_tagged_character_string(&apdu[0], + &char_string); break; case PROP_OBJECT_TYPE: apdu_len = encode_tagged_enumerated(&apdu[0], OBJECT_ANALOG_OUTPUT); diff --git a/bacnet-stack/ao.mak b/bacnet-stack/ao.mak index 6343403a..d61cb1a6 100755 --- a/bacnet-stack/ao.mak +++ b/bacnet-stack/ao.mak @@ -7,6 +7,7 @@ BASEDIR = . CFLAGS = -Wall -I. -Itest -DTEST -DTEST_ANALOG_OUTPUT -g SRCS = bacdcode.c \ + bacstr.c \ bigend.c \ ao.c \ test/ctest.c diff --git a/bacnet-stack/arf.c b/bacnet-stack/arf.c index c87d15ed..c2ab9c79 100644 --- a/bacnet-stack/arf.c +++ b/bacnet-stack/arf.c @@ -220,7 +220,7 @@ int arf_ack_encode_apdu( apdu_len += encode_tagged_signed(&apdu[apdu_len], data->type.stream.fileStartPosition); apdu_len += encode_tagged_octet_string(&apdu[apdu_len], - data->fileData, data->fileDataLength); + &data->fileData); apdu_len += encode_closing_tag(&apdu[apdu_len], 0); break; case FILE_RECORD_ACCESS: @@ -230,7 +230,7 @@ int arf_ack_encode_apdu( apdu_len += encode_tagged_unsigned(&apdu[apdu_len], data->type.record.RecordCount); apdu_len += encode_tagged_octet_string(&apdu[apdu_len], - data->fileData, data->fileDataLength); + &data->fileData); apdu_len += encode_closing_tag(&apdu[apdu_len], 1); break; default: @@ -281,9 +281,7 @@ int arf_ack_decode_service_request( return -1; len += decode_octet_string(&apdu[len], len_value_type, - data->fileData, - data->fileDataLength); - data->fileDataLength = len_value_type; + &data->fileData); if (!decode_is_closing_tag_number(&apdu[len], 0)) return -1; // a tag number is not extended so only one octet @@ -320,9 +318,7 @@ int arf_ack_decode_service_request( return -1; len += decode_octet_string(&apdu[len], len_value_type, - data->fileData, - data->fileDataLength); - data->fileDataLength = len_value_type; + &data->fileData); if (!decode_is_closing_tag_number(&apdu[len], 1)) return -1; // a tag number is not extended so only one octet @@ -380,7 +376,6 @@ void testAtomicReadFileAckAccess(Test * pTest, int apdu_len = 0; uint8_t invoke_id = 128; uint8_t test_invoke_id = 0; - uint8_t test_octet_string[128] = "bingo!"; len = arf_ack_encode_apdu( &apdu[0], @@ -389,8 +384,6 @@ void testAtomicReadFileAckAccess(Test * pTest, ct_test(pTest, len != 0); apdu_len = len; - test_data.fileData = test_octet_string; - test_data.fileDataLength = sizeof(test_octet_string); len = arf_ack_decode_apdu( &apdu[0], apdu_len, @@ -411,33 +404,35 @@ void testAtomicReadFileAckAccess(Test * pTest, ct_test(pTest, test_data.type.record.RecordCount == data->type.record.RecordCount); } - ct_test(pTest, test_data.fileDataLength == - data->fileDataLength); + ct_test(pTest, octetstring_length(&test_data.fileData) == + octetstring_length(&data->fileData)); ct_test(pTest, memcmp( - &test_data.fileData[0], - &data->fileData[0], - test_data.fileDataLength) == 0); + octetstring_value(&test_data.fileData), + octetstring_value(&data->fileData), + octetstring_length(&test_data.fileData)) == 0); } void testAtomicReadFileAck(Test * pTest) { BACNET_ATOMIC_READ_FILE_DATA data = {0}; - uint8_t *test_octet_string = "Joshua-Mary-Anna-Christopher"; + uint8_t test_octet_string[32] = "Joshua-Mary-Anna-Christopher"; data.endOfFile = true; data.access = FILE_STREAM_ACCESS; data.type.stream.fileStartPosition = 0; - data.fileData = test_octet_string; - data.fileDataLength = strlen(test_octet_string); + octetstring_init(&data.fileData, + test_octet_string, + sizeof(test_octet_string)); testAtomicReadFileAckAccess(pTest, &data); data.endOfFile = false; data.access = FILE_RECORD_ACCESS; data.type.record.fileStartRecord = 1; data.type.record.RecordCount = 2; - data.fileData = test_octet_string; - data.fileDataLength = strlen(test_octet_string); + octetstring_init(&data.fileData, + test_octet_string, + sizeof(test_octet_string)); testAtomicReadFileAckAccess(pTest, &data); return; diff --git a/bacnet-stack/arf.h b/bacnet-stack/arf.h index d47540d7..cee8e75a 100644 --- a/bacnet-stack/arf.h +++ b/bacnet-stack/arf.h @@ -37,6 +37,7 @@ #include #include #include "bacdcode.h" +#include "bacstr.h" typedef struct BACnet_Atomic_Read_File_Data { @@ -57,10 +58,7 @@ typedef struct BACnet_Atomic_Read_File_Data unsigned RecordCount; } record; } type; - // These are used for the ACK portion - // Set them to an unused buffer for the decode to fill - uint8_t *fileData; - unsigned fileDataLength; + BACNET_OCTET_STRING fileData; bool endOfFile; } BACNET_ATOMIC_READ_FILE_DATA; diff --git a/bacnet-stack/arf.mak b/bacnet-stack/arf.mak index 9047f11f..b75bf76a 100644 --- a/bacnet-stack/arf.mak +++ b/bacnet-stack/arf.mak @@ -7,6 +7,7 @@ BASEDIR = . CFLAGS = -Wall -I. -Itest -DTEST -DTEST_ATOMIC_READ_FILE -DBACDL_BIP=1 -g SRCS = bacdcode.c \ + bacstr.c \ bigend.c \ arf.c \ test/ctest.c diff --git a/bacnet-stack/awf.c b/bacnet-stack/awf.c index 0246d693..4292b826 100644 --- a/bacnet-stack/awf.c +++ b/bacnet-stack/awf.c @@ -64,7 +64,7 @@ int awf_encode_apdu( apdu_len += encode_tagged_signed(&apdu[apdu_len], data->type.stream.fileStartPosition); apdu_len += encode_tagged_octet_string(&apdu[apdu_len], - data->fileData, data->fileDataLength); + &data->fileData); apdu_len += encode_closing_tag(&apdu[apdu_len], 0); break; case FILE_RECORD_ACCESS: @@ -74,7 +74,7 @@ int awf_encode_apdu( apdu_len += encode_tagged_unsigned(&apdu[apdu_len], data->type.record.returnedRecordCount); apdu_len += encode_tagged_octet_string(&apdu[apdu_len], - data->fileData, data->fileDataLength); + &data->fileData); apdu_len += encode_closing_tag(&apdu[apdu_len], 1); break; default: @@ -127,9 +127,7 @@ int awf_decode_service_request( return -1; len += decode_octet_string(&apdu[len], len_value_type, - data->fileData, - data->fileDataLength); - data->fileDataLength = len_value_type; + &data->fileData); if (!decode_is_closing_tag_number(&apdu[len], 0)) return -1; // a tag number is not extended so only one octet @@ -166,9 +164,7 @@ int awf_decode_service_request( return -1; len += decode_octet_string(&apdu[len], len_value_type, - data->fileData, - data->fileDataLength); - data->fileDataLength = len_value_type; + &data->fileData); if (!decode_is_closing_tag_number(&apdu[len], 1)) return -1; // a tag number is not extended so only one octet @@ -322,7 +318,6 @@ void testAtomicWriteFileAccess(Test * pTest, int apdu_len = 0; uint8_t invoke_id = 128; uint8_t test_invoke_id = 0; - uint8_t test_octet_string[128] = "bingo!"; len = awf_encode_apdu( &apdu[0], @@ -331,8 +326,6 @@ void testAtomicWriteFileAccess(Test * pTest, ct_test(pTest, len != 0); apdu_len = len; - test_data.fileData = test_octet_string; - test_data.fileDataLength = sizeof(test_octet_string); len = awf_decode_apdu( &apdu[0], apdu_len, @@ -354,25 +347,26 @@ void testAtomicWriteFileAccess(Test * pTest, ct_test(pTest, test_data.type.record.returnedRecordCount == data->type.record.returnedRecordCount); } - ct_test(pTest, test_data.fileDataLength == - data->fileDataLength); + ct_test(pTest, octetstring_length(&test_data.fileData) == + octetstring_length(&data->fileData)); ct_test(pTest, memcmp( - &test_data.fileData[0], - &data->fileData[0], - test_data.fileDataLength) == 0); + octetstring_value(&test_data.fileData), + octetstring_value(&data->fileData), + octetstring_length(&test_data.fileData)) == 0); } void testAtomicWriteFile(Test * pTest) { BACNET_ATOMIC_WRITE_FILE_DATA data = {0}; - uint8_t *test_octet_string = "Joshua-Mary-Anna-Christopher"; - + uint8_t test_octet_string[32] = "Joshua-Mary-Anna-Christopher"; + data.object_type = OBJECT_FILE; data.object_instance = 1; data.access = FILE_STREAM_ACCESS; data.type.stream.fileStartPosition = 0; - data.fileData = test_octet_string; - data.fileDataLength = strlen(test_octet_string); + octetstring_init(&data.fileData, + test_octet_string, + sizeof(test_octet_string)); testAtomicWriteFileAccess(pTest, &data); data.object_type = OBJECT_FILE; @@ -380,8 +374,9 @@ void testAtomicWriteFile(Test * pTest) data.access = FILE_RECORD_ACCESS; data.type.record.fileStartRecord = 1; data.type.record.returnedRecordCount = 2; - data.fileData = test_octet_string; - data.fileDataLength = strlen(test_octet_string); + octetstring_init(&data.fileData, + test_octet_string, + sizeof(test_octet_string)); testAtomicWriteFileAccess(pTest, &data); return; diff --git a/bacnet-stack/awf.h b/bacnet-stack/awf.h index bcf1ef3d..ec9cbfc7 100644 --- a/bacnet-stack/awf.h +++ b/bacnet-stack/awf.h @@ -55,11 +55,7 @@ typedef struct BACnet_Atomic_Write_File_Data unsigned returnedRecordCount; } record; } type; - // note: set the file data to an empty buffer - // and set the DataLength to the size of the empty buffer - // before decoding the data. - uint8_t *fileData; - unsigned fileDataLength; + BACNET_OCTET_STRING fileData; } BACNET_ATOMIC_WRITE_FILE_DATA; #ifdef __cplusplus diff --git a/bacnet-stack/awf.mak b/bacnet-stack/awf.mak index 428ecf3d..76f794a6 100644 --- a/bacnet-stack/awf.mak +++ b/bacnet-stack/awf.mak @@ -7,6 +7,7 @@ BASEDIR = . CFLAGS = -Wall -I. -Itest -DTEST -DTEST_ATOMIC_WRITE_FILE -DBACDL_BIP=1 -g SRCS = bacdcode.c \ + bacstr.c \ bigend.c \ awf.c \ test/ctest.c diff --git a/bacnet-stack/bacapp.mak b/bacnet-stack/bacapp.mak index 62bf9131..c4f36538 100644 --- a/bacnet-stack/bacapp.mak +++ b/bacnet-stack/bacapp.mak @@ -7,6 +7,7 @@ BASEDIR = . CFLAGS = -Wall -I. -Itest -DTEST -DTEST_BACNET_APPLICATION_DATA -g SRCS = bacdcode.c \ + bacstr.c \ bacapp.c \ bigend.c \ test/ctest.c diff --git a/bacnet-stack/bacdcode.c b/bacnet-stack/bacdcode.c index e97ff099..5e171190 100644 --- a/bacnet-stack/bacdcode.c +++ b/bacnet-stack/bacdcode.c @@ -807,16 +807,16 @@ int encode_tagged_object_id( // from clause 20.2.8 Encoding of an Octet String Value // returns the number of apdu bytes consumed -int encode_octet_string(uint8_t * apdu, const uint8_t *octet_string, - unsigned len) +int encode_octet_string(uint8_t * apdu, BACNET_OCTET_STRING *octet_string) { - unsigned i; + int len = 0; /* return value */ - // limit - 6 octets is the most our tag and type could be - if (len > (MAX_APDU - 6)) - len = MAX_APDU - 6; - for (i = 0; i < len; i++) { - apdu[i] = octet_string[i]; + if (octet_string) + { + /* FIXME: might need to pass in the length of the APDU + to bounds check since it might not be the only data chunk */ + len = octetstring_length(octet_string); + memmove(&apdu[0], octetstring_value(octet_string), len); } return len; @@ -825,17 +825,22 @@ int encode_octet_string(uint8_t * apdu, const uint8_t *octet_string, // from clause 20.2.8 Encoding of an Octet String Value // and 20.2.1 General Rules for Encoding BACnet Tags // returns the number of apdu bytes consumed -int encode_tagged_octet_string(uint8_t * apdu, const uint8_t *octet_string, - unsigned len) +int encode_tagged_octet_string(uint8_t * apdu, + BACNET_OCTET_STRING *octet_string) { - int apdu_len; - - apdu_len = encode_tag(&apdu[0], BACNET_APPLICATION_TAG_OCTET_STRING, - false, len); - if ((apdu_len + len) < MAX_APDU) - apdu_len += encode_octet_string(&apdu[apdu_len], octet_string, len); - else - apdu_len = 0; + int apdu_len = 0; + + if (octet_string) + { + apdu_len = encode_tag(&apdu[0], BACNET_APPLICATION_TAG_OCTET_STRING, + false, octetstring_length(octet_string)); + /* FIXME: probably need to pass in the length of the APDU + to bounds check since it might not be the only data chunk */ + if ((apdu_len + octetstring_length(octet_string)) < MAX_APDU) + apdu_len += encode_octet_string(&apdu[apdu_len], octet_string); + else + apdu_len = 0; + } return apdu_len; } @@ -844,21 +849,14 @@ int encode_tagged_octet_string(uint8_t * apdu, const uint8_t *octet_string, // and 20.2.1 General Rules for Encoding BACnet Tags // returns the number of apdu bytes consumed int decode_octet_string(uint8_t * apdu, uint32_t len_value, - uint8_t *buffer, size_t buffer_len) + BACNET_OCTET_STRING *octet_string) { int len = 0; // return value - uint32_t i = 0; // counter + bool status = false; - // FIXME: issue warning? - if (len_value > buffer_len) - len_value = buffer_len; - - if (len_value) { - for (i = 0; i < len_value; i++) { - buffer[i] = apdu[i]; - } - len += len_value; - } + status = octetstring_init(octet_string,&apdu[0],len_value); + if (status) + len = len_value; return len; } @@ -883,27 +881,28 @@ int encode_bacnet_string(uint8_t * apdu, const char *char_string, int len) // from clause 20.2.9 Encoding of a Character String Value // returns the number of apdu bytes consumed -int encode_bacnet_character_string(uint8_t * apdu, const char *char_string) +int encode_bacnet_character_string(uint8_t * apdu, + BACNET_CHARACTER_STRING *char_string) { int len; - len = strlen(char_string); - len = encode_bacnet_string(&apdu[0], char_string, len); + len = characterstring_length(char_string); + apdu[0] = characterstring_encoding(char_string); + memmove(apdu, characterstring_value(char_string), len); - return len; + return len + 1 /* for encoding */; } // from clause 20.2.9 Encoding of a Character String Value // and 20.2.1 General Rules for Encoding BACnet Tags // returns the number of apdu bytes consumed -int encode_tagged_character_string(uint8_t * apdu, const char *char_string) +int encode_tagged_character_string(uint8_t * apdu, + BACNET_CHARACTER_STRING *char_string) { int len = 0; int string_len = 0; - // find the size of the apdu first - not necessarily effecient - // but reuses existing functions - string_len = encode_bacnet_character_string(&apdu[1], char_string); + string_len = characterstring_length(char_string) + 1 /* for encoding */; len = encode_tag(&apdu[0], BACNET_APPLICATION_TAG_CHARACTER_STRING, false, string_len); if ((len + string_len) < MAX_APDU) @@ -918,28 +917,15 @@ int encode_tagged_character_string(uint8_t * apdu, const char *char_string) // and 20.2.1 General Rules for Encoding BACnet Tags // returns the number of apdu bytes consumed int decode_character_string(uint8_t * apdu, uint32_t len_value, - char *char_string, size_t string_len) + BACNET_CHARACTER_STRING *char_string) { int len = 0; // return value - uint32_t i = 0; // counter + bool status = false; - // FIXME: issue warning? - if (len_value > string_len) - len_value = string_len; - - if (len_value) { - // decode ANSI X3.4 - if (apdu[len] == 0) { - len++; - len_value--; - for (i = 0; i < len_value; i++) { - char_string[i] = apdu[len + i]; - } - // terminate the c string - char_string[i] = 0; - len += len_value; - } - } + status = characterstring_init(char_string, apdu[0], (char *)&apdu[1], + len_value-1); + if (status) + len = len_value; return len; } @@ -1509,40 +1495,54 @@ void testBACDCodeOctetString(Test * pTest) { uint8_t array[MAX_APDU] = { 0 }; uint8_t encoded_array[MAX_APDU] = { 0 }; - char test_string[MAX_APDU] = { "" }; - char decoded_string[MAX_APDU] = { "" }; + BACNET_OCTET_STRING octet_string; + BACNET_OCTET_STRING test_octet_string; + uint8_t test_value[MAX_APDU] = { "" }; int i; // for loop counter int apdu_len; int len; - char *test_string0 = ""; uint8_t tag_number = 0; uint32_t len_value = 0; + bool status = false; + int diff = 0; /* for memcmp */ - apdu_len = encode_tagged_octet_string(&array[0], (uint8_t *)&test_string0[0], 0); + status = octetstring_init( + &octet_string, + NULL, + 0); + ct_test(pTest,status == true); + apdu_len = encode_tagged_octet_string(&array[0], &octet_string); len = decode_tag_number_and_value(&array[0], &tag_number, &len_value); - len += decode_octet_string(&array[len], len_value, - (uint8_t *)&decoded_string[0], sizeof(decoded_string)); + ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OCTET_STRING); + len += decode_octet_string(&array[len], len_value, &test_octet_string); ct_test(pTest, apdu_len == len); - ct_test(pTest, memcmp(&test_string0[0], &decoded_string[0], - len_value) == 0); + diff = memcmp(octetstring_value(&octet_string), &test_value[0], + octetstring_length(&octet_string)); + ct_test(pTest,diff == 0); + for (i = 0; i < (MAX_APDU - 6); i++) { - test_string[i] = '0' + (i % 10); - apdu_len = - encode_tagged_octet_string(&encoded_array[0], - (uint8_t *)&test_string[0], i); + test_value[i] = '0' + (i % 10); + status = octetstring_init( + &octet_string, + test_value, + i); + ct_test(pTest,status == true); + apdu_len = encode_tagged_octet_string(&encoded_array[0],&octet_string); len = decode_tag_number_and_value(&encoded_array[0], &tag_number, &len_value); + ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OCTET_STRING); len += decode_octet_string(&encoded_array[len], len_value, - (uint8_t *)&decoded_string[0], sizeof(decoded_string)); + &test_octet_string); if (apdu_len != len) { printf("test octet string=#%d\n", i); } ct_test(pTest, apdu_len == len); - if (memcmp(&test_string[0], &decoded_string[0], len_value) != 0) { + diff = memcmp(octetstring_value(&octet_string), &test_value[0], + octetstring_length(&octet_string)); + if (diff) { printf("test octet string=#%d\n", i); } - ct_test(pTest, memcmp(&test_string[0], &decoded_string[0], - len_value) == 0); + ct_test(pTest,diff == 0); } return; @@ -1552,39 +1552,53 @@ void testBACDCodeCharacterString(Test * pTest) { uint8_t array[MAX_APDU] = { 0 }; uint8_t encoded_array[MAX_APDU] = { 0 }; - char test_string[MAX_APDU] = { "" }; - char decoded_string[MAX_APDU] = { "" }; + BACNET_CHARACTER_STRING char_string; + BACNET_CHARACTER_STRING test_char_string; + char test_value[MAX_APDU] = { "" }; int i; // for loop counter int apdu_len; int len; - char *test_string0 = ""; uint8_t tag_number = 0; uint32_t len_value = 0; + int diff = 0; /* for comparison */ + bool status = false; - apdu_len = encode_tagged_character_string(&array[0], &test_string0[0]); + status = characterstring_init( + &char_string, + CHARACTER_ANSI, + NULL, + 0); + ct_test(pTest,status == true); + apdu_len = encode_tagged_character_string(&array[0], &char_string); len = decode_tag_number_and_value(&array[0], &tag_number, &len_value); - len += decode_character_string(&array[len], len_value, - &decoded_string[0], sizeof(decoded_string)); + ct_test(pTest,tag_number == BACNET_APPLICATION_TAG_CHARACTER_STRING); + len += decode_character_string(&array[len], len_value, &test_char_string); ct_test(pTest, apdu_len == len); - ct_test(pTest, strcmp(&test_string0[0], &decoded_string[0]) == 0); + diff = memcmp(characterstring_value(&char_string), &test_value[0], + characterstring_length(&char_string)); + ct_test(pTest, diff == 0); for (i = 0; i < (MAX_APDU - 6); i++) { - test_string[i] = 'S'; - test_string[i + 1] = '\0'; + test_value[i] = 'S'; + test_value[i + 1] = '\0'; + status = characterstring_init_ansi(&char_string, test_value); + ct_test(pTest,status == true); apdu_len = - encode_tagged_character_string(&encoded_array[0], - &test_string[0]); + encode_tagged_character_string(&encoded_array[0], &char_string); len = decode_tag_number_and_value(&encoded_array[0], &tag_number, &len_value); + ct_test(pTest,tag_number == BACNET_APPLICATION_TAG_CHARACTER_STRING); len += decode_character_string(&encoded_array[len], len_value, - &decoded_string[0], sizeof(decoded_string)); + &test_char_string); if (apdu_len != len) { - printf("test string=#%d\n", i); + printf("test string=#%d apdu_len=%d len=%d\n", i,apdu_len,len); } ct_test(pTest, apdu_len == len); - if (strcmp(&test_string[0], &decoded_string[0]) != 0) { + diff = memcmp(characterstring_value(&char_string), &test_value[0], + characterstring_length(&char_string)); + if (diff) { printf("test string=#%d\n", i); } - ct_test(pTest, strcmp(&test_string[0], &decoded_string[0]) == 0); + ct_test(pTest, diff == 0); } return; diff --git a/bacnet-stack/bacdcode.h b/bacnet-stack/bacdcode.h index 01b23813..1b1082bc 100644 --- a/bacnet-stack/bacdcode.h +++ b/bacnet-stack/bacdcode.h @@ -100,25 +100,23 @@ int encode_tagged_object_id(uint8_t * apdu, int object_type, uint32_t instance); // from clause 20.2.8 Encoding of an Octet String Value // and 20.2.1 General Rules for Encoding BACnet Tags // returns the number of apdu bytes consumed -int encode_octet_string(uint8_t * apdu, const uint8_t *octet_string, - unsigned len); -int encode_tagged_octet_string(uint8_t * apdu, const uint8_t *octet_string, - unsigned len); +int encode_octet_string(uint8_t * apdu, + BACNET_OCTET_STRING *octet_string); +int encode_tagged_octet_string(uint8_t * apdu, + BACNET_OCTET_STRING *octet_string); int decode_octet_string(uint8_t * apdu, uint32_t len_value, - uint8_t *buffer, size_t buffer_len); + BACNET_OCTET_STRING *octet_string); // from clause 20.2.9 Encoding of a Character String Value // and 20.2.1 General Rules for Encoding BACnet Tags // returns the number of apdu bytes consumed -int encode_bacnet_string(uint8_t * apdu, - const char *char_string, int string_len); int encode_bacnet_character_string(uint8_t * apdu, - const char *char_string); + BACNET_CHARACTER_STRING *char_string); int encode_tagged_character_string(uint8_t * apdu, - const char *char_string); + BACNET_CHARACTER_STRING *char_string); int decode_character_string(uint8_t * apdu, uint32_t len_value, - char *char_string, size_t string_len); + BACNET_CHARACTER_STRING *char_string); // from clause 20.2.4 Encoding of an Unsigned Integer Value // and 20.2.1 General Rules for Encoding BACnet Tags diff --git a/bacnet-stack/bacdcode.mak b/bacnet-stack/bacdcode.mak index f3012795..04e84013 100644 --- a/bacnet-stack/bacdcode.mak +++ b/bacnet-stack/bacdcode.mak @@ -6,6 +6,7 @@ CFLAGS = -Wall -I. -Itest -g -DTEST -DTEST_DECODE TARGET = bacdcode SRCS = bacdcode.c \ + bacstr.c \ bigend.c \ test/ctest.c diff --git a/bacnet-stack/bacerror.mak b/bacnet-stack/bacerror.mak index 37469ecf..a4ef15d0 100644 --- a/bacnet-stack/bacerror.mak +++ b/bacnet-stack/bacerror.mak @@ -7,6 +7,7 @@ BASEDIR = . CFLAGS = -Wall -I. -Itest -DTEST -DTEST_BACERROR -g SRCS = bacdcode.c \ + bacstr.c \ bigend.c \ bacerror.c \ test/ctest.c diff --git a/bacnet-stack/bacfile.c b/bacnet-stack/bacfile.c index 457e9a13..4f316da4 100644 --- a/bacnet-stack/bacfile.c +++ b/bacnet-stack/bacfile.c @@ -153,6 +153,7 @@ int bacfile_encode_property_apdu( { int apdu_len = 0; // return value char text_string[32] = {""}; + BACNET_CHARACTER_STRING char_string; (void)array_index; switch (property) @@ -164,17 +165,22 @@ int bacfile_encode_property_apdu( break; case PROP_OBJECT_NAME: sprintf(text_string,"FILE %d",object_instance); - apdu_len = encode_tagged_character_string(&apdu[0], text_string); + characterstring_init_ansi(&char_string, text_string); + apdu_len = encode_tagged_character_string(&apdu[0], + &char_string); break; case PROP_OBJECT_TYPE: apdu_len = encode_tagged_enumerated(&apdu[0], OBJECT_FILE); break; case PROP_DESCRIPTION: + characterstring_init_ansi(&char_string, bacfile_name(object_instance)); apdu_len = encode_tagged_character_string(&apdu[0], - bacfile_name(object_instance)); + &char_string); break; case PROP_FILE_TYPE: - apdu_len = encode_tagged_character_string(&apdu[0],"TEXT"); + characterstring_init_ansi(&char_string, "TEXT"); + apdu_len = encode_tagged_character_string(&apdu[0], + &char_string); break; case PROP_FILE_SIZE: apdu_len = encode_tagged_unsigned(&apdu[0], @@ -300,6 +306,7 @@ bool bacfile_read_data(BACNET_ATOMIC_READ_FILE_DATA *data) char *pFilename = NULL; bool found = false; FILE *pFile = NULL; + size_t len = 0; pFilename = bacfile_name(data->object_instance); if (pFilename) @@ -311,23 +318,24 @@ bool bacfile_read_data(BACNET_ATOMIC_READ_FILE_DATA *data) (void)fseek(pFile, data->type.stream.fileStartPosition, SEEK_SET); - data->fileDataLength = fread(data->fileData, 1, + len = fread(octetstring_value(&data->fileData), 1, data->type.stream.requestedOctetCount, pFile); - if (data->fileDataLength < data->type.stream.requestedOctetCount) + if (len < data->type.stream.requestedOctetCount) data->endOfFile = true; else data->endOfFile = false; + octetstring_truncate(&data->fileData,len); fclose(pFile); } else { - data->fileDataLength = 0; + octetstring_truncate(&data->fileData,0); data->endOfFile = true; } } else { - data->fileDataLength = 0; + octetstring_truncate(&data->fileData,0); data->endOfFile = true; } diff --git a/bacnet-stack/bacstr.c b/bacnet-stack/bacstr.c index a240ce01..6ed2254b 100644 --- a/bacnet-stack/bacstr.c +++ b/bacnet-stack/bacstr.c @@ -34,6 +34,7 @@ #include #include +#include /* for strlen */ #include "bacstr.h" #include "bits.h" @@ -87,10 +88,19 @@ uint8_t bitstring_bits_used(BACNET_BIT_STRING *bit_string) return bit_string->bits_used; } +uint8_t bitstring_bits_capacity(BACNET_BIT_STRING *bit_string) +{ + if (bit_string) + return (sizeof(bit_string->value) * 8); + else + return 0; +} + /* returns false if the string exceeds capacity initialize by using length=0 */ bool characterstring_init( BACNET_CHARACTER_STRING *char_string, + uint8_t encoding, char *value, size_t length) { @@ -100,6 +110,7 @@ bool characterstring_init( if (char_string) { char_string->length = 0; + char_string->encoding = encoding; if (length <= sizeof(char_string->value)) { if (value) @@ -124,6 +135,16 @@ bool characterstring_init( return status; } +bool characterstring_init_ansi( + BACNET_CHARACTER_STRING *char_string, + char *value) +{ + return characterstring_init( + char_string, + CHARACTER_ANSI, + value, value?strlen(value):0); +} + /* returns false if the string exceeds capacity */ bool characterstring_append( BACNET_CHARACTER_STRING *char_string, @@ -171,25 +192,16 @@ bool characterstring_truncate( } /* returns the length. Returns the value in parameter. */ -size_t characterstring_value(BACNET_CHARACTER_STRING *char_string, char *value) +char *characterstring_value(BACNET_CHARACTER_STRING *char_string) { - size_t i; /* counter */ - size_t length = 0; /* return value */ + char *value = NULL; if (char_string) { - /* FIXME: validate length is within bounds? */ - length = char_string->length; - if (value) - { - for (i = 0; i < sizeof(char_string->value); i++) - { - value[i] = char_string->value[i]; - } - } + value = char_string->value; } - return length; + return value; } /* returns the length. */ @@ -206,6 +218,31 @@ size_t characterstring_length(BACNET_CHARACTER_STRING *char_string) return length; } +size_t characterstring_capacity(BACNET_CHARACTER_STRING *char_string) +{ + size_t length = 0; + + if (char_string) + { + length = sizeof(char_string->value); + } + + return length; +} + +/* returns the encoding. */ +uint8_t characterstring_encoding(BACNET_CHARACTER_STRING *char_string) +{ + uint8_t encoding = 0; + + if (char_string) + { + encoding = char_string->encoding; + } + + return encoding; +} + /* returns false if the string exceeds capacity initialize by using length=0 */ bool octetstring_init( @@ -290,25 +327,16 @@ bool octetstring_truncate( } /* returns the length. Returns the value in parameter. */ -size_t octetstring_value(BACNET_OCTET_STRING *octet_string, uint8_t *value) +uint8_t *octetstring_value(BACNET_OCTET_STRING *octet_string) { - size_t i; /* counter */ - size_t length = 0; /* return value */ + uint8_t *value = NULL; if (octet_string) { - /* FIXME: validate length is within bounds? */ - length = octet_string->length; - if (value) - { - for (i = 0; i < sizeof(octet_string->value); i++) - { - value[i] = octet_string->value[i]; - } - } + value = octet_string->value; } - return length; + return value; } /* returns the length. */ @@ -325,6 +353,20 @@ size_t octetstring_length(BACNET_OCTET_STRING *octet_string) return length; } +/* returns the length. */ +size_t octetstring_capacity(BACNET_OCTET_STRING *octet_string) +{ + size_t length = 0; + + if (octet_string) + { + /* FIXME: validate length is within bounds? */ + length = sizeof(octet_string->value); + } + + return length; +} + #ifdef TEST #include #include @@ -363,7 +405,7 @@ void testBitString(Test * pTest) void testCharacterString(Test * pTest) { BACNET_CHARACTER_STRING bacnet_string; - char value[MAX_APDU] = "Joshua,Mary,Anna,Christopher"; + char *value = "Joshua,Mary,Anna,Christopher"; char test_value[MAX_APDU] = "Patricia"; char test_append_value[MAX_APDU] = " and the Kids"; char test_append_string[MAX_APDU] = ""; @@ -373,37 +415,38 @@ void testCharacterString(Test * pTest) size_t i = 0; // verify initialization - status = characterstring_init(&bacnet_string,NULL,0); + status = characterstring_init(&bacnet_string,CHARACTER_ANSI,NULL,0); ct_test(pTest, status == true); ct_test(pTest,characterstring_length(&bacnet_string) == 0); - ct_test(pTest, characterstring_value(&bacnet_string,&value[0]) == 0); - for (i = 0; i < sizeof(value); i++) - { - ct_test(pTest, value[i] == 0); - } + ct_test(pTest,characterstring_encoding(&bacnet_string) == CHARACTER_ANSI); /* bounds check */ - status = characterstring_init(&bacnet_string,NULL,sizeof(value)+1); + status = characterstring_init( + &bacnet_string, + CHARACTER_ANSI, + NULL, + characterstring_capacity(&bacnet_string)+1); ct_test(pTest, status == false); - status = characterstring_init(&bacnet_string,NULL,sizeof(value)); - ct_test(pTest, status == true); - status = characterstring_truncate(&bacnet_string,sizeof(value)+1); + status = characterstring_truncate( + &bacnet_string,characterstring_capacity(&bacnet_string)+1); ct_test(pTest, status == false); - status = characterstring_truncate(&bacnet_string,sizeof(value)); + 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, &test_value[0], test_length); ct_test(pTest, status == true); - length = characterstring_value(&bacnet_string,&value[0]); + value = characterstring_value(&bacnet_string); + length = characterstring_length(&bacnet_string); ct_test(pTest, length == test_length); for (i = 0; i < test_length; i++) { ct_test(pTest, value[i] == test_value[i]); } - test_length = strlen(test_append_value); status = characterstring_append( &bacnet_string, @@ -413,7 +456,8 @@ void testCharacterString(Test * pTest) strcat(test_append_string,test_append_value); test_length = strlen(test_append_string); ct_test(pTest, status == true); - length = characterstring_value(&bacnet_string,&value[0]); + length = characterstring_length(&bacnet_string); + value = characterstring_value(&bacnet_string); ct_test(pTest, length == test_length); for (i = 0; i < test_length; i++) { @@ -424,7 +468,7 @@ void testCharacterString(Test * pTest) void testOctetString(Test * pTest) { BACNET_OCTET_STRING bacnet_string; - uint8_t value[MAX_APDU] = "Joshua,Mary,Anna,Christopher"; + uint8_t *value = NULL; uint8_t test_value[MAX_APDU] = "Patricia"; uint8_t test_append_value[MAX_APDU] = " and the Kids"; uint8_t test_append_string[MAX_APDU] = ""; @@ -437,19 +481,21 @@ void testOctetString(Test * pTest) status = octetstring_init(&bacnet_string,NULL,0); ct_test(pTest, status == true); ct_test(pTest,octetstring_length(&bacnet_string) == 0); - ct_test(pTest, octetstring_value(&bacnet_string,&value[0]) == 0); - for (i = 0; i < sizeof(value); i++) + value = octetstring_value(&bacnet_string); + for (i = 0; i < octetstring_capacity(&bacnet_string); i++) { ct_test(pTest, value[i] == 0); } /* bounds check */ - status = octetstring_init(&bacnet_string,NULL,sizeof(value)+1); + status = octetstring_init(&bacnet_string,NULL, + octetstring_capacity(&bacnet_string)+1); ct_test(pTest, status == false); - status = octetstring_init(&bacnet_string,NULL,sizeof(value)); + status = octetstring_init(&bacnet_string,NULL, + octetstring_capacity(&bacnet_string)); ct_test(pTest, status == true); - status = octetstring_truncate(&bacnet_string,sizeof(value)+1); + status = octetstring_truncate(&bacnet_string,octetstring_capacity(&bacnet_string)+1); ct_test(pTest, status == false); - status = octetstring_truncate(&bacnet_string,sizeof(value)); + status = octetstring_truncate(&bacnet_string,octetstring_capacity(&bacnet_string)); ct_test(pTest, status == true); test_length = strlen((char *)test_value); @@ -458,7 +504,8 @@ void testOctetString(Test * pTest) &test_value[0], test_length); ct_test(pTest, status == true); - length = octetstring_value(&bacnet_string,&value[0]); + length = octetstring_length(&bacnet_string); + value = octetstring_value(&bacnet_string); ct_test(pTest, length == test_length); for (i = 0; i < test_length; i++) { @@ -474,7 +521,8 @@ void testOctetString(Test * pTest) strcat((char *)test_append_string,(char *)test_append_value); test_length = strlen((char *)test_append_string); ct_test(pTest, status == true); - length = octetstring_value(&bacnet_string,&value[0]); + length = octetstring_length(&bacnet_string); + value = octetstring_value(&bacnet_string); ct_test(pTest, length == test_length); for (i = 0; i < test_length; i++) { diff --git a/bacnet-stack/bacstr.h b/bacnet-stack/bacstr.h index 8f757e38..9f79d773 100644 --- a/bacnet-stack/bacstr.h +++ b/bacnet-stack/bacstr.h @@ -51,7 +51,9 @@ typedef struct BACnet_Bit_String typedef struct BACnet_Character_String { size_t length; - char value[MAX_APDU]; + uint8_t encoding; + /* limit - 6 octets is the most our tag and type could be */ + char value[MAX_APDU-6]; } BACNET_CHARACTER_STRING; /* FIXME: convert the bacdcode library to use BACNET_OCTET_STRING @@ -59,7 +61,8 @@ typedef struct BACnet_Character_String typedef struct BACnet_Octet_String { size_t length; - uint8_t value[MAX_APDU]; + /* limit - 6 octets is the most our tag and type could be */ + uint8_t value[MAX_APDU-6]; } BACNET_OCTET_STRING; #ifdef __cplusplus @@ -70,13 +73,19 @@ void bitstring_init(BACNET_BIT_STRING *bit_string); void bitstring_set_bit(BACNET_BIT_STRING *bit_string, uint8_t bit, bool value); bool bitstring_bit(BACNET_BIT_STRING *bit_string, uint8_t bit); uint8_t bitstring_bits_used(BACNET_BIT_STRING *bit_string); +uint8_t bitstring_bits_capacity(BACNET_BIT_STRING *bit_string); /* returns false if the string exceeds capacity initialize by using length=0 */ bool characterstring_init( BACNET_CHARACTER_STRING *char_string, + uint8_t encoding, char *value, size_t length); +/* used for ANSI C-Strings */ +bool characterstring_init_ansi( + BACNET_CHARACTER_STRING *char_string, + char *value); /* returns false if the string exceeds capacity */ bool characterstring_append( BACNET_CHARACTER_STRING *char_string, @@ -88,9 +97,15 @@ bool characterstring_append( bool characterstring_truncate( BACNET_CHARACTER_STRING *char_string, size_t length); -/* returns the length. Returns the value in parameter. */ -size_t characterstring_value(BACNET_CHARACTER_STRING *char_string, char *value); +bool characterstring_set_encoding( + BACNET_CHARACTER_STRING *char_string, + uint8_t encoding); +/* Returns the value */ +char *characterstring_value(BACNET_CHARACTER_STRING *char_string); +/* returns the length */ size_t characterstring_length(BACNET_CHARACTER_STRING *char_string); +uint8_t characterstring_encoding(BACNET_CHARACTER_STRING *char_string); +size_t characterstring_capacity(BACNET_CHARACTER_STRING *char_string); /* returns false if the string exceeds capacity initialize by using length=0 */ @@ -109,9 +124,11 @@ bool octetstring_append( bool octetstring_truncate( BACNET_OCTET_STRING *octet_string, size_t length); -/* returns the length. Returns the value in parameter. */ -size_t octetstring_value(BACNET_OCTET_STRING *octet_string, uint8_t *value); +/* Returns the value */ +uint8_t *octetstring_value(BACNET_OCTET_STRING *octet_string); +/* Returns the length.*/ size_t octetstring_length(BACNET_OCTET_STRING *octet_string); +size_t octetstring_capacity(BACNET_OCTET_STRING *octet_string); #ifdef __cplusplus } diff --git a/bacnet-stack/device.c b/bacnet-stack/device.c index 2456f01f..41050d9a 100644 --- a/bacnet-stack/device.c +++ b/bacnet-stack/device.c @@ -25,6 +25,7 @@ #include #include +#include /* for memmove*/ #include "bacdef.h" #include "bacdcode.h" #include "bacenum.h" @@ -39,16 +40,16 @@ static uint32_t Object_Instance_Number = 0; // FIXME: it is likely that this name is configurable, // so consider a fixed sized string -static const char *Object_Name = "SimpleServer"; +static char Object_Name[16] = "SimpleServer"; static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL; -static const char *Vendor_Name = "ASHRAE"; +static char Vendor_Name[16] = "ASHRAE"; // vendor id assigned by ASHRAE static uint16_t Vendor_Identifier = 0; -static const char *Model_Name = "GNU"; -static const char *Firmware_Revision = "1.0"; -static const char *Application_Software_Version = "1.0"; -//static char *Location = "USA"; -static const char *Description = "server"; +static char Model_Name[16] = "GNU"; +static char Firmware_Revision[16] = "1.0"; +static char Application_Software_Version[16] = "1.0"; +static char Location[16] = "USA"; +static char Description[16] = "server"; //static uint8_t Protocol_Version = 1; - constant, not settable //static uint8_t Protocol_Revision = 4; - constant, not settable //Protocol_Services_Supported @@ -88,10 +89,16 @@ uint32_t Device_Object_Instance_Number(void) return Object_Instance_Number; } -void Device_Set_Object_Instance_Number(uint32_t object_id) +bool Device_Set_Object_Instance_Number(uint32_t object_id) { - // FIXME: bounds check? - Object_Instance_Number = object_id; + bool status = true; /* return value */ + + if (object_id <= BACNET_MAX_INSTANCE) + Object_Instance_Number = object_id; + else + status = false; + + return status; } bool Device_Valid_Object_Instance_Number(uint32_t object_id) @@ -117,9 +124,18 @@ const char *Device_Vendor_Name(void) return Vendor_Name; } -void Device_Set_Vendor_Name(const char *name) +bool Device_Set_Vendor_Name(const char *name, size_t length) { - Vendor_Name = name; + bool status = false; /*return value*/ + + if (length < sizeof(Vendor_Name)) + { + memmove(Vendor_Name,name,length); + Vendor_Name[length] = 0; + status = true; + } + + return status; } uint16_t Device_Vendor_Identifier(void) @@ -137,9 +153,18 @@ const char *Device_Model_Name(void) return Model_Name; } -void Device_Set_Model_Name(const char *name) +bool Device_Set_Model_Name(const char *name, size_t length) { - Model_Name = name; + bool status = false; /*return value*/ + + if (length < sizeof(Model_Name)) + { + memmove(Model_Name,name,length); + Model_Name[length] = 0; + status = true; + } + + return status; } const char *Device_Firmware_Revision(void) @@ -147,9 +172,18 @@ const char *Device_Firmware_Revision(void) return Firmware_Revision; } -void Device_Set_Firmware_Revision(const char *name) +bool Device_Set_Firmware_Revision(const char *name, size_t length) { - Firmware_Revision = name; + bool status = false; /*return value*/ + + if (length < sizeof(Firmware_Revision)) + { + memmove(Firmware_Revision,name,length); + Firmware_Revision[length] = 0; + status = true; + } + + return status; } const char *Device_Application_Software_Version(void) @@ -157,9 +191,18 @@ const char *Device_Application_Software_Version(void) return Application_Software_Version; } -void Device_Set_Application_Software_Version(const char *name) +bool Device_Set_Application_Software_Version(const char *name, size_t length) { - Application_Software_Version = name; + bool status = false; /*return value*/ + + if (length < sizeof(Application_Software_Version)) + { + memmove(Application_Software_Version,name,length); + Application_Software_Version[length] = 0; + status = true; + } + + return status; } const char *Device_Description(void) @@ -167,9 +210,37 @@ const char *Device_Description(void) return Description; } -void Device_Set_Description(const char *name) +bool Device_Set_Description(const char *name, size_t length) { - Description = name; + bool status = false; /*return value*/ + + if (length < sizeof(Description)) + { + memmove(Description,name,length); + Description[length] = 0; + status = true; + } + + return status; +} + +const char *Device_Location(void) +{ + return Location; +} + +bool Device_Set_Location(const char *name, size_t length) +{ + bool status = false; /*return value*/ + + if (length < sizeof(Location)) + { + memmove(Location,name,length); + Location[length] = 0; + status = true; + } + + return status; } uint8_t Device_Protocol_Version(void) @@ -301,6 +372,7 @@ int Device_Encode_Property_APDU( int apdu_len = 0; // return value int len = 0; // apdu len intermediate value BACNET_BIT_STRING bit_string; + BACNET_CHARACTER_STRING char_string; unsigned i = 0; int object_type = 0; uint32_t instance = 0; @@ -313,32 +385,44 @@ int Device_Encode_Property_APDU( Object_Instance_Number); break; case PROP_OBJECT_NAME: - apdu_len = encode_tagged_character_string(&apdu[0], Object_Name); + characterstring_init(&char_string,CHARACTER_ANSI, + Object_Name,strlen(Object_Name)); + apdu_len = encode_tagged_character_string(&apdu[0], &char_string); break; case PROP_OBJECT_TYPE: apdu_len = encode_tagged_enumerated(&apdu[0], OBJECT_DEVICE); break; case PROP_DESCRIPTION: - apdu_len = encode_tagged_character_string(&apdu[0], Description); + characterstring_init(&char_string,CHARACTER_ANSI, + Description,strlen(Description)); + apdu_len = encode_tagged_character_string(&apdu[0], &char_string); break; case PROP_SYSTEM_STATUS: apdu_len = encode_tagged_enumerated(&apdu[0], System_Status); break; case PROP_VENDOR_NAME: - apdu_len = encode_tagged_character_string(&apdu[0], Vendor_Name); + characterstring_init(&char_string,CHARACTER_ANSI, + Vendor_Name,strlen(Vendor_Name)); + apdu_len = encode_tagged_character_string(&apdu[0], &char_string); break; case PROP_VENDOR_IDENTIFIER: apdu_len = encode_tagged_unsigned(&apdu[0], Vendor_Identifier); break; case PROP_MODEL_NAME: - apdu_len = encode_tagged_character_string(&apdu[0], Model_Name); + characterstring_init(&char_string,CHARACTER_ANSI, + Model_Name,strlen(Model_Name)); + apdu_len = encode_tagged_character_string(&apdu[0], &char_string); break; case PROP_FIRMWARE_REVISION: - apdu_len = encode_tagged_character_string(&apdu[0], Firmware_Revision); + characterstring_init(&char_string,CHARACTER_ANSI, + Firmware_Revision,strlen(Firmware_Revision)); + apdu_len = encode_tagged_character_string(&apdu[0], &char_string); break; case PROP_APPLICATION_SOFTWARE_VERSION: - apdu_len = encode_tagged_character_string(&apdu[0], - Application_Software_Version); + characterstring_init(&char_string,CHARACTER_ANSI, + Application_Software_Version, + strlen(Application_Software_Version)); + apdu_len = encode_tagged_character_string(&apdu[0], &char_string); break; // if you support time //case PROP_LOCAL_TIME: @@ -376,7 +460,7 @@ int Device_Encode_Property_APDU( // initialize all the services to not-supported bitstring_set_bit(&bit_string, (uint8_t)i, false); } - // initialize those we support + /* FIXME: set the services that YOUR device executes */ bitstring_set_bit(&bit_string, SERVICE_SUPPORTED_WHO_IS, true); bitstring_set_bit(&bit_string, SERVICE_SUPPORTED_I_AM, true); bitstring_set_bit(&bit_string, SERVICE_SUPPORTED_READ_PROPERTY, true); @@ -389,8 +473,10 @@ int Device_Encode_Property_APDU( // initialize all the object types to not-supported bitstring_set_bit(&bit_string, (uint8_t)i, false); } + /* FIXME: indicate the objects that YOU support */ bitstring_set_bit(&bit_string, OBJECT_DEVICE, true); bitstring_set_bit(&bit_string, OBJECT_ANALOG_INPUT, true); + bitstring_set_bit(&bit_string, OBJECT_ANALOG_OUTPUT, true); apdu_len = encode_tagged_bitstring(&apdu[0], &bit_string); break; case PROP_OBJECT_LIST: @@ -490,10 +576,9 @@ bool Device_Write_Property( if (wp_data->value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) { if ((wp_data->value.type.Object_Id.type == OBJECT_DEVICE) && - (wp_data->value.type.Object_Id.instance <= BACNET_MAX_INSTANCE)) + (Device_Set_Object_Instance_Number( + wp_data->value.type.Object_Id.instance))) { - Device_Set_Object_Instance_Number( - wp_data->value.type.Object_Id.instance); I_Am_Request = true; status = true; } @@ -561,18 +646,18 @@ bool Device_Write_Property( *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; - + case PROP_OBJECT_NAME: if (wp_data->value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) { - BACNET_CHARACTER_STRING Character_String = wp_data->value.type.Character_String; - - char decoded_string[MAX_APDU] = { "" }; - int decoded = 0; - //decoded = decode_character_string(&data->application_data[tag_len], len_value_type, &decoded_string[0], sizeof(decoded_string)); - - //Device_Set_Vendor_Name(const char *name); - status = true; + status = Device_Set_Vendor_Name( + characterstring_value(&wp_data->value.type.Character_String), + characterstring_length(&wp_data->value.type.Character_String)); + if (!status) + { + *error_class = ERROR_CLASS_PROPERTY; + *error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY; + } } else { @@ -580,7 +665,7 @@ bool Device_Write_Property( *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; - + default: *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_WRITE_ACCESS_DENIED; @@ -597,20 +682,34 @@ bool Device_Write_Property( void testDevice(Test * pTest) { - Device_Set_Object_Instance_Number(111); - ct_test(pTest, Device_Object_Instance_Number() == 111); - + bool status = false; + const char *name = "Patricia"; + + status = Device_Set_Object_Instance_Number(0); + ct_test(pTest, Device_Object_Instance_Number() == 0); + ct_test(pTest, status == true); + status = Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE); + ct_test(pTest, Device_Object_Instance_Number() == BACNET_MAX_INSTANCE); + ct_test(pTest, status == true); + status = Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE/2); + ct_test(pTest, Device_Object_Instance_Number() == (BACNET_MAX_INSTANCE/2)); + ct_test(pTest, status == true); + status = Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE+1); + ct_test(pTest, Device_Object_Instance_Number() != (BACNET_MAX_INSTANCE+1)); + ct_test(pTest, status == false); + + Device_Set_System_Status(STATUS_NON_OPERATIONAL); ct_test(pTest, Device_System_Status() == STATUS_NON_OPERATIONAL); - Device_Set_Vendor_Name("MyName"); - ct_test(pTest, strcmp(Device_Vendor_Name(),"MyName") == 0); + Device_Set_Vendor_Name(name,strlen(name)); + ct_test(pTest, strcmp(Device_Vendor_Name(),name) == 0); Device_Set_Vendor_Identifier(42); ct_test(pTest, Device_Vendor_Identifier() == 42); - Device_Set_Model_Name("MyModel"); - ct_test(pTest, strcmp(Device_Model_Name(),"MyModel") == 0); + Device_Set_Model_Name(name,strlen(name)); + ct_test(pTest, strcmp(Device_Model_Name(),name) == 0); return; } diff --git a/bacnet-stack/device.h b/bacnet-stack/device.h index ce1c3a1f..66919708 100644 --- a/bacnet-stack/device.h +++ b/bacnet-stack/device.h @@ -45,7 +45,7 @@ extern "C" { #endif /* __cplusplus */ uint32_t Device_Object_Instance_Number(void); -void Device_Set_Object_Instance_Number(uint32_t object_id); +bool Device_Set_Object_Instance_Number(uint32_t object_id); bool Device_Valid_Object_Instance_Number(uint32_t object_id); unsigned Device_Object_List_Count(void); bool Device_Object_List_Identifier(unsigned array_index, @@ -56,22 +56,25 @@ BACNET_DEVICE_STATUS Device_System_Status(void); void Device_Set_System_Status(BACNET_DEVICE_STATUS status); const char *Device_Vendor_Name(void); -void Device_Set_Vendor_Name(const char *name); +bool Device_Set_Vendor_Name(const char *name, size_t length); uint16_t Device_Vendor_Identifier(void); void Device_Set_Vendor_Identifier(uint16_t vendor_id); const char *Device_Model_Name(void); -void Device_Set_Model_Name(const char *name); +bool Device_Set_Model_Name(const char *name, size_t length); const char *Device_Firmware_Revision(void); -void Device_Set_Firmware_Revision(const char *name); +bool Device_Set_Firmware_Revision(const char *name, size_t length); const char *Device_Application_Software_Version(void); -void Device_Set_Application_Software_Version(const char *name); +bool Device_Set_Application_Software_Version(const char *name, size_t length); const char *Device_Description(void); -void Device_Set_Description(const char *name); +bool Device_Set_Description(const char *name, size_t length); + +const char *Device_Location(void); +bool Device_Set_Location(const char *name, size_t length); // some stack-centric constant values - no set methods uint8_t Device_Protocol_Version(void); diff --git a/bacnet-stack/device.mak b/bacnet-stack/device.mak index 05b426d5..098c6638 100644 --- a/bacnet-stack/device.mak +++ b/bacnet-stack/device.mak @@ -8,6 +8,7 @@ CFLAGS = -Wall -I. -Itest -DTEST -DTEST_DEVICE -g SRCS = bacdcode.c \ bigend.c \ + bacstr.c \ device.c \ test/ctest.c diff --git a/bacnet-stack/handlers.c b/bacnet-stack/handlers.c index 62555f14..564a52dc 100644 --- a/bacnet-stack/handlers.c +++ b/bacnet-stack/handlers.c @@ -713,7 +713,6 @@ void AtomicReadFileHandler( int bytes_sent = 0; BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT; BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT; - char buffer[MAX_APDU - 16] = ""; // for reply data, less apdu overhead fprintf(stderr,"Received Atomic-Read-File Request!\n"); len = arf_decode_service_request( @@ -754,9 +753,8 @@ void AtomicReadFileHandler( { if (data.access == FILE_STREAM_ACCESS) { - data.fileData = (uint8_t *)&buffer[0]; - data.fileDataLength = sizeof(buffer); - if (data.type.stream.requestedOctetCount < data.fileDataLength) + if (data.type.stream.requestedOctetCount < + octetstring_capacity(&data.fileData)) { if (bacfile_read_data(&data)) { @@ -855,12 +853,13 @@ void AtomicReadFileAckHandler( (void)fseek(pFile, data.type.stream.fileStartPosition, SEEK_SET); - if (fwrite(data.fileData,data.fileDataLength,1,pFile) != 1) + if (fwrite(octetstring_value(&data.fileData), + octetstring_length(&data.fileData),1,pFile) != 1) fprintf(stderr,"Failed to write to %s (%u)!\n", pFilename, instance); fclose(pFile); } - } + } } else if (data.access == FILE_RECORD_ACCESS) { diff --git a/bacnet-stack/iam.mak b/bacnet-stack/iam.mak index b560b00c..97dc37dd 100755 --- a/bacnet-stack/iam.mak +++ b/bacnet-stack/iam.mak @@ -7,6 +7,7 @@ BASEDIR = . CFLAGS = -Wall -I. -Itest -DTEST -DTEST_IAM -g SRCS = bacdcode.c \ + bacstr.c \ bigend.c \ npdu.c \ apdu.c \ diff --git a/bacnet-stack/npdu.mak b/bacnet-stack/npdu.mak index b8f2b4ab..38c38a49 100644 --- a/bacnet-stack/npdu.mak +++ b/bacnet-stack/npdu.mak @@ -7,6 +7,7 @@ BASEDIR = . CFLAGS = -Wall -I. -Itest -DTEST -DTEST_NPDU -g SRCS = bacdcode.c \ + bacstr.c \ bigend.c \ npdu.c \ apdu.c \ diff --git a/bacnet-stack/ports/linux/main.c b/bacnet-stack/ports/linux/main.c index c3e2f054..97f995a4 100644 --- a/bacnet-stack/ports/linux/main.c +++ b/bacnet-stack/ports/linux/main.c @@ -47,20 +47,6 @@ // buffers used for receiving static uint8_t Rx_Buf[MAX_MPDU] = {0}; -static void Init_Device_Parameters(void) -{ - // configure my initial values - Device_Set_Object_Instance_Number(111); - Device_Set_Vendor_Name("Lithonia Lighting"); - Device_Set_Vendor_Identifier(42); - Device_Set_Model_Name("Simple BACnet Server"); - Device_Set_Firmware_Revision("1.00"); - Device_Set_Application_Software_Version("none"); - Device_Set_Description("Example of a simple BACnet server"); - - return; -} - static void LocalIAmHandler( uint8_t *service_request, uint16_t service_len, @@ -275,8 +261,8 @@ int main(int argc, char *argv[]) signal(SIGINT, sig_handler); signal(SIGHUP, sig_handler); signal(SIGTERM, sig_handler); - // setup this BACnet Server - Init_Device_Parameters(); + // setup this BACnet Server device + Device_Set_Object_Instance_Number(111); Init_Service_Handlers(); #ifdef BACDL_ETHERNET // init the physical layer diff --git a/bacnet-stack/ports/rtos32/main.c b/bacnet-stack/ports/rtos32/main.c index bb7b4fde..34154c67 100644 --- a/bacnet-stack/ports/rtos32/main.c +++ b/bacnet-stack/ports/rtos32/main.c @@ -67,20 +67,6 @@ volatile struct mstp_port_struct_t MSTP_Port; // port data static uint8_t MSTP_MAC_Address = 0x05; // local MAC address #endif -static void Init_Device_Parameters(void) -{ - // configure my initial values - Device_Set_Object_Instance_Number(126); - Device_Set_Vendor_Name("Lithonia Lighting"); - Device_Set_Vendor_Identifier(42); - Device_Set_Model_Name("Simple BACnet Server"); - Device_Set_Firmware_Revision("1.00"); - Device_Set_Application_Software_Version("none"); - Device_Set_Description("Example of a simple BACnet server"); - - return; -} - static void Init_Service_Handlers(void) { // we need to handle who-is to support dynamic device binding @@ -264,7 +250,7 @@ int main(int argc, char *argv[]) (void)argc; (void)argv; - Init_Device_Parameters(); + Device_Set_Object_Instance_Number(126); Init_Service_Handlers(); // init the physical layer #ifdef BACDL_BIP diff --git a/bacnet-stack/reject.mak b/bacnet-stack/reject.mak index b9b81247..a59f6daf 100644 --- a/bacnet-stack/reject.mak +++ b/bacnet-stack/reject.mak @@ -7,6 +7,7 @@ BASEDIR = . CFLAGS = -Wall -I. -Itest -DTEST -DTEST_REJECT -g SRCS = bacdcode.c \ + bacstr.c \ bigend.c \ reject.c \ test/ctest.c diff --git a/bacnet-stack/rp.mak b/bacnet-stack/rp.mak index 9d2dcf8a..5a336e46 100644 --- a/bacnet-stack/rp.mak +++ b/bacnet-stack/rp.mak @@ -7,6 +7,7 @@ BASEDIR = . CFLAGS = -Wall -I. -Itest -DTEST -DTEST_READ_PROPERTY -g SRCS = bacdcode.c \ + bacstr.c \ bigend.c \ rp.c \ test/ctest.c diff --git a/bacnet-stack/rpm.mak b/bacnet-stack/rpm.mak index 1fd30546..b4d52166 100644 --- a/bacnet-stack/rpm.mak +++ b/bacnet-stack/rpm.mak @@ -9,6 +9,7 @@ CFLAGS = -Wall -I. -Itest -DTEST -DTEST_READ_PROPERTY_MULTIPLE -g SRCS = bacdcode.c \ bacerror.c \ bacapp.c \ + bacstr.c \ bigend.c \ rpm.c \ test/ctest.c diff --git a/bacnet-stack/test.sh b/bacnet-stack/test.sh index f6277ff0..d9baeb00 100755 --- a/bacnet-stack/test.sh +++ b/bacnet-stack/test.sh @@ -4,70 +4,15 @@ rm test.log touch test.log -make -f crc.mak clean -make -f crc.mak -./crc >> test.log -make -f crc.mak clean - -make -f ringbuf.mak clean -make -f ringbuf.mak -./ringbuf >> test.log -make -f ringbuf.mak clean - -make -f mstp.mak clean -make -f mstp.mak -./mstp >> test.log -make -f mstp.mak clean - -make -f iam.mak clean -make -f iam.mak -./iam >> test.log -make -f iam.mak clean - -make -f whois.mak clean -make -f whois.mak -./whois >> test.log -make -f whois.mak clean - -make -f bacdcode.mak clean -make -f bacdcode.mak -./bacdcode >> test.log -make -f bacdcode.mak clean - -make -f iam.mak clean -make -f iam.mak -./iam >> test.log -make -f iam.mak clean - -make -f whois.mak clean -make -f whois.mak -./whois >> test.log -make -f whois.mak clean - -make -f npdu.mak clean -make -f npdu.mak -./npdu >> test.log -make -f npdu.mak clean - -make -f reject.mak clean -make -f reject.mak -./reject >> test.log -make -f reject.mak clean - make -f abort.mak clean make -f abort.mak ./abort >> test.log make -f abort.mak clean -make -f bacerror.mak clean -make -f bacerror.mak -./bacerror >> test.log -make -f bacerror.mak clean - -make -f device.mak clean -make -f device.mak -./device >> test.log -make -f device.mak clean +make -f address.mak clean +make -f address.mak +./address >> test.log +make -f address.mak clean make -f ai.mak clean make -f ai.mak @@ -79,17 +24,102 @@ make -f ao.mak ./analog_output >> test.log make -f ao.mak clean -make -f wp.mak clean -make -f wp.mak -./writeproperty >> test.log -make -f wp.mak clean +make -f arf.mak clean +make -f arf.mak +./atomicreadfile >> test.log +make -f arf.mak clean -make -f address.mak clean -make -f address.mak -./address >> test.log -make -f address.mak clean +make -f awf.mak clean +make -f awf.mak +./atomicwritefile >> test.log +make -f awf.mak clean + +make -f bacapp.mak clean +make -f bacapp.mak +./bacapp >> test.log +make -f bacapp.mak clean + +make -f bacdcode.mak clean +make -f bacdcode.mak +./bacdcode >> test.log +make -f bacdcode.mak clean + +make -f bacerror.mak clean +make -f bacerror.mak +./bacerror >> test.log +make -f bacerror.mak clean + +make -f bacstr.mak clean +make -f bacstr.mak +./bacstr >> test.log +make -f bacstr.mak clean + +make -f crc.mak clean +make -f crc.mak +./crc >> test.log +make -f crc.mak clean + +make -f device.mak clean +make -f device.mak +./device >> test.log +make -f device.mak clean + +make -f iam.mak clean +make -f iam.mak +./iam >> test.log +make -f iam.mak clean make -f indtext.mak clean make -f indtext.mak ./indtext >> test.log make -f indtext.mak clean + +make -f mstp.mak clean +make -f mstp.mak +./mstp >> test.log +make -f mstp.mak clean + +make -f npdu.mak clean +make -f npdu.mak +./npdu >> test.log +make -f npdu.mak clean + +make -f reject.mak clean +make -f reject.mak +./reject >> test.log +make -f reject.mak clean + +make -f ringbuf.mak clean +make -f ringbuf.mak +./ringbuf >> test.log +make -f ringbuf.mak clean + +make -f rp.mak clean +make -f rp.mak +./readproperty >> test.log +make -f rp.mak clean + +make -f rpm.mak clean +make -f rpm.mak +./rpm >> test.log +make -f rpm.mak clean + +make -f sbuf.mak clean +make -f sbuf.mak +./sbuf >> test.log +make -f sbuf.mak clean + +make -f tsm.mak clean +make -f tsm.mak +./tsm >> test.log +make -f tsm.mak clean + +make -f whois.mak clean +make -f whois.mak +./whois >> test.log +make -f whois.mak clean + +make -f wp.mak clean +make -f wp.mak +./writeproperty >> test.log +make -f wp.mak clean diff --git a/bacnet-stack/tsm.c b/bacnet-stack/tsm.c index 1b7aedd6..30692167 100644 --- a/bacnet-stack/tsm.c +++ b/bacnet-stack/tsm.c @@ -250,23 +250,12 @@ void tsm_free_invoke_id(uint8_t invokeID) #include #include "ctest.h" +// flag to send an I-Am +bool I_Am_Request = true; + void testTSM(Test * pTest) { - //unsigned i; - uint8_t invokeID = 0; - BACNET_ADDRESS dest = {0}; - uint8_t pdu[MAX_PDU] = {0}; - uint16_t pdu_len = 0; - - memset(pdu,0xa5,sizeof(pdu)); - pdu_len = sizeof(pdu); - - invokeID = tsm_request_confirmed_unsegmented_transaction( - &dest, - &pdu[0], - pdu_len); - ct_test(pTest, invokeID != 0); - + /* FIXME: add some unit testing...*/ return; } diff --git a/bacnet-stack/tsm.mak b/bacnet-stack/tsm.mak index c3d60d8b..cf5111ca 100644 --- a/bacnet-stack/tsm.mak +++ b/bacnet-stack/tsm.mak @@ -6,9 +6,17 @@ BASEDIR = . #CFLAGS = -Wall -I. -g CFLAGS = -Wall -I. -Itest -DTEST -DTEST_TSM -g -SRCS = bacdcode.c \ +SRCS = address.c \ + bacdcode.c \ + bacstr.c \ bigend.c \ device.c \ + ai.c \ + ao.c \ + iam.c \ + npdu.c \ + apdu.c \ + datalink.c \ tsm.c \ test/ctest.c diff --git a/bacnet-stack/whois.mak b/bacnet-stack/whois.mak index 856b30de..7a962b4c 100644 --- a/bacnet-stack/whois.mak +++ b/bacnet-stack/whois.mak @@ -7,6 +7,7 @@ BASEDIR = . CFLAGS = -Wall -I. -Itest -DTEST -DTEST_WHOIS -g SRCS = bacdcode.c \ + bacstr.c \ bigend.c \ whois.c \ test/ctest.c diff --git a/bacnet-stack/wp.mak b/bacnet-stack/wp.mak index a915d1b1..7c8bf9d0 100644 --- a/bacnet-stack/wp.mak +++ b/bacnet-stack/wp.mak @@ -7,6 +7,7 @@ BASEDIR = . CFLAGS = -Wall -I. -Itest -DTEST -DTEST_WRITE_PROPERTY -DBACDL_BIP=1 -g SRCS = bacdcode.c \ + bacstr.c \ bigend.c \ bacapp.c \ wp.c \