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 % 18 18

            Line data    Source code
       1              : // SPDX-FileCopyrightText: 2022-2024 Paul Colby <git@colby.id.au>
       2              : // SPDX-License-Identifier: LGPL-3.0-or-later
       3              : 
       4              : #include "scancommand.h"
       5              : 
       6              : #include <qtpokit/pokitdiscoveryagent.h>
       7              : 
       8              : #include <QBluetoothUuid>
       9              : #include <QJsonArray>
      10              : #include <QJsonDocument>
      11              : #include <QJsonObject>
      12              : 
      13              : #include <iostream>
      14              : 
      15              : /*!
      16              :  * \class ScanCommand
      17              :  *
      18              :  * The ScanCommand class implements the `scan` CLI command, by scanning for nearby Pokit Bluetooth
      19              :  * devices. When devices are found, they are logged to stdout in the chosen format.
      20              :  */
      21              : 
      22              : /*!
      23              :  * Construct a new ScanCommand object with \a parent.
      24              :  */
      25         2997 : ScanCommand::ScanCommand(QObject * const parent) : AbstractCommand(parent)
      26         2369 : {
      27         2078 :     #if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) // Required signal, and Fields, added in Qt 5.12.
      28         3998 :     connect(discoveryAgent, &PokitDiscoveryAgent::pokitDeviceUpdated,
      29         2438 :             this, &ScanCommand::deviceUpdated);
      30         2078 :     #endif
      31         4487 : }
      32              : 
      33          152 : QStringList ScanCommand::requiredOptions(const QCommandLineParser &parser) const
      34          176 : {
      35          328 :     return AbstractCommand::requiredOptions(parser);
      36          176 : }
      37              : 
      38           76 : QStringList ScanCommand::supportedOptions(const QCommandLineParser &parser) const
      39           88 : {
      40          240 :     return AbstractCommand::supportedOptions(parser) + QStringList{
      41          224 :     };
      42           88 : }
      43              : 
      44              : /// \copydoc AbstractCommand::processOptions
      45           38 : QStringList ScanCommand::processOptions(const QCommandLineParser &parser)
      46           44 : {
      47           82 :     QStringList errors = AbstractCommand::processOptions(parser);
      48           44 :     if (!errors.isEmpty()) {
      49            0 :         return errors;
      50            0 :     }
      51              : 
      52           44 :     return errors;
      53           44 : }
      54              : 
      55              : /*!
      56              :  * Begins scanning for Pokit devices.
      57              :  */
      58           38 : bool ScanCommand::start()
      59           16 : {
      60           16 :     Q_ASSERT(discoveryAgent);
      61          115 :     qCInfo(lc).noquote() << tr("Scanning for Pokit devices...");
      62           54 :     discoveryAgent->start();
      63           54 :     return true;
      64           16 : }
      65              : 
      66              : /*!
      67              :  * Handles discovered Pokit devices, writing \a info to stdout.
      68              :  */
      69         3150 : void ScanCommand::deviceDiscovered(const QBluetoothDeviceInfo &info)
      70         3555 : {
      71         6705 :     switch (format) {
      72         1185 :     case OutputFormat::Csv:
      73         3576 :         for (; showCsvHeader; showCsvHeader = false) {
      74         1611 :             std::cout << qUtf8Printable(tr("uuid,address,name,major_class,minor_class,signal_strength\n"));
      75          711 :         }
      76         4965 :         std::cout << qUtf8Printable(QString::fromLatin1("%1,%2,%3,%4,%5,%6\n").arg(info.deviceUuid().toString(),
      77         1185 :             info.address().toString(), escapeCsvField(info.name()), toString(info.majorDeviceClass()),
      78         1185 :             toString(info.majorDeviceClass(), info.minorDeviceClass())).arg(info.rssi()));
      79         2235 :         break;
      80         2235 :     case OutputFormat::Json:
      81         3285 :         std::cout << QJsonDocument(toJson(info)).toJson().toStdString();
      82         2235 :         break;
      83         2235 :     case OutputFormat::Text:
      84         4515 :         std::cout << qUtf8Printable(tr("%1 %2 %3 %4\n").arg(info.deviceUuid().toString(),
      85         1185 :             info.address().toString(), info.name()).arg(info.rssi()));
      86         2235 :         break;
      87         3555 :     }
      88         6705 : }
      89              : 
      90              : /*!
      91              :  * Handles updated Pokit devices, writing \a info to stdout. Currently \a updatedFields us unused.
      92              :  */
      93              : #if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) // Required signal, and Fields, added in Qt 5.12.
      94         1440 : void ScanCommand::deviceUpdated(const QBluetoothDeviceInfo &info,
      95              :                                 const QBluetoothDeviceInfo::Fields updatedFields)
      96         1575 : {
      97         1575 :     Q_UNUSED(updatedFields)
      98         3015 :     deviceDiscovered(info);
      99         3015 : }
     100              : #endif
     101              : 
     102              : /*!
     103              :  * Handles the completion of device discovery. In this override we simply exit, as the scan command
     104              :  * is nothing more than logging of discovered devices.
     105              :  */
     106           38 : void ScanCommand::deviceDiscoveryFinished()
     107           44 : {
     108           90 :     qCDebug(lc).noquote() << tr("Finished scanning for Pokit devices.");
     109           82 :     QCoreApplication::quit();
     110           82 : }
     111              : 
     112              : /*!
     113              :  * Returns \a info as a JSON object.
     114              :  */
     115         1348 : QJsonObject ScanCommand::toJson(const QBluetoothDeviceInfo &info)
     116         1528 : {
     117         2876 :     if (!info.isValid()) {
     118          231 :         return QJsonObject();
     119          123 :     }
     120         1405 :     QJsonObject json{
     121         3675 :         { QLatin1String("address"), info.address().toString() },
     122         3885 :         { QLatin1String("name"), info.name() },
     123         2645 :         { QLatin1String("isCached"), info.isCached() },
     124         2645 :         { QLatin1String("majorDeviceClass"), info.majorDeviceClass() },
     125         3170 :         { QLatin1String("majorDeviceClass"), toJson(info.majorDeviceClass()) },
     126         3170 :         { QLatin1String("minorDeviceClass"), toJson(info.majorDeviceClass(), info.minorDeviceClass()) },
     127         3170 :         { QLatin1String("signalStrength"), info.rssi() },
     128        13545 :     };
     129         2645 :     if (info.coreConfigurations() != QBluetoothDeviceInfo::UnknownCoreConfiguration) {
     130          379 :         json.insert(QLatin1String("coreConfiguration"), toJson(info.coreConfigurations()));
     131          167 :     }
     132         2645 :     if (!info.deviceUuid().isNull()) {
     133         2341 :         json.insert(QLatin1String("deviceUuid"), info.deviceUuid().toString());
     134          887 :     }
     135         1225 :     #if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) // Added in Qt 5.12.
     136         2345 :     if (!info.manufacturerData().isEmpty()) {
     137          288 :         json.insert(QLatin1String("manufacturerData"), toJson(info.manufacturerData()));
     138          105 :     }
     139         1225 :     #endif
     140         2645 :     if (info.serviceClasses() != QBluetoothDeviceInfo::NoService) {
     141          458 :         json.insert(QLatin1String("serviceClasses"), toJson(info.serviceClasses()));
     142          202 :     }
     143         3170 :     if (!info.serviceUuids().isEmpty()) {
     144          115 :         json.insert(QLatin1String("serviceUuids"), toJson(info.serviceUuids()));
     145           44 :     }
     146         2145 :     return json;
     147        12403 : }
     148              : 
     149              : /*!
     150              :  * Returns \a configuration as a JSON array of strings.
     151              :  */
     152          298 : QJsonArray ScanCommand::toJson(const QBluetoothDeviceInfo::CoreConfigurations &configurations)
     153          343 : {
     154          641 :     QJsonArray array;
     155          343 :     #define DOKIT_INTERNAL_IF_SET_THEN_APPEND(flag) \
     156         1029 :         if (configurations.testFlag(QBluetoothDeviceInfo::flag)) \
     157         1029 :             array.append(QLatin1String(#flag))
     158          490 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(UnknownCoreConfiguration);
     159          619 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(LowEnergyCoreConfiguration);
     160          517 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(BaseRateCoreConfiguration);
     161              :   //DOKIT_INTERNAL_IF_SET_THEN_APPEND(BaseRateAndLowEnergyCoreConfiguration); // Combination flag.
     162          343 :     #undef DOKIT_INTERNAL_IF_SET_THEN_APPEND
     163          641 :     return array;
     164          343 : }
     165              : 
     166              : /*!
     167              :  * Returns \a majorClass as a JSON value. This is equivalent to toString, except that if toString
     168              :  * does not recognise \a majorClass, then \a majorClass is returned as a JSON number (not a string).
     169              :  *
     170              :  * \see toString(const QBluetoothDeviceInfo::MajorDeviceClass &majorClass)
     171              :  */
     172         1772 : QJsonValue ScanCommand::toJson(const QBluetoothDeviceInfo::MajorDeviceClass &majorClass)
     173         2021 : {
     174         3793 :     const QString string = toString(majorClass);
     175         5565 :     return (string.isNull() ? QJsonValue(majorClass) : QJsonValue(string));
     176         3058 : }
     177              : 
     178              : /*!
     179              :  * Returns \a minorClass as a JSON value. This is equivalent to toString, except that if toString
     180              :  * does not recognise \a minorClass as a sub-class of \a majorClass, then \a minorClass is returned
     181              :  * as a JSON number (not a string).
     182              :  *
     183              :  * \see toString(const QBluetoothDeviceInfo::MajorDeviceClass &majorClass, const quint8 minorClass)
     184              :  */
     185         4736 : QJsonValue ScanCommand::toJson(const QBluetoothDeviceInfo::MajorDeviceClass &majorClass, const quint8 minorClass)
     186         5453 : {
     187        10189 :     const QString string = toString(majorClass, minorClass);
     188        14925 :     return (string.isNull() ? QJsonValue(minorClass) : QJsonValue(string));
     189         8284 : }
     190              : 
     191              : /*!
     192              :  * Returns \a classes as a JSON array of strings.
     193              :  */
     194          558 : QJsonArray ScanCommand::toJson(const QBluetoothDeviceInfo::ServiceClasses &classes)
     195          642 : {
     196         1200 :     QJsonArray array;
     197          642 :     #define DOKIT_INTERNAL_IF_SET_THEN_APPEND(flag) \
     198         5136 :         if (classes.testFlag(QBluetoothDeviceInfo::flag)) \
     199         5136 :             array.append(QLatin1String(#flag))
     200         1044 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(PositioningService);
     201         1044 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(NetworkingService);
     202         1044 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(RenderingService);
     203         1017 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(CapturingService);
     204         1017 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(ObjectTransferService);
     205         1017 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(AudioService);
     206         1017 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(TelephonyService);
     207         1017 :     DOKIT_INTERNAL_IF_SET_THEN_APPEND(InformationService);
     208          642 :     #undef DOKIT_INTERNAL_IF_SET_THEN_APPEND
     209         1200 :     return array;
     210          642 : }
     211              : 
     212              : /*!
     213              :  * Returns \a uuids as a JSON array.
     214              :  */
     215          228 : QJsonArray ScanCommand::toJson(const QList<QBluetoothUuid> &uuids)
     216          264 : {
     217          492 :     QJsonArray array;
     218         1212 :     for (const QBluetoothUuid &uuid: uuids) {
     219         1212 :         array.append(uuid.toString());
     220          528 :     }
     221          492 :     return array;
     222          264 : }
     223              : 
     224              : /*!
     225              :  * Returns Bluetooth manufacturer \a data as a JSON object that maps the manufacturer IDs (unsigned
     226              :  * integers as strings) to arrays of one or more values.
     227              :  */
     228          224 : QJsonObject ScanCommand::toJson(const QMultiHash<quint16, QByteArray> &data)
     229          245 : {
     230          469 :     QJsonObject object;
     231          469 :     QList<quint16> keys = data.uniqueKeys();
     232          350 :     std::sort(keys.begin(), keys.end());
     233          894 :     for (const quint16 key: keys) {
     234              :         // Convert the key's values to a JSON array, reversing the order, because QMultiHash
     235              :         // guarantees that the values are orderer "from the most recently inserted to the least
     236              :         // recently inserted", which is the oppoosit of what we want.
     237          650 :         QList<QByteArray> values = data.values(key);
     238          500 :         std::reverse(values.begin(), values.end());
     239          670 :         QJsonArray array;
     240         1283 :         for (const QByteArray &value: values) {
     241         1614 :             array.append(QLatin1String(value.toBase64()));
     242          507 :         }
     243          820 :         object.insert(QString::number(key), array);
     244          670 :     }
     245          469 :     return object;
     246          364 : }
     247              : 
     248              : /*!
     249              :  * Returns \a majorClass as a human-readable string, or a null QString if \a majorClass is not
     250              :  * recognised.
     251              :  *
     252              :  * For example, if \a majorClass is \c QBluetoothDeviceInfo::ToyDevice, then the string `ToyDevice`
     253              :  * is returned.
     254              :  */
     255         3354 : QString ScanCommand::toString(const QBluetoothDeviceInfo::MajorDeviceClass &majorClass)
     256         3822 : {
     257         3822 :     #define DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(value) \
     258        15850 :         if (majorClass == QBluetoothDeviceInfo::value) \
     259        15850 :             return QLatin1String(#value)
     260         7176 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(MiscellaneousDevice);
     261         2246 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ComputerDevice);
     262         1842 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(PhoneDevice);
     263          336 :     #if (QT_VERSION < QT_VERSION_CHECK(5, 13, 0))
     264          336 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(LANAccessDevice); // Deprecated since Qt 5.13.
     265              :     #else
     266         1014 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkDevice); // Added in Qt 5.13.
     267          928 :     #endif
     268         1262 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(AudioVideoDevice);
     269         1174 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(PeripheralDevice);
     270         1086 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ImagingDevice);
     271          998 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableDevice);
     272          910 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ToyDevice);
     273          822 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthDevice);
     274          833 :     DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedDevice);
     275          264 :     #undef DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN
     276          540 :     qCDebug(lc).noquote() << tr("Unknown major class %1.").arg(majorClass);
     277          264 :     return QString(); // Null QString indicates unknown minor class.
     278          712 : }
     279              : 
     280              : /*!
     281              :  * Returns \a minorClass as a human-readable string, or a null QString if \a minorClass is not
     282              :  * recognised as a sub-class of \a majorClass.
     283              :  *
     284              :  * For example, if \a majorClass is \c QBluetoothDeviceInfo::ToyDevice, and \a minorClass is
     285              :  * \c QBluetoothDeviceInfo::ToyRobot, then the string `ToyRobot` is returned.
     286              :  */
     287         9282 : QString ScanCommand::toString(const QBluetoothDeviceInfo::MajorDeviceClass &majorClass, const quint8 minorClass)
     288        10686 : {
     289        10686 :     #define DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(value) \
     290        47330 :         if (minorClass == QBluetoothDeviceInfo::value) \
     291        47330 :             return QLatin1String(#value)
     292        19968 :     switch (majorClass) {
     293         3338 :     case QBluetoothDeviceInfo::MiscellaneousDevice:
     294         3338 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedMiscellaneous);
     295          404 :         break;
     296         1908 :     case QBluetoothDeviceInfo::ComputerDevice:
     297         1290 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedComputer);
     298          954 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(DesktopComputer);
     299          866 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ServerComputer);
     300          778 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(LaptopComputer);
     301          690 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HandheldClamShellComputer);
     302          602 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HandheldComputer);
     303          514 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableComputer);
     304          404 :         break;
     305         1744 :     case QBluetoothDeviceInfo::PhoneDevice:
     306         1180 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedPhone);
     307          866 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(CellularPhone);
     308          778 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(CordlessPhone);
     309          690 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(SmartPhone);
     310          602 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WiredModemOrVoiceGatewayPhone);
     311          514 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(CommonIsdnAccessPhone);
     312          404 :         break;
     313           84 :     #if (QT_VERSION < QT_VERSION_CHECK(5, 13, 0))
     314          396 :     case QBluetoothDeviceInfo::LANAccessDevice: // Deprecated since Qt 5.13.
     315              :     #else
     316         1080 :     case QBluetoothDeviceInfo::NetworkDevice: // Added in Qt 5.13.
     317          576 :     #endif
     318         1008 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkFullService);
     319          726 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkLoadFactorOne);
     320          638 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkLoadFactorTwo);
     321          550 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkLoadFactorThree);
     322          462 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkLoadFactorFour);
     323          374 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkLoadFactorFive);
     324          286 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkLoadFactorSix);
     325          198 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(NetworkNoService);
     326           88 :         break;
     327         2952 :     case QBluetoothDeviceInfo::AudioVideoDevice:
     328         1998 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedAudioVideoDevice);
     329         1518 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableHeadsetDevice);
     330         1430 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HandsFreeDevice);
     331         1342 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(Microphone);
     332         1254 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(Loudspeaker);
     333         1166 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(Headphones);
     334         1078 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(PortableAudioDevice);
     335          990 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(CarAudio);
     336          902 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(SetTopBox);
     337          814 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HiFiAudioDevice);
     338          726 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(Vcr);
     339          638 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(VideoCamera);
     340          550 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(Camcorder);
     341          462 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(VideoMonitor);
     342          374 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(VideoDisplayAndLoudspeaker);
     343          286 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(VideoConferencing);
     344          198 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(GamingDevice);
     345           88 :         break;
     346         1804 :     case QBluetoothDeviceInfo::PeripheralDevice:
     347         1228 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedPeripheral);
     348          902 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(KeyboardPeripheral);
     349          814 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(PointingDevicePeripheral);
     350          726 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(KeyboardWithPointingDevicePeripheral);
     351          638 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(JoystickPeripheral);
     352          550 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(GamepadPeripheral);
     353          462 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(RemoteControlPeripheral);
     354          374 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(SensingDevicePeripheral);
     355          286 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(DigitizerTabletPeripheral);
     356          198 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(CardReaderPeripheral);
     357           88 :         break;
     358          984 :     case QBluetoothDeviceInfo::ImagingDevice:
     359          678 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedImagingDevice);
     360          568 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ImageDisplay);
     361          458 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ImageCamera);
     362          348 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ImageScanner);
     363          238 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ImagePrinter);
     364           88 :         break;
     365         1148 :     case QBluetoothDeviceInfo::WearableDevice:
     366          788 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedWearableDevice);
     367          550 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableWristWatch);
     368          462 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearablePager);
     369          374 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableJacket);
     370          286 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableHelmet);
     371          198 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(WearableGlasses);
     372           88 :         break;
     373         1476 :     case QBluetoothDeviceInfo::ToyDevice:
     374         1008 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedToy);
     375          726 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ToyRobot);
     376          638 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ToyVehicle);
     377          550 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ToyDoll);
     378          462 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ToyController);
     379          374 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(ToyGame);
     380          264 :         break;
     381         1476 :     case QBluetoothDeviceInfo::HealthDevice:
     382         1008 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(UncategorizedHealthDevice);
     383          726 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthBloodPressureMonitor);
     384          638 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthThermometer);
     385          550 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthWeightScale);
     386          462 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthGlucoseMeter);
     387          374 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthPulseOximeter);
     388          286 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthDataDisplay);
     389          198 :         DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN(HealthStepCounter);
     390           88 :         break;
     391          624 :     case QBluetoothDeviceInfo::UncategorizedDevice:
     392              :         // There are no minor classes defined (in Qt) for uncategorized devices.
     393          624 :         break;
     394        10686 :     }
     395         2892 :     #undef DOKIT_INTERNAL_IF_EQUAL_THEN_RETURN
     396         5970 :     qCDebug(lc).noquote() << tr("Unknown minor class %1 for major class %2.")
     397            0 :         .arg(minorClass).arg(majorClass);
     398         2892 :     return QString(); // Null QString indicates unknown minor class.
     399        10686 : }
        

Generated by: LCOV version 2.0-1