added ReadPropertyMultiple client demo application, bacrpm.
This commit is contained in:
@@ -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 )
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
} 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 */
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 "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
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 "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
@@ -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) {
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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