1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:critical reason:data-parser
4
5#include "qmodbusdeviceidentification.h"
6#include "qmodbus_symbols_p.h"
7
8QT_BEGIN_NAMESPACE
9
10/*!
11 \class QModbusDeviceIdentification
12 \inmodule QtSerialBus
13 \since 5.8
14
15 \brief The QModbusDeviceIdentification is a container class representing
16 the physical and functional description of a Modbus server.
17
18 The Device Identification interface is modeled as an address space composed
19 of a set of addressable data elements. The data elements are called objects
20 and an \l ObjectId identifies them.
21*/
22
23/*!
24 \enum QModbusDeviceIdentification::ObjectId
25
26 This enum describes the possible server objects. The interface consists of
27 three categories of objects:
28
29 Basic Device Identification. All objects of this category are mandatory.
30
31 \value VendorNameObjectId The vendor name of the device.
32 \value ProductCodeObjectId The product code of the device.
33 \value MajorMinorRevisionObjectId The product version numbering.
34
35 Regular Device Identification. All objects of this category are standard
36 defined and optional.
37
38 \value VendorUrlObjectId The vendor URL of the device.
39 \value ProductNameObjectId The product name of the device.
40 \value ModelNameObjectId The model name of the device.
41 \value UserApplicationNameObjectId The user application name of the device.
42
43 Reserved range (i.e., ReservedObjectId >= ObjectId < ProductDependentObjectId).
44 Do not use.
45
46 \value ReservedObjectId First value of reserved object Ids.
47
48 Extended Device Identification. All of these data are device dependent and
49 optional.
50
51 \value ProductDependentObjectId First possible value of product dependent
52 identifiers.
53 \value UndefinedObjectId Do not use.
54*/
55
56/*!
57 \enum QModbusDeviceIdentification::ReadDeviceIdCode
58
59 Defines the access type of the read identification request.
60
61 Stream access:
62
63 \value BasicReadDeviceIdCode Request to get the basic device
64 identification.
65 \value RegularReadDeviceIdCode Request to get the regular device
66 identification.
67 \value ExtendedReadDeviceIdCode Request to get the extended device
68 identification.
69
70 Individual access:
71
72 \value IndividualReadDeviceIdCode Request to get one specific identification
73 object.
74*/
75
76/*!
77 \enum QModbusDeviceIdentification::ConformityLevel
78
79 Defines the identification conformity level of the device and type of
80 supported access.
81
82 \value BasicConformityLevel Basic identification (stream access).
83 \value RegularConformityLevel Regular identification (stream access).
84 \value ExtendedConformityLevel Extended identification (stream access).
85 \value BasicIndividualConformityLevel Basic identification (stream access and
86 individual access).
87 \value RegularIndividualConformityLevel Regular identification (stream access
88 and individual access).
89 \value ExtendedIndividualConformityLevel Extended identification (stream access
90 and individual access).
91
92 \sa ReadDeviceIdCode
93*/
94
95/*!
96 \fn QModbusDeviceIdentification::QModbusDeviceIdentification()
97
98 Constructs an invalid QModbusDeviceIdentification object.
99*/
100
101/*!
102 \fn bool QModbusDeviceIdentification::isValid() const
103
104 Returns \c true if the device identification object is valid; otherwise
105 \c false.
106
107 A device identification object is considered valid if \l ProductNameObjectId,
108 \l ProductCodeObjectId and \l MajorMinorRevisionObjectId are set to a
109 non-empty value. Still the object can contain valid object id's and
110 associated data.
111
112 \note A default constructed device identification object is invalid.
113*/
114
115/*!
116 \fn QList<int> QModbusDeviceIdentification::objectIds() const
117
118 Returns a list containing all the object id's in the
119 \c QModbusDeviceIdentification object in ascending order.
120
121 \sa ObjectId
122*/
123
124/*!
125 \fn void QModbusDeviceIdentification::remove(uint objectId)
126
127 Removes the item for the given \a objectId.
128
129 \sa ObjectId
130*/
131
132/*!
133 \fn bool QModbusDeviceIdentification::contains(uint objectId) const
134
135 Returns \c true if there is an item for the given \a objectId; otherwise \c
136 false.
137
138 \sa ObjectId
139*/
140
141/*!
142 \fn QByteArray QModbusDeviceIdentification::value(uint objectId) const
143
144 Returns the value associated with the \a objectId. If there is no item with
145 the \a objectId, the function returns a \l{default-constructed value}.
146
147 \sa ObjectId
148*/
149
150/*!
151 \fn bool QModbusDeviceIdentification::insert(uint objectId, const QByteArray &value)
152
153 Inserts a new item with the \a objectId and a value of \a value. If there
154 is already an item with the \a objectId, that item's value is replaced with
155 \a value.
156
157 Returns \c true if the size of \a value is less than 245 bytes and the
158 \a objectId is less then \l QModbusDeviceIdentification::UndefinedObjectId.
159
160 \sa ObjectId
161*/
162
163/*!
164 \fn ConformityLevel QModbusDeviceIdentification::conformityLevel() const
165
166 Returns the identification conformity level of the device and type of
167 supported access.
168*/
169
170/*!
171 \fn void QModbusDeviceIdentification::setConformityLevel(ConformityLevel level)
172
173 Sets the identification conformity level of the device and type of
174 supported access to \a level.
175*/
176
177/*!
178 Converts the byte array \a ba to a QModbusDeviceIdentification object.
179
180 \note: The returned object might be empty or even invalid if some error
181 occurs while processing the byte array.
182
183 \sa isValid()
184*/
185QModbusDeviceIdentification QModbusDeviceIdentification::fromByteArray(const QByteArray &ba)
186{
187 QModbusDeviceIdentification qmdi;
188 // header 6 bytes: mei type + read device id + conformity level + more follows
189 // + next object id + number of object
190 // data 2 bytes: + object id + object size of the first object -> 8
191 if (ba.size() >= 8) {
192 if (ba[0] != EncapsulatedInterfaceTransport::ReadDeviceIdentification)
193 return qmdi;
194 if (ba.size() < (8 + quint8(ba[7])))
195 return qmdi;
196 } else {
197 return qmdi;
198 }
199
200 ConformityLevel level = ConformityLevel(quint8(ba[2]));
201 switch (level) {
202 case BasicConformityLevel:
203 case RegularConformityLevel:
204 case ExtendedConformityLevel:
205 case BasicIndividualConformityLevel:
206 case RegularIndividualConformityLevel:
207 case ExtendedIndividualConformityLevel:
208 qmdi.setConformityLevel(level);
209 break;
210 default:
211 return qmdi;
212 }
213
214 quint8 numOfObjects = ba[5];
215 quint8 objectSize = quint8(ba[7]);
216 qmdi.insert(objectId: quint8(ba[6]), data: ba.mid(index: 8, len: objectSize));
217
218 // header + object id + object size + second object id (9 bytes) + first object size
219 int nextSizeField = 9 + objectSize;
220 for (int i = 1; i < numOfObjects; ++i) {
221 if (ba.size() <= nextSizeField)
222 break;
223 objectSize = ba[nextSizeField];
224 if (ba.size() < (nextSizeField + objectSize))
225 break;
226 qmdi.insert(objectId: quint8(ba[nextSizeField - 1]), data: ba.mid(index: nextSizeField + 1, len: objectSize));
227 nextSizeField += objectSize + 2; // object size + object id field + object size field
228 }
229 return qmdi;
230}
231
232QT_END_NAMESPACE
233

source code of qtserialbus/src/serialbus/qmodbusdeviceidentification.cpp