diff --git a/apps/blinkt/device.c b/apps/blinkt/device.c index 1bdaba20..0a1873f9 100644 --- a/apps/blinkt/device.c +++ b/apps/blinkt/device.c @@ -74,8 +74,8 @@ static object_functions_t My_Object_Table[] = { Device_Property_Lists, DeviceGetRRInfo, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, - NULL /* Remove_List_Element */, - NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }, + NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, + NULL /* Timer */ }, #if (BACNET_PROTOCOL_REVISION >= 17) { OBJECT_NETWORK_PORT, Network_Port_Init, Network_Port_Count, Network_Port_Index_To_Instance, Network_Port_Valid_Instance, @@ -93,7 +93,7 @@ static object_functions_t My_Object_Table[] = { NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - NULL /* Create */, NULL /* Delete */ , NULL /* Timer */ }, + NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }, #if (BACNET_PROTOCOL_REVISION >= 14) { OBJECT_LIGHTING_OUTPUT, Lighting_Output_Init, Lighting_Output_Count, Lighting_Output_Index_To_Instance, Lighting_Output_Valid_Instance, @@ -102,14 +102,14 @@ static object_functions_t My_Object_Table[] = { NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - Lighting_Output_Create, Lighting_Output_Delete, Lighting_Output_Timer}, + Lighting_Output_Create, Lighting_Output_Delete, Lighting_Output_Timer }, { OBJECT_CHANNEL, Channel_Init, Channel_Count, Channel_Index_To_Instance, Channel_Valid_Instance, Channel_Object_Name, Channel_Read_Property, Channel_Write_Property, Channel_Property_Lists, NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - Channel_Create, Channel_Delete, NULL /* Timer */ }, + Channel_Create, Channel_Delete, NULL /* Timer */ }, #endif #if (BACNET_PROTOCOL_REVISION >= 24) { OBJECT_COLOR, Color_Init, Color_Count, Color_Index_To_Instance, @@ -118,7 +118,7 @@ static object_functions_t My_Object_Table[] = { NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - Color_Create, Color_Delete, Color_Timer}, + Color_Create, Color_Delete, Color_Timer }, { OBJECT_COLOR_TEMPERATURE, Color_Temperature_Init, Color_Temperature_Count, Color_Temperature_Index_To_Instance, Color_Temperature_Valid_Instance, Color_Temperature_Object_Name, Color_Temperature_Read_Property, @@ -127,7 +127,7 @@ static object_functions_t My_Object_Table[] = { NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, Color_Temperature_Create, Color_Temperature_Delete, - Color_Temperature_Timer}, + Color_Temperature_Timer }, #endif { MAX_BACNET_OBJECT_TYPE, NULL /* Init */, NULL /* Count */, NULL /* Index_To_Instance */, NULL /* Valid_Instance */, @@ -136,7 +136,7 @@ static object_functions_t My_Object_Table[] = { NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - NULL /* Create */, NULL /* Delete */, NULL /* Timer */ } + NULL /* Create */, NULL /* Delete */, NULL /* Timer */ } }; /** Glue function to let the Device object, when called by a handler, @@ -329,6 +329,24 @@ static uint32_t Database_Revision = 0; static BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE; static const char *Reinit_Password = "filister"; +/** + * @brief Sets the ReinitializeDevice password + * + * The password shall be a null terminated C string of up to + * 20 ASCII characters for those devices that require the password. + * + * For those devices that do not require a password, set to NULL or + * point to a zero length C string (null terminated). + * + * @param the ReinitializeDevice password; can be NULL or empty string + */ +bool Device_Reinitialize_Password_Set(const char *password) +{ + Reinit_Password = password; + + return true; +} + /** Commands a Device re-initialization, to a given state. * The request's password must match for the operation to succeed. * This implementation provides a framework, but doesn't @@ -345,6 +363,7 @@ static const char *Reinit_Password = "filister"; bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) { bool status = false; + bool password_success = false; /* From 16.4.1.1.2 Password This optional parameter shall be a CharacterString of up to @@ -352,12 +371,21 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) protection, the service request shall be denied if the parameter is absent or if the password is incorrect. For those devices that do not require a password, this parameter shall be ignored.*/ - if (characterstring_length(&rd_data->password) > 20) { - rd_data->error_class = ERROR_CLASS_SERVICES; - rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; - } else if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) { - /* Note: you could use a mix of state and password to - accomplish multiple things before restarting */ + if (Reinit_Password && strlen(Reinit_Password) > 0) { + if (characterstring_length(&rd_data->password) > 20) { + rd_data->error_class = ERROR_CLASS_SERVICES; + rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; + } else if (characterstring_ansi_same( + &rd_data->password, Reinit_Password)) { + password_success = true; + } else { + rd_data->error_class = ERROR_CLASS_SECURITY; + rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE; + } + } else { + password_success = true; + } + if (password_success) { switch (rd_data->state) { case BACNET_REINIT_COLDSTART: case BACNET_REINIT_WARMSTART: @@ -387,9 +415,6 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; break; } - } else { - rd_data->error_class = ERROR_CLASS_SECURITY; - rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE; } return status; @@ -1103,9 +1128,8 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata) case PROP_OBJECT_LIST: count = Device_Object_List_Count(); apdu_len = bacnet_array_encode(rpdata->object_instance, - rpdata->array_index, - Device_Object_List_Element_Encode, - count, apdu, apdu_max); + rpdata->array_index, Device_Object_List_Element_Encode, count, + apdu, apdu_max); if (apdu_len == BACNET_STATUS_ABORT) { rpdata->error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED; @@ -1635,8 +1659,8 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) } #endif if (wp_data->object_property == PROP_OBJECT_NAME) { - status = Device_Write_Property_Object_Name(wp_data, - pObject->Object_Write_Property); + status = Device_Write_Property_Object_Name( + wp_data, pObject->Object_Write_Property); } else { status = pObject->Object_Write_Property(wp_data); } @@ -1663,8 +1687,7 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) * @return The length of the apdu encoded or #BACNET_STATUS_ERROR or * #BACNET_STATUS_ABORT or #BACNET_STATUS_REJECT. */ -int Device_Add_List_Element( - BACNET_LIST_ELEMENT_DATA * list_element) +int Device_Add_List_Element(BACNET_LIST_ELEMENT_DATA *list_element) { int status = BACNET_STATUS_ERROR; struct object_functions *pObject = NULL; @@ -1698,8 +1721,7 @@ int Device_Add_List_Element( * @return The length of the apdu encoded or #BACNET_STATUS_ERROR or * #BACNET_STATUS_ABORT or #BACNET_STATUS_REJECT. */ -int Device_Remove_List_Element( - BACNET_LIST_ELEMENT_DATA * list_element) +int Device_Remove_List_Element(BACNET_LIST_ELEMENT_DATA *list_element) { int status = BACNET_STATUS_ERROR; struct object_functions *pObject = NULL; @@ -1805,8 +1827,7 @@ void Device_COV_Clear(BACNET_OBJECT_TYPE object_type, uint32_t object_instance) * @param data - CreateObject data, including error codes if failures * @return true if object has been created */ -bool Device_Create_Object( - BACNET_CREATE_OBJECT_DATA *data) +bool Device_Create_Object(BACNET_CREATE_OBJECT_DATA *data) { bool status = false; struct object_functions *pObject = NULL; @@ -1865,8 +1886,7 @@ bool Device_Create_Object( * @param data - DeleteObject data, including error codes if failures * @return true if object has been deleted */ -bool Device_Delete_Object( - BACNET_DELETE_OBJECT_DATA *data) +bool Device_Delete_Object(BACNET_DELETE_OBJECT_DATA *data) { bool status = false; struct object_functions *pObject = NULL; @@ -1997,8 +2017,7 @@ bool DeviceGetRRInfo(BACNET_READ_RANGE_DATA *pRequest, /* Info on the request */ * @brief Updates all the object timers with elapsed milliseconds * @param milliseconds - number of milliseconds elapsed */ -void Device_Timer( - uint16_t milliseconds) +void Device_Timer(uint16_t milliseconds) { struct object_functions *pObject; unsigned count = 0; diff --git a/apps/piface/device.c b/apps/piface/device.c index 29a9b7d6..d90db89b 100644 --- a/apps/piface/device.c +++ b/apps/piface/device.c @@ -67,8 +67,8 @@ static object_functions_t My_Object_Table[] = { Device_Property_Lists, DeviceGetRRInfo, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, - NULL /* Remove_List_Element */, - NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }, + NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, + NULL /* Timer */ }, #if (BACNET_PROTOCOL_REVISION >= 17) { OBJECT_NETWORK_PORT, Network_Port_Init, Network_Port_Count, Network_Port_Index_To_Instance, Network_Port_Valid_Instance, @@ -95,7 +95,7 @@ static object_functions_t My_Object_Table[] = { NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - Binary_Output_Create, Binary_Output_Delete, NULL /* Timer */}, + Binary_Output_Create, Binary_Output_Delete, NULL /* Timer */ }, { MAX_BACNET_OBJECT_TYPE, NULL /* Init */, NULL /* Count */, NULL /* Index_To_Instance */, NULL /* Valid_Instance */, NULL /* Object_Name */, NULL /* Read_Property */, @@ -103,7 +103,7 @@ static object_functions_t My_Object_Table[] = { NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - NULL /* Create */, NULL /* Delete */ , NULL /* Timer */} + NULL /* Create */, NULL /* Delete */, NULL /* Timer */ } }; /** Glue function to let the Device object, when called by a handler, @@ -296,6 +296,24 @@ static uint32_t Database_Revision = 0; static BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE; static const char *Reinit_Password = "raspberry"; +/** + * @brief Sets the ReinitializeDevice password + * + * The password shall be a null terminated C string of up to + * 20 ASCII characters for those devices that require the password. + * + * For those devices that do not require a password, set to NULL or + * point to a zero length C string (null terminated). + * + * @param the ReinitializeDevice password; can be NULL or empty string + */ +bool Device_Reinitialize_Password_Set(const char *password) +{ + Reinit_Password = password; + + return true; +} + /** Commands a Device re-initialization, to a given state. * The request's password must match for the operation to succeed. * This implementation provides a framework, but doesn't @@ -312,6 +330,7 @@ static const char *Reinit_Password = "raspberry"; bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) { bool status = false; + bool password_success = false; /* From 16.4.1.1.2 Password This optional parameter shall be a CharacterString of up to @@ -319,12 +338,21 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) protection, the service request shall be denied if the parameter is absent or if the password is incorrect. For those devices that do not require a password, this parameter shall be ignored.*/ - if (characterstring_length(&rd_data->password) > 20) { - rd_data->error_class = ERROR_CLASS_SERVICES; - rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; - } else if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) { - /* Note: you could use a mix of state and password to - accomplish multiple things before restarting */ + if (Reinit_Password && strlen(Reinit_Password) > 0) { + if (characterstring_length(&rd_data->password) > 20) { + rd_data->error_class = ERROR_CLASS_SERVICES; + rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; + } else if (characterstring_ansi_same( + &rd_data->password, Reinit_Password)) { + password_success = true; + } else { + rd_data->error_class = ERROR_CLASS_SECURITY; + rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE; + } + } else { + password_success = true; + } + if (password_success) { switch (rd_data->state) { case BACNET_REINIT_COLDSTART: case BACNET_REINIT_WARMSTART: @@ -1070,9 +1098,8 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata) case PROP_OBJECT_LIST: count = Device_Object_List_Count(); apdu_len = bacnet_array_encode(rpdata->object_instance, - rpdata->array_index, - Device_Object_List_Element_Encode, - count, apdu, apdu_max); + rpdata->array_index, Device_Object_List_Element_Encode, count, + apdu, apdu_max); if (apdu_len == BACNET_STATUS_ABORT) { rpdata->error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED; @@ -1230,7 +1257,7 @@ int Device_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata) } else { rpdata->error_class = ERROR_CLASS_OBJECT; rpdata->error_code = ERROR_CODE_UNKNOWN_OBJECT; - } + } } else { rpdata->error_class = ERROR_CLASS_OBJECT; rpdata->error_code = ERROR_CODE_UNKNOWN_OBJECT; @@ -1602,8 +1629,8 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) } #endif if (wp_data->object_property == PROP_OBJECT_NAME) { - status = Device_Write_Property_Object_Name(wp_data, - pObject->Object_Write_Property); + status = Device_Write_Property_Object_Name( + wp_data, pObject->Object_Write_Property); } else { status = pObject->Object_Write_Property(wp_data); } @@ -1630,8 +1657,7 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) * @return The length of the apdu encoded or #BACNET_STATUS_ERROR or * #BACNET_STATUS_ABORT or #BACNET_STATUS_REJECT. */ -int Device_Add_List_Element( - BACNET_LIST_ELEMENT_DATA * list_element) +int Device_Add_List_Element(BACNET_LIST_ELEMENT_DATA *list_element) { int status = BACNET_STATUS_ERROR; struct object_functions *pObject = NULL; @@ -1665,8 +1691,7 @@ int Device_Add_List_Element( * @return The length of the apdu encoded or #BACNET_STATUS_ERROR or * #BACNET_STATUS_ABORT or #BACNET_STATUS_REJECT. */ -int Device_Remove_List_Element( - BACNET_LIST_ELEMENT_DATA * list_element) +int Device_Remove_List_Element(BACNET_LIST_ELEMENT_DATA *list_element) { int status = BACNET_STATUS_ERROR; struct object_functions *pObject = NULL; @@ -1772,8 +1797,7 @@ void Device_COV_Clear(BACNET_OBJECT_TYPE object_type, uint32_t object_instance) * @param data - CreateObject data, including error codes if failures * @return true if object has been created */ -bool Device_Create_Object( - BACNET_CREATE_OBJECT_DATA *data) +bool Device_Create_Object(BACNET_CREATE_OBJECT_DATA *data) { bool status = false; struct object_functions *pObject = NULL; @@ -1832,8 +1856,7 @@ bool Device_Create_Object( * @param data - DeleteObject data, including error codes if failures * @return true if object has been deleted */ -bool Device_Delete_Object( - BACNET_DELETE_OBJECT_DATA *data) +bool Device_Delete_Object(BACNET_DELETE_OBJECT_DATA *data) { bool status = false; struct object_functions *pObject = NULL; diff --git a/ports/at91sam7s/device.c b/ports/at91sam7s/device.c index 4020b021..d218a1f8 100644 --- a/ports/at91sam7s/device.c +++ b/ports/at91sam7s/device.c @@ -67,12 +67,11 @@ static struct my_object_functions { read_property_function Object_Read_Property; write_property_function Object_Write_Property; rpm_property_lists_function Object_RPM_List; -} Object_Table[] = { - { OBJECT_DEVICE, NULL, /* don't init - recursive! */ - Device_Count, Device_Index_To_Instance, - Device_Valid_Object_Instance_Number, - Device_Object_Name, Device_Read_Property_Local, - Device_Write_Property_Local, Device_Property_Lists }, +} Object_Table[] = { { OBJECT_DEVICE, NULL, /* don't init - recursive! */ + Device_Count, Device_Index_To_Instance, + Device_Valid_Object_Instance_Number, + Device_Object_Name, Device_Read_Property_Local, + Device_Write_Property_Local, Device_Property_Lists }, { OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count, Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance, Analog_Input_Object_Name, Analog_Input_Read_Property, NULL, @@ -159,8 +158,7 @@ static int Read_Property_Common( } apdu = rpdata->application_data; if (property_list_common(rpdata->object_property)) { - apdu_len = property_list_common_encode(rpdata, - Object_Instance_Number); + apdu_len = property_list_common_encode(rpdata, Object_Instance_Number); } else if (rpdata->object_property == PROP_OBJECT_NAME) { /* only array properties can have array options */ if (rpdata->array_index != BACNET_ARRAY_ALL) { @@ -180,9 +178,8 @@ static int Read_Property_Common( } else if (rpdata->object_property == PROP_PROPERTY_LIST) { Device_Objects_Property_List( rpdata->object_type, rpdata->object_instance, &property_list); - apdu_len = property_list_encode(rpdata, - property_list.Required.pList, property_list.Optional.pList, - property_list.Proprietary.pList); + apdu_len = property_list_encode(rpdata, property_list.Required.pList, + property_list.Optional.pList, property_list.Proprietary.pList); #endif } else if (pObject->Object_Read_Property) { apdu_len = pObject->Object_Read_Property(rpdata); @@ -332,12 +329,64 @@ bool Device_Set_Object_Name(BACNET_CHARACTER_STRING *object_name) return status; } +/** + * @brief Sets the ReinitializeDevice password + * + * The password shall be a null terminated C string of up to + * 20 ASCII characters for those devices that require the password. + * + * For those devices that do not require a password, set to NULL or + * point to a zero length C string (null terminated). + * + * @param the ReinitializeDevice password; can be NULL or empty string + */ +bool Device_Reinitialize_Password_Set(const char *password) +{ + Reinit_Password = password; + + return true; +} + +/** + * @brief Commands a Device re-initialization, to a given state. + * The request's password must match for the operation to succeed. + * This implementation provides a framework, but doesn't + * actually *DO* anything. + * @note You could use a mix of states and passwords to multiple outcomes. + * @note You probably want to restart *after* the simple ack has been sent + * from the return handler, so just set a local flag here. + * @ingroup ObjIntf + * + * @param rd_data [in,out] The information from the RD request. + * On failure, the error class and code will be set. + * @return True if succeeds (password is correct), else False. + */ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) { bool status = false; + bool password_success = false; - /* Note: you could use a mix of state and password to multiple things */ - if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) { + /* From 16.4.1.1.2 Password + This optional parameter shall be a CharacterString of up to + 20 characters. For those devices that require the password as a + protection, the service request shall be denied if the parameter + is absent or if the password is incorrect. For those devices that + do not require a password, this parameter shall be ignored.*/ + if (Reinit_Password && strlen(Reinit_Password) > 0) { + if (characterstring_length(&rd_data->password) > 20) { + rd_data->error_class = ERROR_CLASS_SERVICES; + rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; + } else if (characterstring_ansi_same( + &rd_data->password, Reinit_Password)) { + password_success = true; + } else { + rd_data->error_class = ERROR_CLASS_SECURITY; + rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE; + } + } else { + password_success = true; + } + if (password_success) { switch (rd_data->state) { case BACNET_REINIT_COLDSTART: case BACNET_REINIT_WARMSTART: @@ -367,9 +416,6 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; break; } - } else { - rd_data->error_class = ERROR_CLASS_SECURITY; - rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE; } return status; @@ -705,9 +751,8 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata) case PROP_OBJECT_LIST: count = Device_Object_List_Count(); apdu_len = bacnet_array_encode(rpdata->object_instance, - rpdata->array_index, - Device_Object_List_Element_Encode, - count, apdu, apdu_max); + rpdata->array_index, Device_Object_List_Element_Encode, count, + apdu, apdu_max); if (apdu_len == BACNET_STATUS_ABORT) { rpdata->error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED; @@ -745,8 +790,7 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata) encode_application_unsigned(&apdu[0], dlmstp_max_master()); break; case 9600: - apdu_len = - encode_application_unsigned(&apdu[0], rs485_baud_rate()); + apdu_len = encode_application_unsigned(&apdu[0], rs485_baud_rate()); break; default: rpdata->error_class = ERROR_CLASS_PROPERTY; diff --git a/ports/bdk-atxx4-mstp/device.c b/ports/bdk-atxx4-mstp/device.c index 22933dba..04e16e94 100644 --- a/ports/bdk-atxx4-mstp/device.c +++ b/ports/bdk-atxx4-mstp/device.c @@ -67,12 +67,11 @@ static struct my_object_functions { read_property_function Object_Read_Property; write_property_function Object_Write_Property; rpm_property_lists_function Object_RPM_List; -} Object_Table[] = { - { OBJECT_DEVICE, NULL, /* don't init - recursive! */ - Device_Count, Device_Index_To_Instance, - Device_Valid_Object_Instance_Number, - Device_Object_Name, Device_Read_Property_Local, - Device_Write_Property_Local, Device_Property_Lists }, +} Object_Table[] = { { OBJECT_DEVICE, NULL, /* don't init - recursive! */ + Device_Count, Device_Index_To_Instance, + Device_Valid_Object_Instance_Number, + Device_Object_Name, Device_Read_Property_Local, + Device_Write_Property_Local, Device_Property_Lists }, { OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count, Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance, Analog_Input_Object_Name, Analog_Input_Read_Property, NULL, @@ -161,8 +160,7 @@ int Device_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata) #if (BACNET_PROTOCOL_REVISION >= 14) if ((int)rpdata->object_property == PROP_PROPERTY_LIST) { Device_Objects_Property_List(rpdata->object_type, - rpdata->object_instance, - &property_list); + rpdata->object_instance, &property_list); apdu_len = property_list_encode(rpdata, property_list.Required.pList, property_list.Optional.pList, @@ -306,12 +304,64 @@ bool Device_Object_Name( return status; } +/** + * @brief Sets the ReinitializeDevice password + * + * The password shall be a null terminated C string of up to + * 20 ASCII characters for those devices that require the password. + * + * For those devices that do not require a password, set to NULL or + * point to a zero length C string (null terminated). + * + * @param the ReinitializeDevice password; can be NULL or empty string + */ +bool Device_Reinitialize_Password_Set(const char *password) +{ + Reinit_Password = password; + + return true; +} + +/** + * @brief Commands a Device re-initialization, to a given state. + * The request's password must match for the operation to succeed. + * This implementation provides a framework, but doesn't + * actually *DO* anything. + * @note You could use a mix of states and passwords to multiple outcomes. + * @note You probably want to restart *after* the simple ack has been sent + * from the return handler, so just set a local flag here. + * @ingroup ObjIntf + * + * @param rd_data [in,out] The information from the RD request. + * On failure, the error class and code will be set. + * @return True if succeeds (password is correct), else False. + */ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) { bool status = false; + bool password_success = false; - /* Note: you could use a mix of state and password to multiple things */ - if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) { + /* From 16.4.1.1.2 Password + This optional parameter shall be a CharacterString of up to + 20 characters. For those devices that require the password as a + protection, the service request shall be denied if the parameter + is absent or if the password is incorrect. For those devices that + do not require a password, this parameter shall be ignored.*/ + if (Reinit_Password && strlen(Reinit_Password) > 0) { + if (characterstring_length(&rd_data->password) > 20) { + rd_data->error_class = ERROR_CLASS_SERVICES; + rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; + } else if (characterstring_ansi_same( + &rd_data->password, Reinit_Password)) { + password_success = true; + } else { + rd_data->error_class = ERROR_CLASS_SECURITY; + rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE; + } + } else { + password_success = true; + } + if (password_success) { switch (rd_data->state) { case BACNET_REINIT_COLDSTART: case BACNET_REINIT_WARMSTART: @@ -341,9 +391,6 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; break; } - } else { - rd_data->error_class = ERROR_CLASS_SECURITY; - rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE; } return status; @@ -695,9 +742,8 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata) case PROP_OBJECT_LIST: count = Device_Object_List_Count(); apdu_len = bacnet_array_encode(rpdata->object_instance, - rpdata->array_index, - Device_Object_List_Element_Encode, - count, apdu, apdu_max); + rpdata->array_index, Device_Object_List_Element_Encode, count, + apdu, apdu_max); if (apdu_len == BACNET_STATUS_ABORT) { rpdata->error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED; diff --git a/ports/pic18f6720/device.c b/ports/pic18f6720/device.c index 263b19af..19829774 100644 --- a/ports/pic18f6720/device.c +++ b/ports/pic18f6720/device.c @@ -52,14 +52,65 @@ static uint32_t Object_Instance_Number = 12345; static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL; static uint8_t Database_Revision; BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE; -static char Reinit_Password[16] = "filister"; +static const char *Reinit_Password = "filister"; +/** + * @brief Sets the ReinitializeDevice password + * + * The password shall be a null terminated C string of up to + * 20 ASCII characters for those devices that require the password. + * + * For those devices that do not require a password, set to NULL or + * point to a zero length C string (null terminated). + * + * @param the ReinitializeDevice password; can be NULL or empty string + */ +bool Device_Reinitialize_Password_Set(const char *password) +{ + Reinit_Password = password; + + return true; +} + +/** Commands a Device re-initialization, to a given state. + * The request's password must match for the operation to succeed. + * This implementation provides a framework, but doesn't + * actually *DO* anything. + * @note You could use a mix of states and passwords to multiple outcomes. + * @note You probably want to restart *after* the simple ack has been sent + * from the return handler, so just set a local flag here. + * @ingroup ObjIntf + * + * @param rd_data [in,out] The information from the RD request. + * On failure, the error class and code will be set. + * @return True if succeeds (password is correct), else False. + */ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) { bool status = false; + bool password_success = false; - /* Note: you could use a mix of state and password to multiple things */ - if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) { + /* From 16.4.1.1.2 Password + This optional parameter shall be a CharacterString of up to + 20 characters. For those devices that require the password as a + protection, the service request shall be denied if the parameter + is absent or if the password is incorrect. For those devices that + do not require a password, this parameter shall be ignored.*/ + if (Reinit_Password && strlen(Reinit_Password) > 0) { + if (characterstring_length(&rd_data->password) > 20) { + rd_data->error_class = ERROR_CLASS_SERVICES; + rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; + } else if (characterstring_ansi_same( + &rd_data->password, Reinit_Password)) { + password_success = true; + } else { + rd_data->error_class = ERROR_CLASS_SECURITY; + rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE; + } + } else { + password_success = true; + } + if (password_success) { switch (rd_data->state) { case BACNET_REINIT_COLDSTART: case BACNET_REINIT_WARMSTART: @@ -89,9 +140,6 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; break; } - } else { - rd_data->error_class = ERROR_CLASS_SECURITY; - rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE; } return status; diff --git a/ports/rx62n/device.c b/ports/rx62n/device.c index d1a1511c..cee884e7 100644 --- a/ports/rx62n/device.c +++ b/ports/rx62n/device.c @@ -271,12 +271,64 @@ uint32_t Device_Index_To_Instance(unsigned index) return Object_Instance_Number; } +/** + * @brief Sets the ReinitializeDevice password + * + * The password shall be a null terminated C string of up to + * 20 ASCII characters for those devices that require the password. + * + * For those devices that do not require a password, set to NULL or + * point to a zero length C string (null terminated). + * + * @param the ReinitializeDevice password; can be NULL or empty string + */ +bool Device_Reinitialize_Password_Set(const char *password) +{ + Reinit_Password = password; + + return true; +} + +/** + * @brief Commands a Device re-initialization, to a given state. + * The request's password must match for the operation to succeed. + * This implementation provides a framework, but doesn't + * actually *DO* anything. + * @note You could use a mix of states and passwords to multiple outcomes. + * @note You probably want to restart *after* the simple ack has been sent + * from the return handler, so just set a local flag here. + * @ingroup ObjIntf + * + * @param rd_data [in,out] The information from the RD request. + * On failure, the error class and code will be set. + * @return True if succeeds (password is correct), else False. + */ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) { bool status = false; + bool password_success = false; - /* Note: you could use a mix of state and password to multiple things */ - if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) { + /* From 16.4.1.1.2 Password + This optional parameter shall be a CharacterString of up to + 20 characters. For those devices that require the password as a + protection, the service request shall be denied if the parameter + is absent or if the password is incorrect. For those devices that + do not require a password, this parameter shall be ignored.*/ + if (Reinit_Password && strlen(Reinit_Password) > 0) { + if (characterstring_length(&rd_data->password) > 20) { + rd_data->error_class = ERROR_CLASS_SERVICES; + rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; + } else if (characterstring_ansi_same( + &rd_data->password, Reinit_Password)) { + password_success = true; + } else { + rd_data->error_class = ERROR_CLASS_SECURITY; + rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE; + } + } else { + password_success = true; + } + if (password_success) { switch (rd_data->state) { case BACNET_REINIT_COLDSTART: case BACNET_REINIT_WARMSTART: @@ -306,9 +358,6 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; break; } - } else { - rd_data->error_class = ERROR_CLASS_SECURITY; - rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE; } return status; diff --git a/ports/stm32f10x/device.c b/ports/stm32f10x/device.c index 30cb8a39..d1e41c14 100644 --- a/ports/stm32f10x/device.c +++ b/ports/stm32f10x/device.c @@ -342,12 +342,64 @@ bool Device_Set_Object_Name(BACNET_CHARACTER_STRING *object_name) return status; } +/** + * @brief Sets the ReinitializeDevice password + * + * The password shall be a null terminated C string of up to + * 20 ASCII characters for those devices that require the password. + * + * For those devices that do not require a password, set to NULL or + * point to a zero length C string (null terminated). + * + * @param the ReinitializeDevice password; can be NULL or empty string + */ +bool Device_Reinitialize_Password_Set(const char *password) +{ + Reinit_Password = password; + + return true; +} + +/** + * @brief Commands a Device re-initialization, to a given state. + * The request's password must match for the operation to succeed. + * This implementation provides a framework, but doesn't + * actually *DO* anything. + * @note You could use a mix of states and passwords to multiple outcomes. + * @note You probably want to restart *after* the simple ack has been sent + * from the return handler, so just set a local flag here. + * @ingroup ObjIntf + * + * @param rd_data [in,out] The information from the RD request. + * On failure, the error class and code will be set. + * @return True if succeeds (password is correct), else False. + */ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) { bool status = false; + bool password_success = false; - /* Note: you could use a mix of state and password to multiple things */ - if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) { + /* From 16.4.1.1.2 Password + This optional parameter shall be a CharacterString of up to + 20 characters. For those devices that require the password as a + protection, the service request shall be denied if the parameter + is absent or if the password is incorrect. For those devices that + do not require a password, this parameter shall be ignored.*/ + if (Reinit_Password && strlen(Reinit_Password) > 0) { + if (characterstring_length(&rd_data->password) > 20) { + rd_data->error_class = ERROR_CLASS_SERVICES; + rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; + } else if (characterstring_ansi_same( + &rd_data->password, Reinit_Password)) { + password_success = true; + } else { + rd_data->error_class = ERROR_CLASS_SECURITY; + rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE; + } + } else { + password_success = true; + } + if (password_success) { switch (rd_data->state) { case BACNET_REINIT_COLDSTART: case BACNET_REINIT_WARMSTART: @@ -379,9 +431,6 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; break; } - } else { - rd_data->error_class = ERROR_CLASS_SECURITY; - rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE; } return status; diff --git a/ports/stm32f4xx/device.c b/ports/stm32f4xx/device.c index 3276a98d..59e52ac6 100644 --- a/ports/stm32f4xx/device.c +++ b/ports/stm32f4xx/device.c @@ -336,12 +336,64 @@ bool Device_Set_Object_Name(BACNET_CHARACTER_STRING *object_name) return status; } +/** + * @brief Sets the ReinitializeDevice password + * + * The password shall be a null terminated C string of up to + * 20 ASCII characters for those devices that require the password. + * + * For those devices that do not require a password, set to NULL or + * point to a zero length C string (null terminated). + * + * @param the ReinitializeDevice password; can be NULL or empty string + */ +bool Device_Reinitialize_Password_Set(const char *password) +{ + Reinit_Password = password; + + return true; +} + +/** + * @brief Commands a Device re-initialization, to a given state. + * The request's password must match for the operation to succeed. + * This implementation provides a framework, but doesn't + * actually *DO* anything. + * @note You could use a mix of states and passwords to multiple outcomes. + * @note You probably want to restart *after* the simple ack has been sent + * from the return handler, so just set a local flag here. + * @ingroup ObjIntf + * + * @param rd_data [in,out] The information from the RD request. + * On failure, the error class and code will be set. + * @return True if succeeds (password is correct), else False. + */ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) { bool status = false; + bool password_success = false; - /* Note: you could use a mix of state and password to multiple things */ - if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) { + /* From 16.4.1.1.2 Password + This optional parameter shall be a CharacterString of up to + 20 characters. For those devices that require the password as a + protection, the service request shall be denied if the parameter + is absent or if the password is incorrect. For those devices that + do not require a password, this parameter shall be ignored.*/ + if (Reinit_Password && strlen(Reinit_Password) > 0) { + if (characterstring_length(&rd_data->password) > 20) { + rd_data->error_class = ERROR_CLASS_SERVICES; + rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; + } else if (characterstring_ansi_same( + &rd_data->password, Reinit_Password)) { + password_success = true; + } else { + rd_data->error_class = ERROR_CLASS_SECURITY; + rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE; + } + } else { + password_success = true; + } + if (password_success) { switch (rd_data->state) { case BACNET_REINIT_COLDSTART: case BACNET_REINIT_WARMSTART: @@ -373,9 +425,6 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; break; } - } else { - rd_data->error_class = ERROR_CLASS_SECURITY; - rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE; } return status; diff --git a/src/bacnet/basic/object/device.c b/src/bacnet/basic/object/device.c index 39b361b2..b1ccdf65 100644 --- a/src/bacnet/basic/object/device.c +++ b/src/bacnet/basic/object/device.c @@ -98,8 +98,8 @@ static object_functions_t My_Object_Table[] = { Device_Property_Lists, DeviceGetRRInfo, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, - NULL /* Remove_List_Element */, - NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }, + NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, + NULL /* Timer */ }, #if (BACNET_PROTOCOL_REVISION >= 17) { OBJECT_NETWORK_PORT, Network_Port_Init, Network_Port_Count, Network_Port_Index_To_Instance, Network_Port_Valid_Instance, @@ -108,7 +108,7 @@ static object_functions_t My_Object_Table[] = { NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - NULL /* Create */, NULL /* Delete */ , NULL /* Timer */}, + NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }, #endif { OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count, Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance, @@ -118,7 +118,7 @@ static object_functions_t My_Object_Table[] = { Analog_Input_Encode_Value_List, Analog_Input_Change_Of_Value, Analog_Input_Change_Of_Value_Clear, Analog_Input_Intrinsic_Reporting, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - NULL /* Create */, NULL /* Delete */ , NULL /* Timer */}, + NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }, { OBJECT_ANALOG_OUTPUT, Analog_Output_Init, Analog_Output_Count, Analog_Output_Index_To_Instance, Analog_Output_Valid_Instance, Analog_Output_Object_Name, Analog_Output_Read_Property, @@ -126,7 +126,7 @@ static object_functions_t My_Object_Table[] = { NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - Analog_Output_Create, Analog_Output_Delete, NULL /* Timer */}, + Analog_Output_Create, Analog_Output_Delete, NULL /* Timer */ }, { OBJECT_ANALOG_VALUE, Analog_Value_Init, Analog_Value_Count, Analog_Value_Index_To_Instance, Analog_Value_Valid_Instance, Analog_Value_Object_Name, Analog_Value_Read_Property, @@ -152,7 +152,7 @@ static object_functions_t My_Object_Table[] = { NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - Binary_Output_Create, Binary_Output_Delete, NULL /* Timer */}, + Binary_Output_Create, Binary_Output_Delete, NULL /* Timer */ }, { OBJECT_BINARY_VALUE, Binary_Value_Init, Binary_Value_Count, Binary_Value_Index_To_Instance, Binary_Value_Valid_Instance, Binary_Value_Object_Name, Binary_Value_Read_Property, @@ -171,8 +171,8 @@ static object_functions_t My_Object_Table[] = { CharacterString_Value_Change_Of_Value, CharacterString_Value_Change_Of_Value_Clear, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, - NULL /* Remove_List_Element */, - NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }, + NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, + NULL /* Timer */ }, { OBJECT_COMMAND, Command_Init, Command_Count, Command_Index_To_Instance, Command_Valid_Instance, Command_Object_Name, Command_Read_Property, Command_Write_Property, Command_Property_Lists, @@ -197,8 +197,8 @@ static object_functions_t My_Object_Table[] = { NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, Notification_Class_Add_List_Element, - Notification_Class_Remove_List_Element, - NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }, + Notification_Class_Remove_List_Element, NULL /* Create */, + NULL /* Delete */, NULL /* Timer */ }, #endif { OBJECT_LIFE_SAFETY_POINT, Life_Safety_Point_Init, Life_Safety_Point_Count, Life_Safety_Point_Index_To_Instance, Life_Safety_Point_Valid_Instance, @@ -207,7 +207,7 @@ static object_functions_t My_Object_Table[] = { NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - NULL /* Create */, NULL /* Delete */ , NULL /* Timer */}, + NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }, { OBJECT_LOAD_CONTROL, Load_Control_Init, Load_Control_Count, Load_Control_Index_To_Instance, Load_Control_Valid_Instance, Load_Control_Object_Name, Load_Control_Read_Property, @@ -215,7 +215,7 @@ static object_functions_t My_Object_Table[] = { NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - NULL /* Create */, NULL /* Delete */ , NULL /* Timer */}, + NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }, { OBJECT_MULTI_STATE_INPUT, Multistate_Input_Init, Multistate_Input_Count, Multistate_Input_Index_To_Instance, Multistate_Input_Valid_Instance, Multistate_Input_Object_Name, Multistate_Input_Read_Property, @@ -223,7 +223,7 @@ static object_functions_t My_Object_Table[] = { NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - NULL /* Create */, NULL /* Delete */ , NULL /* Timer */}, + NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }, { OBJECT_MULTI_STATE_OUTPUT, Multistate_Output_Init, Multistate_Output_Count, Multistate_Output_Index_To_Instance, Multistate_Output_Valid_Instance, Multistate_Output_Object_Name, @@ -232,7 +232,7 @@ static object_functions_t My_Object_Table[] = { NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - Multistate_Output_Create, Multistate_Output_Delete, NULL /* Timer */}, + Multistate_Output_Create, Multistate_Output_Delete, NULL /* Timer */ }, { OBJECT_MULTI_STATE_VALUE, Multistate_Value_Init, Multistate_Value_Count, Multistate_Value_Index_To_Instance, Multistate_Value_Valid_Instance, Multistate_Value_Object_Name, Multistate_Value_Read_Property, @@ -241,7 +241,7 @@ static object_functions_t My_Object_Table[] = { Multistate_Value_Encode_Value_List, Multistate_Value_Change_Of_Value, Multistate_Value_Change_Of_Value_Clear, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - NULL /* Create */, NULL /* Delete */ , NULL /* Timer */}, + NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }, { OBJECT_TRENDLOG, Trend_Log_Init, Trend_Log_Count, Trend_Log_Index_To_Instance, Trend_Log_Valid_Instance, Trend_Log_Object_Name, Trend_Log_Read_Property, @@ -249,7 +249,7 @@ static object_functions_t My_Object_Table[] = { NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - NULL /* Create */, NULL /* Delete */ , NULL /* Timer */}, + NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }, #if (BACNET_PROTOCOL_REVISION >= 14) { OBJECT_LIGHTING_OUTPUT, Lighting_Output_Init, Lighting_Output_Count, Lighting_Output_Index_To_Instance, Lighting_Output_Valid_Instance, @@ -258,7 +258,7 @@ static object_functions_t My_Object_Table[] = { NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - Lighting_Output_Create, Lighting_Output_Delete, Lighting_Output_Timer}, + Lighting_Output_Create, Lighting_Output_Delete, Lighting_Output_Timer }, { OBJECT_CHANNEL, Channel_Init, Channel_Count, Channel_Index_To_Instance, Channel_Valid_Instance, Channel_Object_Name, Channel_Read_Property, Channel_Write_Property, Channel_Property_Lists, @@ -274,7 +274,7 @@ static object_functions_t My_Object_Table[] = { NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - Color_Create, Color_Delete, Color_Timer}, + Color_Create, Color_Delete, Color_Timer }, { OBJECT_COLOR_TEMPERATURE, Color_Temperature_Init, Color_Temperature_Count, Color_Temperature_Index_To_Instance, Color_Temperature_Valid_Instance, Color_Temperature_Object_Name, Color_Temperature_Read_Property, @@ -283,7 +283,7 @@ static object_functions_t My_Object_Table[] = { NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, Color_Temperature_Create, Color_Temperature_Delete, - Color_Temperature_Timer}, + Color_Temperature_Timer }, #endif #if defined(BACFILE) { OBJECT_FILE, bacfile_init, bacfile_count, bacfile_index_to_instance, @@ -292,7 +292,7 @@ static object_functions_t My_Object_Table[] = { NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - bacfile_create, bacfile_delete, NULL /* Timer */}, + bacfile_create, bacfile_delete, NULL /* Timer */ }, #endif { OBJECT_OCTETSTRING_VALUE, OctetString_Value_Init, OctetString_Value_Count, OctetString_Value_Index_To_Instance, OctetString_Value_Valid_Instance, @@ -318,8 +318,8 @@ static object_functions_t My_Object_Table[] = { Schedule_Property_Lists, NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, - NULL /* Remove_List_Element */, - NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }, + NULL /* Remove_List_Element */, NULL /* Create */, NULL /* Delete */, + NULL /* Timer */ }, { OBJECT_ACCUMULATOR, Accumulator_Init, Accumulator_Count, Accumulator_Index_To_Instance, Accumulator_Valid_Instance, Accumulator_Object_Name, Accumulator_Read_Property, @@ -327,7 +327,7 @@ static object_functions_t My_Object_Table[] = { NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */, NULL /* Add_List_Element */, NULL /* Remove_List_Element */, - NULL /* Create */, NULL /* Delete */ , NULL /* Timer */}, + NULL /* Create */, NULL /* Delete */, NULL /* Timer */ }, { MAX_BACNET_OBJECT_TYPE, NULL /* Init */, NULL /* Count */, NULL /* Index_To_Instance */, NULL /* Valid_Instance */, NULL /* Object_Name */, NULL /* Read_Property */, @@ -528,6 +528,24 @@ static uint32_t Database_Revision = 0; static BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE; static const char *Reinit_Password = "filister"; +/** + * @brief Sets the ReinitializeDevice password + * + * The password shall be a null terminated C string of up to + * 20 ASCII characters for those devices that require the password. + * + * For those devices that do not require a password, set to NULL or + * point to a zero length C string (null terminated). + * + * @param the ReinitializeDevice password; can be NULL or empty string + */ +bool Device_Reinitialize_Password_Set(const char *password) +{ + Reinit_Password = password; + + return true; +} + /** Commands a Device re-initialization, to a given state. * The request's password must match for the operation to succeed. * This implementation provides a framework, but doesn't @@ -544,6 +562,7 @@ static const char *Reinit_Password = "filister"; bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) { bool status = false; + bool password_success = false; /* From 16.4.1.1.2 Password This optional parameter shall be a CharacterString of up to @@ -551,12 +570,21 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) protection, the service request shall be denied if the parameter is absent or if the password is incorrect. For those devices that do not require a password, this parameter shall be ignored.*/ - if (characterstring_length(&rd_data->password) > 20) { - rd_data->error_class = ERROR_CLASS_SERVICES; - rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; - } else if (characterstring_ansi_same(&rd_data->password, Reinit_Password)) { - /* Note: you could use a mix of state and password to - accomplish multiple things before restarting */ + if (Reinit_Password && strlen(Reinit_Password) > 0) { + if (characterstring_length(&rd_data->password) > 20) { + rd_data->error_class = ERROR_CLASS_SERVICES; + rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; + } else if (characterstring_ansi_same( + &rd_data->password, Reinit_Password)) { + password_success = true; + } else { + rd_data->error_class = ERROR_CLASS_SECURITY; + rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE; + } + } else { + password_success = true; + } + if (password_success) { switch (rd_data->state) { case BACNET_REINIT_COLDSTART: case BACNET_REINIT_WARMSTART: @@ -586,9 +614,6 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data) rd_data->error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE; break; } - } else { - rd_data->error_class = ERROR_CLASS_SECURITY; - rd_data->error_code = ERROR_CODE_PASSWORD_FAILURE; } return status; @@ -1306,9 +1331,8 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata) case PROP_OBJECT_LIST: count = Device_Object_List_Count(); apdu_len = bacnet_array_encode(rpdata->object_instance, - rpdata->array_index, - Device_Object_List_Element_Encode, - count, apdu, apdu_max); + rpdata->array_index, Device_Object_List_Element_Encode, count, + apdu, apdu_max); if (apdu_len == BACNET_STATUS_ABORT) { rpdata->error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED; @@ -1838,8 +1862,8 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) } #endif if (wp_data->object_property == PROP_OBJECT_NAME) { - status = Device_Write_Property_Object_Name(wp_data, - pObject->Object_Write_Property); + status = Device_Write_Property_Object_Name( + wp_data, pObject->Object_Write_Property); } else { status = pObject->Object_Write_Property(wp_data); } @@ -1866,8 +1890,7 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) * @return The length of the apdu encoded or #BACNET_STATUS_ERROR or * #BACNET_STATUS_ABORT or #BACNET_STATUS_REJECT. */ -int Device_Add_List_Element( - BACNET_LIST_ELEMENT_DATA * list_element) +int Device_Add_List_Element(BACNET_LIST_ELEMENT_DATA *list_element) { int status = BACNET_STATUS_ERROR; struct object_functions *pObject = NULL; @@ -1901,8 +1924,7 @@ int Device_Add_List_Element( * @return The length of the apdu encoded or #BACNET_STATUS_ERROR or * #BACNET_STATUS_ABORT or #BACNET_STATUS_REJECT. */ -int Device_Remove_List_Element( - BACNET_LIST_ELEMENT_DATA * list_element) +int Device_Remove_List_Element(BACNET_LIST_ELEMENT_DATA *list_element) { int status = BACNET_STATUS_ERROR; struct object_functions *pObject = NULL; @@ -2008,8 +2030,7 @@ void Device_COV_Clear(BACNET_OBJECT_TYPE object_type, uint32_t object_instance) * @param data - CreateObject data, including error codes if failures * @return true if object has been created */ -bool Device_Create_Object( - BACNET_CREATE_OBJECT_DATA *data) +bool Device_Create_Object(BACNET_CREATE_OBJECT_DATA *data) { bool status = false; struct object_functions *pObject = NULL; @@ -2068,8 +2089,7 @@ bool Device_Create_Object( * @param data - DeleteObject data, including error codes if failures * @return true if object has been deleted */ -bool Device_Delete_Object( - BACNET_DELETE_OBJECT_DATA *data) +bool Device_Delete_Object(BACNET_DELETE_OBJECT_DATA *data) { bool status = false; struct object_functions *pObject = NULL; @@ -2236,8 +2256,7 @@ bool DeviceGetRRInfo(BACNET_READ_RANGE_DATA *pRequest, /* Info on the request */ * @brief Updates all the object timers with elapsed milliseconds * @param milliseconds - number of milliseconds elapsed */ -void Device_Timer( - uint16_t milliseconds) +void Device_Timer(uint16_t milliseconds) { struct object_functions *pObject; unsigned count = 0; diff --git a/src/bacnet/basic/object/device.h b/src/bacnet/basic/object/device.h index 58ba15c7..6e07896b 100644 --- a/src/bacnet/basic/object/device.h +++ b/src/bacnet/basic/object/device.h @@ -254,6 +254,9 @@ extern "C" { BACNET_STACK_EXPORT BACNET_REINITIALIZED_STATE Device_Reinitialized_State( void); + BACNET_STACK_EXPORT + bool Device_Reinitialize_Password_Set( + const char *password); BACNET_STACK_EXPORT rr_info_function Device_Objects_RR_Info( diff --git a/src/bacnet/basic/service/h_dcc.c b/src/bacnet/basic/service/h_dcc.c index ba0e9152..57cd508f 100644 --- a/src/bacnet/basic/service/h_dcc.c +++ b/src/bacnet/basic/service/h_dcc.c @@ -173,8 +173,8 @@ void handler_device_communication_control(uint8_t *service_request, if (len > 0) goto DCC_ABORT; #endif - - if (characterstring_ansi_same(&password, My_Password)) { + if ((My_Password[0] == '\0') || + characterstring_ansi_same(&password, My_Password)) { len = encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL); diff --git a/test/bacnet/basic/object/device/src/main.c b/test/bacnet/basic/object/device/src/main.c index 332f0215..769df022 100644 --- a/test/bacnet/basic/object/device/src/main.c +++ b/test/bacnet/basic/object/device/src/main.c @@ -41,15 +41,16 @@ static void test_Device_Data_Sharing(void) rpdata.application_data = &apdu[0]; rpdata.application_data_len = sizeof(apdu); rpdata.object_type = OBJECT_DEVICE; - rpdata.object_instance = Device_Index_To_Instance(0);; + rpdata.object_instance = Device_Index_To_Instance(0); + ; Device_Property_Lists(&pRequired, &pOptional, &pProprietary); while ((*pRequired) != -1) { rpdata.object_property = *pRequired; rpdata.array_index = BACNET_ARRAY_ALL; len = Device_Read_Property(&rpdata); - zassert_not_equal(len, BACNET_STATUS_ERROR, + zassert_not_equal(len, BACNET_STATUS_ERROR, "property '%s': failed to ReadProperty!\n", - bactext_property_name(rpdata.object_property)); + bactext_property_name(rpdata.object_property)); if (len > 0) { test_len = bacapp_decode_application_data(rpdata.application_data, (uint8_t)rpdata.application_data_len, &value); @@ -83,9 +84,9 @@ static void test_Device_Data_Sharing(void) rpdata.object_property = *pOptional; rpdata.array_index = BACNET_ARRAY_ALL; len = Device_Read_Property(&rpdata); - zassert_not_equal(len, BACNET_STATUS_ERROR, + zassert_not_equal(len, BACNET_STATUS_ERROR, "property '%s': failed to ReadProperty!\n", - bactext_property_name(rpdata.object_property)); + bactext_property_name(rpdata.object_property)); if (len > 0) { test_len = bacapp_decode_application_data(rpdata.application_data, (uint8_t)rpdata.application_data_len, &value); @@ -127,6 +128,7 @@ static void testDevice(void) { bool status = false; const char *name = "Patricia"; + BACNET_REINITIALIZE_DEVICE_DATA rd_data; status = Device_Set_Object_Instance_Number(0); zassert_equal(Device_Object_Instance_Number(), 0, NULL); @@ -151,22 +153,74 @@ static void testDevice(void) Device_Set_Model_Name(name, strlen(name)); zassert_equal(strcmp(Device_Model_Name(), name), 0, NULL); + /* Reinitialize with no device password */ + rd_data.error_class = ERROR_CLASS_DEVICE; + rd_data.error_code = ERROR_CODE_SUCCESS; + rd_data.state = BACNET_REINIT_COLDSTART; + characterstring_init_ansi(&rd_data.password, NULL); + status = Device_Reinitialize_Password_Set(NULL); + status = Device_Reinitialize(&rd_data); + zassert_true(status, NULL); + zassert_equal(rd_data.error_class, ERROR_CLASS_DEVICE, "error-class=%s", + bactext_error_class_name(rd_data.error_class)); + zassert_equal(rd_data.error_code, ERROR_CODE_SUCCESS, "error-code=%s", + bactext_error_code_name(rd_data.error_code)); + /* Reinitialize with device valid password, service no password */ + status = Device_Reinitialize_Password_Set("valid"); + zassert_true(status, NULL); + status = characterstring_init_ansi(&rd_data.password, NULL); + zassert_true(status, NULL); + status = Device_Reinitialize(&rd_data); + zassert_false(status, NULL); + zassert_equal(rd_data.error_class, ERROR_CLASS_SECURITY, "error-class=%s", + bactext_error_class_name(rd_data.error_class)); + zassert_equal(rd_data.error_code, ERROR_CODE_PASSWORD_FAILURE, + "error-code=%s", bactext_error_code_name(rd_data.error_code)); + /* Reinitialize with device valid password, service invalid password */ + status = characterstring_init_ansi(&rd_data.password, "invalid"); + zassert_true(status, NULL); + status = Device_Reinitialize(&rd_data); + zassert_false(status, NULL); + zassert_equal(rd_data.error_class, ERROR_CLASS_SECURITY, "error-class=%s", + bactext_error_class_name(rd_data.error_class)); + zassert_equal(rd_data.error_code, ERROR_CODE_PASSWORD_FAILURE, + "error-code=%s", bactext_error_code_name(rd_data.error_code)); + /* Reinitialize with device valid password, service valid password */ + characterstring_init_ansi(&rd_data.password, "valid"); + status = Device_Reinitialize(&rd_data); + zassert_true(status, NULL); + /* Reinitialize with device valid password, service too long password */ + characterstring_init_ansi(&rd_data.password, "abcdefghijklmnopqrstuvwxyz"); + status = Device_Reinitialize(&rd_data); + zassert_false(status, NULL); + zassert_equal(rd_data.error_class, ERROR_CLASS_SERVICES, "error-class=%s", + bactext_error_class_name(rd_data.error_class)); + zassert_equal(rd_data.error_code, ERROR_CODE_PARAMETER_OUT_OF_RANGE, + "error-code=%s", bactext_error_code_name(rd_data.error_code)); + /* Reinitialize with device no password, unsupported state */ + status = Device_Reinitialize_Password_Set(NULL); + zassert_true(status, NULL); + rd_data.state = BACNET_REINIT_MAX; + status = Device_Reinitialize(&rd_data); + zassert_false(status, NULL); + zassert_equal(rd_data.error_class, ERROR_CLASS_SERVICES, "error-class=%s", + bactext_error_class_name(rd_data.error_class)); + zassert_equal(rd_data.error_code, ERROR_CODE_PARAMETER_OUT_OF_RANGE, + "error-code=%s", bactext_error_code_name(rd_data.error_code)); + return; } /** * @} */ - #if defined(CONFIG_ZTEST_NEW_API) ZTEST_SUITE(device_tests, NULL, NULL, NULL, NULL, NULL); #else void test_main(void) { - ztest_test_suite(device_tests, - ztest_unit_test(testDevice), - ztest_unit_test(test_Device_Data_Sharing) - ); + ztest_test_suite(device_tests, ztest_unit_test(testDevice), + ztest_unit_test(test_Device_Data_Sharing)); ztest_run_test_suite(device_tests); }