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-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         9205 : ScanCommand::ScanCommand(QObject * const parent) : AbstractCommand(parent)
      29         6089 : {
      30         5510 :     #if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) // Required signal, and Fields, added in Qt 5.12.
      31         9350 :     connect(discoveryAgent, &PokitDiscoveryAgent::pokitDeviceUpdated,
      32         7310 :             this, &ScanCommand::deviceUpdated);
      33         5510 :     #endif
      34        10127 : }
      35              : 
      36          280 : QStringList ScanCommand::requiredOptions(const QCommandLineParser &parser) const
      37          444 : {
      38          724 :     return AbstractCommand::requiredOptions(parser);
      39          444 : }
      40              : 
      41          140 : QStringList ScanCommand::supportedOptions(const QCommandLineParser &parser) const
      42          222 : {
      43          502 :     return AbstractCommand::supportedOptions(parser) + QStringList{
      44          434 :     };
      45          222 : }
      46              : 
      47              : /// \copydoc AbstractCommand::processOptions
      48           70 : QStringList ScanCommand::processOptions(const QCommandLineParser &parser)
      49          111 : {
      50          181 :     QStringList errors = AbstractCommand::processOptions(parser);
      51          111 :     if (!errors.isEmpty()) {
      52            0 :         return errors;
      53            0 :     }
      54              : 
      55          111 :     return errors;
      56          111 : }
      57              : 
      58              : /*!
      59              :  * Begins scanning for Pokit devices.
      60              :  */
      61           70 : bool ScanCommand::start()
      62           26 : {
      63           26 :     Q_ASSERT(discoveryAgent);
      64          246 :     qCInfo(lc).noquote() << tr("Scanning for Pokit devices...");
      65           96 :     discoveryAgent->start();
      66           96 :     return true;
      67           26 : }
      68              : 
      69              : /*!
      70              :  * Handles discovered Pokit devices, writing \a info to stdout.
      71              :  */
      72         6030 : void ScanCommand::deviceDiscovered(const QBluetoothDeviceInfo &info)
      73         9180 : {
      74        15210 :     switch (format) {
      75         3060 :     case OutputFormat::Csv:
      76         8112 :         for (; showCsvHeader; showCsvHeader = false) {
      77         3870 :             std::cout << qUtf8Printable(tr("uuid,address,name,major_class,minor_class,signal_strength\n"));
      78         1836 :         }
      79        11040 :         std::cout << qUtf8Printable(QString::fromLatin1("%1,%2,%3,%4,%5,%6\n").arg(info.deviceUuid().toString(),
      80         3060 :             info.address().toString(), escapeCsvField(info.name()), toString(info.majorDeviceClass()),
      81         3060 :             toString(info.majorDeviceClass(), info.minorDeviceClass())).arg(info.rssi()));
      82         5070 :         break;
      83         5070 :     case OutputFormat::Json:
      84         7080 :         std::cout << QJsonDocument(toJson(info)).toJson().toStdString();
      85         5070 :         break;
      86         5070 :     case OutputFormat::Text:
      87        10050 :         std::cout << qUtf8Printable(tr("%1 %2 %3 %4\n").arg(info.deviceUuid().toString(),
      88         3060 :             info.address().toString(), info.name()).arg(info.rssi()));
      89         5070 :         break;
      90         9180 :     }
      91        15210 : }
      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         2880 : void ScanCommand::deviceUpdated(const QBluetoothDeviceInfo &info,
      98              :                                 const QBluetoothDeviceInfo::Fields updatedFields)
      99         4185 : {
     100         4185 :     Q_UNUSED(updatedFields)
     101         7065 :     deviceDiscovered(info);
     102         7065 : }
     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           70 : void ScanCommand::deviceDiscoveryFinished()
     110          111 : {
     111          215 :     qCDebug(lc).noquote() << tr("Finished scanning for Pokit devices.");
     112          181 :     QCoreApplication::quit();
     113          181 : }
     114              : 
     115              : /*!
     116              :  * Returns \a info as a JSON object.
     117              :  */
     118         2564 : QJsonObject ScanCommand::toJson(const QBluetoothDeviceInfo &info)
     119         3930 : {
     120         6494 :     if (!info.isValid()) {
     121          519 :         return QJsonObject();
     122          315 :     }
     123         3615 :     QJsonObject json{
     124         8335 :         { u"address"_s, info.address().toString() },
     125         8335 :         { u"name"_s, info.name() },
     126         7785 :         { u"isCached"_s, info.isCached() },
     127         7855 :         { u"majorDeviceClass"_s, info.majorDeviceClass() },
     128         8335 :         { u"majorDeviceClass"_s, toJson(info.majorDeviceClass()) },
     129         8335 :         { u"minorDeviceClass"_s, toJson(info.majorDeviceClass(), info.minorDeviceClass()) },
     130         8335 :         { u"signalStrength"_s, info.rssi() },
     131        29935 :     };
     132         5975 :     if (info.coreConfigurations() != QBluetoothDeviceInfo::UnknownCoreConfiguration) {
     133         1086 :         json.insert(u"coreConfiguration"_s, toJson(info.coreConfigurations()));
     134          426 :     }
     135         6302 :     if (!info.deviceUuid().isNull()) {
     136         6594 :         json.insert(u"deviceUuid"_s, info.deviceUuid().toString());
     137         2280 :     }
     138         3255 :     #if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) // Added in Qt 5.12.
     139         5495 :     if (!info.manufacturerData().isEmpty()) {
     140          783 :         json.insert(u"manufacturerData"_s, toJson(info.manufacturerData()));
     141          279 :     }
     142         3255 :     #endif
     143         5975 :     if (info.serviceClasses() != QBluetoothDeviceInfo::NoService) {
     144         1335 :         json.insert(u"serviceClasses"_s, toJson(info.serviceClasses()));
     145          519 :     }
     146         7585 :     if (!info.serviceUuids().isEmpty()) {
     147          312 :         json.insert(u"serviceUuids"_s, toJson(info.serviceUuids()));
     148          111 :     }
     149         5580 :     return json;
     150        17065 : }
     151              : 
     152              : /*!
     153              :  * Returns \a configuration as a JSON array of strings.
     154              :  */
     155          554 : QJsonArray ScanCommand::toJson(const QBluetoothDeviceInfo::CoreConfigurations &configurations)
     156          870 : {
     157         1424 :     QJsonArray array;
     158          870 :     #define DOKIT_INTERNAL_IF_SET_THEN_APPEND(flag) \
     159         2610 :         if (configurations.testFlag(QBluetoothDeviceInfo::flag)) \
     160         2610 :             array.append(QLatin1String(#flag))
     161         1288 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(UnknownCoreConfiguration);
     162         1532 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(LowEnergyCoreConfiguration);
     163         1326 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(BaseRateCoreConfiguration);
     164              :   //DOKIT_INTERNAL_IF_SET_THEN_APPEND(BaseRateAndLowEnergyCoreConfiguration); // Combination flag.
     165          870 :     #undef DOKIT_INTERNAL_IF_SET_THEN_APPEND
     166         1424 :     return array;
     167          870 : }
     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         3340 : QJsonValue ScanCommand::toJson(const QBluetoothDeviceInfo::MajorDeviceClass &majorClass)
     176         5169 : {
     177         8509 :     const QString string = toString(majorClass);
     178        11849 :     return (string.isNull() ? QJsonValue(majorClass) : QJsonValue(string));
     179         6255 : }
     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         8800 : QJsonValue ScanCommand::toJson(const QBluetoothDeviceInfo::MajorDeviceClass &majorClass, const quint8 minorClass)
     189        13827 : {
     190        22627 :     const QString string = toString(majorClass, minorClass);
     191        31427 :     return (string.isNull() ? QJsonValue(minorClass) : QJsonValue(string));
     192        16785 : }
     193              : 
     194              : /*!
     195              :  * Returns \a classes as a JSON array of strings.
     196              :  */
     197         1038 : QJsonArray ScanCommand::toJson(const QBluetoothDeviceInfo::ServiceClasses &classes)
     198         1629 : {
     199         2667 :     QJsonArray array;
     200         1629 :     #define DOKIT_INTERNAL_IF_SET_THEN_APPEND(flag) \
     201        13032 :         if (classes.testFlag(QBluetoothDeviceInfo::flag)) \
     202        13032 :             array.append(QLatin1String(#flag))
     203         2657 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(PositioningService);
     204         2657 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(NetworkingService);
     205         2657 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(RenderingService);
     206         2607 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(CapturingService);
     207         2607 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(ObjectTransferService);
     208         2607 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(AudioService);
     209         2607 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(TelephonyService);
     210         2607 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(InformationService);
     211         1629 :     #undef DOKIT_INTERNAL_IF_SET_THEN_APPEND
     212         2667 :     return array;
     213         1629 : }
     214              : 
     215              : /*!
     216              :  * Returns \a uuids as a JSON array.
     217              :  */
     218          420 : QJsonArray ScanCommand::toJson(const QList<QBluetoothUuid> &uuids)
     219          666 : {
     220         1086 :     QJsonArray array;
     221         2592 :     for (const QBluetoothUuid &uuid: uuids) {
     222         2568 :         array.append(uuid.toString());
     223         1332 :     }
     224         1086 :     return array;
     225          666 : }
     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          448 : QJsonObject ScanCommand::toJson(const QMultiHash<quint16, QByteArray> &data)
     232          651 : {
     233         1099 :     QJsonObject object;
     234         1099 :     QList<quint16> keys = data.uniqueKeys();
     235          973 :     std::sort(keys.begin(), keys.end());
     236         2018 :     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         1370 :         QList<QByteArray> values = data.values(key);
     241         1390 :         std::reverse(values.begin(), values.end());
     242         1570 :         QJsonArray array;
     243         2947 :         for (const QByteArray &value: values) {
     244         3570 :             array.append(QLatin1String(value.toBase64()));
     245         1359 :         }
     246         1950 :         object.insert(QString::number(key), array);
     247         1570 :     }
     248         1099 :     return object;
     249          777 : }
     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         6330 : QString ScanCommand::toString(const QBluetoothDeviceInfo::MajorDeviceClass &majorClass)
     259         9783 : {
     260         9783 :     #define DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(value) \
     261        40371 :         if (majorClass == QBluetoothDeviceInfo::value) \
     262        40371 :             return QLatin1String(#value)
     263        16113 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(MiscellaneousDevice);
     264         5788 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ComputerDevice);
     265         4720 :     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         2828 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkDevice); // Added in Qt 5.13.
     270         2523 :     #endif
     271         3272 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(AudioVideoDevice);
     272         3044 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(PeripheralDevice);
     273         2816 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ImagingDevice);
     274         2588 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableDevice);
     275         2360 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ToyDevice);
     276         2132 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthDevice);
     277         2075 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedDevice);
     278          666 :     #undef DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN
     279         1815 :     qCDebug(lc).noquote() << tr("Unknown major class %1.").arg(majorClass);
     280          666 :     return QString(); // Null QString indicates unknown minor class.
     281         1815 : }
     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        17250 : QString ScanCommand::toString(const QBluetoothDeviceInfo::MajorDeviceClass &majorClass, const quint8 minorClass)
     291        27099 : {
     292        27099 :     #define DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(value) \
     293       119730 :         if (minorClass == QBluetoothDeviceInfo::value) \
     294       119730 :             return QLatin1String(#value)
     295        44349 :     switch (majorClass) {
     296         7532 :     case QBluetoothDeviceInfo::MiscellaneousDevice:
     297         7532 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedMiscellaneous);
     298         1038 :         break;
     299         4248 :     case QBluetoothDeviceInfo::ComputerDevice:
     300         3300 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedComputer);
     301         2626 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(DesktopComputer);
     302         2384 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ServerComputer);
     303         2142 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(LaptopComputer);
     304         1900 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HandheldClamShellComputer);
     305         1658 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HandheldComputer);
     306         1416 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableComputer);
     307         1038 :         break;
     308         3886 :     case QBluetoothDeviceInfo::PhoneDevice:
     309         3020 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedPhone);
     310         2384 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(CellularPhone);
     311         2142 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(CordlessPhone);
     312         1900 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(SmartPhone);
     313         1658 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WiredModemOrVoiceGatewayPhone);
     314         1416 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(CommonIsdnAccessPhone);
     315         1038 :         break;
     316          168 :     #if (QT_VERSION < QT_VERSION_CHECK(5, 13, 0))
     317          576 :     case QBluetoothDeviceInfo::LANAccessDevice: // Deprecated since Qt 5.13.
     318              :     #else
     319         2682 :     case QBluetoothDeviceInfo::NetworkDevice: // Added in Qt 5.13.
     320         1566 :     #endif
     321         2544 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkFullService);
     322         1972 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkLoadFactorOne);
     323         1730 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkLoadFactorTwo);
     324         1488 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkLoadFactorThree);
     325         1246 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkLoadFactorFour);
     326         1004 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkLoadFactorFive);
     327          762 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkLoadFactorSix);
     328          520 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkNoService);
     329          222 :         break;
     330         6516 :     case QBluetoothDeviceInfo::AudioVideoDevice:
     331         4814 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedAudioVideoDevice);
     332         3914 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableHeadsetDevice);
     333         3686 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HandsFreeDevice);
     334         3458 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(Microphone);
     335         3230 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(Loudspeaker);
     336         3002 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(Headphones);
     337         2774 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(PortableAudioDevice);
     338         2546 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(CarAudio);
     339         2318 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(SetTopBox);
     340         2090 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HiFiAudioDevice);
     341         1862 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(Vcr);
     342         1634 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(VideoCamera);
     343         1406 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(Camcorder);
     344         1178 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(VideoMonitor);
     345          950 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(VideoDisplayAndLoudspeaker);
     346          722 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(VideoConferencing);
     347          494 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(GamingDevice);
     348          222 :         break;
     349         3982 :     case QBluetoothDeviceInfo::PeripheralDevice:
     350         3104 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedPeripheral);
     351         2456 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(KeyboardPeripheral);
     352         2214 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(PointingDevicePeripheral);
     353         1972 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(KeyboardWithPointingDevicePeripheral);
     354         1730 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(JoystickPeripheral);
     355         1488 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(GamepadPeripheral);
     356         1246 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(RemoteControlPeripheral);
     357         1004 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(SensingDevicePeripheral);
     358          762 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(DigitizerTabletPeripheral);
     359          520 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(CardReaderPeripheral);
     360          222 :         break;
     361         2172 :     case QBluetoothDeviceInfo::ImagingDevice:
     362         1704 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedImagingDevice);
     363         1424 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ImageDisplay);
     364         1144 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ImageCamera);
     365          864 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ImageScanner);
     366          584 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ImagePrinter);
     367          222 :         break;
     368         2534 :     case QBluetoothDeviceInfo::WearableDevice:
     369         1984 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedWearableDevice);
     370         1488 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableWristWatch);
     371         1246 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearablePager);
     372         1004 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableJacket);
     373          762 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableHelmet);
     374          520 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableGlasses);
     375          222 :         break;
     376         3258 :     case QBluetoothDeviceInfo::ToyDevice:
     377         2544 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedToy);
     378         1972 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ToyRobot);
     379         1730 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ToyVehicle);
     380         1488 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ToyDoll);
     381         1246 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ToyController);
     382         1004 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ToyGame);
     383          666 :         break;
     384         3258 :     case QBluetoothDeviceInfo::HealthDevice:
     385         2544 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedHealthDevice);
     386         1972 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthBloodPressureMonitor);
     387         1730 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthThermometer);
     388         1488 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthWeightScale);
     389         1246 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthGlucoseMeter);
     390         1004 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthPulseOximeter);
     391          762 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthDataDisplay);
     392          520 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthStepCounter);
     393          222 :         break;
     394         1593 :     case QBluetoothDeviceInfo::UncategorizedDevice:
     395              :         // There are no minor classes defined (in Qt) for uncategorized devices.
     396         1593 :         break;
     397        27099 :     }
     398         7371 :     #undef DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN
     399        23505 :     qCDebug(lc).noquote() << tr("Unknown minor class %1 for major class %2.")
     400            0 :         .arg(minorClass).arg(majorClass);
     401         7371 :     return QString(); // Null QString indicates unknown minor class.
     402        27099 : }
        

Generated by: LCOV version 2.4-0