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        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 : }
        

Generated by: LCOV version 2.5-0