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 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); } } }
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>()) {