added ReadPropertyMultiple client demo application, bacrpm.

This commit is contained in:
skarg
2008-11-23 22:25:08 +00:00
parent 815d8f8dbb
commit 7921d2f811
22 changed files with 772 additions and 77 deletions
+6 -1
View File
@@ -1,10 +1,11 @@
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
@echo "utilities are in the bin directory"
clean: lib/Makefile\
demo/readprop/Makefile \
demo/readpropm/Makefile \
demo/writeprop/Makefile \
demo/readfile/Makefile \
demo/writefile/Makefile \
@@ -22,6 +23,7 @@ clean: lib/Makefile\
demo/mstpcap/Makefile
( cd lib ; make clean )
( cd demo/readprop ; make clean )
( cd demo/readpropm ; make clean )
( cd demo/writeprop ; make clean )
( cd demo/readfile ; make clean )
( cd demo/writefile ; make clean )
@@ -44,6 +46,9 @@ library: lib/Makefile
readprop: demo/readprop/Makefile
( cd demo/readprop ; make ; cp bacrp ../../bin )
readpropm: demo/readpropm/Makefile
( cd demo/readpropm ; make ; cp bacrpm ../../bin )
writeprop: demo/writeprop/Makefile
( cd demo/writeprop ; make ; cp bacwp ../../bin )
+11 -29
View File
@@ -1,7 +1,7 @@
/**************************************************************************
*
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
* Inspired by John Stachler <John.Stachler@lennoxind.com>
* Inspired by John Stachler <John.Stachler@lennoxind.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@@ -30,6 +30,7 @@
#include <string.h>
#include "config.h"
#include "txbuf.h"
#include "memcopy.h"
#include "bacdef.h"
#include "bacdcode.h"
#include "apdu.h"
@@ -210,27 +211,6 @@ static unsigned RPM_Object_Property_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,
or 0 if there is no room to fit the encoding. */
int RPM_Encode_Property(
@@ -250,9 +230,10 @@ int RPM_Encode_Property(
len =
rpm_ack_encode_apdu_object_property(&Temp_Buf[0], object_property,
array_index);
len = apdu_copy(&apdu[0], &Temp_Buf[0], offset, len, max_apdu);
if (!len)
len = memcopy(&apdu[0], &Temp_Buf[0], offset, len, max_apdu);
if (!len) {
return 0;
}
apdu_len += len;
len =
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],
error_class, error_code);
len =
apdu_copy(&apdu[0], &Temp_Buf[0], offset + apdu_len, len,
memcopy(&apdu[0], &Temp_Buf[0], offset + apdu_len, len,
max_apdu);
if (!len)
if (!len) {
return 0;
}
} else if ((offset + apdu_len + 1 + len + 1) < max_apdu) {
/* enough room to fit the property value and tags */
len =
@@ -339,7 +321,7 @@ void handler_read_property_multiple(
decode_len++;
len = rpm_ack_encode_apdu_object_end(&Temp_Buf[0]);
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));
if (!copy_len) {
apdu_len =
@@ -362,7 +344,7 @@ void handler_read_property_multiple(
rpm_ack_encode_apdu_object_begin(&Temp_Buf[0], object_type,
object_instance);
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));
if (!copy_len) {
apdu_len =
@@ -389,7 +371,7 @@ void handler_read_property_multiple(
decode_len++;
len = rpm_ack_encode_apdu_object_end(&Temp_Buf[0]);
copy_len =
apdu_copy(&Handler_Transmit_Buffer[npdu_len],
memcopy(&Handler_Transmit_Buffer[npdu_len],
&Temp_Buf[0], apdu_len, len,
sizeof(Handler_Transmit_Buffer));
if (!copy_len) {
+246
View File
@@ -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);
}
}
}
+117
View File
@@ -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;
}
+19
View File
@@ -89,6 +89,25 @@ typedef struct BACnet_Application_Data_Value {
struct BACnet_Application_Data_Value *next;
} 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
extern "C" {
#endif /* __cplusplus */
+6
View File
@@ -33,6 +33,7 @@
#include "npdu.h"
#include "bacapp.h"
#include "bacenum.h"
#include "rpm.h"
#ifdef __cplusplus
extern "C" {
@@ -74,6 +75,11 @@ extern "C" {
uint32_t object_instance,
BACNET_PROPERTY_ID object_property,
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 */
uint8_t Send_Write_Property_Request(
-15
View File
@@ -38,16 +38,6 @@
#include <stdbool.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 {
uint32_t subscriberProcessIdentifier;
uint32_t initiatingDeviceIdentifier;
@@ -57,11 +47,6 @@ typedef struct BACnet_COV_Data {
BACNET_PROPERTY_VALUE *listOfValues;
} BACNET_COV_DATA;
typedef struct BACnet_Property_Reference {
BACNET_PROPERTY_ID propertyIdentifier;
unsigned propertyArrayIndex; /* optional */
} BACNET_PROPERTY_REFERENCE;
typedef struct BACnet_Subscribe_COV_Data {
uint32_t subscriberProcessIdentifier;
BACNET_OBJECT_ID monitoredObjectIdentifier;
+6
View File
@@ -136,6 +136,12 @@ extern "C" {
BACNET_ADDRESS * src,
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,
or sets the error, and returns -1 */
/* resides in h_rp.c */
+60
View File
@@ -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
+16 -1
View File
@@ -40,6 +40,16 @@
#include "bacdef.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
extern "C" {
#endif /* __cplusplus */
@@ -68,6 +78,12 @@ extern "C" {
int rpm_encode_apdu_object_end(
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 */
int rpm_decode_object_id(
uint8_t * apdu,
@@ -129,7 +145,6 @@ extern "C" {
unsigned apdu_len,
BACNET_PROPERTY_ID * object_property,
int32_t * array_index);
#ifdef TEST
#include "ctest.h"
int rpm_decode_apdu(
+14 -10
View File
@@ -55,32 +55,36 @@ extern "C" {
void sbuf_init(
STATIC_BUFFER * b, /* static buffer structure */
char *data, /* actual size, in bytes, of the data block or array of data */
unsigned size); /* number of bytes used */
/* returns true if size==0, false if size > 0 */
char *data, /* data block */
unsigned size); /* actual size, in bytes, of the data block or array of data */
/* returns true if size==0, false if size > 0 */
bool sbuf_empty(
STATIC_BUFFER const *b);
/* returns the data block, or NULL if not initialized */
char *sbuf_data(
STATIC_BUFFER const *b);
/* returns the max size of the data block */
unsigned sbuf_size(
STATIC_BUFFER * b);
/* returns the number of bytes used in the data block */
unsigned sbuf_count(
STATIC_BUFFER * b);
/* returns true if successful, false if not enough room to append data */
/* returns true if successful, false if not enough room to append data */
bool sbuf_put(
STATIC_BUFFER * b, /* static buffer structure */
unsigned offset, /* where to start */
char *data, /* number of bytes used */
char *data, /* data 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(
STATIC_BUFFER * b, /* static buffer structure */
char *data, /* number of bytes used */
unsigned data_size); /* how many to add */
/* returns true if successful, false if not enough room to append data */
char *data, /* data to append */
unsigned data_size); /* how many to append */
/* returns true if successful, false if count is bigger than size */
bool sbuf_truncate(
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
}
+3
View File
@@ -65,6 +65,7 @@ CORE_SRC = \
$(BACNET_CORE)/abort.c \
$(BACNET_CORE)/reject.c \
$(BACNET_CORE)/bacerror.c \
$(BACNET_CORE)/memcopy.c \
$(BACNET_CORE)/filename.c \
$(BACNET_CORE)/tsm.c \
$(BACNET_CORE)/bacaddr.c \
@@ -80,6 +81,7 @@ HANDLER_SRC = \
$(BACNET_HANDLER)/h_rp.c \
$(BACNET_HANDLER)/h_rp_a.c \
$(BACNET_HANDLER)/h_rpm.c \
$(BACNET_HANDLER)/h_rpm_a.c \
$(BACNET_HANDLER)/h_wp.c \
$(BACNET_HANDLER)/h_arf.c \
$(BACNET_HANDLER)/h_arf_a.c \
@@ -98,6 +100,7 @@ HANDLER_SRC = \
$(BACNET_HANDLER)/s_iam.c \
$(BACNET_HANDLER)/s_rd.c \
$(BACNET_HANDLER)/s_rp.c \
$(BACNET_HANDLER)/s_rpm.c \
$(BACNET_HANDLER)/s_ts.c \
$(BACNET_HANDLER)/s_whohas.c \
$(BACNET_HANDLER)/s_whois.c \
+17 -7
View File
@@ -82,6 +82,9 @@
<Unit filename="..\demo\handler\h_rpm.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\demo\handler\h_rpm_a.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\demo\handler\h_ts.c">
<Option compilerVar="CC" />
</Unit>
@@ -118,9 +121,12 @@
<Unit filename="..\demo\handler\s_rd.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\demo\handler\s_rp.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\demo\handler\s_rp.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\demo\handler\s_rpm.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\demo\handler\s_ts.c">
<Option compilerVar="CC" />
</Unit>
@@ -228,7 +234,8 @@
<Unit filename="..\include\ringbuf.h" />
<Unit filename="..\include\rp.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\tsm.h" />
<Unit filename="..\include\txbuf.h" />
@@ -328,9 +335,12 @@
<Unit filename="..\src\keylist.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\src\mstp.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\src\memcopy.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\src\mstp.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\src\npdu.c">
<Option compilerVar="CC" />
</Unit>
+6 -3
View File
@@ -209,9 +209,12 @@
<Unit filename="..\src\keylist.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\src\mstp.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\src\memcopy.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\src\mstp.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\src\mstptext.c">
<Option compilerVar="CC" />
</Unit>
+3
View File
@@ -51,6 +51,7 @@ CORE1_SRC = $(BACNET_CORE)\apdu.c \
$(BACNET_CORE)\reject.c \
$(BACNET_CORE)\bacerror.c \
$(BACNET_CORE)\filename.c \
$(BACNET_CORE)\memcopy.c \
$(BACNET_CORE)\tsm.c \
$(BACNET_CORE)\bacaddr.c \
$(BACNET_CORE)\address.c \
@@ -78,6 +79,7 @@ HANDLER_SRC = $(BACNET_HANDLER)\txbuf.c \
$(BACNET_HANDLER)\h_rp.c \
$(BACNET_HANDLER)\h_rp_a.c \
$(BACNET_HANDLER)\h_rpm.c \
$(BACNET_HANDLER)\h_rpm_a.c \
$(BACNET_HANDLER)\h_wp.c \
$(BACNET_HANDLER)\h_arf.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_rd.c \
$(BACNET_HANDLER)\s_rp.c \
$(BACNET_HANDLER)\s_rpm.c \
$(BACNET_HANDLER)\s_ts.c \
$(BACNET_HANDLER)\s_whohas.c \
$(BACNET_HANDLER)\s_whois.c \
+13 -1
View File
@@ -12,11 +12,12 @@ MAKE=$(BORLAND_DIR)\bin\make.exe
all: library \
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"
clean: lib\makefile.b32 \
demo/readprop/makefile.b32 \
demo/readpropm/makefile.b32 \
demo/writeprop/makefile.b32 \
demo/readfile/makefile.b32 \
demo/writefile/makefile.b32 \
@@ -35,6 +36,10 @@ clean: lib\makefile.b32 \
$(MAKE) -i -f makefile.b32 clean
cd ..
cd ..
cd demo/readpropm
$(MAKE) -i -f makefile.b32 clean
cd ..
cd ..
cd demo/writeprop
$(MAKE) -i -f makefile.b32 clean
cd ..
@@ -92,6 +97,13 @@ readprop: demo/readprop/makefile.b32
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
cd demo/writeprop
$(MAKE) -f makefile.b32 all
+1 -1
View File
@@ -439,7 +439,7 @@ bool decode_is_context_tag_with_length(
}
/* 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(
uint8_t * apdu,
uint8_t tag_number)
+110
View File
@@ -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 */
+70
View File
@@ -37,6 +37,7 @@
#include "bacdcode.h"
#include "bacdef.h"
#include "bacapp.h"
#include "memcopy.h"
#include "rpm.h"
/* encode the initial portion of the service */
@@ -105,6 +106,75 @@ int rpm_encode_apdu_object_end(
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 */
int rpm_decode_object_id(
uint8_t * apdu,
+10 -9
View File
@@ -42,9 +42,9 @@
void sbuf_init(
STATIC_BUFFER * b, /* static buffer structure */
char *data, /* actual size, in bytes, of the data block or array of data */
unsigned size)
{ /* number of bytes used */
char *data, /* data block */
unsigned size) /* actual size, in bytes, of the data block or array of data */
{
if (b) {
b->data = data;
b->size = size;
@@ -83,9 +83,9 @@ unsigned sbuf_count(
bool sbuf_put(
STATIC_BUFFER * b, /* static buffer structure */
unsigned offset, /* where to start */
char *data, /* number of bytes used */
char *data, /* data to place in buffer */
unsigned data_size)
{ /* how many to add */
{ /* how many bytes to add */
bool status = false; /* return value */
if (b && b->data) {
@@ -107,13 +107,14 @@ bool sbuf_put(
/* returns true if successful, false if not enough room to append data */
bool sbuf_append(
STATIC_BUFFER * b, /* static buffer structure */
char *data, /* number of bytes used */
char *data, /* data to place in buffer */
unsigned data_size)
{ /* how many to add */
{ /* how many bytes to add */
unsigned count = 0;
if (b)
if (b) {
count = b->count;
}
return sbuf_put(b, count, data, data_size);
}
@@ -122,7 +123,7 @@ bool sbuf_append(
bool sbuf_truncate(
STATIC_BUFFER * b, /* static buffer structure */
unsigned count)
{ /* total number of bytes in use */
{ /* total number of bytes in to remove */
bool status = false; /* return value */
if (b) {
+6
View File
@@ -131,6 +131,12 @@ mstp: logfile test/mstp.mak
( ./test/mstp >> ${LOGFILE} )
( 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
( cd test ; make -f npdu.mak clean )
( cd test ; make -f npdu.mak )
+32
View File
@@ -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