Ejemplo n.º 1
0
bool Routed_Device_Write_Property_Local(
    BACNET_WRITE_PROPERTY_DATA * wp_data)
{
    bool status = false;        /* return value */
    int len = 0;
    BACNET_APPLICATION_DATA_VALUE value;

    /* decode the some of the request */
    len =
        bacapp_decode_application_data(wp_data->application_data,
                                       wp_data->application_data_len, &value);
    if (len < 0) {
        /* error while decoding - a value larger than we can handle */
        wp_data->error_class = ERROR_CLASS_PROPERTY;
        wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
        return false;
    }
    /*  only array properties can have array options */
    if ((wp_data->object_property != PROP_OBJECT_LIST) &&
            (wp_data->array_index != BACNET_ARRAY_ALL)) {
        wp_data->error_class = ERROR_CLASS_PROPERTY;
        wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
        return false;
    }
    /* FIXME: len < application_data_len: more data? */
    switch (wp_data->object_property) {
    case PROP_OBJECT_IDENTIFIER:
        status =
            WPValidateArgType(&value, BACNET_APPLICATION_TAG_OBJECT_ID,
                              &wp_data->error_class, &wp_data->error_code);
        if (status) {
            if ((value.type.Object_Id.type == OBJECT_DEVICE) &&
                    (Routed_Device_Set_Object_Instance_Number(value.type.
                            Object_Id.instance))) {
                /* FIXME: we could send an I-Am broadcast to let the world know */
            } else {
                status = false;
                wp_data->error_class = ERROR_CLASS_PROPERTY;
                wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
            }
        }
        break;
    case PROP_OBJECT_NAME:
        status =
            WPValidateString(&value, MAX_DEV_NAME_LEN, false,
                             &wp_data->error_class, &wp_data->error_code);
        if (status) {
            Routed_Device_Set_Object_Name(characterstring_encoding(&value.
                                          type.Character_String),
                                          characterstring_value(&value.type.Character_String),
                                          characterstring_length(&value.type.Character_String));
        }
        break;
    default:
        status = Device_Write_Property_Local(wp_data);
        break;
    }
    return status;
}
Ejemplo n.º 2
0
bool bacnet_name_set(uint16_t offset,
    BACNET_CHARACTER_STRING * char_string)
{
    uint8_t encoding = 0;
    uint8_t length = 0;
    char *str = NULL;

    length = characterstring_length(char_string);
    encoding = characterstring_encoding(char_string);
    str = characterstring_value(char_string);
    return bacnet_name_save(offset, encoding, str, length);
}
Ejemplo n.º 3
0
void handler_who_has(
    uint8_t * service_request,
    uint16_t service_len,
    BACNET_ADDRESS * src)
{
    int len = 0;
    BACNET_WHO_HAS_DATA data;
    bool directed_to_me = false;
    int object_type = 0;
    uint32_t object_instance = 0;
    char *object_name = NULL;
    bool found = false;

    (void) src;
    len = whohas_decode_service_request(service_request, service_len, &data);
    if (len > 0) {
        if ((data.low_limit == -1) || (data.high_limit == -1))
            directed_to_me = true;
        else if ((Device_Object_Instance_Number() >= (uint32_t) data.low_limit)
            && (Device_Object_Instance_Number() <= (uint32_t) data.high_limit))
            directed_to_me = true;
        if (directed_to_me) {
            /* do we have such an object?  If so, send an I-Have.
               note: we should have only 1 of such an object */
            if (data.object_name) {
                /* valid name in my device? */
                object_name = characterstring_value(&data.object.name);
                found =
                    Device_Valid_Object_Name(object_name, &object_type,
                    &object_instance);
                if (found)
                    Send_I_Have(Device_Object_Instance_Number(), object_type,
                        object_instance, object_name);
            } else {
                /* valid object in my device? */
                object_name =
                    Device_Valid_Object_Id(data.object.identifier.type,
                    data.object.identifier.instance);
                if (object_name)
                    Send_I_Have(Device_Object_Instance_Number(),
                        data.object.identifier.type,
                        data.object.identifier.instance, object_name);
            }
        }
    }

    return;
}
Ejemplo n.º 4
0
/** Handler for a Reinitialize Device (RD) request.
 * @ingroup DMRD
 * This handler will be invoked by apdu_handler() if it has been enabled
 * by a call to apdu_set_confirmed_handler().
 * This handler builds a response packet, which is
 * - an Abort if
 *   - the message is segmented
 *   - if decoding fails
 * - an Error if
 *   - the RD password is incorrect
 *   - the Reinitialize Device operation fails
 * - a Reject if the request state is invalid
 * - else tries to send a simple ACK for the RD on success.
 *
 * @param service_request [in] The contents of the service request.
 * @param service_len [in] The length of the service_request.
 * @param src [in] BACNET_ADDRESS of the source of the message
 * @param service_data [in] The BACNET_CONFIRMED_SERVICE_DATA information
 *                          decoded from the APDU header of this message.
 */
