diff options
author | Aaron McCarthy <aaron.mccarthy@nokia.com> | 2010-06-25 12:08:29 +1000 |
---|---|---|
committer | Aaron McCarthy <aaron.mccarthy@nokia.com> | 2010-06-25 12:08:29 +1000 |
commit | 0a3fea2fbfa1121e918e14e589ad023625fc3bee (patch) | |
tree | 044f3cfe4805f07521c8181a470b9311dd793dde /src/connectivity/bluetooth/qbluetoothserviceinfo_bluez.cpp | |
parent | f7f2e75da239574f2edf3db346abd9d90f085f8b (diff) |
Implement (un)register Bluetooth service records with BlueZ.
Diffstat (limited to 'src/connectivity/bluetooth/qbluetoothserviceinfo_bluez.cpp')
-rw-r--r-- | src/connectivity/bluetooth/qbluetoothserviceinfo_bluez.cpp | 225 |
1 files changed, 222 insertions, 3 deletions
diff --git a/src/connectivity/bluetooth/qbluetoothserviceinfo_bluez.cpp b/src/connectivity/bluetooth/qbluetoothserviceinfo_bluez.cpp index ae9bd2fa05..18c5da9da1 100644 --- a/src/connectivity/bluetooth/qbluetoothserviceinfo_bluez.cpp +++ b/src/connectivity/bluetooth/qbluetoothserviceinfo_bluez.cpp @@ -42,24 +42,167 @@ #include "qbluetoothserviceinfo.h" #include "qbluetoothserviceinfo_p.h" +#include "bluez/manager_p.h" +#include "bluez/service_p.h" + +#include <QtCore/QXmlStreamWriter> + QTM_BEGIN_NAMESPACE +static void writeAttribute(QXmlStreamWriter *stream, const QVariant &attribute) +{ + const QString unsignedFormat(QLatin1String("0x%1")); + + switch (attribute.type()) { + case QMetaType::Void: + stream->writeEmptyElement(QLatin1String("nil")); + break; + case QMetaType::UChar: + stream->writeEmptyElement(QLatin1String("uint8")); + stream->writeAttribute(QLatin1String("value"), + unsignedFormat.arg(attribute.value<quint8>(), 2, 16, + QLatin1Char('0'))); + //stream->writeAttribute(QLatin1String("name"), foo); + break; + case QMetaType::UShort: + stream->writeEmptyElement(QLatin1String("uint16")); + stream->writeAttribute(QLatin1String("value"), + unsignedFormat.arg(attribute.value<quint16>(), 4, 16, + QLatin1Char('0'))); + //stream->writeAttribute(QLatin1String("name"), foo); + case QMetaType::UInt: + stream->writeEmptyElement(QLatin1String("uint32")); + stream->writeAttribute(QLatin1String("value"), + unsignedFormat.arg(attribute.value<quint32>(), 8, 16, + QLatin1Char('0'))); + //stream->writeAttribute(QLatin1String("name"), foo); + break; + case QMetaType::Char: + stream->writeEmptyElement(QLatin1String("int8")); + stream->writeAttribute(QLatin1String("value"), + QString::number(attribute.value<uchar>(), 16)); + //stream->writeAttribute(QLatin1String("name"), foo); + break; + case QMetaType::Short: + stream->writeEmptyElement(QLatin1String("int16")); + stream->writeAttribute(QLatin1String("value"), + QString::number(attribute.value<qint16>(), 16)); + //stream->writeAttribute(QLatin1String("name"), foo); + break; + case QMetaType::Int: + stream->writeEmptyElement(QLatin1String("int32")); + stream->writeAttribute(QLatin1String("value"), + QString::number(attribute.value<qint32>(), 16)); + //stream->writeAttribute(QLatin1String("name"), foo); + break; + case QMetaType::QString: + stream->writeEmptyElement(QLatin1String("text")); + if (/* require hex encoding */ false) { + stream->writeAttribute(QLatin1String("value"), + attribute.value<QString>().toUtf8().toHex()); + stream->writeAttribute(QLatin1String("encoding"), QLatin1String("hex")); + } else { + stream->writeAttribute(QLatin1String("value"), attribute.value<QString>()); + stream->writeAttribute(QLatin1String("encoding"), QLatin1String("normal")); + } + //stream->writeAttribute(QLatin1String("name"), foo); + break; + case QMetaType::Bool: + stream->writeEmptyElement(QLatin1String("boolean")); + if (attribute.value<bool>()) + stream->writeAttribute(QLatin1String("value"), QLatin1String("true")); + else + stream->writeAttribute(QLatin1String("value"), QLatin1String("false")); + //stream->writeAttribute(QLatin1String("name"), foo); + break; + case QMetaType::QUrl: + stream->writeEmptyElement(QLatin1String("url")); + stream->writeAttribute(QLatin1String("value"), attribute.value<QUrl>().toString()); + //stream->writeAttribute(QLatin1String("name"), foo); + break; + case QVariant::UserType: + if (attribute.userType() == qMetaTypeId<QBluetoothUuid>()) { + stream->writeEmptyElement(QLatin1String("uuid")); + + QBluetoothUuid uuid = attribute.value<QBluetoothUuid>(); + switch (uuid.minimumSize()) { + case 0: + stream->writeAttribute(QLatin1String("value"), + unsignedFormat.arg(quint16(0), 4, 16, QLatin1Char('0'))); + break; + case 2: + stream->writeAttribute(QLatin1String("value"), + unsignedFormat.arg(uuid.toUInt16(), 4, 16, + QLatin1Char('0'))); + break; + case 4: + stream->writeAttribute(QLatin1String("value"), + unsignedFormat.arg(uuid.toUInt32(), 8, 16, + QLatin1Char('0'))); + break; + case 16: + stream->writeAttribute(QLatin1String("value"), uuid.toString().mid(1, 36)); + break; + default: + stream->writeAttribute(QLatin1String("value"), uuid.toString().mid(1, 36)); + } + } else if (attribute.userType() == qMetaTypeId<QBluetoothServiceInfo::Sequence>()) { + stream->writeStartElement(QLatin1String("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>()) { + const QBluetoothServiceInfo::Alternative *alternative = + static_cast<const QBluetoothServiceInfo::Alternative *>(attribute.data()); + foreach (const QVariant &v, *alternative) + writeAttribute(stream, v); + stream->writeEndElement(); + } + break; + default: + qDebug() << "Unknown variant type", attribute.userType(); + } +} + bool QBluetoothServiceInfo::isRegistered() const { - return false; + Q_D(const QBluetoothServiceInfo); + + return d->registered; } bool QBluetoothServiceInfo::registerService() const { - return false; + Q_D(const QBluetoothServiceInfo); + + return d->registerService(); } bool QBluetoothServiceInfo::unregisterService() const { - return false; + Q_D(const QBluetoothServiceInfo); + + if (!d->registered) + return false; + + if (!d->ensureSdpConnection()) + return false; + + QDBusPendingReply<> reply = d->service->RemoveRecord(d->serviceRecord); + reply.waitForFinished(); + if (reply.isError()) + return false; + + d->serviceRecord = 0; + + d->registered = false; + return true; } QBluetoothServiceInfoPrivate::QBluetoothServiceInfoPrivate() +: service(0), serviceRecord(0), registered(false) { } @@ -69,10 +212,86 @@ QBluetoothServiceInfoPrivate::~QBluetoothServiceInfoPrivate() void QBluetoothServiceInfoPrivate::setRegisteredAttribute(quint16 attributeId, const QVariant &value) const { + Q_UNUSED(attributeId); + Q_UNUSED(value); + + registerService(); } void QBluetoothServiceInfoPrivate::removeRegisteredAttribute(quint16 attributeId) const { + Q_UNUSED(attributeId); + + registerService(); +} + +bool QBluetoothServiceInfoPrivate::ensureSdpConnection() const +{ + if (service) + return true; + + OrgBluezManagerInterface manager(QLatin1String("org.bluez"), QLatin1String("/"), + QDBusConnection::systemBus()); + + QDBusPendingReply<QDBusObjectPath> reply = manager.FindAdapter(QLatin1String("any")); + reply.waitForFinished(); + if (reply.isError()) + return false; + + service = new OrgBluezServiceInterface(QLatin1String("org.bluez"), reply.value().path(), + QDBusConnection::systemBus()); + + return true; +} + +bool QBluetoothServiceInfoPrivate::registerService() const +{ + if (!ensureSdpConnection()) + return false; + + QString xmlServiceRecord; + + QXmlStreamWriter stream(&xmlServiceRecord); + stream.setAutoFormatting(true); + + stream.writeStartDocument(QLatin1String("1.0")); + + stream.writeStartElement(QLatin1String("record")); + + const QString unsignedFormat(QLatin1String("0x%1")); + + QMap<quint16, QVariant>::ConstIterator i = attributes.constBegin(); + while (i != attributes.constEnd()) { + QString t = unsignedFormat.arg(i.key(), 4, QLatin1Char('0')); + stream.writeStartElement(QLatin1String("attribute")); + stream.writeAttribute(QLatin1String("id"), + unsignedFormat.arg(i.key(), 4, 16, QLatin1Char('0'))); + writeAttribute(&stream, i.value()); + stream.writeEndElement(); + + ++i; + } + + stream.writeEndElement(); + + stream.writeEndDocument(); + + if (!registered) { + QDBusPendingReply<uint> reply = service->AddRecord(xmlServiceRecord); + reply.waitForFinished(); + if (reply.isError()) + return false; + + serviceRecord = reply.value(); + } else { + QDBusPendingReply<> reply = service->UpdateRecord(serviceRecord, xmlServiceRecord); + reply.waitForFinished(); + if (reply.isError()) + return false; + } + + registered = true; + return true; } QTM_END_NAMESPACE |