1// Copyright (C) 2022 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
4#include "qcansignaldescription.h"
5#include "qcansignaldescription_p.h"
6
7QT_BEGIN_NAMESPACE
8
9/*!
10 \class QCanSignalDescription
11 \inmodule QtSerialBus
12 \since 6.5
13 \preliminary
14
15 \brief The QCanSignalDescription class describes the rules to extract one
16 value out of the CAN frame and represent it in an application-defined
17 format.
18
19 The QCanSignalDescription class can be used to provide a signal description
20 and later use it to decode a received \l QCanBusFrame or encode the input
21 data into a \l QCanBusFrame that can be sent to the receiver.
22
23 \section2 General Description
24
25 Each CAN frame can contain multiple values. The rules to extract the values
26 from a CAN frame include the following:
27 \list
28 \li Data source (frame ID or payload).
29 \li Data endianness. See \l {Data Endianness Processing} section for
30 more details.
31 \li Data format.
32 \li Start bit position.
33 \li Data length in bits.
34 \li Multiplexing options.
35 \endlist
36
37 Start bit position is specified relative to the selected data source. The
38 bits are counted starting from the LSB.
39
40 Once the data is extracted, it might require conversion to an
41 application-defined format. The following parameters can be used for that:
42 \list
43 \li Various parameters for converting the extracted value to a physical
44 value (factor, offset, scale).
45 \li Expected data range.
46 \li Data units.
47 \endlist
48
49 The QCanSignalDescription class provides methods to control all those
50 parameters.
51
52 \section2 Data Endianness Processing
53
54 Little endian and big endian data is encoded differently.
55 For big endian values, start bit positions are given for the most
56 significant bit. For little endian values, the start position is that of
57 the least significant bit.
58
59 Let's consider two examples. In both examples we will encode two 12-bit
60 values in the 3-byte payload.
61
62 \section3 Little Endian
63
64 For the little endian case the data layout can be represented by the
65 following image:
66
67 \image canbus_signals_le.png
68
69 Here the columns represent bit numbers, and the rows represent byte numbers.
70 \c {LSB} marks the first (least significant) bit of the value, and \c {MSB}
71 marks the last (most significant) bit of the value. The blue color marks the
72 first value, and the orange color marks the second value.
73
74 The information about these values will be encoded in QCanSignalDescription
75 in the following way:
76
77 \code
78 QCanSignalDescription signal1;
79 signal1.setDataEndian(QSysInfo::Endian::LittleEndian);
80 signal1.setStartBit(0);
81 signal1.setBitLength(12);
82 // other parameters for signal1
83
84 QCanSignalDescription signal2;
85 signal2.setDataEndian(QSysInfo::Endian::LittleEndian);
86 signal2.setStartBit(12);
87 signal2.setBitLength(12);
88 // other parameters for signal2
89 \endcode
90
91 \section3 Big Endian
92
93 The following image represents the value layout for the big endian case:
94
95 \image canbus_signals_be.png
96
97 The values can be represented in QCanSignalDescription in the following
98 way:
99
100 \code
101 QCanSignalDescription signal1;
102 signal1.setDataEndian(QSysInfo::Endian::BigEndian);
103 signal1.setStartBit(7);
104 signal1.setBitLength(12);
105 // other parameters for signal1
106
107 QCanSignalDescription signal2;
108 signal2.setDataEndian(QSysInfo::Endian::BigEndian);
109 signal2.setStartBit(11);
110 signal2.setBitLength(12);
111 // other parameters for signal2
112 \endcode
113
114 Note how the start bits are different from the little endian case. Also the
115 values are aligned differently.
116
117 \section2 Multiplexed Signals Explained
118
119 There are two common ways to encode the data in the CAN payload:
120 \list
121 \li Each range of bits always represents the same signal. For example,
122 \c {Bytes 0-1} in a payload can represent an engine speed (in rpm),
123 and \c {Bytes 2-3} can represent the vehicle speed (in km/h).
124 \li The same range of bits can represent different data, depending on
125 the values of some other bits in the payload. For example, if
126 \c {Byte 0} has the value \c {0}, the \c {Bytes 1-2} represent an
127 engine speed (in rpm), and if \c {Byte 0} has the value \c {1}, the
128 same \c {Bytes 1-2} represent a vehicle speed (in km/h).
129 \endlist
130
131 The second case uses signal multiplexing. In the provided example we will
132 have three signals. The first signal represents the value of \c {Byte 0} and
133 acts like a multiplexor signal. The other two signals represent an engine
134 speed and a vehicle speed respectively, but only one of them can be
135 extracted from the CAN payload at a time. Which signal should be extracted
136 is defined by the value of the multiplexor signal.
137
138 In more complicated cases the payload can have multiple multiplexor signals.
139 In such cases the signal can be extracted from the payload only when all
140 multiplexors contain the expected values.
141
142 \section2 Value Conversions
143
144 In many cases the signals transferred over CAN bus cannot hold the full
145 range of the physical values that they represent. To overcome these
146 limitations, the physical values are converted to a smaller range before
147 transmission, and can be restored on the receiving end.
148
149 The following formulas are used to convert between the physical value and
150 the signal's value:
151
152 \badcode
153 physicalValue = scaling * (signalValue * factor + offset);
154 signalValue = (physicalValue / scaling - offset) / factor;
155 \endcode
156
157 The factor and scaling parameters cannot be equal to \c {0}.
158
159 If any of the parameters equals to \l qQNaN(), it is not used during the
160 conversion. If all of the parameters are equal to \l qQNaN() (which is the
161 default), the conversion is not performed.
162*/
163
164/*!
165 \struct QCanSignalDescription::MultiplexValueRange
166 \inmodule QtSerialBus
167 \since 6.5
168
169 \brief Defines a range of values for a multiplexor signal.
170
171 Each multiplexor signal can have several ranges of values assigned to it.
172 This type represents one range. Both minimum and maximum values are
173 included in the range. Minimum and maximum values can be equal, so a
174 MultiplexValueRange is never empty. If maximum is less than minimum, the
175 values will be swapped while doing the range check.
176
177 \sa {Multiplexed Signals Explained}
178*/
179
180/*!
181 \variable QCanSignalDescription::MultiplexValueRange::minimum
182 \brief the minimum value of the range.
183*/
184
185/*!
186 \variable QCanSignalDescription::MultiplexValueRange::maximum
187 \brief the maximum value of the range.
188*/
189
190/*!
191 \typealias QCanSignalDescription::MultiplexValues
192*/
193
194/*!
195 \typealias QCanSignalDescription::MultiplexSignalValues
196*/
197
198/*!
199 Creates an empty signal description.
200*/
201QCanSignalDescription::QCanSignalDescription() : d(new QCanSignalDescriptionPrivate)
202{
203}
204
205/*!
206 Creates a signal description with the values copied from \a other.
207*/
208QCanSignalDescription::QCanSignalDescription(const QCanSignalDescription &other) : d(other.d)
209{
210}
211
212/*!
213 \fn QCanSignalDescription::QCanSignalDescription(QCanSignalDescription &&other) noexcept
214
215 Creates a signal description by moving from \a other.
216
217 \note The moved-from QCanSignalDescription object can only be destroyed or
218 assigned to. The effect of calling other functions than the destructor or
219 one of the assignment operators is undefined.
220*/
221
222/*!
223 \fn QCanSignalDescription::~QCanSignalDescription()
224
225 Destroys this signal description.
226*/
227
228QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QCanSignalDescriptionPrivate)
229
230/*!
231 Assigns the values from \a other to this signal description.
232*/
233QCanSignalDescription &QCanSignalDescription::operator=(const QCanSignalDescription &other)
234{
235 d = other.d;
236 return *this;
237}
238
239/*!
240 \fn QCanSignalDescription &QCanSignalDescription::operator=(QCanSignalDescription &&other) noexcept
241
242 Move-assigns the values from \a other to this signal description.
243
244 \note The moved-from QCanSignalDescription object can only be destroyed or
245 assigned to. The effect of calling other functions than the destructor or
246 one of the assignment operators is undefined.
247*/
248
249/*!
250 Returns \c true when the signal description is valid and \c false otherwise.
251
252 A valid signal description \e must fulfill the following conditions:
253 \list
254 \li have a non-empty \l name()
255 \li have \l bitLength() \c {== 32} if the \l dataFormat() is
256 \l {QtCanBus::DataFormat::}{Float}
257 \li have \l bitLength() \c {== 64} if the \l dataFormat() is
258 \l {QtCanBus::DataFormat::}{Double}
259 \li the \l bitLength() \e must be a multiple of \c 8 if the
260 \l dataFormat() is \l {QtCanBus::DataFormat::}{AsciiString}
261 \li the \l bitLength() \e must be greater than \c 0 and less than or
262 equal to \c {64}.
263 \endlist
264
265 \sa bitLength(), dataFormat(), name()
266*/
267bool QCanSignalDescription::isValid() const
268{
269 const bool formatMatch = [this]() {
270 if (d->format == QtCanBus::DataFormat::Float)
271 return d->dataLength == 32;
272 if (d->format == QtCanBus::DataFormat::Double)
273 return d->dataLength == 64;
274 if (d->format == QtCanBus::DataFormat::AsciiString)
275 return d->dataLength % 8 == 0;
276 return d->dataLength > 0 && d->dataLength <= 64;
277 }();
278 return !d->name.isEmpty() && formatMatch;
279}
280
281/*!
282 Returns the name of the signal.
283
284 \sa setName(), isValid()
285*/
286QString QCanSignalDescription::name() const
287{
288 return d->name;
289}
290
291/*!
292 Sets the name of the signal to \a name.
293
294 The signal's name must be unique within a CAN message.
295
296 \sa name()
297*/
298void QCanSignalDescription::setName(const QString &name)
299{
300 d.detach();
301 d->name = name;
302}
303
304/*!
305 Returns the physical unit (e.g. km/h) of the signal's value or an empty
306 string if the unit is not set.
307
308//! [qcansignaldesc-aux-parameter]
309 This parameter is introduced only for extra description. It's not used
310 during signal processing.
311//! [qcansignaldesc-aux-parameter]
312
313 \sa setPhysicalUnit()
314*/
315QString QCanSignalDescription::physicalUnit() const
316{
317 return d->unit;
318}
319
320/*!
321 Sets the physical \a unit (e.g. km/h) of the signal's value.
322
323 \include qcansignaldescription.cpp qcansignaldesc-aux-parameter
324
325 \sa physicalUnit()
326*/
327void QCanSignalDescription::setPhysicalUnit(const QString &unit)
328{
329 d.detach();
330 d->unit = unit;
331}
332
333/*!
334 Returns the receiver node for this signal.
335
336 \include qcansignaldescription.cpp qcansignaldesc-aux-parameter
337
338 \sa setReceiver()
339*/
340QString QCanSignalDescription::receiver() const
341{
342 return d->receiver;
343}
344
345/*!
346 Sets the \a receiver node for this signal.
347
348 \include qcansignaldescription.cpp qcansignaldesc-aux-parameter
349
350 \sa receiver()
351*/
352void QCanSignalDescription::setReceiver(const QString &receiver)
353{
354 d.detach();
355 d->receiver = receiver;
356}
357
358/*!
359 Returns the comment for the signal.
360
361 \include qcansignaldescription.cpp qcansignaldesc-aux-parameter
362
363 \sa setComment()
364*/
365QString QCanSignalDescription::comment() const
366{
367 return d->comment;
368}
369
370/*!
371 Sets the comment for the signal to \a text.
372
373 \include qcansignaldescription.cpp qcansignaldesc-aux-parameter
374
375 \sa comment()
376*/
377void QCanSignalDescription::setComment(const QString &text)
378{
379 d.detach();
380 d->comment = text;
381}
382
383/*!
384 Returns the data source of the signal's value.
385
386 By default, \l {QtCanBus::DataSource::}{Payload} is used.
387
388 \sa setDataSource(), QtCanBus::DataSource
389*/
390QtCanBus::DataSource QCanSignalDescription::dataSource() const
391{
392 return d->source;
393}
394
395/*!
396 Sets the data source of the signal's value to \a source.
397
398 \sa dataSource(), QtCanBus::DataSource
399*/
400void QCanSignalDescription::setDataSource(QtCanBus::DataSource source)
401{
402 d.detach();
403 d->source = source;
404}
405
406/*!
407 Returns the data endian of the signal's value.
408
409 By default, \l {QSysInfo::}{BigEndian} is used.
410
411 \note The data endian is ignored if the \l dataFormat() is set to
412 \l {QtCanBus::DataFormat::}{AsciiString}.
413
414 \sa setDataEndian(), QSysInfo::Endian
415*/
416QSysInfo::Endian QCanSignalDescription::dataEndian() const
417{
418 return d->endian;
419}
420
421/*!
422 Sets the data endian of the signal's value to \a endian.
423
424 \sa dataEndian(), QSysInfo::Endian
425*/
426void QCanSignalDescription::setDataEndian(QSysInfo::Endian endian)
427{
428 d.detach();
429 d->endian = endian;
430}
431
432/*!
433 Returns the data format of the signal's value.
434
435 By default, \l {QtCanBus::DataFormat::}{SignedInteger} is used.
436
437 \sa setDataFormat(), QtCanBus::DataFormat
438*/
439QtCanBus::DataFormat QCanSignalDescription::dataFormat() const
440{
441 return d->format;
442}
443
444/*!
445 Sets the data format of the signal's value to \a format.
446
447 \sa dataFormat(), QtCanBus::DataFormat
448*/
449void QCanSignalDescription::setDataFormat(QtCanBus::DataFormat format)
450{
451 d.detach();
452 d->format = format;
453}
454
455/*!
456 Returns the start bit of the signal's value in the \l dataSource().
457
458 \sa setStartBit(), bitLength(), setBitLength()
459*/
460quint16 QCanSignalDescription::startBit() const
461{
462 return d->startBit;
463}
464
465/*!
466 Sets the start bit of the signal's value in the \l dataSource() to \a bit.
467
468 \sa startBit(), bitLength(), setBitLength()
469*/
470void QCanSignalDescription::setStartBit(quint16 bit)
471{
472 d.detach();
473 d->startBit = bit;
474}
475
476/*!
477 Returns the bit length of the signal's value.
478
479 \sa setBitLength(), startBit(), setStartBit()
480*/
481quint16 QCanSignalDescription::bitLength() const
482{
483 return d->dataLength;
484}
485
486/*!
487 Sets the bit length of the signal's value to \a length.
488
489 \sa bitLength(), startBit(), setStartBit()
490*/
491void QCanSignalDescription::setBitLength(quint16 length)
492{
493 d.detach();
494 d->dataLength = length;
495}
496
497/*!
498 Returns the factor that is used to convert the signal's value to a physical
499 value and back.
500
501 By default the function returns \l qQNaN(), which means that a factor is not
502 used.
503
504 The \l {Value Conversions} section explains how this parameter is used.
505
506 \sa setFactor(), offset(), scaling()
507*/
508double QCanSignalDescription::factor() const
509{
510 return d->factor;
511}
512
513/*!
514 Sets the factor that is used to convert the signal's value to a physical
515 value and back to \a factor.
516
517 Pass \l qQNaN() to this method to skip this parameter during the conversion.
518
519 The factor cannot be 0. An attempt to set a zero factor is equivalent to
520 setting it to \l qQNaN().
521
522 The \l {Value Conversions} section explains how this parameter is used.
523
524 \sa factor(), setOffset(), setScaling()
525*/
526void QCanSignalDescription::setFactor(double factor)
527{
528 d.detach();
529 if (qFuzzyIsNull(d: factor))
530 d->factor = qQNaN();
531 else
532 d->factor = factor;
533}
534
535/*!
536 Returns the offset that is used to convert the signal's value to a physical
537 value and back.
538
539 By default the function returns \l qQNaN(), which means that an offset is
540 not used.
541
542 The \l {Value Conversions} section explains how this parameter is used.
543
544 \sa setOffset(), factor(), scaling()
545*/
546double QCanSignalDescription::offset() const
547{
548 return d->offset;
549}
550
551/*!
552 Sets the offset that is used to convert the signal's value to a physical
553 value and back to \a offset.
554
555 Pass \l qQNaN() to this method to skip this parameter during the conversion.
556
557 The \l {Value Conversions} section explains how this parameter is used.
558
559 \sa offset(), setFactor(), setScaling()
560*/
561void QCanSignalDescription::setOffset(double offset)
562{
563 d.detach();
564 d->offset = offset;
565}
566
567/*!
568 Returns the scaling that is used to convert the signal's value to a physical
569 value and back.
570
571 By default the function returns \l qQNaN(), which means that scaling is not
572 used.
573
574 The \l {Value Conversions} section explains how this parameter is used.
575
576 \sa setScaling(), offset(), factor()
577*/
578double QCanSignalDescription::scaling() const
579{
580 return d->scaling;
581}
582
583/*!
584 Sets the scaling that is used to convert the signal's value to a physical
585 value and back to \a scaling.
586
587 Pass \l qQNaN() to this method to skip this parameter during the conversion.
588
589 The scaling cannot be 0. An attempt to set zero scaling is equivalent to
590 setting it to \l qQNaN().
591
592 The \l {Value Conversions} section explains how this parameter is used.
593
594 \sa scaling(), setOffset(), setFactor()
595*/
596void QCanSignalDescription::setScaling(double scaling)
597{
598 d.detach();
599 if (qFuzzyIsNull(d: scaling))
600 d->scaling = qQNaN();
601 else
602 d->scaling = scaling;
603}
604
605/*!
606 Returns the minimum supported value for the signal.
607
608 By default the function returns \l qQNaN(), which means that there is no
609 minimum value.
610
611 \sa setRange(), maximum()
612*/
613double QCanSignalDescription::minimum() const
614{
615 return d->minimum;
616}
617
618/*!
619 Returns the maximum supported value for the signal.
620
621 By default the function returns \l qQNaN(), which means that there is no
622 maximum value.
623
624 \sa setRange(), minimum()
625*/
626double QCanSignalDescription::maximum() const
627{
628 return d->maximum;
629}
630
631/*!
632 Sets the \a minimum and \a maximum for the signal's value.
633
634 Setting one or both of the parameters to \l qQNaN() means that the
635 corresponding limit will not be used.
636
637 \sa minimum(), maximum()
638*/
639void QCanSignalDescription::setRange(double minimum, double maximum)
640{
641 d.detach();
642 if (qIsNaN(d: minimum) || qIsNaN(d: maximum) || minimum <= maximum) {
643 d->minimum = minimum;
644 d->maximum = maximum;
645 } else {
646 qWarning(msg: "Minimum value is greater than maximum. The values will be swapped.");
647 d->minimum = maximum;
648 d->maximum = minimum;
649 }
650}
651
652/*!
653 Returns the multiplex state of the signal.
654
655 See the \l {Multiplexed Signals Explained} section for more details on
656 multiplexed signals.
657
658 By default this method returns \l {QtCanBus::MultiplexState::}{None}.
659
660 \sa setMultiplexState(), QtCanBus::MultiplexState
661*/
662QtCanBus::MultiplexState QCanSignalDescription::multiplexState() const
663{
664 return d->muxState;
665}
666
667/*!
668 Sets the multiplex state of the signal to \a state.
669
670 See the \l {Multiplexed Signals Explained} section for more details on
671 multiplexed signals.
672
673 \sa multiplexState(), QtCanBus::MultiplexState
674*/
675void QCanSignalDescription::setMultiplexState(QtCanBus::MultiplexState state)
676{
677 d.detach();
678 d->muxState = state;
679}
680
681/*!
682 Returns the \l {Multiplexed Signals Explained}{multiplexor signals} and
683 their desired values that are used to properly identify this signal.
684
685 The returned hash contains signal names as keys and respective desired
686 ranges of values as values.
687
688 This signal's value can be extracted from the payload only when all the
689 signals from the hash have the expected values.
690
691 \sa multiplexState(), clearMultiplexSignals(), setMultiplexSignals(),
692 addMultiplexSignal()
693*/
694QCanSignalDescription::MultiplexSignalValues QCanSignalDescription::multiplexSignals() const
695{
696 return d->muxSignals;
697}
698
699/*!
700 Removes all \l {Multiplexed Signals Explained}{multiplexor signals} for
701 this signal.
702
703 \sa multiplexSignals(), setMultiplexSignals(), addMultiplexSignal()
704*/
705void QCanSignalDescription::clearMultiplexSignals()
706{
707 d.detach();
708 d->muxSignals.clear();
709}
710
711/*!
712 Sets the \l {Multiplexed Signals Explained}{multiplexor signals} for this
713 signal to \a multiplexorSignals.
714
715 The \a multiplexorSignals hash \e must contain signal names as keys and
716 respective desired value ranges as values.
717
718 \sa multiplexState(), multiplexSignals(), clearMultiplexSignals(),
719 addMultiplexSignal()
720*/
721void QCanSignalDescription::setMultiplexSignals(const MultiplexSignalValues &multiplexorSignals)
722{
723 d.detach();
724 d->muxSignals = multiplexorSignals;
725}
726
727/*!
728 Adds a new \l {Multiplexed Signals Explained}{multiplexor signal} for this
729 signal. The \a name parameter contains the name of the multiplexor signal,
730 and the \a ranges parameter contains the desired value ranges.
731
732 If this signal already has desired value ranges for the multiplexor signal
733 \a name, the ranges are overwritten.
734
735 \sa multiplexState(), multiplexSignals(), clearMultiplexSignals(),
736 setMultiplexSignals()
737*/
738void QCanSignalDescription::addMultiplexSignal(const QString &name, const MultiplexValues &ranges)
739{
740 d.detach();
741 d->muxSignals.insert(key: name, value: ranges);
742}
743
744/*!
745 \overload
746
747 This is a convenience overload for the case when the multiplexor signal is
748 expected to have only one specific value, not a range of values.
749
750 The \a name parameter contains the name of the multiplexor signal,
751 and the \a value parameter contains the desired value.
752
753 If this signal already has desired value ranges for the multiplexor signal
754 \a name, the ranges are overwritten.
755
756 \sa multiplexState(), multiplexSignals(), clearMultiplexSignals(),
757 setMultiplexSignals()
758*/
759void QCanSignalDescription::addMultiplexSignal(const QString &name, const QVariant &value)
760{
761 d.detach();
762 d->muxSignals.insert(key: name, value: { {.minimum: value, .maximum: value} });
763}
764
765#ifndef QT_NO_DEBUG_STREAM
766QDebug QCanSignalDescription::debugStreaming(QDebug dbg, const QCanSignalDescription &sig)
767{
768 QDebugStateSaver saver(dbg);
769 dbg.nospace() << "QCanSignalDescription(" << sig.name() << ", Source = " << sig.dataSource()
770 << ", Format = " << sig.dataFormat() << ", Endian = " << sig.dataEndian()
771 << ", StartBit = " << sig.startBit() << ", BitLength = " << sig.bitLength();
772 if (!sig.physicalUnit().isEmpty())
773 dbg << ", Units = " << sig.physicalUnit();
774 if (!sig.receiver().isEmpty())
775 dbg << ", Receiver = " << sig.receiver();
776 if (!sig.comment().isEmpty())
777 dbg << ", Comment = " << sig.comment();
778 dbg << ", Factor = " << sig.factor() << ", Offset = " << sig.offset()
779 << ", Scaling = " << sig.scaling();
780 dbg << ", Minimum = " << sig.minimum() << ", Maximum = " << sig.maximum();
781 dbg << ", Multiplex State = " << sig.multiplexState();
782 const auto muxSignals = sig.multiplexSignals();
783 if (!muxSignals.isEmpty()) {
784 dbg << ", Multiplexor Signals: {";
785 for (auto it = muxSignals.cbegin(); it != muxSignals.cend(); ++it) {
786 if (it != muxSignals.cbegin())
787 dbg << ", ";
788 dbg << "(" << it.key() << ", " << it.value() << ")";
789 }
790 dbg << "}";
791 }
792 dbg << ")";
793 return dbg;
794}
795
796QDebug QCanSignalDescription::MultiplexValueRange::debugStreaming(QDebug dbg,
797 const MultiplexValueRange &range)
798{
799 QDebugStateSaver saver(dbg);
800 dbg.nospace() << "MultiplexValueRange(" << range.minimum << ", " << range.maximum << ")";
801 return dbg;
802}
803#endif // QT_NO_DEBUG_STREAM
804
805template <typename T>
806static bool checkValue(const QVariant &valueVar,
807 const QCanSignalDescription::MultiplexValues &ranges)
808{
809 const T val = valueVar.value<T>();
810 for (const auto &pair : ranges) {
811 T min = pair.minimum.value<T>();
812 T max = pair.maximum.value<T>();
813 if (min > max)
814 max = std::exchange(min, max);
815 if (val >= min && val <= max)
816 return true;
817 }
818 return false;
819}
820
821bool QCanSignalDescriptionPrivate::muxValueInRange(
822 const QVariant &value, const QCanSignalDescription::MultiplexValues &ranges) const
823{
824 // Use the current data format to convert QVariant values.
825 // Do we really need it for Float, Double and Ascii?
826 switch (format) {
827 case QtCanBus::DataFormat::SignedInteger:
828 return checkValue<qint64>(valueVar: value, ranges);
829 case QtCanBus::DataFormat::UnsignedInteger:
830 return checkValue<quint64>(valueVar: value, ranges);
831 case QtCanBus::DataFormat::Float:
832 return checkValue<float>(valueVar: value, ranges);
833 case QtCanBus::DataFormat::Double:
834 return checkValue<double>(valueVar: value, ranges);
835 case QtCanBus::DataFormat::AsciiString:
836 return checkValue<QByteArray>(valueVar: value, ranges);
837 }
838
839 Q_UNREACHABLE_RETURN(false);
840}
841
842QCanSignalDescriptionPrivate *QCanSignalDescriptionPrivate::get(const QCanSignalDescription &desc)
843{
844 return desc.d.data();
845}
846
847QT_END_NAMESPACE
848

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