void handler_reinitialize_device(
    uint8_t * service_request,
    uint16_t service_len,
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
    BACNET_REINITIALIZE_DEVICE_DATA rd_data;
    int len = 0;
    int pdu_len = 0;
    BACNET_NPDU_DATA npdu_data;
    BACNET_ADDRESS my_address;

    /* encode the NPDU portion of the packet */
    datalink_get_my_address(&my_address);
    npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
    pdu_len =
        npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
        &npdu_data);
#if PRINT_ENABLED
    fprintf(stderr, "ReinitializeDevice!\n");
#endif
    if (service_data->segmented_message) {
        len =
            abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
            service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
            true);
#if PRINT_ENABLED
        fprintf(stderr,
            "ReinitializeDevice: Sending Abort - segmented message.\n");
#endif
        goto RD_ABORT;
    }
    /* decode the service request only */
    len =
        rd_decode_service_request(service_request, service_len, &rd_data.state,
        &rd_data.password);
#if PRINT_ENABLED
    if (len > 0) {
        fprintf(stderr, "ReinitializeDevice: state=%u password=%s\n",
            (unsigned) rd_data.state,
            characterstring_value(&rd_data.password));
    } else {
        fprintf(stderr, "ReinitializeDevice: Unable to decode request!\n");
    }
#endif
    /* bad decoding or something we didn't understand - send an abort */
    if (len < 0) {
        len =
            abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
            service_data->invoke_id, ABORT_REASON_OTHER, true);
#if PRINT_ENABLED
        fprintf(stderr,
            "ReinitializeDevice: Sending Abort - could not decode.\n");
#endif
        goto RD_ABORT;
    }
    /* check the data from the request */
    if (rd_data.state >= MAX_BACNET_REINITIALIZED_STATE) {
        len =
            reject_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
            service_data->invoke_id, REJECT_REASON_UNDEFINED_ENUMERATION);
#if PRINT_ENABLED
        fprintf(stderr,
            "ReinitializeDevice: Sending Reject - undefined enumeration\n");
#endif
    } else {
#if BAC_ROUTING
        /* Check to see if the current Device supports this service. */
        len =
            Routed_Device_Service_Approval
            (SERVICE_CONFIRMED_REINITIALIZE_DEVICE, (int) rd_data.state,
            &Handler_Transmit_Buffer[pdu_len], service_data->invoke_id);
        if (len > 0)
            goto RD_ABORT;
#endif

        if (Device_Reinitialize(&rd_data)) {
            len =
                encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
                service_data->invoke_id,
                SERVICE_CONFIRMED_REINITIALIZE_DEVICE);
#if PRINT_ENABLED
            fprintf(stderr, "ReinitializeDevice: Sending Simple Ack!\n");
#endif
        } else {
            len =
                bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
                service_data->invoke_id, SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
                rd_data.error_class, rd_data.error_code);
#if PRINT_ENABLED
            fprintf(stderr, "ReinitializeDevice: Sending Error.\n");
