Revision control
++ // Copyright (C) 2017 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
++ // Qt-Security score:critical reason:data-parser
++
++ #include "qmodbusdeviceidentification.h"
++ #include "qmodbus_symbols_p.h"
++
++ QT_BEGIN_NAMESPACE
++
++ /*!
++ \class QModbusDeviceIdentification
++ \inmodule QtSerialBus
++ \since 5.8
++
++ \brief The QModbusDeviceIdentification is a container class representing
++ the physical and functional description of a Modbus server.
++
++ The Device Identification interface is modeled as an address space composed
++ of a set of addressable data elements. The data elements are called objects
++ and an \l ObjectId identifies them.
++ */
++
++ /*!
++ \enum QModbusDeviceIdentification::ObjectId
++
++ This enum describes the possible server objects. The interface consists of
++ three categories of objects:
++
++ Basic Device Identification. All objects of this category are mandatory.
++
++ \value VendorNameObjectId The vendor name of the device.
++ \value ProductCodeObjectId The product code of the device.
++ \value MajorMinorRevisionObjectId The product version numbering.
++
++ Regular Device Identification. All objects of this category are standard
++ defined and optional.
++
++ \value VendorUrlObjectId The vendor URL of the device.
++ \value ProductNameObjectId The product name of the device.
++ \value ModelNameObjectId The model name of the device.
++ \value UserApplicationNameObjectId The user application name of the device.
++
++ Reserved range (i.e., ReservedObjectId >= ObjectId < ProductDependentObjectId).
++ Do not use.
++
++ \value ReservedObjectId First value of reserved object Ids.
++
++ Extended Device Identification. All of these data are device dependent and
++ optional.
++
++ \value ProductDependentObjectId First possible value of product dependent
++ identifiers.
++ \value UndefinedObjectId Do not use.
++ */
++
++ /*!
++ \enum QModbusDeviceIdentification::ReadDeviceIdCode
++
++ Defines the access type of the read identification request.
++
++ Stream access:
++
++ \value BasicReadDeviceIdCode Request to get the basic device
++ identification.
++ \value RegularReadDeviceIdCode Request to get the regular device
++ identification.
++ \value ExtendedReadDeviceIdCode Request to get the extended device
++ identification.
++
++ Individual access:
++
++ \value IndividualReadDeviceIdCode Request to get one specific identification
++ object.
++ */
++
++ /*!
++ \enum QModbusDeviceIdentification::ConformityLevel
++
++ Defines the identification conformity level of the device and type of
++ supported access.
++
++ \value BasicConformityLevel Basic identification (stream access).
++ \value RegularConformityLevel Regular identification (stream access).
++ \value ExtendedConformityLevel Extended identification (stream access).
++ \value BasicIndividualConformityLevel Basic identification (stream access and
++ individual access).
++ \value RegularIndividualConformityLevel Regular identification (stream access
++ and individual access).
++ \value ExtendedIndividualConformityLevel Extended identification (stream access
++ and individual access).
++
++ \sa ReadDeviceIdCode
++ */
++
++ /*!
++ \fn QModbusDeviceIdentification::QModbusDeviceIdentification()
++
++ Constructs an invalid QModbusDeviceIdentification object.
++ */
++
++ /*!
++ \fn bool QModbusDeviceIdentification::isValid() const
++
++ Returns \c true if the device identification object is valid; otherwise
++ \c false.
++
++ A device identification object is considered valid if \l ProductNameObjectId,
++ \l ProductCodeObjectId and \l MajorMinorRevisionObjectId are set to a
++ non-empty value. Still the object can contain valid object id's and
++ associated data.
++
++ \note A default constructed device identification object is invalid.
++ */
++
++ /*!
++ \fn QList<int> QModbusDeviceIdentification::objectIds() const
++
++ Returns a list containing all the object id's in the
++ \c QModbusDeviceIdentification object in ascending order.
++
++ \sa ObjectId
++ */
++
++ /*!
++ \fn void QModbusDeviceIdentification::remove(uint objectId)
++
++ Removes the item for the given \a objectId.
++
++ \sa ObjectId
++ */
++
++ /*!
++ \fn bool QModbusDeviceIdentification::contains(uint objectId) const
++
++ Returns \c true if there is an item for the given \a objectId; otherwise \c
++ false.
++
++ \sa ObjectId
++ */
++
++ /*!
++ \fn QByteArray QModbusDeviceIdentification::value(uint objectId) const
++
++ Returns the value associated with the \a objectId. If there is no item with
++ the \a objectId, the function returns a \l{default-constructed value}.
++
++ \sa ObjectId
++ */
++
++ /*!
++ \fn bool QModbusDeviceIdentification::insert(uint objectId, const QByteArray &value)
++
++ Inserts a new item with the \a objectId and a value of \a value. If there
++ is already an item with the \a objectId, that item's value is replaced with
++ \a value.
++
++ Returns \c true if the size of \a value is less than 245 bytes and the
++ \a objectId is less then \l QModbusDeviceIdentification::UndefinedObjectId.
++
++ \sa ObjectId
++ */
++
++ /*!
++ \fn ConformityLevel QModbusDeviceIdentification::conformityLevel() const
++
++ Returns the identification conformity level of the device and type of
++ supported access.
++ */
++
++ /*!
++ \fn void QModbusDeviceIdentification::setConformityLevel(ConformityLevel level)
++
++ Sets the identification conformity level of the device and type of
++ supported access to \a level.
++ */
++
++ /*!
++ Converts the byte array \a ba to a QModbusDeviceIdentification object.
++
++ \note: The returned object might be empty or even invalid if some error
++ occurs while processing the byte array.
++
++ \sa isValid()
++ */
++ QModbusDeviceIdentification QModbusDeviceIdentification::fromByteArray(const QByteArray &ba)
++ {
++ QModbusDeviceIdentification qmdi;
++ // header 6 bytes: mei type + read device id + conformity level + more follows
++ // + next object id + number of object
++ // data 2 bytes: + object id + object size of the first object -> 8
++ if (ba.size() >= 8) {
++ if (ba[0] != EncapsulatedInterfaceTransport::ReadDeviceIdentification)
++ return qmdi;
++ if (ba.size() < (8 + quint8(ba[7])))
++ return qmdi;
++ } else {
++ return qmdi;
++ }
++
++ ConformityLevel level = ConformityLevel(quint8(ba[2]));
++ switch (level) {
++ case BasicConformityLevel:
++ case RegularConformityLevel:
++ case ExtendedConformityLevel:
++ case BasicIndividualConformityLevel:
++ case RegularIndividualConformityLevel:
++ case ExtendedIndividualConformityLevel:
++ qmdi.setConformityLevel(level);
++ break;
++ default:
++ return qmdi;
++ }
++
++ quint8 numOfObjects = ba[5];
++ quint8 objectSize = quint8(ba[7]);
++ qmdi.insert(quint8(ba[6]), ba.mid(8, objectSize));
++
++ // header + object id + object size + second object id (9 bytes) + first object size
++ int nextSizeField = 9 + objectSize;
++ for (int i = 1; i < numOfObjects; ++i) {
++ if (ba.size() <= nextSizeField)
++ break;
++ objectSize = ba[nextSizeField];
++ if (ba.size() < (nextSizeField + objectSize))
++ break;
++ qmdi.insert(quint8(ba[nextSizeField - 1]), ba.mid(nextSizeField + 1, objectSize));
++ nextSizeField += objectSize + 2; // object size + object id field + object size field
++ }
++ return qmdi;
++ }
++
++ QT_END_NAMESPACE