added ReadPropertyMultiple client demo application, bacrpm.
This commit is contained in:
@@ -1,10 +1,11 @@
|
|||||||
all: library readprop writeprop readfile writefile reinit server dcc \
|
all: library readprop writeprop readfile writefile reinit server dcc \
|
||||||
whohas whois ucov timesync epics mstpcap \
|
whohas whois ucov timesync epics readpropm mstpcap \
|
||||||
whoisrouter iamrouter initrouter
|
whoisrouter iamrouter initrouter
|
||||||
@echo "utilities are in the bin directory"
|
@echo "utilities are in the bin directory"
|
||||||
|
|
||||||
clean: lib/Makefile\
|
clean: lib/Makefile\
|
||||||
demo/readprop/Makefile \
|
demo/readprop/Makefile \
|
||||||
|
demo/readpropm/Makefile \
|
||||||
demo/writeprop/Makefile \
|
demo/writeprop/Makefile \
|
||||||
demo/readfile/Makefile \
|
demo/readfile/Makefile \
|
||||||
demo/writefile/Makefile \
|
demo/writefile/Makefile \
|
||||||
@@ -22,6 +23,7 @@ clean: lib/Makefile\
|
|||||||
demo/mstpcap/Makefile
|
demo/mstpcap/Makefile
|
||||||
( cd lib ; make clean )
|
( cd lib ; make clean )
|
||||||
( cd demo/readprop ; make clean )
|
( cd demo/readprop ; make clean )
|
||||||
|
( cd demo/readpropm ; make clean )
|
||||||
( cd demo/writeprop ; make clean )
|
( cd demo/writeprop ; make clean )
|
||||||
( cd demo/readfile ; make clean )
|
( cd demo/readfile ; make clean )
|
||||||
( cd demo/writefile ; make clean )
|
( cd demo/writefile ; make clean )
|
||||||
@@ -44,6 +46,9 @@ library: lib/Makefile
|
|||||||
readprop: demo/readprop/Makefile
|
readprop: demo/readprop/Makefile
|
||||||
( cd demo/readprop ; make ; cp bacrp ../../bin )
|
( cd demo/readprop ; make ; cp bacrp ../../bin )
|
||||||
|
|
||||||
|
readpropm: demo/readpropm/Makefile
|
||||||
|
( cd demo/readpropm ; make ; cp bacrpm ../../bin )
|
||||||
|
|
||||||
writeprop: demo/writeprop/Makefile
|
writeprop: demo/writeprop/Makefile
|
||||||
( cd demo/writeprop ; make ; cp bacwp ../../bin )
|
( cd demo/writeprop ; make ; cp bacwp ../../bin )
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "txbuf.h"
|
#include "txbuf.h"
|
||||||
|
#include "memcopy.h"
|
||||||
#include "bacdef.h"
|
#include "bacdef.h"
|
||||||
#include "bacdcode.h"
|
#include "bacdcode.h"
|
||||||
#include "apdu.h"
|
#include "apdu.h"
|
||||||
@@ -210,27 +211,6 @@ static unsigned RPM_Object_Property_Count(
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy len bytes from src to offset of dest if there is enough space. */
|
|
||||||
int apdu_copy(
|
|
||||||
uint8_t * dest,
|
|
||||||
uint8_t * src,
|
|
||||||
int offset,
|
|
||||||
int len,
|
|
||||||
int max)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int copy_len = 0;
|
|
||||||
|
|
||||||
if (len <= (max - offset)) {
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
dest[offset + i] = src[i];
|
|
||||||
copy_len++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return copy_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Encode the RPM property returning the length of the encoding,
|
/* Encode the RPM property returning the length of the encoding,
|
||||||
or 0 if there is no room to fit the encoding. */
|
or 0 if there is no room to fit the encoding. */
|
||||||
int RPM_Encode_Property(
|
int RPM_Encode_Property(
|
||||||
@@ -250,9 +230,10 @@ int RPM_Encode_Property(
|
|||||||
len =
|
len =
|
||||||
rpm_ack_encode_apdu_object_property(&Temp_Buf[0], object_property,
|
rpm_ack_encode_apdu_object_property(&Temp_Buf[0], object_property,
|
||||||
array_index);
|
array_index);
|
||||||
len = apdu_copy(&apdu[0], &Temp_Buf[0], offset, len, max_apdu);
|
len = memcopy(&apdu[0], &Temp_Buf[0], offset, len, max_apdu);
|
||||||
if (!len)
|
if (!len) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
len =
|
len =
|
||||||
Encode_Property_APDU(&Temp_Buf[0], object_type, object_instance,
|
Encode_Property_APDU(&Temp_Buf[0], object_type, object_instance,
|
||||||
@@ -263,10 +244,11 @@ int RPM_Encode_Property(
|
|||||||
rpm_ack_encode_apdu_object_property_error(&Temp_Buf[0],
|
rpm_ack_encode_apdu_object_property_error(&Temp_Buf[0],
|
||||||
error_class, error_code);
|
error_class, error_code);
|
||||||
len =
|
len =
|
||||||
apdu_copy(&apdu[0], &Temp_Buf[0], offset + apdu_len, len,
|
memcopy(&apdu[0], &Temp_Buf[0], offset + apdu_len, len,
|
||||||
max_apdu);
|
max_apdu);
|
||||||
if (!len)
|
if (!len) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
} else if ((offset + apdu_len + 1 + len + 1) < max_apdu) {
|
} else if ((offset + apdu_len + 1 + len + 1) < max_apdu) {
|
||||||
/* enough room to fit the property value and tags */
|
/* enough room to fit the property value and tags */
|
||||||
len =
|
len =
|
||||||
@@ -339,7 +321,7 @@ void handler_read_property_multiple(
|
|||||||
decode_len++;
|
decode_len++;
|
||||||
len = rpm_ack_encode_apdu_object_end(&Temp_Buf[0]);
|
len = rpm_ack_encode_apdu_object_end(&Temp_Buf[0]);
|
||||||
copy_len =
|
copy_len =
|
||||||
apdu_copy(&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
|
memcopy(&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
|
||||||
apdu_len, len, sizeof(Handler_Transmit_Buffer));
|
apdu_len, len, sizeof(Handler_Transmit_Buffer));
|
||||||
if (!copy_len) {
|
if (!copy_len) {
|
||||||
apdu_len =
|
apdu_len =
|
||||||
@@ -362,7 +344,7 @@ void handler_read_property_multiple(
|
|||||||
rpm_ack_encode_apdu_object_begin(&Temp_Buf[0], object_type,
|
rpm_ack_encode_apdu_object_begin(&Temp_Buf[0], object_type,
|
||||||
object_instance);
|
object_instance);
|
||||||
copy_len =
|
copy_len =
|
||||||
apdu_copy(&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
|
memcopy(&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
|
||||||
apdu_len, len, sizeof(Handler_Transmit_Buffer));
|
apdu_len, len, sizeof(Handler_Transmit_Buffer));
|
||||||
if (!copy_len) {
|
if (!copy_len) {
|
||||||
apdu_len =
|
apdu_len =
|
||||||
@@ -389,7 +371,7 @@ void handler_read_property_multiple(
|
|||||||
decode_len++;
|
decode_len++;
|
||||||
len = rpm_ack_encode_apdu_object_end(&Temp_Buf[0]);
|
len = rpm_ack_encode_apdu_object_end(&Temp_Buf[0]);
|
||||||
copy_len =
|
copy_len =
|
||||||
apdu_copy(&Handler_Transmit_Buffer[npdu_len],
|
memcopy(&Handler_Transmit_Buffer[npdu_len],
|
||||||
&Temp_Buf[0], apdu_len, len,
|
&Temp_Buf[0], apdu_len, len,
|
||||||
sizeof(Handler_Transmit_Buffer));
|
sizeof(Handler_Transmit_Buffer));
|
||||||
if (!copy_len) {
|
if (!copy_len) {
|
||||||
|
|||||||
@@ -0,0 +1,246 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Steve Karg <skarg@users.sourceforge.net>
|
||||||
|
*
|
||||||
|
* 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 <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "config.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "txbuf.h"
|
||||||
|
#include "bacdef.h"
|
||||||
|
#include "bacdcode.h"
|
||||||
|
#include "address.h"
|
||||||
|
#include "tsm.h"
|
||||||
|
#include "npdu.h"
|
||||||
|
#include "apdu.h"
|
||||||
|
#include "device.h"
|
||||||
|
#include "datalink.h"
|
||||||
|
#include "bactext.h"
|
||||||
|
#include "rpm.h"
|
||||||
|
/* some demo stuff needed */
|
||||||
|
#include "handlers.h"
|
||||||
|
#include "txbuf.h"
|
||||||
|
|
||||||
|
/* returns the number of bytes decoded, or -1 on error */
|
||||||
|
/* note: initial the linked list of read_access_data */
|
||||||
|
static int rpm_ack_decode_service_request(
|
||||||
|
uint8_t * apdu,
|
||||||
|
int apdu_len, /* total length of the apdu */
|
||||||
|
BACNET_READ_ACCESS_DATA * read_access_data)
|
||||||
|
{
|
||||||
|
int decoded_len = 0; /* return value */
|
||||||
|
int len = 0; /* number of bytes returned from decoding */
|
||||||
|
BACNET_READ_ACCESS_DATA *rpm_object;
|
||||||
|
BACNET_READ_ACCESS_DATA *old_rpm_object;
|
||||||
|
BACNET_PROPERTY_REFERENCE *rpm_property;
|
||||||
|
BACNET_PROPERTY_REFERENCE *old_rpm_property;
|
||||||
|
BACNET_APPLICATION_DATA_VALUE *value;
|
||||||
|
BACNET_APPLICATION_DATA_VALUE *old_value;
|
||||||
|
|
||||||
|
rpm_object = read_access_data;
|
||||||
|
old_rpm_object = rpm_object;
|
||||||
|
while (rpm_object && apdu_len) {
|
||||||
|
len = rpm_ack_decode_object_id(
|
||||||
|
apdu, apdu_len,
|
||||||
|
&rpm_object->object_type,
|
||||||
|
&rpm_object->object_instance);
|
||||||
|
if (len <= 0) {
|
||||||
|
old_rpm_object->next = NULL;
|
||||||
|
free(rpm_object);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
decoded_len += len;
|
||||||
|
apdu_len -= len;
|
||||||
|
apdu += len;
|
||||||
|
rpm_property = calloc(1, sizeof(BACNET_PROPERTY_REFERENCE));
|
||||||
|
rpm_object->listOfProperties = rpm_property;
|
||||||
|
old_rpm_property = rpm_property;
|
||||||
|
while (rpm_property && apdu_len) {
|
||||||
|
len = rpm_ack_decode_object_property(
|
||||||
|
apdu,
|
||||||
|
apdu_len,
|
||||||
|
&rpm_property->propertyIdentifier,
|
||||||
|
&rpm_property->propertyArrayIndex);
|
||||||
|
if (len <= 0) {
|
||||||
|
old_rpm_property->next = NULL;
|
||||||
|
free(rpm_property);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
decoded_len += len;
|
||||||
|
apdu_len -= len;
|
||||||
|
apdu += len;
|
||||||
|
if (apdu_len && decode_is_opening_tag_number(apdu, 4)) {
|
||||||
|
decoded_len++;
|
||||||
|
apdu_len--;
|
||||||
|
apdu++;
|
||||||
|
/* note: if this is an array, there will be
|
||||||
|
more than one element to decode */
|
||||||
|
value = calloc(1, sizeof(BACNET_APPLICATION_DATA_VALUE));
|
||||||
|
rpm_property->value = value;
|
||||||
|
old_value = value;
|
||||||
|
while (value && (apdu_len > 0)) {
|
||||||
|
len = bacapp_decode_application_data(
|
||||||
|
apdu,
|
||||||
|
apdu_len,
|
||||||
|
value);
|
||||||
|
decoded_len += len;
|
||||||
|
apdu_len -= len;
|
||||||
|
apdu += len;
|
||||||
|
if (apdu_len && decode_is_closing_tag_number(apdu, 4)) {
|
||||||
|
decoded_len++;
|
||||||
|
apdu_len--;
|
||||||
|
apdu++;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
old_value = value;
|
||||||
|
value = calloc(1, sizeof(BACNET_APPLICATION_DATA_VALUE));
|
||||||
|
old_value->next = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
old_rpm_property = rpm_property;
|
||||||
|
rpm_property = calloc(1, sizeof(BACNET_PROPERTY_REFERENCE));
|
||||||
|
old_rpm_property->next = rpm_property;
|
||||||
|
}
|
||||||
|
len = rpm_decode_object_end(apdu, apdu_len);
|
||||||
|
if (len) {
|
||||||
|
decoded_len += len;
|
||||||
|
apdu_len -= len;
|
||||||
|
apdu += len;
|
||||||
|
}
|
||||||
|
if (apdu_len) {
|
||||||
|
old_rpm_object = rpm_object;
|
||||||
|
rpm_object = calloc(1, sizeof(BACNET_READ_ACCESS_DATA));
|
||||||
|
old_rpm_object->next = rpm_object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return decoded_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* for debugging... */
|
||||||
|
static void PrintReadPropertyMultipleData(
|
||||||
|
BACNET_READ_ACCESS_DATA * rpm_data)
|
||||||
|
{
|
||||||
|
BACNET_PROPERTY_REFERENCE *listOfProperties;
|
||||||
|
BACNET_APPLICATION_DATA_VALUE *value;
|
||||||
|
bool array_value = false;
|
||||||
|
|
||||||
|
if (rpm_data) {
|
||||||
|
#if PRINT_ENABLED
|
||||||
|
fprintf(stdout, "%s #%u\r\n",
|
||||||
|
bactext_object_type_name(rpm_data->object_type),
|
||||||
|
rpm_data->object_instance);
|
||||||
|
fprintf(stdout, "{\r\n");
|
||||||
|
#endif
|
||||||
|
listOfProperties = rpm_data->listOfProperties;
|
||||||
|
while (listOfProperties) {
|
||||||
|
#if PRINT_ENABLED
|
||||||
|
fprintf(stdout, " %s: ",
|
||||||
|
bactext_property_name(listOfProperties->propertyIdentifier));
|
||||||
|
#endif
|
||||||
|
if (listOfProperties->propertyArrayIndex != BACNET_ARRAY_ALL) {
|
||||||
|
#if PRINT_ENABLED
|
||||||
|
fprintf(stdout, "[%d]", listOfProperties->propertyArrayIndex);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
value = listOfProperties->value;
|
||||||
|
#if PRINT_ENABLED
|
||||||
|
if (value->next) {
|
||||||
|
fprintf(stdout, "{");
|
||||||
|
array_value = true;
|
||||||
|
} else {
|
||||||
|
array_value = false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
while (value) {
|
||||||
|
bacapp_print_value(stdout,
|
||||||
|
value,
|
||||||
|
listOfProperties->propertyIdentifier);
|
||||||
|
#if PRINT_ENABLED
|
||||||
|
if (value->next) {
|
||||||
|
fprintf(stdout, ",\r\n ");
|
||||||
|
} else {
|
||||||
|
if (array_value) {
|
||||||
|
fprintf(stdout, "}\r\n");
|
||||||
|
} else {
|
||||||
|
fprintf(stdout, "\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
value = value->next;
|
||||||
|
}
|
||||||
|
listOfProperties = listOfProperties->next;
|
||||||
|
}
|
||||||
|
#if PRINT_ENABLED
|
||||||
|
fprintf(stdout, "}\r\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handler_read_property_multiple_ack(
|
||||||
|
uint8_t * service_request,
|
||||||
|
uint16_t service_len,
|
||||||
|
BACNET_ADDRESS * src,
|
||||||
|
BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
BACNET_READ_ACCESS_DATA * rpm_data;
|
||||||
|
BACNET_READ_ACCESS_DATA * old_rpm_data;
|
||||||
|
BACNET_PROPERTY_REFERENCE *rpm_property;
|
||||||
|
BACNET_PROPERTY_REFERENCE *old_rpm_property;
|
||||||
|
BACNET_APPLICATION_DATA_VALUE *value;
|
||||||
|
BACNET_APPLICATION_DATA_VALUE *old_value;
|
||||||
|
|
||||||
|
(void) src;
|
||||||
|
(void) service_data; /* we could use these... */
|
||||||
|
|
||||||
|
rpm_data = calloc(1, sizeof(BACNET_READ_ACCESS_DATA));
|
||||||
|
if (rpm_data) {
|
||||||
|
len = rpm_ack_decode_service_request(service_request, service_len,
|
||||||
|
rpm_data);
|
||||||
|
}
|
||||||
|
#if 1
|
||||||
|
fprintf(stderr, "Received Read-Property-Multiple Ack!\n");
|
||||||
|
#endif
|
||||||
|
if (len > 0) {
|
||||||
|
while (rpm_data) {
|
||||||
|
PrintReadPropertyMultipleData(rpm_data);
|
||||||
|
rpm_property = rpm_data->listOfProperties;
|
||||||
|
while (rpm_property) {
|
||||||
|
value = rpm_property->value;
|
||||||
|
while (value) {
|
||||||
|
old_value = value;
|
||||||
|
value = value->next;
|
||||||
|
free(old_value);
|
||||||
|
}
|
||||||
|
old_rpm_property = rpm_property;
|
||||||
|
rpm_property = rpm_property->next;
|
||||||
|
free(old_rpm_property);
|
||||||
|
}
|
||||||
|
old_rpm_data = rpm_data;
|
||||||
|
rpm_data = rpm_data->next;
|
||||||
|
free(old_rpm_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Steve Karg <skarg@users.sourceforge.net>
|
||||||
|
*
|
||||||
|
* 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 <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "config.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "txbuf.h"
|
||||||
|
#include "bacdef.h"
|
||||||
|
#include "bacdcode.h"
|
||||||
|
#include "address.h"
|
||||||
|
#include "tsm.h"
|
||||||
|
#include "npdu.h"
|
||||||
|
#include "apdu.h"
|
||||||
|
#include "device.h"
|
||||||
|
#include "datalink.h"
|
||||||
|
#include "dcc.h"
|
||||||
|
#include "rpm.h"
|
||||||
|
/* some demo stuff needed */
|
||||||
|
#include "handlers.h"
|
||||||
|
#include "sbuf.h"
|
||||||
|
|
||||||
|
/* returns invoke id of 0 if device is not bound or no tsm available */
|
||||||
|
uint8_t Send_Read_Property_Multiple_Request(
|
||||||
|
uint8_t * pdu,
|
||||||
|
size_t max_pdu,
|
||||||
|
uint32_t device_id, /* destination device */
|
||||||
|
BACNET_READ_ACCESS_DATA *read_access_data)
|
||||||
|
{
|
||||||
|
BACNET_ADDRESS dest;
|
||||||
|
BACNET_ADDRESS my_address;
|
||||||
|
unsigned max_apdu = 0;
|
||||||
|
uint8_t invoke_id = 0;
|
||||||
|
bool status = false;
|
||||||
|
int len = 0;
|
||||||
|
int pdu_len = 0;
|
||||||
|
int bytes_sent = 0;
|
||||||
|
BACNET_NPDU_DATA npdu_data;
|
||||||
|
|
||||||
|
if (!dcc_communication_enabled())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* is the device bound? */
|
||||||
|
status = address_get_by_device(device_id, &max_apdu, &dest);
|
||||||
|
/* is there a tsm available? */
|
||||||
|
if (status)
|
||||||
|
invoke_id = tsm_next_free_invokeID();
|
||||||
|
if (invoke_id) {
|
||||||
|
/* encode the NPDU portion of the packet */
|
||||||
|
datalink_get_my_address(&my_address);
|
||||||
|
npdu_encode_npdu_data(&npdu_data, true, MESSAGE_PRIORITY_NORMAL);
|
||||||
|
pdu_len =
|
||||||
|
npdu_encode_pdu(&pdu[0], &dest, &my_address,
|
||||||
|
&npdu_data);
|
||||||
|
/* encode the APDU portion of the packet */
|
||||||
|
len = rpm_encode_apdu(
|
||||||
|
&pdu[pdu_len],
|
||||||
|
max_pdu - pdu_len,
|
||||||
|
invoke_id,
|
||||||
|
read_access_data);
|
||||||
|
if (len <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
pdu_len += len;
|
||||||
|
/* is it small enough for the the destination to receive?
|
||||||
|
note: if there is a bottleneck router in between
|
||||||
|
us and the destination, we won't know unless
|
||||||
|
we have a way to check for that and update the
|
||||||
|
max_apdu in the address binding table. */
|
||||||
|
if ((unsigned) pdu_len < max_apdu) {
|
||||||
|
tsm_set_confirmed_unsegmented_transaction(invoke_id, &dest,
|
||||||
|
&npdu_data, &pdu[0], (uint16_t) pdu_len);
|
||||||
|
bytes_sent =
|
||||||
|
datalink_send_pdu(&dest, &npdu_data,
|
||||||
|
&pdu[0], pdu_len);
|
||||||
|
#if PRINT_ENABLED
|
||||||
|
if (bytes_sent <= 0)
|
||||||
|
fprintf(stderr,
|
||||||
|
"Failed to Send ReadPropertyMultiple Request (%s)!\n",
|
||||||
|
strerror(errno));
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
tsm_free_invoke_id(invoke_id);
|
||||||
|
invoke_id = 0;
|
||||||
|
#if PRINT_ENABLED
|
||||||
|
fprintf(stderr,
|
||||||
|
"Failed to Send ReadPropertyMultiple Request "
|
||||||
|
"(exceeds destination maximum APDU)!\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return invoke_id;
|
||||||
|
}
|
||||||
@@ -89,6 +89,25 @@ typedef struct BACnet_Application_Data_Value {
|
|||||||
struct BACnet_Application_Data_Value *next;
|
struct BACnet_Application_Data_Value *next;
|
||||||
} BACNET_APPLICATION_DATA_VALUE;
|
} BACNET_APPLICATION_DATA_VALUE;
|
||||||
|
|
||||||
|
struct BACnet_Property_Reference;
|
||||||
|
typedef struct BACnet_Property_Reference {
|
||||||
|
BACNET_PROPERTY_ID propertyIdentifier;
|
||||||
|
int32_t propertyArrayIndex; /* optional */
|
||||||
|
BACNET_APPLICATION_DATA_VALUE *value;
|
||||||
|
/* simple linked list */
|
||||||
|
struct BACnet_Property_Reference *next;
|
||||||
|
} BACNET_PROPERTY_REFERENCE;
|
||||||
|
|
||||||
|
struct BACnet_Property_Value;
|
||||||
|
typedef struct BACnet_Property_Value {
|
||||||
|
BACNET_PROPERTY_ID propertyIdentifier;
|
||||||
|
int32_t propertyArrayIndex;
|
||||||
|
BACNET_APPLICATION_DATA_VALUE value;
|
||||||
|
uint8_t priority;
|
||||||
|
/* simple linked list */
|
||||||
|
struct BACnet_Property_Value *next;
|
||||||
|
} BACNET_PROPERTY_VALUE;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
#include "npdu.h"
|
#include "npdu.h"
|
||||||
#include "bacapp.h"
|
#include "bacapp.h"
|
||||||
#include "bacenum.h"
|
#include "bacenum.h"
|
||||||
|
#include "rpm.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -74,6 +75,11 @@ extern "C" {
|
|||||||
uint32_t object_instance,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID object_property,
|
BACNET_PROPERTY_ID object_property,
|
||||||
int32_t array_index);
|
int32_t array_index);
|
||||||
|
uint8_t Send_Read_Property_Multiple_Request(
|
||||||
|
uint8_t * pdu,
|
||||||
|
size_t max_pdu,
|
||||||
|
uint32_t device_id, /* destination device */
|
||||||
|
BACNET_READ_ACCESS_DATA *read_access_data);
|
||||||
|
|
||||||
/* returns the invoke ID for confirmed request, or 0 if failed */
|
/* returns the invoke ID for confirmed request, or 0 if failed */
|
||||||
uint8_t Send_Write_Property_Request(
|
uint8_t Send_Write_Property_Request(
|
||||||
|
|||||||
@@ -38,16 +38,6 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "bacapp.h"
|
#include "bacapp.h"
|
||||||
|
|
||||||
struct BACnet_Property_Value;
|
|
||||||
typedef struct BACnet_Property_Value {
|
|
||||||
BACNET_PROPERTY_ID propertyIdentifier;
|
|
||||||
uint32_t propertyArrayIndex;
|
|
||||||
BACNET_APPLICATION_DATA_VALUE value;
|
|
||||||
uint8_t priority;
|
|
||||||
/* simple linked list */
|
|
||||||
struct BACnet_Property_Value *next;
|
|
||||||
} BACNET_PROPERTY_VALUE;
|
|
||||||
|
|
||||||
typedef struct BACnet_COV_Data {
|
typedef struct BACnet_COV_Data {
|
||||||
uint32_t subscriberProcessIdentifier;
|
uint32_t subscriberProcessIdentifier;
|
||||||
uint32_t initiatingDeviceIdentifier;
|
uint32_t initiatingDeviceIdentifier;
|
||||||
@@ -57,11 +47,6 @@ typedef struct BACnet_COV_Data {
|
|||||||
BACNET_PROPERTY_VALUE *listOfValues;
|
BACNET_PROPERTY_VALUE *listOfValues;
|
||||||
} BACNET_COV_DATA;
|
} BACNET_COV_DATA;
|
||||||
|
|
||||||
typedef struct BACnet_Property_Reference {
|
|
||||||
BACNET_PROPERTY_ID propertyIdentifier;
|
|
||||||
unsigned propertyArrayIndex; /* optional */
|
|
||||||
} BACNET_PROPERTY_REFERENCE;
|
|
||||||
|
|
||||||
typedef struct BACnet_Subscribe_COV_Data {
|
typedef struct BACnet_Subscribe_COV_Data {
|
||||||
uint32_t subscriberProcessIdentifier;
|
uint32_t subscriberProcessIdentifier;
|
||||||
BACNET_OBJECT_ID monitoredObjectIdentifier;
|
BACNET_OBJECT_ID monitoredObjectIdentifier;
|
||||||
|
|||||||
@@ -136,6 +136,12 @@ extern "C" {
|
|||||||
BACNET_ADDRESS * src,
|
BACNET_ADDRESS * src,
|
||||||
BACNET_CONFIRMED_SERVICE_DATA * service_data);
|
BACNET_CONFIRMED_SERVICE_DATA * service_data);
|
||||||
|
|
||||||
|
void handler_read_property_multiple_ack(
|
||||||
|
uint8_t * service_request,
|
||||||
|
uint16_t service_len,
|
||||||
|
BACNET_ADDRESS * src,
|
||||||
|
BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data);
|
||||||
|
|
||||||
/* Encodes the property APDU and returns the length,
|
/* Encodes the property APDU and returns the length,
|
||||||
or sets the error, and returns -1 */
|
or sets the error, and returns -1 */
|
||||||
/* resides in h_rp.c */
|
/* resides in h_rp.c */
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/*####COPYRIGHTBEGIN####
|
||||||
|
-------------------------------------------
|
||||||
|
Copyright (C) 2005 by Steve Karg
|
||||||
|
|
||||||
|
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.
|
||||||
|
-------------------------------------------
|
||||||
|
####COPYRIGHTEND####*/
|
||||||
|
|
||||||
|
/* Functional Description: Memory copy function */
|
||||||
|
|
||||||
|
#ifndef MEMCOPY_H
|
||||||
|
#define MEMCOPY_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
/* copy len bytes from src to offset of dest if there is enough space. */
|
||||||
|
/* returns 0 if there is not enough space, or 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 */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
#endif
|
||||||
@@ -40,6 +40,16 @@
|
|||||||
#include "bacdef.h"
|
#include "bacdef.h"
|
||||||
#include "bacapp.h"
|
#include "bacapp.h"
|
||||||
|
|
||||||
|
struct BACnet_Read_Access_Data;
|
||||||
|
typedef struct BACnet_Read_Access_Data {
|
||||||
|
BACNET_OBJECT_TYPE object_type;
|
||||||
|
uint32_t object_instance;
|
||||||
|
/* simple linked list of values */
|
||||||
|
BACNET_PROPERTY_REFERENCE *listOfProperties;
|
||||||
|
struct BACnet_Read_Access_Data *next;
|
||||||
|
} BACNET_READ_ACCESS_DATA;
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
@@ -68,6 +78,12 @@ extern "C" {
|
|||||||
int rpm_encode_apdu_object_end(
|
int rpm_encode_apdu_object_end(
|
||||||
uint8_t * apdu);
|
uint8_t * apdu);
|
||||||
|
|
||||||
|
int rpm_encode_apdu(
|
||||||
|
uint8_t * apdu,
|
||||||
|
size_t max_apdu,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
BACNET_READ_ACCESS_DATA *read_access_data);
|
||||||
|
|
||||||
/* decode the object portion of the service request only */
|
/* decode the object portion of the service request only */
|
||||||
int rpm_decode_object_id(
|
int rpm_decode_object_id(
|
||||||
uint8_t * apdu,
|
uint8_t * apdu,
|
||||||
@@ -129,7 +145,6 @@ extern "C" {
|
|||||||
unsigned apdu_len,
|
unsigned apdu_len,
|
||||||
BACNET_PROPERTY_ID * object_property,
|
BACNET_PROPERTY_ID * object_property,
|
||||||
int32_t * array_index);
|
int32_t * array_index);
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
int rpm_decode_apdu(
|
int rpm_decode_apdu(
|
||||||
|
|||||||
+14
-10
@@ -55,32 +55,36 @@ extern "C" {
|
|||||||
|
|
||||||
void sbuf_init(
|
void sbuf_init(
|
||||||
STATIC_BUFFER * b, /* static buffer structure */
|
STATIC_BUFFER * b, /* static buffer structure */
|
||||||
char *data, /* actual size, in bytes, of the data block or array of data */
|
char *data, /* data block */
|
||||||
unsigned size); /* number of bytes used */
|
unsigned size); /* actual size, in bytes, of the data block or array of data */
|
||||||
/* returns true if size==0, false if size > 0 */
|
|
||||||
|
/* returns true if size==0, false if size > 0 */
|
||||||
bool sbuf_empty(
|
bool sbuf_empty(
|
||||||
STATIC_BUFFER const *b);
|
STATIC_BUFFER const *b);
|
||||||
|
/* returns the data block, or NULL if not initialized */
|
||||||
char *sbuf_data(
|
char *sbuf_data(
|
||||||
STATIC_BUFFER const *b);
|
STATIC_BUFFER const *b);
|
||||||
|
/* returns the max size of the data block */
|
||||||
unsigned sbuf_size(
|
unsigned sbuf_size(
|
||||||
STATIC_BUFFER * b);
|
STATIC_BUFFER * b);
|
||||||
|
/* returns the number of bytes used in the data block */
|
||||||
unsigned sbuf_count(
|
unsigned sbuf_count(
|
||||||
STATIC_BUFFER * b);
|
STATIC_BUFFER * b);
|
||||||
/* returns true if successful, false if not enough room to append data */
|
/* returns true if successful, false if not enough room to append data */
|
||||||
bool sbuf_put(
|
bool sbuf_put(
|
||||||
STATIC_BUFFER * b, /* static buffer structure */
|
STATIC_BUFFER * b, /* static buffer structure */
|
||||||
unsigned offset, /* where to start */
|
unsigned offset, /* where to start */
|
||||||
char *data, /* number of bytes used */
|
char *data, /* data to add */
|
||||||
unsigned data_size); /* how many to add */
|
unsigned data_size); /* how many to add */
|
||||||
/* returns true if successful, false if not enough room to append data */
|
/* returns true if successful, false if not enough room to append data */
|
||||||
bool sbuf_append(
|
bool sbuf_append(
|
||||||
STATIC_BUFFER * b, /* static buffer structure */
|
STATIC_BUFFER * b, /* static buffer structure */
|
||||||
char *data, /* number of bytes used */
|
char *data, /* data to append */
|
||||||
unsigned data_size); /* how many to add */
|
unsigned data_size); /* how many to append */
|
||||||
/* returns true if successful, false if not enough room to append data */
|
/* returns true if successful, false if count is bigger than size */
|
||||||
bool sbuf_truncate(
|
bool sbuf_truncate(
|
||||||
STATIC_BUFFER * b, /* static buffer structure */
|
STATIC_BUFFER * b, /* static buffer structure */
|
||||||
unsigned count); /* total number of bytes in use */
|
unsigned count); /* new number of bytes used in buffer */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ CORE_SRC = \
|
|||||||
$(BACNET_CORE)/abort.c \
|
$(BACNET_CORE)/abort.c \
|
||||||
$(BACNET_CORE)/reject.c \
|
$(BACNET_CORE)/reject.c \
|
||||||
$(BACNET_CORE)/bacerror.c \
|
$(BACNET_CORE)/bacerror.c \
|
||||||
|
$(BACNET_CORE)/memcopy.c \
|
||||||
$(BACNET_CORE)/filename.c \
|
$(BACNET_CORE)/filename.c \
|
||||||
$(BACNET_CORE)/tsm.c \
|
$(BACNET_CORE)/tsm.c \
|
||||||
$(BACNET_CORE)/bacaddr.c \
|
$(BACNET_CORE)/bacaddr.c \
|
||||||
@@ -80,6 +81,7 @@ HANDLER_SRC = \
|
|||||||
$(BACNET_HANDLER)/h_rp.c \
|
$(BACNET_HANDLER)/h_rp.c \
|
||||||
$(BACNET_HANDLER)/h_rp_a.c \
|
$(BACNET_HANDLER)/h_rp_a.c \
|
||||||
$(BACNET_HANDLER)/h_rpm.c \
|
$(BACNET_HANDLER)/h_rpm.c \
|
||||||
|
$(BACNET_HANDLER)/h_rpm_a.c \
|
||||||
$(BACNET_HANDLER)/h_wp.c \
|
$(BACNET_HANDLER)/h_wp.c \
|
||||||
$(BACNET_HANDLER)/h_arf.c \
|
$(BACNET_HANDLER)/h_arf.c \
|
||||||
$(BACNET_HANDLER)/h_arf_a.c \
|
$(BACNET_HANDLER)/h_arf_a.c \
|
||||||
@@ -98,6 +100,7 @@ HANDLER_SRC = \
|
|||||||
$(BACNET_HANDLER)/s_iam.c \
|
$(BACNET_HANDLER)/s_iam.c \
|
||||||
$(BACNET_HANDLER)/s_rd.c \
|
$(BACNET_HANDLER)/s_rd.c \
|
||||||
$(BACNET_HANDLER)/s_rp.c \
|
$(BACNET_HANDLER)/s_rp.c \
|
||||||
|
$(BACNET_HANDLER)/s_rpm.c \
|
||||||
$(BACNET_HANDLER)/s_ts.c \
|
$(BACNET_HANDLER)/s_ts.c \
|
||||||
$(BACNET_HANDLER)/s_whohas.c \
|
$(BACNET_HANDLER)/s_whohas.c \
|
||||||
$(BACNET_HANDLER)/s_whois.c \
|
$(BACNET_HANDLER)/s_whois.c \
|
||||||
|
|||||||
@@ -82,6 +82,9 @@
|
|||||||
<Unit filename="..\demo\handler\h_rpm.c">
|
<Unit filename="..\demo\handler\h_rpm.c">
|
||||||
<Option compilerVar="CC" />
|
<Option compilerVar="CC" />
|
||||||
</Unit>
|
</Unit>
|
||||||
|
<Unit filename="..\demo\handler\h_rpm_a.c">
|
||||||
|
<Option compilerVar="CC" />
|
||||||
|
</Unit>
|
||||||
<Unit filename="..\demo\handler\h_ts.c">
|
<Unit filename="..\demo\handler\h_ts.c">
|
||||||
<Option compilerVar="CC" />
|
<Option compilerVar="CC" />
|
||||||
</Unit>
|
</Unit>
|
||||||
@@ -120,6 +123,9 @@
|
|||||||
</Unit>
|
</Unit>
|
||||||
<Unit filename="..\demo\handler\s_rp.c">
|
<Unit filename="..\demo\handler\s_rp.c">
|
||||||
<Option compilerVar="CC" />
|
<Option compilerVar="CC" />
|
||||||
|
</Unit>
|
||||||
|
<Unit filename="..\demo\handler\s_rpm.c">
|
||||||
|
<Option compilerVar="CC" />
|
||||||
</Unit>
|
</Unit>
|
||||||
<Unit filename="..\demo\handler\s_ts.c">
|
<Unit filename="..\demo\handler\s_ts.c">
|
||||||
<Option compilerVar="CC" />
|
<Option compilerVar="CC" />
|
||||||
@@ -229,6 +235,7 @@
|
|||||||
<Unit filename="..\include\rp.h" />
|
<Unit filename="..\include\rp.h" />
|
||||||
<Unit filename="..\include\rpm.h" />
|
<Unit filename="..\include\rpm.h" />
|
||||||
<Unit filename="..\include\sbuf.h" />
|
<Unit filename="..\include\sbuf.h" />
|
||||||
|
<Unit filename="..\include\memcopy.h" />
|
||||||
<Unit filename="..\include\timesync.h" />
|
<Unit filename="..\include\timesync.h" />
|
||||||
<Unit filename="..\include\tsm.h" />
|
<Unit filename="..\include\tsm.h" />
|
||||||
<Unit filename="..\include\txbuf.h" />
|
<Unit filename="..\include\txbuf.h" />
|
||||||
@@ -328,6 +335,9 @@
|
|||||||
<Unit filename="..\src\keylist.c">
|
<Unit filename="..\src\keylist.c">
|
||||||
<Option compilerVar="CC" />
|
<Option compilerVar="CC" />
|
||||||
</Unit>
|
</Unit>
|
||||||
|
<Unit filename="..\src\memcopy.c">
|
||||||
|
<Option compilerVar="CC" />
|
||||||
|
</Unit>
|
||||||
<Unit filename="..\src\mstp.c">
|
<Unit filename="..\src\mstp.c">
|
||||||
<Option compilerVar="CC" />
|
<Option compilerVar="CC" />
|
||||||
</Unit>
|
</Unit>
|
||||||
|
|||||||
@@ -209,6 +209,9 @@
|
|||||||
<Unit filename="..\src\keylist.c">
|
<Unit filename="..\src\keylist.c">
|
||||||
<Option compilerVar="CC" />
|
<Option compilerVar="CC" />
|
||||||
</Unit>
|
</Unit>
|
||||||
|
<Unit filename="..\src\memcopy.c">
|
||||||
|
<Option compilerVar="CC" />
|
||||||
|
</Unit>
|
||||||
<Unit filename="..\src\mstp.c">
|
<Unit filename="..\src\mstp.c">
|
||||||
<Option compilerVar="CC" />
|
<Option compilerVar="CC" />
|
||||||
</Unit>
|
</Unit>
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ CORE1_SRC = $(BACNET_CORE)\apdu.c \
|
|||||||
$(BACNET_CORE)\reject.c \
|
$(BACNET_CORE)\reject.c \
|
||||||
$(BACNET_CORE)\bacerror.c \
|
$(BACNET_CORE)\bacerror.c \
|
||||||
$(BACNET_CORE)\filename.c \
|
$(BACNET_CORE)\filename.c \
|
||||||
|
$(BACNET_CORE)\memcopy.c \
|
||||||
$(BACNET_CORE)\tsm.c \
|
$(BACNET_CORE)\tsm.c \
|
||||||
$(BACNET_CORE)\bacaddr.c \
|
$(BACNET_CORE)\bacaddr.c \
|
||||||
$(BACNET_CORE)\address.c \
|
$(BACNET_CORE)\address.c \
|
||||||
@@ -78,6 +79,7 @@ HANDLER_SRC = $(BACNET_HANDLER)\txbuf.c \
|
|||||||
$(BACNET_HANDLER)\h_rp.c \
|
$(BACNET_HANDLER)\h_rp.c \
|
||||||
$(BACNET_HANDLER)\h_rp_a.c \
|
$(BACNET_HANDLER)\h_rp_a.c \
|
||||||
$(BACNET_HANDLER)\h_rpm.c \
|
$(BACNET_HANDLER)\h_rpm.c \
|
||||||
|
$(BACNET_HANDLER)\h_rpm_a.c \
|
||||||
$(BACNET_HANDLER)\h_wp.c \
|
$(BACNET_HANDLER)\h_wp.c \
|
||||||
$(BACNET_HANDLER)\h_arf.c \
|
$(BACNET_HANDLER)\h_arf.c \
|
||||||
$(BACNET_HANDLER)\h_arf_a.c \
|
$(BACNET_HANDLER)\h_arf_a.c \
|
||||||
@@ -96,6 +98,7 @@ HANDLER_SRC = $(BACNET_HANDLER)\txbuf.c \
|
|||||||
$(BACNET_HANDLER)\s_iam.c \
|
$(BACNET_HANDLER)\s_iam.c \
|
||||||
$(BACNET_HANDLER)\s_rd.c \
|
$(BACNET_HANDLER)\s_rd.c \
|
||||||
$(BACNET_HANDLER)\s_rp.c \
|
$(BACNET_HANDLER)\s_rp.c \
|
||||||
|
$(BACNET_HANDLER)\s_rpm.c \
|
||||||
$(BACNET_HANDLER)\s_ts.c \
|
$(BACNET_HANDLER)\s_ts.c \
|
||||||
$(BACNET_HANDLER)\s_whohas.c \
|
$(BACNET_HANDLER)\s_whohas.c \
|
||||||
$(BACNET_HANDLER)\s_whois.c \
|
$(BACNET_HANDLER)\s_whois.c \
|
||||||
|
|||||||
@@ -12,11 +12,12 @@ MAKE=$(BORLAND_DIR)\bin\make.exe
|
|||||||
|
|
||||||
all: library \
|
all: library \
|
||||||
readprop writeprop readfile writefile server dcc reinit \
|
readprop writeprop readfile writefile server dcc reinit \
|
||||||
whois whohas timesync ucov epics
|
whois whohas timesync ucov epics readpropm
|
||||||
@echo "demo utilities are in the bin directory"
|
@echo "demo utilities are in the bin directory"
|
||||||
|
|
||||||
clean: lib\makefile.b32 \
|
clean: lib\makefile.b32 \
|
||||||
demo/readprop/makefile.b32 \
|
demo/readprop/makefile.b32 \
|
||||||
|
demo/readpropm/makefile.b32 \
|
||||||
demo/writeprop/makefile.b32 \
|
demo/writeprop/makefile.b32 \
|
||||||
demo/readfile/makefile.b32 \
|
demo/readfile/makefile.b32 \
|
||||||
demo/writefile/makefile.b32 \
|
demo/writefile/makefile.b32 \
|
||||||
@@ -35,6 +36,10 @@ clean: lib\makefile.b32 \
|
|||||||
$(MAKE) -i -f makefile.b32 clean
|
$(MAKE) -i -f makefile.b32 clean
|
||||||
cd ..
|
cd ..
|
||||||
cd ..
|
cd ..
|
||||||
|
cd demo/readpropm
|
||||||
|
$(MAKE) -i -f makefile.b32 clean
|
||||||
|
cd ..
|
||||||
|
cd ..
|
||||||
cd demo/writeprop
|
cd demo/writeprop
|
||||||
$(MAKE) -i -f makefile.b32 clean
|
$(MAKE) -i -f makefile.b32 clean
|
||||||
cd ..
|
cd ..
|
||||||
@@ -92,6 +97,13 @@ readprop: demo/readprop/makefile.b32
|
|||||||
cd ..
|
cd ..
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
|
readpropm: demo/readpropm/makefile.b32
|
||||||
|
cd demo/readpropm
|
||||||
|
$(MAKE) -f makefile.b32 all
|
||||||
|
$(MAKE) -f makefile.b32 install
|
||||||
|
cd ..
|
||||||
|
cd ..
|
||||||
|
|
||||||
writeprop: demo/writeprop/makefile.b32
|
writeprop: demo/writeprop/makefile.b32
|
||||||
cd demo/writeprop
|
cd demo/writeprop
|
||||||
$(MAKE) -f makefile.b32 all
|
$(MAKE) -f makefile.b32 all
|
||||||
|
|||||||
@@ -439,7 +439,7 @@ bool decode_is_context_tag_with_length(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* from clause 20.2.1.3.2 Constructed Data */
|
/* from clause 20.2.1.3.2 Constructed Data */
|
||||||
/* returns the number of apdu bytes consumed */
|
/* returns the true if the tag matches */
|
||||||
bool decode_is_opening_tag_number(
|
bool decode_is_opening_tag_number(
|
||||||
uint8_t * apdu,
|
uint8_t * apdu,
|
||||||
uint8_t tag_number)
|
uint8_t tag_number)
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
/*####COPYRIGHTBEGIN####
|
||||||
|
-------------------------------------------
|
||||||
|
Copyright (C) 2008 Steve Karg
|
||||||
|
|
||||||
|
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.
|
||||||
|
-------------------------------------------
|
||||||
|
####COPYRIGHTEND####*/
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/* copy len bytes from src to offset of dest if there is enough space. */
|
||||||
|
/* returns 0 if there is not enough space, or 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 */
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
size_t copy_len = 0;
|
||||||
|
char *s1, *s2;
|
||||||
|
|
||||||
|
s1 = dest;
|
||||||
|
s2 = src;
|
||||||
|
if (len <= (max - offset)) {
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
s1[offset + i] = s2[i];
|
||||||
|
copy_len++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return copy_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef TEST
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "ctest.h"
|
||||||
|
|
||||||
|
void test_memcopy(
|
||||||
|
Test * pTest)
|
||||||
|
{
|
||||||
|
char *data1 = "Joshua";
|
||||||
|
char *data2 = "Anna";
|
||||||
|
char buffer[480] = "";
|
||||||
|
char big_buffer[480] = "";
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
len = memcopy(&buffer[0], &data1[0], 0,
|
||||||
|
sizeof(data1), sizeof(buffer));
|
||||||
|
ct_test(pTest, len == sizeof(data1));
|
||||||
|
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));
|
||||||
|
ct_test(pTest, len == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef TEST_MEM_COPY
|
||||||
|
int main(
|
||||||
|
void)
|
||||||
|
{
|
||||||
|
Test *pTest;
|
||||||
|
bool rc;
|
||||||
|
|
||||||
|
pTest = ct_create("Memory Copy", NULL);
|
||||||
|
|
||||||
|
/* individual tests */
|
||||||
|
rc = ct_addTestFunction(pTest, test_memcopy);
|
||||||
|
assert(rc);
|
||||||
|
|
||||||
|
ct_setStream(pTest, stdout);
|
||||||
|
ct_run(pTest);
|
||||||
|
(void) ct_report(pTest);
|
||||||
|
|
||||||
|
ct_destroy(pTest);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* TEST */
|
||||||
@@ -37,6 +37,7 @@
|
|||||||
#include "bacdcode.h"
|
#include "bacdcode.h"
|
||||||
#include "bacdef.h"
|
#include "bacdef.h"
|
||||||
#include "bacapp.h"
|
#include "bacapp.h"
|
||||||
|
#include "memcopy.h"
|
||||||
#include "rpm.h"
|
#include "rpm.h"
|
||||||
|
|
||||||
/* encode the initial portion of the service */
|
/* encode the initial portion of the service */
|
||||||
@@ -105,6 +106,75 @@ int rpm_encode_apdu_object_end(
|
|||||||
return apdu_len;
|
return apdu_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 */
|
||||||
|
|
||||||
|
len = rpm_encode_apdu_init(&apdu_temp[0], invoke_id);
|
||||||
|
len = memcopy(&apdu[0], &apdu_temp[0], apdu_len, len, max_apdu);
|
||||||
|
if (len == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
apdu_len += len;
|
||||||
|
rpm_object = read_access_data;
|
||||||
|
while (rpm_object) {
|
||||||
|
len = encode_context_object_id(&apdu_temp[0], 0,
|
||||||
|
rpm_object->object_type,
|
||||||
|
rpm_object->object_instance);
|
||||||
|
len = memcopy(&apdu[0], &apdu_temp[0], apdu_len, len, max_apdu);
|
||||||
|
if (len == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
apdu_len += len;
|
||||||
|
/* Tag 1: sequence of ReadAccessSpecification */
|
||||||
|
len = encode_opening_tag(&apdu_temp[0], 1);
|
||||||
|
len = memcopy(&apdu[0], &apdu_temp[0], apdu_len, len, max_apdu);
|
||||||
|
if (len == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
apdu_len += len;
|
||||||
|
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 = memcopy(&apdu[0], &apdu_temp[0], apdu_len, len, 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 = memcopy(&apdu[0], &apdu_temp[0], apdu_len, len, max_apdu);
|
||||||
|
if (len == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
apdu_len += len;
|
||||||
|
}
|
||||||
|
rpm_property = rpm_property->next;
|
||||||
|
}
|
||||||
|
len = encode_closing_tag(&apdu_temp[0], 1);
|
||||||
|
len = memcopy(&apdu[0], &apdu_temp[0], apdu_len, len, max_apdu);
|
||||||
|
if (len == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
apdu_len += len;
|
||||||
|
rpm_object = rpm_object->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return apdu_len;
|
||||||
|
}
|
||||||
|
|
||||||
/* decode the object portion of the service request only */
|
/* decode the object portion of the service request only */
|
||||||
int rpm_decode_object_id(
|
int rpm_decode_object_id(
|
||||||
uint8_t * apdu,
|
uint8_t * apdu,
|
||||||
|
|||||||
+10
-9
@@ -42,9 +42,9 @@
|
|||||||
|
|
||||||
void sbuf_init(
|
void sbuf_init(
|
||||||
STATIC_BUFFER * b, /* static buffer structure */
|
STATIC_BUFFER * b, /* static buffer structure */
|
||||||
char *data, /* actual size, in bytes, of the data block or array of data */
|
char *data, /* data block */
|
||||||
unsigned size)
|
unsigned size) /* actual size, in bytes, of the data block or array of data */
|
||||||
{ /* number of bytes used */
|
{
|
||||||
if (b) {
|
if (b) {
|
||||||
b->data = data;
|
b->data = data;
|
||||||
b->size = size;
|
b->size = size;
|
||||||
@@ -83,9 +83,9 @@ unsigned sbuf_count(
|
|||||||
bool sbuf_put(
|
bool sbuf_put(
|
||||||
STATIC_BUFFER * b, /* static buffer structure */
|
STATIC_BUFFER * b, /* static buffer structure */
|
||||||
unsigned offset, /* where to start */
|
unsigned offset, /* where to start */
|
||||||
char *data, /* number of bytes used */
|
char *data, /* data to place in buffer */
|
||||||
unsigned data_size)
|
unsigned data_size)
|
||||||
{ /* how many to add */
|
{ /* how many bytes to add */
|
||||||
bool status = false; /* return value */
|
bool status = false; /* return value */
|
||||||
|
|
||||||
if (b && b->data) {
|
if (b && b->data) {
|
||||||
@@ -107,13 +107,14 @@ bool sbuf_put(
|
|||||||
/* returns true if successful, false if not enough room to append data */
|
/* returns true if successful, false if not enough room to append data */
|
||||||
bool sbuf_append(
|
bool sbuf_append(
|
||||||
STATIC_BUFFER * b, /* static buffer structure */
|
STATIC_BUFFER * b, /* static buffer structure */
|
||||||
char *data, /* number of bytes used */
|
char *data, /* data to place in buffer */
|
||||||
unsigned data_size)
|
unsigned data_size)
|
||||||
{ /* how many to add */
|
{ /* how many bytes to add */
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
|
|
||||||
if (b)
|
if (b) {
|
||||||
count = b->count;
|
count = b->count;
|
||||||
|
}
|
||||||
|
|
||||||
return sbuf_put(b, count, data, data_size);
|
return sbuf_put(b, count, data, data_size);
|
||||||
}
|
}
|
||||||
@@ -122,7 +123,7 @@ bool sbuf_append(
|
|||||||
bool sbuf_truncate(
|
bool sbuf_truncate(
|
||||||
STATIC_BUFFER * b, /* static buffer structure */
|
STATIC_BUFFER * b, /* static buffer structure */
|
||||||
unsigned count)
|
unsigned count)
|
||||||
{ /* total number of bytes in use */
|
{ /* total number of bytes in to remove */
|
||||||
bool status = false; /* return value */
|
bool status = false; /* return value */
|
||||||
|
|
||||||
if (b) {
|
if (b) {
|
||||||
|
|||||||
@@ -131,6 +131,12 @@ mstp: logfile test/mstp.mak
|
|||||||
( ./test/mstp >> ${LOGFILE} )
|
( ./test/mstp >> ${LOGFILE} )
|
||||||
( cd test ; make -f mstp.mak clean )
|
( cd test ; make -f mstp.mak clean )
|
||||||
|
|
||||||
|
memcopy: logfile test/memcopy.mak
|
||||||
|
( cd test ; make -f memcopy.mak clean )
|
||||||
|
( cd test ; make -f memcopy.mak )
|
||||||
|
( ./test/memcopy >> ${LOGFILE} )
|
||||||
|
( cd test ; make -f memcopy.mak clean )
|
||||||
|
|
||||||
npdu: logfile test/npdu.mak
|
npdu: logfile test/npdu.mak
|
||||||
( cd test ; make -f npdu.mak clean )
|
( cd test ; make -f npdu.mak clean )
|
||||||
( cd test ; make -f npdu.mak )
|
( cd test ; make -f npdu.mak )
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#Makefile to build test case
|
||||||
|
CC = gcc
|
||||||
|
SRC_DIR = ../src
|
||||||
|
INCLUDES = -I../include -I.
|
||||||
|
DEFINES = -DBIG_ENDIAN=0 -DTEST -DTEST_MEM_COPY
|
||||||
|
|
||||||
|
CFLAGS = -Wall $(INCLUDES) $(DEFINES) -g
|
||||||
|
|
||||||
|
SRCS = $(SRC_DIR)/memcopy.c \
|
||||||
|
ctest.c
|
||||||
|
|
||||||
|
TARGET = memcopy
|
||||||
|
|
||||||
|
all: ${TARGET}
|
||||||
|
|
||||||
|
OBJS = ${SRCS:.c=.o}
|
||||||
|
|
||||||
|
${TARGET}: ${OBJS}
|
||||||
|
${CC} -o $@ ${OBJS}
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
${CC} -c ${CFLAGS} $*.c -o $@
|
||||||
|
|
||||||
|
depend:
|
||||||
|
rm -f .depend
|
||||||
|
${CC} -MM ${CFLAGS} *.c >> .depend
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf core ${TARGET} $(OBJS) *.bak *.1 *.ini
|
||||||
|
|
||||||
|
include: .depend
|
||||||
|
|
||||||
Reference in New Issue
Block a user