#endif
        }
    }
  RD_ABORT:
    pdu_len += len;
    len =
        datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
        pdu_len);
    if (len <= 0) {
#if PRINT_ENABLED
        fprintf(stderr, "ReinitializeDevice: Failed to send PDU (%s)!\n",
            strerror(errno));
#endif
    }

    return;
}
Ejemplo n.º 5
0
void DecodeBlock(
    char cBlockNum,
    uint8_t * pData)
{
    int iLen;
    uint32_t ulTemp;
    int tag_len;
    uint8_t tag_number;
    uint32_t len_value_type;
    BACNET_CHARACTER_STRING bsName;
    DATABLOCK Response;

    iLen = 0;

    if (cBlockNum >= MY_MAX_BLOCK)
        return;

    tag_len =
        decode_tag_number_and_value(&pData[iLen], &tag_number,
        &len_value_type);
    iLen += tag_len;
    if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT)
        return;

    iLen += decode_unsigned(&pData[iLen], len_value_type, &ulTemp);
    Response.cMyByte1 = (char) ulTemp;

    tag_len =
        decode_tag_number_and_value(&pData[iLen], &tag_number,
        &len_value_type);
    iLen += tag_len;
    if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT)
        return;

    iLen += decode_unsigned(&pData[iLen], len_value_type, &ulTemp);
    Response.cMyByte2 = (char) ulTemp;

    tag_len =
        decode_tag_number_and_value(&pData[iLen], &tag_number,
        &len_value_type);
    iLen += tag_len;
    if (tag_number != BACNET_APPLICATION_TAG_REAL)
        return;

    iLen += decode_real(&pData[iLen], &Response.fMyReal);

    tag_len =
        decode_tag_number_and_value(&pData[iLen], &tag_number,
        &len_value_type);
    iLen += tag_len;
    if (tag_number != BACNET_APPLICATION_TAG_CHARACTER_STRING)
        return;

    iLen += decode_character_string(&pData[iLen], len_value_type, &bsName);
    strncpy(Response.sMyString, characterstring_value(&bsName), MY_MAX_STR);
    Response.sMyString[MY_MAX_STR] = '\0';      /* Make sure it is nul terminated */

    printf("Private Transfer Read Block Response\n");
    printf("Data Block: %d\n", (int) cBlockNum);
    printf("  First Byte  : %d\n", (int) Response.cMyByte1);
    printf("  Second Byte : %d\n", (int) Response.cMyByte2);
    printf("  Real        : %f\n", Response.fMyReal);
    printf("  String      : %s\n\n", Response.sMyString);
}
Ejemplo n.º 6
0
static void ProcessPT(
    BACNET_PRIVATE_TRANSFER_DATA * data)
{
    int iLen;   /* Index to current location in data */
    char cBlockNumber;
    uint32_t ulTemp;
    int tag_len;
    uint8_t tag_number;
    uint32_t len_value_type;
    BACNET_CHARACTER_STRING bsTemp;

    iLen = 0;

    /* Decode the block number */
    tag_len =
        decode_tag_number_and_value(&data->serviceParameters[iLen],
        &tag_number, &len_value_type);
    iLen += tag_len;
    if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT) {
        /* Bail out early if wrong type */
        /* and signal unexpected error */
        data->serviceParametersLen = 0;
        return;
    }

    iLen +=
        decode_unsigned(&data->serviceParameters[iLen], len_value_type,
        &ulTemp);
    cBlockNumber = (char) ulTemp;
    if (cBlockNumber < MY_MAX_BLOCK) {
        if (data->serviceNumber == MY_SVC_READ) {
            /*  Read Response is an unsigned int with
               0 for success or a non 0 error code
               For a successful read the 0 success
               code is followed by the block number
               and then the block contents which
               consist of 2 unsigned ints (in 0 to 255
               range as they are really chars) a single
               precision real and a string which
               will be up to 32 chars + a nul */

            iLen = 0;

            /* Signal success */
            iLen += encode_application_unsigned(&IOBufferPT[iLen], MY_ERR_OK);
            /* Followed by the block number */
            iLen +=
                encode_application_unsigned(&IOBufferPT[iLen], cBlockNumber);
            /* And Then the block contents */
            iLen +=
                encode_application_unsigned(&IOBufferPT[iLen],
                MyData[(int8_t) cBlockNumber].cMyByte1);
            iLen +=
                encode_application_unsigned(&IOBufferPT[iLen],
                MyData[(int8_t) cBlockNumber].cMyByte2);
            iLen +=
                encode_application_real(&IOBufferPT[iLen],
                MyData[(int8_t) cBlockNumber].fMyReal);
            characterstring_init_ansi(&bsTemp,
                (char *) MyData[(int8_t) cBlockNumber].sMyString);
            iLen +=
                encode_application_character_string(&IOBufferPT[iLen],
                &bsTemp);
        } else {
            /* Write operation */
            /*  Write block consists of the block number
               followed by the block contents as
               described above for the read operation.
               The returned result is an unsigned
               response which is 0 for success and
               a non 0 error code otherwise. */

            tag_len =
                decode_tag_number_and_value(&data->serviceParameters[iLen],
                &tag_number, &len_value_type);
            iLen += tag_len;
            if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT) {
                data->serviceParametersLen = 0;
                return;
            }
            iLen +=
                decode_unsigned(&data->serviceParameters[iLen], len_value_type,
                &ulTemp);
            MyData[(int8_t) cBlockNumber].cMyByte1 = (char) ulTemp;

            tag_len =
                decode_tag_number_and_value(&data->serviceParameters[iLen],
                &tag_number, &len_value_type);
            iLen += tag_len;
            if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT) {
                data->serviceParametersLen = 0;
                return;
            }
            iLen +=
                decode_unsigned(&data->serviceParameters[iLen], len_value_type,
                &ulTemp);
            MyData[(int8_t) cBlockNumber].cMyByte2 = (char) ulTemp;

            tag_len =
                decode_tag_number_and_value(&data->serviceParameters[iLen],
                &tag_number, &len_value_type);
            iLen += tag_len;
            if (tag_number != BACNET_APPLICATION_TAG_REAL) {
                data->serviceParametersLen = 0;
                return;
            }
            iLen +=
                decode_real(&data->serviceParameters[iLen],
                &MyData[(int8_t) cBlockNumber].fMyReal);

            tag_len =
                decode_tag_number_and_value(&data->serviceParameters[iLen],
                &tag_number, &len_value_type);
            iLen += tag_len;
            if (tag_number != BACNET_APPLICATION_TAG_CHARACTER_STRING) {
                data->serviceParametersLen = 0;
                return;
            }
            decode_character_string(&data->serviceParameters[iLen],
                len_value_type, &bsTemp);
            /* Only copy as much as we can accept */
            strncpy((char *) MyData[(int8_t) cBlockNumber].sMyString,
                characterstring_value(&bsTemp), MY_MAX_STR);
            /* Make sure it is nul terminated */
            MyData[(int8_t) cBlockNumber].sMyString[MY_MAX_STR] = '\0';
            /* Signal success */
            iLen = encode_application_unsigned(&IOBufferPT[0], MY_ERR_OK);
        }
    } else {
        /* Signal bad index */
        iLen = encode_application_unsigned(&IOBufferPT[0], MY_ERR_BAD_INDEX);
    }
    data->serviceParametersLen = iLen;
    data->serviceParameters = IOBufferPT;
}
Ejemplo n.º 7
0
/** Handler for a Device Communication Control (DCC) request.
 * @ingroup DMDCC
 * This handler will be invoked by apdu_handler() if it has been enabled
 * by a call to apdu_set_confirmed_handler().
 * This handler builds a response packet, which is
 * - an Abort if
 *   - the message is segmented
 *   - if decoding fails
 *   - if not a known DCC state
 * - an Error if the DCC password is incorrect
 * - else tries to send a simple ACK for the DCC on success,
 *   and sets the DCC state requested.
 *
 * @param service_request [in] The contents of the service request.
 * @param service_len [in] The length of the service_request.
 * @param src [in] BACNET_ADDRESS of the source of the message
 * @param service_data [in] The BACNET_CONFIRMED_SERVICE_DATA information
 *                          decoded from the APDU header of this message.
 */
