void QLowEnergyControllerPrivate::discoverServiceDetails(const QBluetoothUuid &service)
{
    if (!serviceList.contains(service)) {
        qCWarning(QT_BT_ANDROID) << "Discovery of unknown service" << service.toString()
                                 << "not possible";
        return;
    }

    if (!hub)
        return;

    //cut leading { and trailing } {xxx-xxx}
    QString tempUuid = service.toString();
    tempUuid.chop(1); //remove trailing '}'
    tempUuid.remove(0, 1); //remove first '{'

    QAndroidJniEnvironment env;
    QAndroidJniObject uuid = QAndroidJniObject::fromString(tempUuid);
    bool result = hub->javaObject().callMethod<jboolean>("discoverServiceDetails",
                                                         "(Ljava/lang/String;)Z",
                                                         uuid.object<jstring>());
    if (!result) {
        QSharedPointer<QLowEnergyServicePrivate> servicePrivate =
                serviceList.value(service);
        if (!servicePrivate.isNull()) {
            servicePrivate->setError(QLowEnergyService::UnknownError);
            servicePrivate->setState(QLowEnergyService::DiscoveryRequired);
        }
        qCWarning(QT_BT_ANDROID) << "Cannot discover details for" << service.toString();
        return;
    }

    qCDebug(QT_BT_ANDROID) << "Discovery of" << service << "started";
}
Ejemplo n.º 2
0
void tst_QBluetoothUuid::tst_assignment()
{
    QBluetoothUuid uuid(QBluetoothUuid::PublicBrowseGroup);

    {
        QBluetoothUuid copy = uuid;

        QCOMPARE(uuid.toUInt16(), copy.toUInt16());
    }

    {
        QBluetoothUuid copy1;
        QBluetoothUuid copy2;

        QVERIFY(copy1.isNull());
        QVERIFY(copy2.isNull());

        copy1 = copy2 = uuid;

        QVERIFY(!copy1.isNull());
        QVERIFY(!copy2.isNull());

        QCOMPARE(uuid.toUInt16(), copy1.toUInt16());
        QCOMPARE(uuid.toUInt16(), copy2.toUInt16());
    }
}
Ejemplo n.º 3
0
/*!
    Returns the type of the descriptor.

    \sa name()
 */
