Line data Source code
1 : // SPDX-FileCopyrightText: 2022-2026 Paul Colby <git@colby.id.au>
2 : // SPDX-License-Identifier: LGPL-3.0-or-later
3 :
4 : #include "scancommand.h"
5 : #include "../stringliterals_p.h"
6 :
7 : #include <qtpokit/pokitdiscoveryagent.h>
8 :
9 : #include <QBluetoothUuid>
10 : #include <QJsonArray>
11 : #include <QJsonDocument>
12 : #include <QJsonObject>
13 :
14 : #include <iostream>
15 :
16 : DOKIT_USE_STRINGLITERALS
17 :
18 : /*!
19 : * \class ScanCommand
20 : *
21 : * The ScanCommand class implements the `scan` CLI command, by scanning for nearby Pokit Bluetooth
22 : * devices. When devices are found, they are logged to stdout in the chosen format.
23 : */
24 :
25 : /*!
26 : * Construct a new ScanCommand object with \a parent.
27 : */
28 13059 : ScanCommand::ScanCommand(QObject * const parent) : AbstractCommand(parent)
29 7122 : {
30 6540 : #if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) // Required signal, and Fields, added in Qt 5.12.
31 12180 : connect(discoveryAgent, &PokitDiscoveryAgent::pokitDeviceUpdated,
32 9540 : this, &ScanCommand::deviceUpdated);
33 6540 : #endif
34 13059 : }
35 :
36 412 : QStringList ScanCommand::requiredOptions(const QCommandLineParser &parser) const
37 512 : {
38 924 : return AbstractCommand::requiredOptions(parser);
39 512 : }
40 :
41 206 : QStringList ScanCommand::supportedOptions(const QCommandLineParser &parser) const
42 256 : {
43 668 : return AbstractCommand::supportedOptions(parser) + QStringList{
44 558 : };
45 256 : }
46 :
47 : /// \copydoc AbstractCommand::processOptions
48 103 : QStringList ScanCommand::processOptions(const QCommandLineParser &parser)
49 128 : {
50 231 : QStringList errors = AbstractCommand::processOptions(parser);
51 128 : if (!errors.isEmpty()) {
52 0 : return errors;
53 0 : }
54 :
55 128 : return errors;
56 128 : }
57 :
58 : /*!
59 : * Begins scanning for Pokit devices.
60 : */
61 103 : bool ScanCommand::start()
62 56 : {
63 56 : Q_ASSERT(discoveryAgent);
64 387 : qCInfo(lc).noquote() << tr("Scanning for Pokit devices...");
65 159 : discoveryAgent->start();
66 159 : return true;
67 56 : }
68 :
69 : /*!
70 : * Handles discovered Pokit devices, writing \a info to stdout.
71 : */
72 8865 : void ScanCommand::deviceDiscovered(const QBluetoothDeviceInfo &info)
73 10710 : {
74 19575 : switch (format) {
75 3570 : case OutputFormat::Csv:
76 10440 : for (; showCsvHeader; showCsvHeader = false) {
77 5175 : std::cout << qUtf8Printable(tr("uuid,address,name,major_class,minor_class,signal_strength\n"));
78 2142 : }
79 15675 : std::cout << qUtf8Printable(QString::fromLatin1("%1,%2,%3,%4,%5,%6\n").arg(info.deviceUuid().toString(),
80 3570 : info.address().toString(), escapeCsvField(info.name()), toString(info.majorDeviceClass()),
81 3570 : toString(info.majorDeviceClass(), info.minorDeviceClass())).arg(info.rssi()));
82 6525 : break;
83 6525 : case OutputFormat::Json:
84 9480 : std::cout << QJsonDocument(toJson(info)).toJson().toStdString();
85 6525 : break;
86 6525 : case OutputFormat::Text:
87 13995 : std::cout << qUtf8Printable(tr("%1 %2 %3 %4\n").arg(info.deviceUuid().toString(),
88 3570 : info.address().toString(), info.name()).arg(info.rssi()));
89 6525 : break;
90 10710 : }
91 19575 : }
92 :
93 : /*!
94 : * Handles updated Pokit devices, writing \a info to stdout. Currently \a updatedFields us unused.
95 : */
96 : #if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) // Required signal, and Fields, added in Qt 5.12.
97 4230 : void ScanCommand::deviceUpdated(const QBluetoothDeviceInfo &info,
98 : const QBluetoothDeviceInfo::Fields updatedFields)
99 4950 : {
100 4950 : Q_UNUSED(updatedFields)
101 9180 : deviceDiscovered(info);
102 9180 : }
103 : #endif
104 :
105 : /*!
106 : * Handles the completion of device discovery. In this override we simply exit, as the scan command
107 : * is nothing more than logging of discovered devices.
108 : */
109 103 : void ScanCommand::deviceDiscoveryFinished()
110 128 : {
111 286 : qCDebug(lc).noquote() << tr("Finished scanning for Pokit devices.");
112 231 : QCoreApplication::quit();
113 231 : }
114 :
115 : /*!
116 : * Returns \a info as a JSON object.
117 : */
118 3770 : QJsonObject ScanCommand::toJson(const QBluetoothDeviceInfo &info)
119 4576 : {
120 8346 : if (!info.isValid()) {
121 666 : return QJsonObject();
122 366 : }
123 4210 : QJsonObject json{
124 11150 : { u"address"_s, info.address().toString() },
125 11150 : { u"name"_s, info.name() },
126 10600 : { u"isCached"_s, info.isCached() },
127 10670 : { u"majorDeviceClass"_s, info.majorDeviceClass() },
128 11150 : { u"majorDeviceClass"_s, toJson(info.majorDeviceClass()) },
129 11150 : { u"minorDeviceClass"_s, toJson(info.majorDeviceClass(), info.minorDeviceClass()) },
130 11150 : { u"signalStrength"_s, info.rssi() },
131 40660 : };
132 7680 : if (info.coreConfigurations() != QBluetoothDeviceInfo::UnknownCoreConfiguration) {
133 1440 : json.insert(u"coreConfiguration"_s, toJson(info.coreConfigurations()));
134 494 : }
135 8356 : if (!info.deviceUuid().isNull()) {
136 9026 : json.insert(u"deviceUuid"_s, info.deviceUuid().toString());
137 2654 : }
138 3850 : #if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) // Added in Qt 5.12.
139 7140 : if (!info.manufacturerData().isEmpty()) {
140 1053 : json.insert(u"manufacturerData"_s, toJson(info.manufacturerData()));
141 330 : }
142 3850 : #endif
143 7680 : if (info.serviceClasses() != QBluetoothDeviceInfo::NoService) {
144 1773 : json.insert(u"serviceClasses"_s, toJson(info.serviceClasses()));
145 604 : }
146 10130 : if (!info.serviceUuids().isEmpty()) {
147 425 : json.insert(u"serviceUuids"_s, toJson(info.serviceUuids()));
148 128 : }
149 7140 : return json;
150 24736 : }
151 :
152 : /*!
153 : * Returns \a configuration as a JSON array of strings.
154 : */
155 815 : QJsonArray ScanCommand::toJson(const QBluetoothDeviceInfo::CoreConfigurations &configurations)
156 1006 : {
157 1821 : QJsonArray array;
158 1006 : #define DOKIT_INTERNAL_IF_SET_THEN_APPEND(flag) \
159 3018 : if (configurations.testFlag(QBluetoothDeviceInfo::flag)) \
160 3018 : array.append(QLatin1String(#flag))
161 1630 : DOKIT_INTERNAL_IF_SET_THEN_APPEND(UnknownCoreConfiguration);
162 1941 : DOKIT_INTERNAL_IF_SET_THEN_APPEND(LowEnergyCoreConfiguration);
163 1676 : DOKIT_INTERNAL_IF_SET_THEN_APPEND(BaseRateCoreConfiguration);
164 : //DOKIT_INTERNAL_IF_SET_THEN_APPEND(BaseRateAndLowEnergyCoreConfiguration); // Combination flag.
165 1006 : #undef DOKIT_INTERNAL_IF_SET_THEN_APPEND
166 1821 : return array;
167 1006 : }
168 :
169 : /*!
170 : * Returns \a majorClass as a JSON value. This is equivalent to toString, except that if toString
171 : * does not recognise \a majorClass, then \a majorClass is returned as a JSON number (not a string).
172 : *
173 : * \see toString(const QBluetoothDeviceInfo::MajorDeviceClass &majorClass)
174 : */
175 4912 : QJsonValue ScanCommand::toJson(const QBluetoothDeviceInfo::MajorDeviceClass &majorClass)
176 6002 : {
177 10914 : const QString string = toString(majorClass);
178 15826 : return (string.isNull() ? QJsonValue(majorClass) : QJsonValue(string));
179 7484 : }
180 :
181 : /*!
182 : * Returns \a minorClass as a JSON value. This is equivalent to toString, except that if toString
183 : * does not recognise \a minorClass as a sub-class of \a majorClass, then \a minorClass is returned
184 : * as a JSON number (not a string).
185 : *
186 : * \see toString(const QBluetoothDeviceInfo::MajorDeviceClass &majorClass, const quint8 minorClass)
187 : */
188 12946 : QJsonValue ScanCommand::toJson(const QBluetoothDeviceInfo::MajorDeviceClass &majorClass, const quint8 minorClass)
189 15986 : {
190 28932 : const QString string = toString(majorClass, minorClass);
191 41878 : return (string.isNull() ? QJsonValue(minorClass) : QJsonValue(string));
192 20042 : }
193 :
194 : /*!
195 : * Returns \a classes as a JSON array of strings.
196 : */
197 1527 : QJsonArray ScanCommand::toJson(const QBluetoothDeviceInfo::ServiceClasses &classes)
198 1884 : {
199 3411 : QJsonArray array;
200 1884 : #define DOKIT_INTERNAL_IF_SET_THEN_APPEND(flag) \
201 15072 : if (classes.testFlag(QBluetoothDeviceInfo::flag)) \
202 15072 : array.append(QLatin1String(#flag))
203 3364 : DOKIT_INTERNAL_IF_SET_THEN_APPEND(PositioningService);
204 3364 : DOKIT_INTERNAL_IF_SET_THEN_APPEND(NetworkingService);
205 3364 : DOKIT_INTERNAL_IF_SET_THEN_APPEND(RenderingService);
206 3300 : DOKIT_INTERNAL_IF_SET_THEN_APPEND(CapturingService);
207 3300 : DOKIT_INTERNAL_IF_SET_THEN_APPEND(ObjectTransferService);
208 3300 : DOKIT_INTERNAL_IF_SET_THEN_APPEND(AudioService);
209 3300 : DOKIT_INTERNAL_IF_SET_THEN_APPEND(TelephonyService);
210 3300 : DOKIT_INTERNAL_IF_SET_THEN_APPEND(InformationService);
211 1884 : #undef DOKIT_INTERNAL_IF_SET_THEN_APPEND
212 3411 : return array;
213 1884 : }
214 :
215 : /*!
216 : * Returns \a uuids as a JSON array.
217 : */
218 618 : QJsonArray ScanCommand::toJson(const QList<QBluetoothUuid> &uuids)
219 768 : {
220 1386 : QJsonArray array;
221 3390 : for (const QBluetoothUuid &uuid: uuids) {
222 3444 : array.append(uuid.toString());
223 1536 : }
224 1386 : return array;
225 768 : }
226 :
227 : /*!
228 : * Returns Bluetooth manufacturer \a data as a JSON object that maps the manufacturer IDs (unsigned
229 : * integers as strings) to arrays of one or more values.
230 : */
231 658 : QJsonObject ScanCommand::toJson(const QMultiHash<quint16, QByteArray> &data)
232 770 : {
233 1428 : QJsonObject object;
234 1428 : QList<quint16> keys = data.uniqueKeys();
235 1260 : std::sort(keys.begin(), keys.end());
236 2698 : for (const quint16 key: keys) {
237 : // Convert the key's values to a JSON array, reversing the order, because QMultiHash
238 : // guarantees that the values are order "from the most recently inserted to the least
239 : // recently inserted", which is the opposite of what we want.
240 1670 : QList<QByteArray> values = data.values(key);
241 1800 : std::reverse(values.begin(), values.end());
242 2040 : QJsonArray array;
243 3946 : for (const QByteArray &value: values) {
244 4983 : array.append(QLatin1String(value.toBase64()));
245 1614 : }
246 2580 : object.insert(QString::number(key), array);
247 2040 : }
248 1428 : return object;
249 938 : }
250 :
251 : /*!
252 : * Returns \a majorClass as a human-readable string, or a null QString if \a majorClass is not
253 : * recognised.
254 : *
255 : * For example, if \a majorClass is \c QBluetoothDeviceInfo::ToyDevice, then the string `ToyDevice`
256 : * is returned.
257 : */
258 9309 : QString ScanCommand::toString(const QBluetoothDeviceInfo::MajorDeviceClass &majorClass)
259 11364 : {
260 11364 : #define DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(value) \
261 46780 : if (majorClass == QBluetoothDeviceInfo::value) \
262 46780 : return QLatin1String(#value)
263 20673 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(MiscellaneousDevice);
264 6705 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ComputerDevice);
265 5467 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(PhoneDevice);
266 672 : #if (QT_VERSION < QT_VERSION_CHECK(5, 13, 0))
267 672 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(LANAccessDevice); // Deprecated since Qt 5.13.
268 : #else
269 3365 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkDevice); // Added in Qt 5.13.
270 3016 : #endif
271 3775 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(AudioVideoDevice);
272 3513 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(PeripheralDevice);
273 3251 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ImagingDevice);
274 2989 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableDevice);
275 2727 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ToyDevice);
276 2465 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthDevice);
277 2419 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedDevice);
278 768 : #undef DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN
279 2570 : qCDebug(lc).noquote() << tr("Unknown major class %1.").arg(majorClass);
280 882 : return QString(); // Null QString indicates unknown minor class.
281 2104 : }
282 :
283 : /*!
284 : * Returns \a minorClass as a human-readable string, or a null QString if \a minorClass is not
285 : * recognised as a sub-class of \a majorClass.
286 : *
287 : * For example, if \a majorClass is \c QBluetoothDeviceInfo::ToyDevice, and \a minorClass is
288 : * \c QBluetoothDeviceInfo::ToyRobot, then the string `ToyRobot` is returned.
289 : */
290 25377 : QString ScanCommand::toString(const QBluetoothDeviceInfo::MajorDeviceClass &majorClass, const quint8 minorClass)
291 31332 : {
292 31332 : #define DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(value) \
293 138260 : if (minorClass == QBluetoothDeviceInfo::value) \
294 138260 : return QLatin1String(#value)
295 56709 : switch (majorClass) {
296 9678 : case QBluetoothDeviceInfo::MiscellaneousDevice:
297 9678 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedMiscellaneous);
298 1208 : break;
299 5436 : case QBluetoothDeviceInfo::ComputerDevice:
300 3958 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedComputer);
301 3208 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(DesktopComputer);
302 2914 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ServerComputer);
303 2620 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(LaptopComputer);
304 2326 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HandheldClamShellComputer);
305 2032 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HandheldComputer);
306 1738 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableComputer);
307 1208 : break;
308 4974 : case QBluetoothDeviceInfo::PhoneDevice:
309 3624 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedPhone);
310 2914 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(CellularPhone);
311 2620 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(CordlessPhone);
312 2326 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(SmartPhone);
313 2032 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WiredModemOrVoiceGatewayPhone);
314 1738 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(CommonIsdnAccessPhone);
315 1208 : break;
316 168 : #if (QT_VERSION < QT_VERSION_CHECK(5, 13, 0))
317 648 : case QBluetoothDeviceInfo::LANAccessDevice: // Deprecated since Qt 5.13.
318 : #else
319 3510 : case QBluetoothDeviceInfo::NetworkDevice: // Added in Qt 5.13.
320 1872 : #endif
321 3040 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkFullService);
322 2398 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkLoadFactorOne);
323 2104 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkLoadFactorTwo);
324 1810 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkLoadFactorThree);
325 1516 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkLoadFactorFour);
326 1222 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkLoadFactorFive);
327 928 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkLoadFactorSix);
328 634 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkNoService);
329 256 : break;
330 8316 : case QBluetoothDeviceInfo::AudioVideoDevice:
331 5472 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedAudioVideoDevice);
332 4502 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableHeadsetDevice);
333 4240 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HandsFreeDevice);
334 3978 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(Microphone);
335 3716 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(Loudspeaker);
336 3454 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(Headphones);
337 3192 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(PortableAudioDevice);
338 2930 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(CarAudio);
339 2668 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(SetTopBox);
340 2406 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HiFiAudioDevice);
341 2144 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(Vcr);
342 1882 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(VideoCamera);
343 1620 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(Camcorder);
344 1358 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(VideoMonitor);
345 1096 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(VideoDisplayAndLoudspeaker);
346 834 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(VideoConferencing);
347 572 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(GamingDevice);
348 256 : break;
349 5082 : case QBluetoothDeviceInfo::PeripheralDevice:
350 3708 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedPeripheral);
351 2986 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(KeyboardPeripheral);
352 2692 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(PointingDevicePeripheral);
353 2398 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(KeyboardWithPointingDevicePeripheral);
354 2104 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(JoystickPeripheral);
355 1810 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(GamepadPeripheral);
356 1516 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(RemoteControlPeripheral);
357 1222 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(SensingDevicePeripheral);
358 928 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(DigitizerTabletPeripheral);
359 634 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(CardReaderPeripheral);
360 256 : break;
361 2772 : case QBluetoothDeviceInfo::ImagingDevice:
362 2038 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedImagingDevice);
363 1704 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ImageDisplay);
364 1370 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ImageCamera);
365 1036 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ImageScanner);
366 702 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ImagePrinter);
367 256 : break;
368 3234 : case QBluetoothDeviceInfo::WearableDevice:
369 2372 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedWearableDevice);
370 1810 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableWristWatch);
371 1516 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearablePager);
372 1222 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableJacket);
373 928 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableHelmet);
374 634 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableGlasses);
375 256 : break;
376 4158 : case QBluetoothDeviceInfo::ToyDevice:
377 3040 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedToy);
378 2398 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ToyRobot);
379 2104 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ToyVehicle);
380 1810 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ToyDoll);
381 1516 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ToyController);
382 1222 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ToyGame);
383 768 : break;
384 4158 : case QBluetoothDeviceInfo::HealthDevice:
385 3040 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedHealthDevice);
386 2398 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthBloodPressureMonitor);
387 2104 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthThermometer);
388 1810 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthWeightScale);
389 1516 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthGlucoseMeter);
390 1222 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthPulseOximeter);
391 928 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthDataDisplay);
392 634 : DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthStepCounter);
393 256 : break;
394 1848 : case QBluetoothDeviceInfo::UncategorizedDevice:
395 : // There are no minor classes defined (in Qt) for uncategorized devices.
396 1848 : break;
397 31332 : }
398 8544 : #undef DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN
399 33894 : qCDebug(lc).noquote() << tr("Unknown minor class %1 for major class %2.")
400 0 : .arg(minorClass).arg(majorClass);
401 9855 : return QString(); // Null QString indicates unknown minor class.
402 31332 : }
|