void handler_device_communication_control(
    uint8_t * service_request,
    uint16_t service_len,
    BACNET_ADDRESS * src,
    BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
    uint16_t timeDuration = 0;
    BACNET_COMMUNICATION_ENABLE_DISABLE state = COMMUNICATION_ENABLE;
    BACNET_CHARACTER_STRING password;
    int len = 0;
    int pdu_len = 0;
    BACNET_NPDU_DATA npdu_data;
    BACNET_ADDRESS my_address;

    /* encode the NPDU portion of the reply packet */
    datalink_get_my_address(&my_address);
    npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
    pdu_len =
        npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
        &npdu_data);
#if PRINT_ENABLED
    fprintf(stderr, "DeviceCommunicationControl!\n");
#endif
    if (service_data->segmented_message) {
        len =
            abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
            service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
            true);
#if PRINT_ENABLED
        fprintf(stderr,
            "DeviceCommunicationControl: "
            "Sending Abort - segmented message.\n");
#endif
        goto DCC_ABORT;
    }
    /* decode the service request only */
    len =
        dcc_decode_service_request(service_request, service_len, &timeDuration,
        &state, &password);
#if PRINT_ENABLED
    if (len > 0)
        fprintf(stderr,
            "DeviceCommunicationControl: " "timeout=%u state=%u password=%s\n",
            (unsigned) timeDuration, (unsigned) state,
            characterstring_value(&password));