QBluetoothUuid::DescriptorType QLowEnergyDescriptor::type() const
{
    const QBluetoothUuid u = uuid();
    bool ok = false;
    quint16 shortUuid = u.toUInt16(&ok);

    if (!ok)
        return QBluetoothUuid::UnknownDescriptorType;

    switch (shortUuid) {
    case QBluetoothUuid::CharacteristicExtendedProperties:
    case QBluetoothUuid::CharacteristicUserDescription:
    case QBluetoothUuid::ClientCharacteristicConfiguration:
    case QBluetoothUuid::ServerCharacteristicConfiguration:
    case QBluetoothUuid::CharacteristicPresentationFormat:
    case QBluetoothUuid::CharacteristicAggregateFormat:
    case QBluetoothUuid::ValidRange:
    case QBluetoothUuid::ExternalReportReference:
    case QBluetoothUuid::ReportReference:
        return (QBluetoothUuid::DescriptorType) shortUuid;
    default:
        break;
    }

    return QBluetoothUuid::UnknownDescriptorType;
}
Ejemplo n.º 4
0
bool ppsSendControlMessage(const char *msg, int service, const QBluetoothUuid &uuid, const QString &address, const QString &serviceName, QObject *sender, const int &subtype)
{
    pps_encoder_t *encoder = beginCtrlMessage(msg, sender);
    pps_encoder_start_object(encoder, "dat");
    pps_encoder_add_int(encoder, "service", service);
    if (subtype != -1)
        pps_encoder_add_int(encoder, "subtype", subtype);

    pps_encoder_add_string(encoder, "uuid", uuid.toString().mid(1,36).toUtf8().constData());

    if (!serviceName.isEmpty()) {
        pps_encoder_add_string(encoder, "name", serviceName.toUtf8().constData());
    }
    if (!address.isEmpty()) {
        pps_encoder_add_string(encoder, "addr", address.toUtf8().constData());
    }

    pps_encoder_error_t rese = pps_encoder_end_object(encoder);

    if (rese != PPS_ENCODER_OK) {
        errno = EPERM;
        return false;
    }

    return endCtrlMessage(encoder);
}
Ejemplo n.º 5
0
void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address,
                                               const QBluetoothUuid &uuid,
                                               QIODevice::OpenMode openMode)
{
    Q_Q(QBluetoothSocket);
    Q_UNUSED(openMode);
    qCDebug(QT_BT_QNX) << "Connecting socket";

    m_peerAddress = address;
#ifdef QT_QNX_BT_BLUETOOTH
    QByteArray b_uuid = uuid.toByteArray();
    b_uuid = b_uuid.mid(1, b_uuid.length() - 2);
    socket = bt_spp_open(address.toString().toUtf8().data(), b_uuid.data(), false);
    if (socket == -1) {
        qCWarning(QT_BT_QNX) << "Could not connect to" << address.toString() << b_uuid <<  qt_error_string(errno);
        errorString = qt_error_string(errno);
        q->setSocketError(QBluetoothSocket::NetworkError);
        return;
    }

    delete readNotifier;
    delete connectWriteNotifier;

    readNotifier = new QSocketNotifier(socket, QSocketNotifier::Read);
    QObject::connect(readNotifier, SIGNAL(activated(int)), this, SLOT(_q_readNotify()));
    connectWriteNotifier = new QSocketNotifier(socket, QSocketNotifier::Write, q);
    QObject::connect(connectWriteNotifier, SIGNAL(activated(int)), this, SLOT(_q_writeNotify()));

    connecting = true;
    q->setOpenMode(openMode);
#else
    m_uuid = uuid;
    if (isServerSocket)
        return;

    if (state != QBluetoothSocket::UnconnectedState) {
        qCDebug(QT_BT_QNX) << "Socket already connected";
        return;
    }

    ppsSendControlMessage("connect_service", 0x1101, uuid, address.toString(), QString(), this, BT_SPP_CLIENT_SUBTYPE);
    ppsRegisterForEvent(QStringLiteral("service_connected"),this);
    ppsRegisterForEvent(QStringLiteral("get_mount_point_path"),this);
#endif
    q->setSocketState(QBluetoothSocket::ConnectingState);
}
void QBluetoothServiceDiscoveryAgentPrivate::populateDiscoveredServices(const QBluetoothDeviceInfo &remoteDevice, const QList<QBluetoothUuid> &uuids)
{
    /* Android doesn't provide decent SDP data. A list of uuids is close to meaning-less
     *
     * The following approach is chosen:
     * - If we see an SPP service class and we see
     * one or more custom uuids we match them up. Such services will always be SPP services.
     * - If we see a custom uuid but no SPP uuid then we return
     * BluetoothServiceInfo instance with just a servuceUuid (no service class set)
     * - Any other service uuid will stand on its own.
     * */

    Q_Q(QBluetoothServiceDiscoveryAgent);

    //find SPP and custom uuid
    QBluetoothUuid uuid;
    int sppIndex = -1;
    QVector<int> customUuids;

    for (int i = 0; i < uuids.count(); i++) {
        uuid = uuids.at(i);

        if (uuid.isNull())
            continue;

        //check for SPP protocol
        bool ok = false;
        quint16 uuid16 = uuid.toUInt16(&ok);
        if (ok && uuid16 == QBluetoothUuid::SerialPort)
            sppIndex = i;

        //check for custom uuid
        if (uuid.minimumSize() == 16)
            customUuids.append(i);
    }

    for (int i = 0; i < uuids.count(); i++) {
        if (i == sppIndex && !customUuids.isEmpty())
            continue;

        QBluetoothServiceInfo serviceInfo;
        serviceInfo.setDevice(remoteDevice);

        QBluetoothServiceInfo::Sequence protocolDescriptorList;
        {
            QBluetoothServiceInfo::Sequence protocol;
            protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::L2cap));
            protocolDescriptorList.append(QVariant::fromValue(protocol));
        }

        if (customUuids.contains(i) && sppIndex > -1) {
            //we have a custom uuid of service class type SPP

            //set rfcomm protocol
            QBluetoothServiceInfo::Sequence protocol;
            protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm))
                     << QVariant::fromValue(0);
            protocolDescriptorList.append(QVariant::fromValue(protocol));

            //set SPP service class uuid
            QBluetoothServiceInfo::Sequence classId;
            classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort));
            serviceInfo.setAttribute(QBluetoothServiceInfo::BluetoothProfileDescriptorList,
                                     classId);
            classId.prepend(QVariant::fromValue(uuids.at(i)));
            serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId);

            serviceInfo.setServiceName(QBluetoothServiceDiscoveryAgent::tr("Serial Port Profile"));
            serviceInfo.setServiceUuid(uuids.at(i));
        } else if (sppIndex == i && customUuids.isEmpty()) {
            //set rfcomm protocol
            QBluetoothServiceInfo::Sequence protocol;
            protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm))
                     << QVariant::fromValue(0);
            protocolDescriptorList.append(QVariant::fromValue(protocol));

            QBluetoothServiceInfo::Sequence classId;
            classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort));
            serviceInfo.setAttribute(QBluetoothServiceInfo::BluetoothProfileDescriptorList,
                                     classId);

            //also we need to set the custom uuid to the SPP uuid
            //otherwise QBluetoothSocket::connectToService() would fail due to a missing service uuid
            serviceInfo.setServiceUuid(uuids.at(i));
        } else if (customUuids.contains(i)) {
            //custom uuid but no serial port
            serviceInfo.setServiceUuid(uuids.at(i));
        }

        //Check if the UUID is in the uuidFilter
        if (!uuidFilter.isEmpty() && !uuidFilter.contains(serviceInfo.serviceUuid()))
            continue;

        serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, protocolDescriptorList);
        serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList,
                                 QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup));

        if (!customUuids.contains(i)) {
            //if we don't have custom uuid use it as class id as well
            QBluetoothServiceInfo::Sequence classId;
            classId << QVariant::fromValue(uuids.at(i));
            serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId);
            QBluetoothUuid::ServiceClassUuid clsId
                = static_cast<QBluetoothUuid::ServiceClassUuid>(uuids.at(i).toUInt16());
            serviceInfo.setServiceName(QBluetoothUuid::serviceClassToString(clsId));
        }

        //don't include the service if we already discovered it before
        if (!isDuplicatedService(serviceInfo)) {
            discoveredServices << serviceInfo;
            //qCDebug(QT_BT_ANDROID) << serviceInfo;
            emit q->serviceDiscovered(serviceInfo);
        }
    }
}
Ejemplo n.º 7
0
static void writeAttribute(QXmlStreamWriter *stream, const QVariant &attribute)
{
    const QString unsignedFormat(QStringLiteral("0x%1"));

    switch (int(attribute.type())) {
    case QMetaType::Void:
        stream->writeEmptyElement(QStringLiteral("nil"));
        break;
    case QMetaType::UChar:
        stream->writeEmptyElement(QStringLiteral("uint8"));
        stream->writeAttribute(QStringLiteral("value"),
                               unsignedFormat.arg(attribute.value<quint8>(), 2, 16,
                                                  QLatin1Char('0')));
        //stream->writeAttribute(QStringLiteral("name"), foo);
        break;
    case QMetaType::UShort:
        stream->writeEmptyElement(QStringLiteral("uint16"));
        stream->writeAttribute(QStringLiteral("value"),
                               unsignedFormat.arg(attribute.value<quint16>(), 4, 16,
                                                  QLatin1Char('0')));
        //stream->writeAttribute(QStringLiteral("name"), foo);
        break;
    case QMetaType::UInt:
        stream->writeEmptyElement(QStringLiteral("uint32"));
        stream->writeAttribute(QStringLiteral("value"),
                               unsignedFormat.arg(attribute.value<quint32>(), 8, 16,
                                                  QLatin1Char('0')));
        //stream->writeAttribute(QStringLiteral("name"), foo);
        break;
    case QMetaType::Char:
        stream->writeEmptyElement(QStringLiteral("int8"));
        stream->writeAttribute(QStringLiteral("value"),
                               QString::number(attribute.value<uchar>(), 16));
        //stream->writeAttribute(QStringLiteral("name"), foo);
        break;
    case QMetaType::Short:
        stream->writeEmptyElement(QStringLiteral("int16"));
        stream->writeAttribute(QStringLiteral("value"),
                               QString::number(attribute.value<qint16>(), 16));
        //stream->writeAttribute(QStringLiteral("name"), foo);
        break;
    case QMetaType::Int:
        stream->writeEmptyElement(QStringLiteral("int32"));
        stream->writeAttribute(QStringLiteral("value"),
                               QString::number(attribute.value<qint32>(), 16));
        //stream->writeAttribute(QStringLiteral("name"), foo);
        break;
    case QMetaType::QString:
        stream->writeEmptyElement(QStringLiteral("text"));
        if (/* require hex encoding */ false) {
            stream->writeAttribute(QStringLiteral("value"), QString::fromLatin1(
                                       attribute.value<QString>().toUtf8().toHex().constData()));
            stream->writeAttribute(QStringLiteral("encoding"), QStringLiteral("hex"));
        } else {
            stream->writeAttribute(QStringLiteral("value"), attribute.value<QString>());
            stream->writeAttribute(QStringLiteral("encoding"), QStringLiteral("normal"));
        }
        //stream->writeAttribute(QStringLiteral("name"), foo);
        break;
            case QMetaType::Bool:
        stream->writeEmptyElement(QStringLiteral("boolean"));
        if (attribute.value<bool>())
            stream->writeAttribute(QStringLiteral("value"), QStringLiteral("true"));
        else
            stream->writeAttribute(QStringLiteral("value"), QStringLiteral("false"));
        //stream->writeAttribute(QStringLiteral("name"), foo);
        break;
            case QMetaType::QUrl:
        stream->writeEmptyElement(QStringLiteral("url"));
        stream->writeAttribute(QStringLiteral("value"), attribute.value<QUrl>().toString());
        //stream->writeAttribute(QStringLiteral("name"), foo);
        break;
            case QVariant::UserType:
        if (attribute.userType() == qMetaTypeId<QBluetoothUuid>()) {
            stream->writeEmptyElement(QStringLiteral("uuid"));

            QBluetoothUuid uuid = attribute.value<QBluetoothUuid>();
            switch (uuid.minimumSize()) {
            case 0:
                stream->writeAttribute(QStringLiteral("value"),
                                       unsignedFormat.arg(quint16(0), 4, 16, QLatin1Char('0')));
                break;
            case 2:
                stream->writeAttribute(QStringLiteral("value"),
                                       unsignedFormat.arg(uuid.toUInt16(), 4, 16,
                                                          QLatin1Char('0')));
                break;
            case 4:
                stream->writeAttribute(QStringLiteral("value"),
                                       unsignedFormat.arg(uuid.toUInt32(), 8, 16,
                                                          QLatin1Char('0')));
                break;
            case 16:
                stream->writeAttribute(QStringLiteral("value"), uuid.toString().mid(1, 36));
                break;
            default:
                stream->writeAttribute(QStringLiteral("value"), uuid.toString().mid(1, 36));
            }
        } else if (attribute.userType() == qMetaTypeId<QBluetoothServiceInfo::Sequence>()) {
            stream->writeStartElement(QStringLiteral("sequence"));
            const QBluetoothServiceInfo::Sequence *sequence =
                    static_cast<const QBluetoothServiceInfo::Sequence *>(attribute.data());
            foreach (const QVariant &v, *sequence)
                writeAttribute(stream, v);
            stream->writeEndElement();
        } else if (attribute.userType() == qMetaTypeId<QBluetoothServiceInfo::Alternative>()) {
void QBluetoothSocketPrivate::connectToServiceConc(const QBluetoothAddress &address,
                                                   const QBluetoothUuid &uuid, QIODevice::OpenMode openMode, int fallbackServiceChannel)
{
    Q_Q(QBluetoothSocket);
    Q_UNUSED(openMode);

    qCDebug(QT_BT_ANDROID) << "connectToServiceConc()" << address.toString() << uuid.toString();

    if (!adapter.isValid()) {
        qCWarning(QT_BT_ANDROID) << "Device does not support Bluetooth";
        errorString = QBluetoothSocket::tr("Device does not support Bluetooth");
        q->setSocketError(QBluetoothSocket::NetworkError);
        q->setSocketState(QBluetoothSocket::UnconnectedState);
        return;
    }

    const int state = adapter.callMethod<jint>("getState");
    if (state != 12 ) { //BluetoothAdapter.STATE_ON
        qCWarning(QT_BT_ANDROID) << "Bt device offline";
        errorString = QBluetoothSocket::tr("Device is powered off");
        q->setSocketError(QBluetoothSocket::NetworkError);
        q->setSocketState(QBluetoothSocket::UnconnectedState);
        return;
    }

    QAndroidJniEnvironment env;
    QAndroidJniObject inputString = QAndroidJniObject::fromString(address.toString());
    remoteDevice = adapter.callObjectMethod("getRemoteDevice",
                                            "(Ljava/lang/String;)Landroid/bluetooth/BluetoothDevice;",
                                            inputString.object<jstring>());
    if (env->ExceptionCheck()) {
        env->ExceptionDescribe();
        env->ExceptionClear();

        errorString = QBluetoothSocket::tr("Cannot access address %1", "%1 = Bt address e.g. 11:22:33:44:55:66").arg(address.toString());
        q->setSocketError(QBluetoothSocket::HostNotFoundError);
        q->setSocketState(QBluetoothSocket::UnconnectedState);
        return;
    }

    //cut leading { and trailing } {xxx-xxx}
    QString tempUuid = uuid.toString();
    tempUuid.chop(1); //remove trailing '}'
    tempUuid.remove(0, 1); //remove first '{'

    inputString = QAndroidJniObject::fromString(tempUuid);
    QAndroidJniObject uuidObject = QAndroidJniObject::callStaticObjectMethod("java/util/UUID", "fromString",
                                                                       "(Ljava/lang/String;)Ljava/util/UUID;",
                                                                       inputString.object<jstring>());

    socketObject = remoteDevice.callObjectMethod("createRfcommSocketToServiceRecord",
                                                 "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;",
                                                 uuidObject.object<jobject>());

    if (env->ExceptionCheck()) {
        env->ExceptionDescribe();
        env->ExceptionClear();

        socketObject = remoteDevice = QAndroidJniObject();
        errorString = QBluetoothSocket::tr("Cannot connect to %1 on %2",
                                           "%1 = uuid, %2 = Bt address").arg(uuid.toString()).arg(address.toString());
        q->setSocketError(QBluetoothSocket::ServiceNotFoundError);
        q->setSocketState(QBluetoothSocket::UnconnectedState);
        return;
    }

    socketObject.callMethod<void>("connect");
    if (env->ExceptionCheck()) {
        env->ExceptionDescribe();
        env->ExceptionClear();

        bool success = fallBackConnect(uuidObject, fallbackServiceChannel);
        if (!success) {
            errorString = QBluetoothSocket::tr("Connection to service failed");
            socketObject = remoteDevice = QAndroidJniObject();
            q->setSocketError(QBluetoothSocket::ServiceNotFoundError);
            q->setSocketState(QBluetoothSocket::UnconnectedState);

            env->ExceptionClear(); //just in case
            return;
        }
    }

    if (inputThread) {
        inputThread->deleteLater();
        inputThread = 0;
    }

    inputStream = socketObject.callObjectMethod("getInputStream", "()Ljava/io/InputStream;");
    outputStream = socketObject.callObjectMethod("getOutputStream", "()Ljava/io/OutputStream;");

    if (env->ExceptionCheck() || !inputStream.isValid() || !outputStream.isValid()) {
        env->ExceptionDescribe();
        env->ExceptionClear();

        //close socket again
        socketObject.callMethod<void>("close");
        if (env->ExceptionCheck()) {
            env->ExceptionDescribe();
            env->ExceptionClear();
        }

        socketObject = inputStream = outputStream = remoteDevice = QAndroidJniObject();


        errorString = QBluetoothSocket::tr("Obtaining streams for service failed");
        q->setSocketError(QBluetoothSocket::NetworkError);
        q->setSocketState(QBluetoothSocket::UnconnectedState);
        return;
    }

    inputThread = new InputStreamThread(this);
    QObject::connect(inputThread, SIGNAL(dataAvailable()),
                     q, SIGNAL(readyRead()), Qt::QueuedConnection);
    QObject::connect(inputThread, SIGNAL(error(int)),
                     this, SLOT(inputThreadError(int)), Qt::QueuedConnection);

    if (!inputThread->run()) {
        //close socket again
        socketObject.callMethod<void>("close");
        if (env->ExceptionCheck()) {
            env->ExceptionDescribe();
            env->ExceptionClear();
        }

        socketObject = inputStream = outputStream = remoteDevice = QAndroidJniObject();

        delete inputThread;
        inputThread = 0;

        errorString = QBluetoothSocket::tr("Input stream thread cannot be started");
        q->setSocketError(QBluetoothSocket::NetworkError);
        q->setSocketState(QBluetoothSocket::UnconnectedState);
        return;
    }

    // only unbuffered behavior supported at this stage
    q->setOpenMode(QIODevice::ReadWrite|QIODevice::Unbuffered);

    q->setSocketState(QBluetoothSocket::ConnectedState);
    emit q->connected();
}
Ejemplo n.º 9
0
void tst_QBluetoothUuid::tst_construction()
{
    {
        QBluetoothUuid nullUuid;

        QVERIFY(nullUuid.isNull());
    }

    {
        QBluetoothUuid uuid(QBluetoothUuid::PublicBrowseGroup);

        QVERIFY(!uuid.isNull());

        bool ok;
        quint16 uuid16;

        uuid16 = uuid.toUInt16(&ok);

        QVERIFY(ok);
        QCOMPARE(uuid16, static_cast<quint16>(QBluetoothUuid::PublicBrowseGroup));
    }

    {
        QBluetoothUuid uuid(QBluetoothUuid::PublicBrowseGroup);

        QBluetoothUuid copy(uuid);

        QCOMPARE(uuid.toUInt16(), copy.toUInt16());
    }

    {
        QBluetoothUuid uuid(QBluetoothUuid::L2cap);

        QVERIFY(!uuid.isNull());

        bool ok;
        quint16 uuid16;

        uuid16 = uuid.toUInt16(&ok);

        QVERIFY(ok);
        QCOMPARE(uuid16, static_cast<quint16>(QBluetoothUuid::L2cap));
    }

    {
        QUuid uuid(0x67c8770b, 0x44f1, 0x410a, 0xab, 0x9a, 0xf9, 0xb5, 0x44, 0x6f, 0x13, 0xee);
        QBluetoothUuid btUuid(uuid);
        QVERIFY(!btUuid.isNull());

        QString uuidString(btUuid.toString());
        QVERIFY(!uuidString.isEmpty());
        QCOMPARE(uuidString, QString("{67c8770b-44f1-410a-ab9a-f9b5446f13ee}"));
    }

    {
        QBluetoothUuid btUuid(QString("67c8770b-44f1-410a-ab9a-f9b5446f13ee"));
        QVERIFY(!btUuid.isNull());

        QString uuidString(btUuid.toString());
        QVERIFY(!uuidString.isEmpty());
        QCOMPARE(uuidString, QString("{67c8770b-44f1-410a-ab9a-f9b5446f13ee}"));
    }

    {
        QBluetoothUuid btUuid(QString("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"));
        QVERIFY(btUuid.isNull());
    }
}
Ejemplo n.º 10
0
static void dumpAttributeVariant(QDebug dbg, const QVariant &var, const QString& indent)
{
    switch (int(var.type())) {
    case QMetaType::Void:
        dbg << QString::asprintf("%sEmpty\n", indent.toUtf8().constData());
        break;
    case QMetaType::UChar:
        dbg << QString::asprintf("%suchar %u\n", indent.toUtf8().constData(), var.toUInt());
        break;
    case QMetaType::UShort:
        dbg << QString::asprintf("%sushort %u\n", indent.toUtf8().constData(), var.toUInt());
        break;
    case QMetaType::UInt:
        dbg << QString::asprintf("%suint %u\n", indent.toUtf8().constData(), var.toUInt());
        break;
    case QMetaType::Char:
        dbg << QString::asprintf("%schar %d\n", indent.toUtf8().constData(), var.toInt());
        break;
    case QMetaType::Short:
        dbg << QString::asprintf("%sshort %d\n", indent.toUtf8().constData(), var.toInt());
        break;
    case QMetaType::Int:
        dbg << QString::asprintf("%sint %d\n", indent.toUtf8().constData(), var.toInt());
        break;
    case QMetaType::QString:
        dbg << QString::asprintf("%sstring %s\n", indent.toUtf8().constData(),
                                 var.toString().toUtf8().constData());
        break;
    case QMetaType::Bool:
        dbg << QString::asprintf("%sbool %d\n", indent.toUtf8().constData(), var.toBool());
        break;
    case QMetaType::QUrl:
        dbg << QString::asprintf("%surl %s\n", indent.toUtf8().constData(),
                                 var.toUrl().toString().toUtf8().constData());
        break;
    case QVariant::UserType:
        if (var.userType() == qMetaTypeId<QBluetoothUuid>()) {
            QBluetoothUuid uuid = var.value<QBluetoothUuid>();
            switch (uuid.minimumSize()) {
            case 0:
                dbg << QString::asprintf("%suuid NULL\n", indent.toUtf8().constData());
                break;
            case 2:
                dbg << QString::asprintf("%suuid2 %04x\n", indent.toUtf8().constData(),
                                         uuid.toUInt16());
                break;
            case 4:
                dbg << QString::asprintf("%suuid %08x\n", indent.toUtf8().constData(),
                                         uuid.toUInt32());
                break;
            case 16:
                dbg << QString::asprintf("%suuid %s\n",
                            indent.toUtf8().constData(),
                            QByteArray(reinterpret_cast<const char *>(uuid.toUInt128().data), 16).toHex().constData());
                break;
            default:
                dbg << QString::asprintf("%suuid ???\n", indent.toUtf8().constData());
            }
        } else if (var.userType() == qMetaTypeId<QBluetoothServiceInfo::Sequence>()) {
            dbg << QString::asprintf("%sSequence\n", indent.toUtf8().constData());
            const QBluetoothServiceInfo::Sequence *sequence = static_cast<const QBluetoothServiceInfo::Sequence *>(var.data());
            foreach (const QVariant &v, *sequence)
                dumpAttributeVariant(dbg, v, indent + QLatin1Char('\t'));
        } else if (var.userType() == qMetaTypeId<QBluetoothServiceInfo::Alternative>()) {