Fixed error-code returned when an object does not support WriteProperty but has properties that are known. (#912)
This commit is contained in:
@@ -307,6 +307,35 @@ void Device_Objects_Property_List(
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determine if the object property is a member of this object instance
|
||||
* @param object_type - object type of the object
|
||||
* @param object_instance - object-instance number of the object
|
||||
* @param object_property - object-property to be checked
|
||||
* @return true if the property is a member of this object instance
|
||||
*/
|
||||
bool Device_Objects_Property_List_Member(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
uint32_t object_instance,
|
||||
BACNET_PROPERTY_ID object_property)
|
||||
{
|
||||
bool found = false;
|
||||
struct special_property_list_t property_list = { 0 };
|
||||
|
||||
Device_Objects_Property_List(object_type, object_instance, &property_list);
|
||||
found = property_list_member(property_list.Required.pList, object_property);
|
||||
if (!found) {
|
||||
found =
|
||||
property_list_member(property_list.Optional.pList, object_property);
|
||||
}
|
||||
if (!found) {
|
||||
found = property_list_member(
|
||||
property_list.Proprietary.pList, object_property);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
||||
static const int Device_Properties_Required[] = {
|
||||
PROP_OBJECT_IDENTIFIER,
|
||||
@@ -1738,8 +1767,17 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
status = pObject->Object_Write_Property(wp_data);
|
||||
}
|
||||
} else {
|
||||
if (Device_Objects_Property_List_Member(
|
||||
wp_data->object_type, wp_data->object_instance,
|
||||
wp_data->object_property)) {
|
||||
/* this property is not writable */
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
} else {
|
||||
/* this property is not supported */
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wp_data->error_class = ERROR_CLASS_OBJECT;
|
||||
|
||||
@@ -256,6 +256,35 @@ void Device_Objects_Property_List(
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determine if the object property is a member of this object instance
|
||||
* @param object_type - object type of the object
|
||||
* @param object_instance - object-instance number of the object
|
||||
* @param object_property - object-property to be checked
|
||||
* @return true if the property is a member of this object instance
|
||||
*/
|
||||
bool Device_Objects_Property_List_Member(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
uint32_t object_instance,
|
||||
BACNET_PROPERTY_ID object_property)
|
||||
{
|
||||
bool found = false;
|
||||
struct special_property_list_t property_list = { 0 };
|
||||
|
||||
Device_Objects_Property_List(object_type, object_instance, &property_list);
|
||||
found = property_list_member(property_list.Required.pList, object_property);
|
||||
if (!found) {
|
||||
found =
|
||||
property_list_member(property_list.Optional.pList, object_property);
|
||||
}
|
||||
if (!found) {
|
||||
found = property_list_member(
|
||||
property_list.Proprietary.pList, object_property);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
||||
static const int Device_Properties_Required[] = {
|
||||
PROP_OBJECT_IDENTIFIER,
|
||||
|
||||
@@ -38,7 +38,9 @@ CFLAGS = -fno-common $(INCLUDES) $(BACNET_FLAGS) -g
|
||||
CFLAGS += -mno-thumb-interwork
|
||||
# dead code removal
|
||||
CFLAGS += -fdata-sections -ffunction-sections
|
||||
|
||||
# C standard to use for compiler
|
||||
CSTANDARD = -std=gnu11
|
||||
CFLAGS += $(CSTANDARD)
|
||||
# enable all relevant warnings that find bugs
|
||||
WARNING_ALL := -Wall -Wextra -Wfloat-equal -Wconversion
|
||||
WARNING_ALL += -Wredundant-decls -Wswitch-default -pedantic
|
||||
@@ -51,11 +53,13 @@ WARNING_ALL += -Wno-implicit-fallthrough
|
||||
# the older Atmel SDK does not meet coding guidelines
|
||||
WARNING_ALL += -Wno-comment -Wno-missing-braces
|
||||
WARNING_ALL += -Wno-unused-variable -Wno-char-subscripts
|
||||
# fix later
|
||||
WARNING_ALL += -Wno-unused-parameter
|
||||
WARNING_ALL += -Wno-type-limits
|
||||
WARNING_ALL += -Wno-redundant-decls
|
||||
#WARNING_ALL += -Werror
|
||||
CFLAGS += $(WARNING_ALL)
|
||||
|
||||
CFLAGS += -Wno-char-subscripts
|
||||
|
||||
LIBRARY = lib$(TARGET).a
|
||||
# -Wa,<options> Pass comma-separated <options> on to the assembler
|
||||
AFLAGS = -Wa,-ahls,-mapcs-32,-adhlns=$(<:.s=.lst)
|
||||
|
||||
+113
-7
@@ -36,10 +36,6 @@
|
||||
/* current version of the BACnet stack */
|
||||
static const char *BACnet_Version = BACNET_VERSION_TEXT;
|
||||
|
||||
/* forward prototype */
|
||||
int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata);
|
||||
bool Device_Write_Property_Local(BACNET_WRITE_PROPERTY_DATA *wp_data);
|
||||
|
||||
static struct my_object_functions {
|
||||
BACNET_OBJECT_TYPE Object_Type;
|
||||
object_init_function Object_Init;
|
||||
@@ -77,7 +73,7 @@ static struct my_object_functions {
|
||||
Network_Port_Object_Name, Network_Port_Read_Property,
|
||||
Network_Port_Write_Property, Network_Port_Property_Lists },
|
||||
#endif
|
||||
{ MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL } };
|
||||
{ MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } };
|
||||
|
||||
/* note: you really only need to define variables for
|
||||
properties that are writable or that may change.
|
||||
@@ -197,6 +193,67 @@ int Device_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handles the writing of the object name property
|
||||
* @param wp_data [in,out] WriteProperty data structure
|
||||
* @param Object_Write_Property object specific function to write the property
|
||||
* @return True on success, else False if there is an error.
|
||||
*/
|
||||
static bool Device_Write_Property_Object_Name(
|
||||
BACNET_WRITE_PROPERTY_DATA *wp_data,
|
||||
write_property_function Object_Write_Property)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
int len = 0;
|
||||
BACNET_CHARACTER_STRING value;
|
||||
BACNET_OBJECT_TYPE object_type = OBJECT_NONE;
|
||||
uint32_t object_instance = 0;
|
||||
int apdu_size = 0;
|
||||
uint8_t *apdu = NULL;
|
||||
|
||||
if (!wp_data) {
|
||||
return false;
|
||||
}
|
||||
apdu = wp_data->application_data;
|
||||
apdu_size = wp_data->application_data_len;
|
||||
len = bacnet_character_string_application_decode(apdu, apdu_size, &value);
|
||||
if (len > 0) {
|
||||
if ((characterstring_encoding(&value) != CHARACTER_ANSI_X34) ||
|
||||
(characterstring_length(&value) == 0) ||
|
||||
(!characterstring_printable(&value))) {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
} else {
|
||||
status = true;
|
||||
}
|
||||
} else if (len == 0) {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
} else {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
}
|
||||
if (status) {
|
||||
/* All the object names in a device must be unique */
|
||||
if (Device_Valid_Object_Name(&value, &object_type, &object_instance)) {
|
||||
if ((object_type == wp_data->object_type) &&
|
||||
(object_instance == wp_data->object_instance)) {
|
||||
/* writing same name to same object */
|
||||
status = true;
|
||||
} else {
|
||||
/* name already exists in some object */
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_DUPLICATE_NAME;
|
||||
status = false;
|
||||
}
|
||||
} else {
|
||||
status = Object_Write_Property(wp_data);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
bool status = false;
|
||||
@@ -208,10 +265,30 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
if (pObject->Object_Valid_Instance &&
|
||||
pObject->Object_Valid_Instance(wp_data->object_instance)) {
|
||||
if (pObject->Object_Write_Property) {
|
||||
status = pObject->Object_Write_Property(wp_data);
|
||||
} else {
|
||||
#if (BACNET_PROTOCOL_REVISION >= 14)
|
||||
if (wp_data->object_property == PROP_PROPERTY_LIST) {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if (wp_data->object_property == PROP_OBJECT_NAME) {
|
||||
status = Device_Write_Property_Object_Name(
|
||||
wp_data, pObject->Object_Write_Property);
|
||||
} else {
|
||||
status = pObject->Object_Write_Property(wp_data);
|
||||
}
|
||||
} else {
|
||||
if (Device_Objects_Property_List_Member(wp_data->object_type,
|
||||
wp_data->object_instance, wp_data->object_property)) {
|
||||
/* this property is not writable */
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
} else {
|
||||
/* this property is not supported */
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wp_data->error_class = ERROR_CLASS_OBJECT;
|
||||
@@ -264,6 +341,35 @@ void Device_Objects_Property_List(BACNET_OBJECT_TYPE object_type,
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determine if the object property is a member of this object instance
|
||||
* @param object_type - object type of the object
|
||||
* @param object_instance - object-instance number of the object
|
||||
* @param object_property - object-property to be checked
|
||||
* @return true if the property is a member of this object instance
|
||||
*/
|
||||
bool Device_Objects_Property_List_Member(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
uint32_t object_instance,
|
||||
BACNET_PROPERTY_ID object_property)
|
||||
{
|
||||
bool found = false;
|
||||
struct special_property_list_t property_list = { 0 };
|
||||
|
||||
Device_Objects_Property_List(object_type, object_instance, &property_list);
|
||||
found = property_list_member(property_list.Required.pList, object_property);
|
||||
if (!found) {
|
||||
found =
|
||||
property_list_member(property_list.Optional.pList, object_property);
|
||||
}
|
||||
if (!found) {
|
||||
found = property_list_member(
|
||||
property_list.Proprietary.pList, object_property);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
void Device_Property_Lists(
|
||||
const int **pRequired, const int **pOptional, const int **pProprietary)
|
||||
{
|
||||
|
||||
@@ -160,6 +160,67 @@ int Device_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handles the writing of the object name property
|
||||
* @param wp_data [in,out] WriteProperty data structure
|
||||
* @param Object_Write_Property object specific function to write the property
|
||||
* @return True on success, else False if there is an error.
|
||||
*/
|
||||
static bool Device_Write_Property_Object_Name(
|
||||
BACNET_WRITE_PROPERTY_DATA *wp_data,
|
||||
write_property_function Object_Write_Property)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
int len = 0;
|
||||
BACNET_CHARACTER_STRING value;
|
||||
BACNET_OBJECT_TYPE object_type = OBJECT_NONE;
|
||||
uint32_t object_instance = 0;
|
||||
int apdu_size = 0;
|
||||
uint8_t *apdu = NULL;
|
||||
|
||||
if (!wp_data) {
|
||||
return false;
|
||||
}
|
||||
apdu = wp_data->application_data;
|
||||
apdu_size = wp_data->application_data_len;
|
||||
len = bacnet_character_string_application_decode(apdu, apdu_size, &value);
|
||||
if (len > 0) {
|
||||
if ((characterstring_encoding(&value) != CHARACTER_ANSI_X34) ||
|
||||
(characterstring_length(&value) == 0) ||
|
||||
(!characterstring_printable(&value))) {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
} else {
|
||||
status = true;
|
||||
}
|
||||
} else if (len == 0) {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
} else {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
}
|
||||
if (status) {
|
||||
/* All the object names in a device must be unique */
|
||||
if (Device_Valid_Object_Name(&value, &object_type, &object_instance)) {
|
||||
if ((object_type == wp_data->object_type) &&
|
||||
(object_instance == wp_data->object_instance)) {
|
||||
/* writing same name to same object */
|
||||
status = true;
|
||||
} else {
|
||||
/* name already exists in some object */
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_DUPLICATE_NAME;
|
||||
status = false;
|
||||
}
|
||||
} else {
|
||||
status = Object_Write_Property(wp_data);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
bool status = false;
|
||||
@@ -171,10 +232,30 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
if (pObject->Object_Valid_Instance &&
|
||||
pObject->Object_Valid_Instance(wp_data->object_instance)) {
|
||||
if (pObject->Object_Write_Property) {
|
||||
status = pObject->Object_Write_Property(wp_data);
|
||||
} else {
|
||||
#if (BACNET_PROTOCOL_REVISION >= 14)
|
||||
if (wp_data->object_property == PROP_PROPERTY_LIST) {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if (wp_data->object_property == PROP_OBJECT_NAME) {
|
||||
status = Device_Write_Property_Object_Name(
|
||||
wp_data, pObject->Object_Write_Property);
|
||||
} else {
|
||||
status = pObject->Object_Write_Property(wp_data);
|
||||
}
|
||||
} else {
|
||||
if (Device_Objects_Property_List_Member(wp_data->object_type,
|
||||
wp_data->object_instance, wp_data->object_property)) {
|
||||
/* this property is not writable */
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
} else {
|
||||
/* this property is not supported */
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wp_data->error_class = ERROR_CLASS_OBJECT;
|
||||
@@ -241,6 +322,35 @@ void Device_Objects_Property_List(BACNET_OBJECT_TYPE object_type,
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determine if the object property is a member of this object instance
|
||||
* @param object_type - object type of the object
|
||||
* @param object_instance - object-instance number of the object
|
||||
* @param object_property - object-property to be checked
|
||||
* @return true if the property is a member of this object instance
|
||||
*/
|
||||
bool Device_Objects_Property_List_Member(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
uint32_t object_instance,
|
||||
BACNET_PROPERTY_ID object_property)
|
||||
{
|
||||
bool found = false;
|
||||
struct special_property_list_t property_list = { 0 };
|
||||
|
||||
Device_Objects_Property_List(object_type, object_instance, &property_list);
|
||||
found = property_list_member(property_list.Required.pList, object_property);
|
||||
if (!found) {
|
||||
found =
|
||||
property_list_member(property_list.Optional.pList, object_property);
|
||||
}
|
||||
if (!found) {
|
||||
found = property_list_member(
|
||||
property_list.Proprietary.pList, object_property);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
void Device_Property_Lists(
|
||||
const int **pRequired, const int **pOptional, const int **pProprietary)
|
||||
{
|
||||
|
||||
@@ -252,6 +252,35 @@ void Device_Objects_Property_List(BACNET_OBJECT_TYPE object_type,
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determine if the object property is a member of this object instance
|
||||
* @param object_type - object type of the object
|
||||
* @param object_instance - object-instance number of the object
|
||||
* @param object_property - object-property to be checked
|
||||
* @return true if the property is a member of this object instance
|
||||
*/
|
||||
bool Device_Objects_Property_List_Member(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
uint32_t object_instance,
|
||||
BACNET_PROPERTY_ID object_property)
|
||||
{
|
||||
bool found = false;
|
||||
struct special_property_list_t property_list = { 0 };
|
||||
|
||||
Device_Objects_Property_List(object_type, object_instance, &property_list);
|
||||
found = property_list_member(property_list.Required.pList, object_property);
|
||||
if (!found) {
|
||||
found =
|
||||
property_list_member(property_list.Optional.pList, object_property);
|
||||
}
|
||||
if (!found) {
|
||||
found = property_list_member(
|
||||
property_list.Proprietary.pList, object_property);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
void Device_Property_Lists(
|
||||
const int **pRequired, const int **pOptional, const int **pProprietary)
|
||||
{
|
||||
|
||||
@@ -274,6 +274,35 @@ void Device_Objects_Property_List(
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determine if the object property is a member of this object instance
|
||||
* @param object_type - object type of the object
|
||||
* @param object_instance - object-instance number of the object
|
||||
* @param object_property - object-property to be checked
|
||||
* @return true if the property is a member of this object instance
|
||||
*/
|
||||
bool Device_Objects_Property_List_Member(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
uint32_t object_instance,
|
||||
BACNET_PROPERTY_ID object_property)
|
||||
{
|
||||
bool found = false;
|
||||
struct special_property_list_t property_list = { 0 };
|
||||
|
||||
Device_Objects_Property_List(object_type, object_instance, &property_list);
|
||||
found = property_list_member(property_list.Required.pList, object_property);
|
||||
if (!found) {
|
||||
found =
|
||||
property_list_member(property_list.Optional.pList, object_property);
|
||||
}
|
||||
if (!found) {
|
||||
found = property_list_member(
|
||||
property_list.Proprietary.pList, object_property);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
||||
static const int Device_Properties_Required[] = {
|
||||
PROP_OBJECT_IDENTIFIER,
|
||||
@@ -1300,8 +1329,17 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
status = pObject->Object_Write_Property(wp_data);
|
||||
}
|
||||
} else {
|
||||
if (Device_Objects_Property_List_Member(
|
||||
wp_data->object_type, wp_data->object_instance,
|
||||
wp_data->object_property)) {
|
||||
/* this property is not writable */
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
} else {
|
||||
/* this property is not supported */
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wp_data->error_class = ERROR_CLASS_OBJECT;
|
||||
|
||||
@@ -2017,8 +2017,17 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
Device_Write_Property_Store(wp_data);
|
||||
}
|
||||
} else {
|
||||
if (Device_Objects_Property_List_Member(
|
||||
wp_data->object_type, wp_data->object_instance,
|
||||
wp_data->object_property)) {
|
||||
/* this property is not writable */
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
} else {
|
||||
/* this property is not supported */
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wp_data->error_class = ERROR_CLASS_OBJECT;
|
||||
|
||||
Reference in New Issue
Block a user