#endif
    /* bad decoding or something we didn't understand - send an abort */
    if (len < 0) {
        len =
            abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
            service_data->invoke_id, ABORT_REASON_OTHER, true);
#if PRINT_ENABLED
        fprintf(stderr,
            "DeviceCommunicationControl: "
            "Sending Abort - could not decode.\n");
#endif
        goto DCC_ABORT;
    }
    if (state >= MAX_BACNET_COMMUNICATION_ENABLE_DISABLE) {
        len =
            reject_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
            service_data->invoke_id, REJECT_REASON_UNDEFINED_ENUMERATION);
#if PRINT_ENABLED
        fprintf(stderr,
            "DeviceCommunicationControl: "
            "Sending Reject - undefined enumeration\n");
#endif
    } else {
#if BAC_ROUTING
        /* Check to see if the current Device supports this service. */
        len =
            Routed_Device_Service_Approval
            (SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL, (int) state,
            &Handler_Transmit_Buffer[pdu_len], service_data->invoke_id);
        if (len > 0)
            goto DCC_ABORT;
#endif

        if (characterstring_ansi_same(&password, My_Password)) {
            len =
                encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
                service_data->invoke_id,
                SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL);
#if PRINT_ENABLED
            fprintf(stderr,
                "DeviceCommunicationControl: " "Sending Simple Ack!\n");
#endif
            dcc_set_status_duration(state, timeDuration);
        } else {
            len =
                bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
                service_data->invoke_id,
                SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
                ERROR_CLASS_SECURITY, ERROR_CODE_PASSWORD_FAILURE);
#if PRINT_ENABLED
            fprintf(stderr,
                "DeviceCommunicationControl: "
                "Sending Error - password failure.\n");
