LCOV - code coverage report
Current view: top level - src/cli - scancommand.cpp (source / functions) Coverage Total Hit
Project: Dokit Lines: 99.0 % 291 288
Version: Functions: 100.0 % 17 17

            Line data    Source code
       1              : // SPDX-FileCopyrightText: 2022-2025 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         6779 : ScanCommand::ScanCommand(QObject * const parent) : AbstractCommand(parent)
      29         3085 : {
      30         2794 :     #if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) // Required signal, and Fields, added in Qt 5.12.
      31         7054 :     connect(discoveryAgent, &PokitDiscoveryAgent::pokitDeviceUpdated,
      32         4294 :             this, &ScanCommand::deviceUpdated);
      33         2794 :     #endif
      34         7642 : }
      35              : 
      36          320 : QStringList ScanCommand::requiredOptions(const QCommandLineParser &parser) const
      37          224 : {
      38          544 :     return AbstractCommand::requiredOptions(parser);
      39          224 : }
      40              : 
      41          160 : QStringList ScanCommand::supportedOptions(const QCommandLineParser &parser) const
      42          112 : {
      43          432 :     return AbstractCommand::supportedOptions(parser) + QStringList{
      44          374 :     };
      45          112 : }
      46              : 
      47              : /// \copydoc AbstractCommand::processOptions
      48           80 : QStringList ScanCommand::processOptions(const QCommandLineParser &parser)
      49           56 : {
      50          136 :     QStringList errors = AbstractCommand::processOptions(parser);
      51           56 :     if (!errors.isEmpty()) {
      52            0 :         return errors;
      53            0 :     }
      54              : 
      55           56 :     return errors;
      56           56 : }
      57              : 
      58              : /*!
      59              :  * Begins scanning for Pokit devices.
      60              :  */
      61           80 : bool ScanCommand::start()
      62           24 : {
      63           24 :     Q_ASSERT(discoveryAgent);
      64          256 :     qCInfo(lc).noquote() << tr("Scanning for Pokit devices...");
      65          104 :     discoveryAgent->start();
      66          104 :     return true;
      67           24 : }
      68              : 
      69              : /*!
      70              :  * Handles discovered Pokit devices, writing \a info to stdout.
      71              :  */
      72         6795 : void ScanCommand::deviceDiscovered(const QBluetoothDeviceInfo &info)
      73         4635 : {
      74        11430 :     switch (format) {
      75         1545 :     case OutputFormat::Csv:
      76         6096 :         for (; showCsvHeader; showCsvHeader = false) {
      77         3060 :             std::cout << qUtf8Printable(tr("uuid,address,name,major_class,minor_class,signal_strength\n"));
      78          927 :         }
      79        10020 :         std::cout << qUtf8Printable(QString::fromLatin1("%1,%2,%3,%4,%5,%6\n").arg(info.deviceUuid().toString(),
      80         1545 :             info.address().toString(), escapeCsvField(info.name()), toString(info.majorDeviceClass()),
      81         1545 :             toString(info.majorDeviceClass(), info.minorDeviceClass())).arg(info.rssi()));
      82         3810 :         break;
      83         3810 :     case OutputFormat::Json:
      84         6075 :         std::cout << QJsonDocument(toJson(info)).toJson().toStdString();
      85         3810 :         break;
      86         3810 :     case OutputFormat::Text:
      87         9090 :         std::cout << qUtf8Printable(tr("%1 %2 %3 %4\n").arg(info.deviceUuid().toString(),
      88         1545 :             info.address().toString(), info.name()).arg(info.rssi()));
      89         3810 :         break;
      90         4635 :     }
      91        11430 : }
      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         3195 : void ScanCommand::deviceUpdated(const QBluetoothDeviceInfo &info,
      98              :                                 const QBluetoothDeviceInfo::Fields updatedFields)
      99         2115 : {
     100         2115 :     Q_UNUSED(updatedFields)
     101         5310 :     deviceDiscovered(info);
     102         5310 : }
     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           80 : void ScanCommand::deviceDiscoveryFinished()
     110           56 : {
     111          165 :     qCDebug(lc).noquote() << tr("Finished scanning for Pokit devices.");
     112          136 :     QCoreApplication::quit();
     113          136 : }
     114              : 
     115              : /*!
     116              :  * Returns \a info as a JSON object.
     117              :  */
     118         2896 : QJsonObject ScanCommand::toJson(const QBluetoothDeviceInfo &info)
     119         1984 : {
     120         4880 :     if (!info.isValid()) {
     121          390 :         return QJsonObject();
     122          159 :     }
     123         1825 :     QJsonObject json{
     124         7155 :         { u"address"_s, info.address().toString() },
     125         7155 :         { u"name"_s, info.name() },
     126         6195 :         { u"isCached"_s, info.isCached() },
     127         6265 :         { u"majorDeviceClass"_s, info.majorDeviceClass() },
     128         7155 :         { u"majorDeviceClass"_s, toJson(info.majorDeviceClass()) },
     129         7155 :         { u"minorDeviceClass"_s, toJson(info.majorDeviceClass(), info.minorDeviceClass()) },
     130         7155 :         { u"signalStrength"_s, info.rssi() },
     131        31870 :     };
     132         4490 :     if (info.coreConfigurations() != QBluetoothDeviceInfo::UnknownCoreConfiguration) {
     133          945 :         json.insert(u"coreConfiguration"_s, toJson(info.coreConfigurations()));
     134          215 :     }
     135         4708 :     if (!info.deviceUuid().isNull()) {
     136         5785 :         json.insert(u"deviceUuid"_s, info.deviceUuid().toString());
     137         1151 :     }
     138         1645 :     #if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) // Added in Qt 5.12.
     139         4130 :     if (!info.manufacturerData().isEmpty()) {
     140          714 :         json.insert(u"manufacturerData"_s, toJson(info.manufacturerData()));
     141          141 :     }
     142         1645 :     #endif
     143         4490 :     if (info.serviceClasses() != QBluetoothDeviceInfo::NoService) {
     144         1161 :         json.insert(u"serviceClasses"_s, toJson(info.serviceClasses()));
     145          262 :     }
     146         5995 :     if (!info.serviceUuids().isEmpty()) {
     147          274 :         json.insert(u"serviceUuids"_s, toJson(info.serviceUuids()));
     148           56 :     }
     149         3775 :     return json;
     150        19024 : }
     151              : 
     152              : /*!
     153              :  * Returns \a configuration as a JSON array of strings.
     154              :  */
     155          631 : QJsonArray ScanCommand::toJson(const QBluetoothDeviceInfo::CoreConfigurations &configurations)
     156          439 : {
     157         1070 :     QJsonArray array;
     158          439 :     #define DOKIT_INTERNAL_IF_SET_THEN_APPEND(flag) \
     159         1317 :         if (configurations.testFlag(QBluetoothDeviceInfo::flag)) \
     160         1317 :             array.append(QLatin1String(#flag))
     161          841 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(UnknownCoreConfiguration);
     162         1122 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(LowEnergyCoreConfiguration);
     163          881 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(BaseRateCoreConfiguration);
     164              :   //DOKIT_INTERNAL_IF_SET_THEN_APPEND(BaseRateAndLowEnergyCoreConfiguration); // Combination flag.
     165          439 :     #undef DOKIT_INTERNAL_IF_SET_THEN_APPEND
     166         1070 :     return array;
     167          439 : }
     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         3785 : QJsonValue ScanCommand::toJson(const QBluetoothDeviceInfo::MajorDeviceClass &majorClass)
     176         2609 : {
     177         6394 :     const QString string = toString(majorClass);
     178        10179 :     return (string.isNull() ? QJsonValue(majorClass) : QJsonValue(string));
     179         4287 : }
     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        10025 : QJsonValue ScanCommand::toJson(const QBluetoothDeviceInfo::MajorDeviceClass &majorClass, const quint8 minorClass)
     189         6977 : {
     190        17002 :     const QString string = toString(majorClass, minorClass);
     191        27027 :     return (string.isNull() ? QJsonValue(minorClass) : QJsonValue(string));
     192        11541 : }
     193              : 
     194              : /*!
     195              :  * Returns \a classes as a JSON array of strings.
     196              :  */
     197         1182 : QJsonArray ScanCommand::toJson(const QBluetoothDeviceInfo::ServiceClasses &classes)
     198          822 : {
     199         2004 :     QJsonArray array;
     200          822 :     #define DOKIT_INTERNAL_IF_SET_THEN_APPEND(flag) \
     201         6576 :         if (classes.testFlag(QBluetoothDeviceInfo::flag)) \
     202         6576 :             array.append(QLatin1String(#flag))
     203         1855 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(PositioningService);
     204         1855 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(NetworkingService);
     205         1855 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(RenderingService);
     206         1797 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(CapturingService);
     207         1797 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(ObjectTransferService);
     208         1797 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(AudioService);
     209         1797 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(TelephonyService);
     210         1797 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(InformationService);
     211          822 :     #undef DOKIT_INTERNAL_IF_SET_THEN_APPEND
     212         2004 :     return array;
     213          822 : }
     214              : 
     215              : /*!
     216              :  * Returns \a uuids as a JSON array.
     217              :  */
     218          480 : QJsonArray ScanCommand::toJson(const QList<QBluetoothUuid> &uuids)
     219          336 : {
     220          816 :     QJsonArray array;
     221         2112 :     for (const QBluetoothUuid &uuid: uuids) {
     222         2004 :         array.append(uuid.toString());
     223          672 :     }
     224          816 :     return array;
     225          336 : }
     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          497 : QJsonObject ScanCommand::toJson(const QMultiHash<quint16, QByteArray> &data)
     232          329 : {
     233          826 :     QJsonObject object;
     234          826 :     QList<quint16> keys = data.uniqueKeys();
     235          630 :     std::sort(keys.begin(), keys.end());
     236         1677 :     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         1030 :         QList<QByteArray> values = data.values(key);
     241          900 :         std::reverse(values.begin(), values.end());
     242         1180 :         QJsonArray array;
     243         2432 :         for (const QByteArray &value: values) {
     244         3057 :             array.append(QLatin1String(value.toBase64()));
     245          687 :         }
     246         1540 :         object.insert(QString::number(key), array);
     247         1180 :     }
     248          826 :     return object;
     249          525 : }
     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         7170 : QString ScanCommand::toString(const QBluetoothDeviceInfo::MajorDeviceClass &majorClass)
     259         4938 : {
     260         4938 :     #define DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(value) \
     261        20374 :         if (majorClass == QBluetoothDeviceInfo::value) \
     262        20374 :             return QLatin1String(#value)
     263        12108 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(MiscellaneousDevice);
     264         3111 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ComputerDevice);
     265         2557 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(PhoneDevice);
     266          336 :     #if (QT_VERSION < QT_VERSION_CHECK(5, 13, 0))
     267          336 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(LANAccessDevice); // Deprecated since Qt 5.13.
     268              :     #else
     269         1499 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkDevice); // Added in Qt 5.13.
     270         1276 :     #endif
     271         1717 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(AudioVideoDevice);
     272         1599 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(PeripheralDevice);
     273         1481 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ImagingDevice);
     274         1363 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableDevice);
     275         1245 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ToyDevice);
     276         1127 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthDevice);
     277         1198 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedDevice);
     278          336 :     #undef DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN
     279          990 :     qCDebug(lc).noquote() << tr("Unknown major class %1.").arg(majorClass);
     280          336 :     return QString(); // Null QString indicates unknown minor class.
     281          916 : }
     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        19650 : QString ScanCommand::toString(const QBluetoothDeviceInfo::MajorDeviceClass &majorClass, const quint8 minorClass)
     291        13674 : {
     292        13674 :     #define DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(value) \
     293        60410 :         if (minorClass == QBluetoothDeviceInfo::value) \
     294        60410 :             return QLatin1String(#value)
     295        33324 :     switch (majorClass) {
     296         5660 :     case QBluetoothDeviceInfo::MiscellaneousDevice:
     297         5660 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedMiscellaneous);
     298          524 :         break;
     299         3192 :     case QBluetoothDeviceInfo::ComputerDevice:
     300         2220 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedComputer);
     301         1434 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(DesktopComputer);
     302         1304 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ServerComputer);
     303         1174 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(LaptopComputer);
     304         1044 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HandheldClamShellComputer);
     305          914 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HandheldComputer);
     306          784 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableComputer);
     307          524 :         break;
     308         2920 :     case QBluetoothDeviceInfo::PhoneDevice:
     309         2032 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedPhone);
     310         1304 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(CellularPhone);
     311         1174 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(CordlessPhone);
     312         1044 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(SmartPhone);
     313          914 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WiredModemOrVoiceGatewayPhone);
     314          784 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(CommonIsdnAccessPhone);
     315          524 :         break;
     316           84 :     #if (QT_VERSION < QT_VERSION_CHECK(5, 13, 0))
     317          468 :     case QBluetoothDeviceInfo::LANAccessDevice: // Deprecated since Qt 5.13.
     318              :     #else
     319         1980 :     case QBluetoothDeviceInfo::NetworkDevice: // Added in Qt 5.13.
     320          792 :     #endif
     321         1716 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkFullService);
     322         1080 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkLoadFactorOne);
     323          950 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkLoadFactorTwo);
     324          820 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkLoadFactorThree);
     325          690 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkLoadFactorFour);
     326          560 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkLoadFactorFive);
     327          430 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkLoadFactorSix);
     328          300 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkNoService);
     329          112 :         break;
     330         4896 :     case QBluetoothDeviceInfo::AudioVideoDevice:
     331         3194 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedAudioVideoDevice);
     332         2048 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableHeadsetDevice);
     333         1930 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HandsFreeDevice);
     334         1812 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(Microphone);
     335         1694 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(Loudspeaker);
     336         1576 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(Headphones);
     337         1458 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(PortableAudioDevice);
     338         1340 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(CarAudio);
     339         1222 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(SetTopBox);
     340         1104 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HiFiAudioDevice);
     341          986 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(Vcr);
     342          868 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(VideoCamera);
     343          750 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(Camcorder);
     344          632 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(VideoMonitor);
     345          514 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(VideoDisplayAndLoudspeaker);
     346          396 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(VideoConferencing);
     347          278 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(GamingDevice);
     348          112 :         break;
     349         2992 :     case QBluetoothDeviceInfo::PeripheralDevice:
     350         2092 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedPeripheral);
     351         1340 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(KeyboardPeripheral);
     352         1210 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(PointingDevicePeripheral);
     353         1080 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(KeyboardWithPointingDevicePeripheral);
     354          950 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(JoystickPeripheral);
     355          820 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(GamepadPeripheral);
     356          690 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(RemoteControlPeripheral);
     357          560 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(SensingDevicePeripheral);
     358          430 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(DigitizerTabletPeripheral);
     359          300 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(CardReaderPeripheral);
     360          112 :         break;
     361         1632 :     case QBluetoothDeviceInfo::ImagingDevice:
     362         1152 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedImagingDevice);
     363          964 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ImageDisplay);
     364          776 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ImageCamera);
     365          588 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ImageScanner);
     366          400 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ImagePrinter);
     367          112 :         break;
     368         1904 :     case QBluetoothDeviceInfo::WearableDevice:
     369         1340 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedWearableDevice);
     370          820 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableWristWatch);
     371          690 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearablePager);
     372          560 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableJacket);
     373          430 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableHelmet);
     374          300 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableGlasses);
     375          112 :         break;
     376         2448 :     case QBluetoothDeviceInfo::ToyDevice:
     377         1716 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedToy);
     378         1080 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ToyRobot);
     379          950 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ToyVehicle);
     380          820 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ToyDoll);
     381          690 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ToyController);
     382          560 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ToyGame);
     383          336 :         break;
     384         2448 :     case QBluetoothDeviceInfo::HealthDevice:
     385         1716 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedHealthDevice);
     386         1080 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthBloodPressureMonitor);
     387          950 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthThermometer);
     388          820 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthWeightScale);
     389          690 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthGlucoseMeter);
     390          560 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthPulseOximeter);
     391          430 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthDataDisplay);
     392          300 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthStepCounter);
     393          112 :         break;
     394          804 :     case QBluetoothDeviceInfo::UncategorizedDevice:
     395              :         // There are no minor classes defined (in Qt) for uncategorized devices.
     396          804 :         break;
     397        13674 :     }
     398         3720 :     #undef DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN
     399        11097 :     qCDebug(lc).noquote() << tr("Unknown minor class %1 for major class %2.")
     400            0 :         .arg(minorClass).arg(majorClass);
     401         3720 :     return QString(); // Null QString indicates unknown minor class.
     402        13674 : }
        

Generated by: LCOV version 2.3.1-1