#endif
        }
    }
  DCC_ABORT:
    pdu_len += len;
    len =
        datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
        pdu_len);
    if (len <= 0) {
#if PRINT_ENABLED
        fprintf(stderr,
            "DeviceCommunicationControl: " "Failed to send PDU (%s)!\n",
            strerror(errno));
#endif
    }

    return;
}
Ejemplo n.º 8
0
/* returns true if successful */
bool Device_Write_Property(
    BACNET_WRITE_PROPERTY_DATA * wp_data,
    BACNET_ERROR_CLASS * error_class,
    BACNET_ERROR_CODE * error_code)
{
    bool status = false;        /* return value */
    int len = 0;
    BACNET_APPLICATION_DATA_VALUE value;

    if (!Device_Valid_Object_Instance_Number(wp_data->object_instance)) {
        *error_class = ERROR_CLASS_OBJECT;
        *error_code = ERROR_CODE_UNKNOWN_OBJECT;
        return false;
    }
    /* decode the some of the request */
    len =
        bacapp_decode_application_data(wp_data->application_data,
        wp_data->application_data_len, &value);
    /* FIXME: len < application_data_len: more data? */
    /* FIXME: len == 0: unable to decode? */
    switch (wp_data->object_property) {
        case PROP_OBJECT_IDENTIFIER:
            if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) {
                if ((value.type.Object_Id.type == OBJECT_DEVICE) &&
                    (Device_Set_Object_Instance_Number(value.type.
                            Object_Id.instance))) {
                    /* FIXME: we could send an I-Am broadcast to let the world know */
                    status = true;
                } else {
                    *error_class = ERROR_CLASS_PROPERTY;
                    *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
                }
            } else {
                *error_class = ERROR_CLASS_PROPERTY;
                *error_code = ERROR_CODE_INVALID_DATA_TYPE;
            }
            break;
        case PROP_NUMBER_OF_APDU_RETRIES:
            if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
                /* FIXME: bounds check? */
                apdu_retries_set((uint8_t) value.type.Unsigned_Int);
                status = true;
            } else {
                *error_class = ERROR_CLASS_PROPERTY;
                *error_code = ERROR_CODE_INVALID_DATA_TYPE;
            }
            break;
        case PROP_APDU_TIMEOUT:
            if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
                /* FIXME: bounds check? */
                apdu_timeout_set((uint16_t) value.type.Unsigned_Int);
                status = true;
            } else {
                *error_class = ERROR_CLASS_PROPERTY;
                *error_code = ERROR_CODE_INVALID_DATA_TYPE;
            }
            break;
        case PROP_VENDOR_IDENTIFIER:
            if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
                /* FIXME: bounds check? */
                Device_Set_Vendor_Identifier((uint16_t) value.
                    type.Unsigned_Int);
                status = true;
            } else {
                *error_class = ERROR_CLASS_PROPERTY;
                *error_code = ERROR_CODE_INVALID_DATA_TYPE;
            }
            break;
        case PROP_SYSTEM_STATUS:
            if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) {
                /* FIXME: bounds check? */
                Device_Set_System_Status((BACNET_DEVICE_STATUS) value.
                    type.Enumerated);
                status = true;
            } else {
                *error_class = ERROR_CLASS_PROPERTY;
                *error_code = ERROR_CODE_INVALID_DATA_TYPE;
            }
            break;
        case PROP_OBJECT_NAME:
            if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) {
                uint8_t encoding;
                encoding =
                    characterstring_encoding(&value.type.Character_String);
                if (encoding == CHARACTER_ANSI_X34) {
                    status =
                        Device_Set_Object_Name(characterstring_value
                        (&value.type.Character_String),
                        characterstring_length(&value.type.Character_String));
                    if (!status) {
                        *error_class = ERROR_CLASS_PROPERTY;
                        *error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
                    }
                } else {
                    *error_class = ERROR_CLASS_PROPERTY;
                    *error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED;
                }
            } else {
                *error_class = ERROR_CLASS_PROPERTY;
                *error_code = ERROR_CODE_INVALID_DATA_TYPE;
            }
            break;
#if defined(BACDL_MSTP)
        case PROP_MAX_INFO_FRAMES:
            if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
                if (value.type.Unsigned_Int <= 255) {
                    dlmstp_set_max_info_frames((uint8_t) value.
                        type.Unsigned_Int);
                    status = true;
                } else {
                    *error_class = ERROR_CLASS_PROPERTY;
                    *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
                }
            } else {
                *error_class = ERROR_CLASS_PROPERTY;
                *error_code = ERROR_CODE_INVALID_DATA_TYPE;
            }
            break;
        case PROP_MAX_MASTER:
            if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
                if ((value.type.Unsigned_Int > 0) &&
                    (value.type.Unsigned_Int <= 127)) {
                    dlmstp_set_max_master((uint8_t) value.type.Unsigned_Int);
                    status = true;
                } else {
                    *error_class = ERROR_CLASS_PROPERTY;
                    *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
                }
            } else {
                *error_class = ERROR_CLASS_PROPERTY;
                *error_code = ERROR_CODE_INVALID_DATA_TYPE;
            }
            break;
#endif
        default:
            *error_class = ERROR_CLASS_PROPERTY;
            *error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
            break;
    }

    return status;
}