summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlex Blasche <alexander.blasche@digia.com>2014-07-03 09:23:25 +0200
committerAlex Blasche <alexander.blasche@digia.com>2014-07-03 09:23:25 +0200
commitf78b5f54d8c7536257629ad39bc300e233584949 (patch)
treee919f3f79a97e14fe927e840b2ad845d5ee92ee3 /src
parentd2c043d9bb1172f37b3d9051b0483c4a0f3a5d05 (diff)
parentcb6bdcb3fb94a38613304b60724e0cd02962cd14 (diff)
Merge branch 'dev' into btle
Conflicts: src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp Change-Id: Ib960b9e8d8800af84d2094bdf26c2652d4c81dba
Diffstat (limited to 'src')
-rw-r--r--src/bluetooth/android/jni_android.cpp4
-rw-r--r--src/bluetooth/bluez/bluez.pri12
-rw-r--r--src/bluetooth/bluez/bluez5_helper.cpp61
-rw-r--r--src/bluetooth/bluez/bluez5_helper_p.h2
-rw-r--r--src/bluetooth/bluez/obex_client1_bluez5.cpp26
-rw-r--r--src/bluetooth/bluez/obex_client1_bluez5_p.h63
-rw-r--r--src/bluetooth/bluez/obex_objectpush1_bluez5.cpp26
-rw-r--r--src/bluetooth/bluez/obex_objectpush1_bluez5_p.h100
-rw-r--r--src/bluetooth/bluez/obex_transfer1_bluez5.cpp26
-rw-r--r--src/bluetooth/bluez/obex_transfer1_bluez5_p.h91
-rw-r--r--src/bluetooth/bluez/org.bluez.Client1.xml15
-rw-r--r--src/bluetooth/bluez/org.bluez.ProfileManager1.xml16
-rw-r--r--src/bluetooth/bluez/org.bluez.obex.ObjectPush1.xml25
-rw-r--r--src/bluetooth/bluez/org.bluez.obex.Transfer1.xml16
-rw-r--r--src/bluetooth/bluez/profile1.cpp26
-rw-r--r--src/bluetooth/bluez/profile1_p.h61
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent.h1
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp75
-rw-r--r--src/bluetooth/qbluetoothlocaldevice.cpp10
-rw-r--r--src/bluetooth/qbluetoothlocaldevice_bluez.cpp131
-rw-r--r--src/bluetooth/qbluetoothlocaldevice_p.h3
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp47
-rw-r--r--src/bluetooth/qbluetoothserviceinfo_bluez.cpp142
-rw-r--r--src/bluetooth/qbluetoothserviceinfo_p.h3
-rw-r--r--src/bluetooth/qbluetoothsocket.h1
-rw-r--r--src/bluetooth/qbluetoothsocket_bluez.cpp2
-rw-r--r--src/bluetooth/qbluetoothtransferreply.cpp15
-rw-r--r--src/bluetooth/qbluetoothtransferreply.h4
-rw-r--r--src/bluetooth/qbluetoothtransferreply_bluez.cpp247
-rw-r--r--src/bluetooth/qbluetoothtransferreply_bluez_p.h24
30 files changed, 1062 insertions, 213 deletions
diff --git a/src/bluetooth/android/jni_android.cpp b/src/bluetooth/android/jni_android.cpp
index ebc46a7c..b7221867 100644
--- a/src/bluetooth/android/jni_android.cpp
+++ b/src/bluetooth/android/jni_android.cpp
@@ -93,7 +93,7 @@ QAndroidJniObject valueForStaticField(JavaNames javaName, JavaNames javaFieldNam
case JavaNames::BluetoothDevice:
className = javaBluetoothDeviceClassName; break;
default:
- qWarning(QT_BT_ANDROID) << "Unknown java class name passed to valueForStaticField():" << javaName;
+ qCWarning(QT_BT_ANDROID) << "Unknown java class name passed to valueForStaticField():" << javaName;
return QAndroidJniObject();
}
@@ -132,7 +132,7 @@ QAndroidJniObject valueForStaticField(JavaNames javaName, JavaNames javaFieldNam
case JavaNames::ExtraUuid:
fieldName = javaExtraUuid; break;
default:
- qWarning(QT_BT_ANDROID) << "Unknown java field name passed to valueForStaticField():" << javaFieldName;
+ qCWarning(QT_BT_ANDROID) << "Unknown java field name passed to valueForStaticField():" << javaFieldName;
return QAndroidJniObject();
}
diff --git a/src/bluetooth/bluez/bluez.pri b/src/bluetooth/bluez/bluez.pri
index 0fa4e5c9..e1cdb58a 100644
--- a/src/bluetooth/bluez/bluez.pri
+++ b/src/bluetooth/bluez/bluez.pri
@@ -26,7 +26,11 @@ HEADERS += bluez/manager_p.h \
bluez/objectmanager_p.h \
bluez/properties_p.h \
bluez/adapter1_bluez5_p.h \
- bluez/device1_bluez5_p.h
+ bluez/device1_bluez5_p.h \
+ bluez/profile1_p.h \
+ bluez/obex_client1_bluez5_p.h \
+ bluez/obex_objectpush1_bluez5_p.h \
+ bluez/obex_transfer1_bluez5_p.h
SOURCES += bluez/manager.cpp \
@@ -44,4 +48,8 @@ SOURCES += bluez/manager.cpp \
bluez/properties.cpp \
bluez/adapter1_bluez5.cpp \
bluez/device1_bluez5.cpp \
- bluez/bluez5_helper.cpp
+ bluez/bluez5_helper.cpp \
+ bluez/profile1.cpp \
+ bluez/obex_client1_bluez5.cpp \
+ bluez/obex_objectpush1_bluez5.cpp \
+ bluez/obex_transfer1_bluez5.cpp
diff --git a/src/bluetooth/bluez/bluez5_helper.cpp b/src/bluetooth/bluez/bluez5_helper.cpp
index c995d948..18ab22b1 100644
--- a/src/bluetooth/bluez/bluez5_helper.cpp
+++ b/src/bluetooth/bluez/bluez5_helper.cpp
@@ -457,4 +457,65 @@ QByteArray parseSdpRecord(sdp_record_t *record)
return xmlOutput;
}
+
+/*!
+ Finds the path for the local adapter with \a wantedAddress or an empty string
+ if no local adapter with the given address can be found.
+ If \a wantedAddress is \c null it returns the first/default adapter or an empty
+ string if none is available.
+
+ If \a ok is false the lookup was aborted due to a dbus error and this function
+ returns an empty string.
+ */
+QString findAdapterForAddress(const QBluetoothAddress &wantedAddress, bool *ok = 0)
+{
+ OrgFreedesktopDBusObjectManagerInterface manager(QStringLiteral("org.bluez"),
+ QStringLiteral("/"),
+ QDBusConnection::systemBus());
+
+ QDBusPendingReply<ManagedObjectList> reply = manager.GetManagedObjects();
+ reply.waitForFinished();
+ if (reply.isError()) {
+ if (ok)
+ *ok = false;
+
+ return QString();
+ }
+
+ typedef QPair<QString, QBluetoothAddress> AddressForPathType;
+ QList<AddressForPathType> localAdapters;
+
+ foreach (const QDBusObjectPath &path, reply.value().keys()) {
+ const InterfaceList ifaceList = reply.value().value(path);
+ foreach (const QString &iface, ifaceList.keys()) {
+ if (iface == QStringLiteral("org.bluez.Adapter1")) {
+ AddressForPathType pair;
+ pair.first = path.path();
+ pair.second = QBluetoothAddress(ifaceList.value(iface).value(
+ QStringLiteral("Address")).toString());
+ if (!pair.second.isNull())
+ localAdapters.append(pair);
+ break;
+ }
+ }
+ }
+
+ if (ok)
+ *ok = true;
+
+ if (localAdapters.isEmpty())
+ return QString(); // -> no local adapter found
+
+ if (wantedAddress.isNull())
+ return localAdapters.front().first; // -> return first found adapter
+
+ foreach (const AddressForPathType &pair, localAdapters) {
+ if (pair.second == wantedAddress)
+ return pair.first; // -> found local adapter with wanted address
+ }
+
+ return QString(); // nothing matching found
+}
+
+
QT_END_NAMESPACE
diff --git a/src/bluetooth/bluez/bluez5_helper_p.h b/src/bluetooth/bluez/bluez5_helper_p.h
index 2429c09c..36595f9c 100644
--- a/src/bluetooth/bluez/bluez5_helper_p.h
+++ b/src/bluetooth/bluez/bluez5_helper_p.h
@@ -45,6 +45,7 @@
#include <QtCore/QObject>
#include <QtDBus/QtDBus>
#include <bluetooth/sdp.h>
+#include <QtBluetooth/QBluetoothAddress>
typedef QMap<QString, QVariantMap> InterfaceList;
typedef QMap<QDBusObjectPath, InterfaceList> ManagedObjectList;
@@ -57,6 +58,7 @@ QT_BEGIN_NAMESPACE
bool isBluez5();
QByteArray parseSdpRecord(sdp_record_t *record);
+QString findAdapterForAddress(const QBluetoothAddress &wantedAddress, bool *ok);
class QtBluezDiscoveryManagerPrivate;
class QtBluezDiscoveryManager : public QObject
diff --git a/src/bluetooth/bluez/obex_client1_bluez5.cpp b/src/bluetooth/bluez/obex_client1_bluez5.cpp
new file mode 100644
index 00000000..fe0fd1f3
--- /dev/null
+++ b/src/bluetooth/bluez/obex_client1_bluez5.cpp
@@ -0,0 +1,26 @@
+/*
+ * This file was generated by qdbusxml2cpp version 0.8
+ * Command line was: qdbusxml2cpp org.bluez.Client1.xml -p asd
+ *
+ * qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+ *
+ * This is an auto-generated file.
+ * This file may have been hand-edited. Look for HAND-EDIT comments
+ * before re-generating it.
+ */
+
+#include "obex_client1_bluez5_p.h"
+
+/*
+ * Implementation of interface class OrgBluezObexClient1Interface
+ */
+
+OrgBluezObexClient1Interface::OrgBluezObexClient1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
+ : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
+{
+}
+
+OrgBluezObexClient1Interface::~OrgBluezObexClient1Interface()
+{
+}
+
diff --git a/src/bluetooth/bluez/obex_client1_bluez5_p.h b/src/bluetooth/bluez/obex_client1_bluez5_p.h
new file mode 100644
index 00000000..f8f0f89a
--- /dev/null
+++ b/src/bluetooth/bluez/obex_client1_bluez5_p.h
@@ -0,0 +1,63 @@
+/*
+ * This file was generated by qdbusxml2cpp version 0.8
+ * Command line was: qdbusxml2cpp org.bluez.Client1.xml -p asd
+ *
+ * qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+ *
+ * This is an auto-generated file.
+ * Do not edit! All changes made to it will be lost.
+ */
+
+#ifndef ASD_H_1399976174
+#define ASD_H_1399976174
+
+#include <QtCore/QObject>
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QVariant>
+#include <QtDBus/QtDBus>
+
+/*
+ * Proxy class for interface org.bluez.obex.Client1
+ */
+class OrgBluezObexClient1Interface: public QDBusAbstractInterface
+{
+ Q_OBJECT
+public:
+ static inline const char *staticInterfaceName()
+ { return "org.bluez.obex.Client1"; }
+
+public:
+ OrgBluezObexClient1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
+
+ ~OrgBluezObexClient1Interface();
+
+public Q_SLOTS: // METHODS
+ inline QDBusPendingReply<QDBusObjectPath> CreateSession(const QString &destination, const QVariantMap &args)
+ {
+ QList<QVariant> argumentList;
+ argumentList << QVariant::fromValue(destination) << QVariant::fromValue(args);
+ return asyncCallWithArgumentList(QLatin1String("CreateSession"), argumentList);
+ }
+
+ inline QDBusPendingReply<> RemoveSession(const QDBusObjectPath &session)
+ {
+ QList<QVariant> argumentList;
+ argumentList << QVariant::fromValue(session);
+ return asyncCallWithArgumentList(QLatin1String("RemoveSession"), argumentList);
+ }
+
+Q_SIGNALS: // SIGNALS
+};
+
+namespace org {
+ namespace bluez {
+ namespace obex {
+ typedef ::OrgBluezObexClient1Interface Client1;
+ }
+ }
+}
+#endif
diff --git a/src/bluetooth/bluez/obex_objectpush1_bluez5.cpp b/src/bluetooth/bluez/obex_objectpush1_bluez5.cpp
new file mode 100644
index 00000000..637a3a62
--- /dev/null
+++ b/src/bluetooth/bluez/obex_objectpush1_bluez5.cpp
@@ -0,0 +1,26 @@
+/*
+ * This file was generated by qdbusxml2cpp version 0.8
+ * Command line was: qdbusxml2cpp org.bluez.obex.ObjectPush1.xml -p obex_objectpush1_bluez5
+ *
+ * qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+ *
+ * This is an auto-generated file.
+ * This file may have been hand-edited. Look for HAND-EDIT comments
+ * before re-generating it.
+ */
+
+#include "obex_objectpush1_bluez5_p.h"
+
+/*
+ * Implementation of interface class OrgBluezObexObjectPush1Interface
+ */
+
+OrgBluezObexObjectPush1Interface::OrgBluezObexObjectPush1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
+ : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
+{
+}
+
+OrgBluezObexObjectPush1Interface::~OrgBluezObexObjectPush1Interface()
+{
+}
+
diff --git a/src/bluetooth/bluez/obex_objectpush1_bluez5_p.h b/src/bluetooth/bluez/obex_objectpush1_bluez5_p.h
new file mode 100644
index 00000000..f8adcab4
--- /dev/null
+++ b/src/bluetooth/bluez/obex_objectpush1_bluez5_p.h
@@ -0,0 +1,100 @@
+/*
+ * This file was generated by qdbusxml2cpp version 0.8
+ * Command line was: qdbusxml2cpp org.bluez.obex.ObjectPush1.xml -p obex_objectpush1_bluez5
+ *
+ * qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+ *
+ * This is an auto-generated file.
+ * Do not edit! All changes made to it will be lost.
+ */
+
+#ifndef OBEX_OBJECTPUSH1_BLUEZ5_H_1399989318
+#define OBEX_OBJECTPUSH1_BLUEZ5_H_1399989318
+
+#include <QtCore/QObject>
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QVariant>
+#include <QtDBus/QtDBus>
+
+/*
+ * Proxy class for interface org.bluez.obex.ObjectPush1
+ */
+class OrgBluezObexObjectPush1Interface: public QDBusAbstractInterface
+{
+ Q_OBJECT
+public:
+ static inline const char *staticInterfaceName()
+ { return "org.bluez.obex.ObjectPush1"; }
+
+public:
+ OrgBluezObexObjectPush1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
+
+ ~OrgBluezObexObjectPush1Interface();
+
+public Q_SLOTS: // METHODS
+ inline QDBusPendingReply<QDBusObjectPath, QVariantMap> ExchangeBusinessCards(const QString &clientfile, const QString &targetfile)
+ {
+ QList<QVariant> argumentList;
+ argumentList << QVariant::fromValue(clientfile) << QVariant::fromValue(targetfile);
+ return asyncCallWithArgumentList(QLatin1String("ExchangeBusinessCards"), argumentList);
+ }
+ inline QDBusReply<QDBusObjectPath> ExchangeBusinessCards(const QString &clientfile, const QString &targetfile, QVariantMap &properties)
+ {
+ QList<QVariant> argumentList;
+ argumentList << QVariant::fromValue(clientfile) << QVariant::fromValue(targetfile);
+ QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("ExchangeBusinessCards"), argumentList);
+ if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 2) {
+ properties = qdbus_cast<QVariantMap>(reply.arguments().at(1));
+ }
+ return reply;
+ }
+
+ inline QDBusPendingReply<QDBusObjectPath, QVariantMap> PullBusinessCard(const QString &targetfile)
+ {
+ QList<QVariant> argumentList;
+ argumentList << QVariant::fromValue(targetfile);
+ return asyncCallWithArgumentList(QLatin1String("PullBusinessCard"), argumentList);
+ }
+ inline QDBusReply<QDBusObjectPath> PullBusinessCard(const QString &targetfile, QVariantMap &properties)
+ {
+ QList<QVariant> argumentList;
+ argumentList << QVariant::fromValue(targetfile);
+ QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("PullBusinessCard"), argumentList);
+ if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 2) {
+ properties = qdbus_cast<QVariantMap>(reply.arguments().at(1));
+ }
+ return reply;
+ }
+
+ inline QDBusPendingReply<QDBusObjectPath, QVariantMap> SendFile(const QString &sourcefile)
+ {
+ QList<QVariant> argumentList;
+ argumentList << QVariant::fromValue(sourcefile);
+ return asyncCallWithArgumentList(QLatin1String("SendFile"), argumentList);
+ }
+ inline QDBusReply<QDBusObjectPath> SendFile(const QString &sourcefile, QVariantMap &properties)
+ {
+ QList<QVariant> argumentList;
+ argumentList << QVariant::fromValue(sourcefile);
+ QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("SendFile"), argumentList);
+ if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 2) {
+ properties = qdbus_cast<QVariantMap>(reply.arguments().at(1));
+ }
+ return reply;
+ }
+
+Q_SIGNALS: // SIGNALS
+};
+
+namespace org {
+ namespace bluez {
+ namespace obex {
+ typedef ::OrgBluezObexObjectPush1Interface ObjectPush1;
+ }
+ }
+}
+#endif
diff --git a/src/bluetooth/bluez/obex_transfer1_bluez5.cpp b/src/bluetooth/bluez/obex_transfer1_bluez5.cpp
new file mode 100644
index 00000000..51f2a013
--- /dev/null
+++ b/src/bluetooth/bluez/obex_transfer1_bluez5.cpp
@@ -0,0 +1,26 @@
+/*
+ * This file was generated by qdbusxml2cpp version 0.8
+ * Command line was: qdbusxml2cpp org.bluez.obex.Transfer1.xml -p obex_transfer1_bluez5
+ *
+ * qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+ *
+ * This is an auto-generated file.
+ * This file may have been hand-edited. Look for HAND-EDIT comments
+ * before re-generating it.
+ */
+
+#include "obex_transfer1_bluez5_p.h"
+
+/*
+ * Implementation of interface class OrgBluezObexTransfer1Interface
+ */
+
+OrgBluezObexTransfer1Interface::OrgBluezObexTransfer1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
+ : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
+{
+}
+
+OrgBluezObexTransfer1Interface::~OrgBluezObexTransfer1Interface()
+{
+}
+
diff --git a/src/bluetooth/bluez/obex_transfer1_bluez5_p.h b/src/bluetooth/bluez/obex_transfer1_bluez5_p.h
new file mode 100644
index 00000000..46b86248
--- /dev/null
+++ b/src/bluetooth/bluez/obex_transfer1_bluez5_p.h
@@ -0,0 +1,91 @@
+/*
+ * This file was generated by qdbusxml2cpp version 0.8
+ * Command line was: qdbusxml2cpp org.bluez.obex.Transfer1.xml -p obex_transfer1_bluez5
+ *
+ * qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+ *
+ * This is an auto-generated file.
+ * Do not edit! All changes made to it will be lost.
+ */
+
+#ifndef OBEX_TRANSFER1_BLUEZ5_H_1400058158
+#define OBEX_TRANSFER1_BLUEZ5_H_1400058158
+
+#include <QtCore/QObject>
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QVariant>
+#include <QtDBus/QtDBus>
+
+/*
+ * Proxy class for interface org.bluez.obex.Transfer1
+ */
+class OrgBluezObexTransfer1Interface: public QDBusAbstractInterface
+{
+ Q_OBJECT
+public:
+ static inline const char *staticInterfaceName()
+ { return "org.bluez.obex.Transfer1"; }
+
+public:
+ OrgBluezObexTransfer1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
+
+ ~OrgBluezObexTransfer1Interface();
+
+ Q_PROPERTY(QString Filename READ filename)
+ inline QString filename() const
+ { return qvariant_cast< QString >(property("Filename")); }
+
+ Q_PROPERTY(QString Name READ name)
+ inline QString name() const
+ { return qvariant_cast< QString >(property("Name")); }
+
+ Q_PROPERTY(QDBusObjectPath Session READ session)
+ inline QDBusObjectPath session() const
+ { return qvariant_cast< QDBusObjectPath >(property("Session")); }
+
+ Q_PROPERTY(qulonglong Size READ size)
+ inline qulonglong size() const
+ { return qvariant_cast< qulonglong >(property("Size")); }
+
+ Q_PROPERTY(QString Status READ status)
+ inline QString status() const
+ { return qvariant_cast< QString >(property("Status")); }
+
+ Q_PROPERTY(qulonglong Transferred READ transferred)
+ inline qulonglong transferred() const
+ { return qvariant_cast< qulonglong >(property("Transferred")); }
+
+public Q_SLOTS: // METHODS
+ inline QDBusPendingReply<> Cancel()
+ {
+ QList<QVariant> argumentList;
+ return asyncCallWithArgumentList(QLatin1String("Cancel"), argumentList);
+ }
+
+ inline QDBusPendingReply<> Resume()
+ {
+ QList<QVariant> argumentList;
+ return asyncCallWithArgumentList(QLatin1String("Resume"), argumentList);
+ }
+
+ inline QDBusPendingReply<> Suspend()
+ {
+ QList<QVariant> argumentList;
+ return asyncCallWithArgumentList(QLatin1String("Suspend"), argumentList);
+ }
+
+Q_SIGNALS: // SIGNALS
+};
+
+namespace org {
+ namespace bluez {
+ namespace obex {
+ typedef ::OrgBluezObexTransfer1Interface Transfer1;
+ }
+ }
+}
+#endif
diff --git a/src/bluetooth/bluez/org.bluez.Client1.xml b/src/bluetooth/bluez/org.bluez.Client1.xml
new file mode 100644
index 00000000..8a5a25c1
--- /dev/null
+++ b/src/bluetooth/bluez/org.bluez.Client1.xml
@@ -0,0 +1,15 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+ <interface name="org.bluez.obex.Client1">
+ <method name="CreateSession">
+ <arg name="destination" type="s" direction="in"/>
+ <arg name="args" type="a{sv}" direction="in"/>
+ <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
+ <arg name="session" type="o" direction="out"/>
+ </method>
+ <method name="RemoveSession">
+ <arg name="session" type="o" direction="in"/>
+ </method>
+ </interface>
+</node>
diff --git a/src/bluetooth/bluez/org.bluez.ProfileManager1.xml b/src/bluetooth/bluez/org.bluez.ProfileManager1.xml
new file mode 100644
index 00000000..54c9fd0e
--- /dev/null
+++ b/src/bluetooth/bluez/org.bluez.ProfileManager1.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+ <interface name="org.bluez.ProfileManager1">
+ <method name="RegisterProfile">
+ <arg name="profile" type="o" direction="in"/>
+ <arg name="UUID" type="s" direction="in"/>
+ <arg name="options" type="a{sv}" direction="in"/>
+ <annotation name="org.qtproject.QtDBus.QtTypeName.In2" value="QVariantMap"/>
+ </method>
+ <method name="UnregisterProfile">
+ <arg name="profile" type="o" direction="in"/>
+ </method>
+ </interface>
+</node>
+
diff --git a/src/bluetooth/bluez/org.bluez.obex.ObjectPush1.xml b/src/bluetooth/bluez/org.bluez.obex.ObjectPush1.xml
new file mode 100644
index 00000000..651f21a5
--- /dev/null
+++ b/src/bluetooth/bluez/org.bluez.obex.ObjectPush1.xml
@@ -0,0 +1,25 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+ <interface name="org.bluez.obex.ObjectPush1">
+ <method name="SendFile">
+ <arg name="sourcefile" type="s" direction="in"/>
+ <arg name="transfer" type="o" direction="out"/>
+ <arg name="properties" type="a{sv}" direction="out"/>
+ <annotation name="org.qtproject.QtDBus.QtTypeName.Out1" value="QVariantMap"/>
+ </method>
+ <method name="PullBusinessCard">
+ <arg name="targetfile" type="s" direction="in"/>
+ <arg name="transfer" type="o" direction="out"/>
+ <arg name="properties" type="a{sv}" direction="out"/>
+ <annotation name="org.qtproject.QtDBus.QtTypeName.Out1" value="QVariantMap"/>
+ </method>
+ <method name="ExchangeBusinessCards">
+ <arg name="clientfile" type="s" direction="in"/>
+ <arg name="targetfile" type="s" direction="in"/>
+ <arg name="transfer" type="o" direction="out"/>
+ <arg name="properties" type="a{sv}" direction="out"/>
+ <annotation name="org.qtproject.QtDBus.QtTypeName.Out1" value="QVariantMap"/>
+ </method>
+ </interface>
+</node>
diff --git a/src/bluetooth/bluez/org.bluez.obex.Transfer1.xml b/src/bluetooth/bluez/org.bluez.obex.Transfer1.xml
new file mode 100644
index 00000000..4ee76f7d
--- /dev/null
+++ b/src/bluetooth/bluez/org.bluez.obex.Transfer1.xml
@@ -0,0 +1,16 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+ <interface name="org.bluez.obex.Transfer1">
+ <method name="Suspend"/>
+ <method name="Resume"/>
+ <method name="Cancel"/>
+ <property name="Status" type="s" access="read"/>
+ <property name="Name" type="s" access="read"/>
+ <property name="Size" type="t" access="read"/>
+ <property name="Filename" type="s" access="read"/>
+ <property name="Transferred" type="t" access="read"/>
+ <property name="Session" type="o" access="read"/>
+ </interface>
+</node>
+
diff --git a/src/bluetooth/bluez/profile1.cpp b/src/bluetooth/bluez/profile1.cpp
new file mode 100644
index 00000000..2cf15d7e
--- /dev/null
+++ b/src/bluetooth/bluez/profile1.cpp
@@ -0,0 +1,26 @@
+/*
+ * This file was generated by qdbusxml2cpp version 0.8
+ * Command line was: qdbusxml2cpp -p profile1 org.bluez.ProfileManager1.xml
+ *
+ * qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+ *
+ * This is an auto-generated file.
+ * This file may have been hand-edited. Look for HAND-EDIT comments
+ * before re-generating it.
+ */
+
+#include "profile1_p.h"
+
+/*
+ * Implementation of interface class OrgBluezProfileManager1Interface
+ */
+
+OrgBluezProfileManager1Interface::OrgBluezProfileManager1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
+ : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
+{
+}
+
+OrgBluezProfileManager1Interface::~OrgBluezProfileManager1Interface()
+{
+}
+
diff --git a/src/bluetooth/bluez/profile1_p.h b/src/bluetooth/bluez/profile1_p.h
new file mode 100644
index 00000000..d94f1916
--- /dev/null
+++ b/src/bluetooth/bluez/profile1_p.h
@@ -0,0 +1,61 @@
+/*
+ * This file was generated by qdbusxml2cpp version 0.8
+ * Command line was: qdbusxml2cpp -p profile1 org.bluez.ProfileManager1.xml
+ *
+ * qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+ *
+ * This is an auto-generated file.
+ * Do not edit! All changes made to it will be lost.
+ */
+
+#ifndef PROFILE1_H_1400142085
+#define PROFILE1_H_1400142085
+
+#include <QtCore/QObject>
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QVariant>
+#include <QtDBus/QtDBus>
+
+/*
+ * Proxy class for interface org.bluez.ProfileManager1
+ */
+class OrgBluezProfileManager1Interface: public QDBusAbstractInterface
+{
+ Q_OBJECT
+public:
+ static inline const char *staticInterfaceName()
+ { return "org.bluez.ProfileManager1"; }
+
+public:
+ OrgBluezProfileManager1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
+
+ ~OrgBluezProfileManager1Interface();
+
+public Q_SLOTS: // METHODS
+ inline QDBusPendingReply<> RegisterProfile(const QDBusObjectPath &profile, const QString &UUID, const QVariantMap &options)
+ {
+ QList<QVariant> argumentList;
+ argumentList << QVariant::fromValue(profile) << QVariant::fromValue(UUID) << QVariant::fromValue(options);
+ return asyncCallWithArgumentList(QLatin1String("RegisterProfile"), argumentList);
+ }
+
+ inline QDBusPendingReply<> UnregisterProfile(const QDBusObjectPath &profile)
+ {
+ QList<QVariant> argumentList;
+ argumentList << QVariant::fromValue(profile);
+ return asyncCallWithArgumentList(QLatin1String("UnregisterProfile"), argumentList);
+ }
+
+Q_SIGNALS: // SIGNALS
+};
+
+namespace org {
+ namespace bluez {
+ typedef ::OrgBluezProfileManager1Interface ProfileManager1;
+ }
+}
+#endif
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent.h b/src/bluetooth/qbluetoothdevicediscoveryagent.h
index 45615e74..89158c53 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent.h
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent.h
@@ -79,6 +79,7 @@ public:
QObject *parent = 0);
~QBluetoothDeviceDiscoveryAgent();
+ // TODO Remove inquiry type in Qt 6 -> not really used anywhere
QBluetoothDeviceDiscoveryAgent::InquiryType inquiryType() const;
void setInquiryType(QBluetoothDeviceDiscoveryAgent::InquiryType type);
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp
index f70c3e64..ed09d598 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp
@@ -186,75 +186,52 @@ void QBluetoothDeviceDiscoveryAgentPrivate::startBluez5()
{
Q_Q(QBluetoothDeviceDiscoveryAgent);
- QDBusPendingReply<ManagedObjectList> reply = managerBluez5->GetManagedObjects();
- reply.waitForFinished();
- if (reply.isError()) {
- errorString = reply.error().message();
- lastError = QBluetoothDeviceDiscoveryAgent::InputOutputError;
- emit q->error(lastError);
- return;
- }
-
-
- OrgBluezAdapter1Interface *tempAdapter = 0;
- QMap<QString, QVariantMap> devicesForAdapter; // dbus path for devices for matching adapter
-
- foreach (const QDBusObjectPath &path, reply.value().keys()) {
- const InterfaceList ifaceList = reply.value().value(path);
- foreach (const QString &iface, ifaceList.keys()) {
- if (iface == QStringLiteral("org.bluez.Adapter1")) {
- if (tempAdapter)
- continue;
-
- if (m_adapterAddress.isNull()) {
- // use the first found adapter as default
- tempAdapter = new OrgBluezAdapter1Interface(QStringLiteral("org.bluez"),
- path.path(),
- QDBusConnection::systemBus());
- } else {
- const QString addressString = ifaceList.value(iface).
- value(QStringLiteral("Address")).toString();
- if (m_adapterAddress == QBluetoothAddress(addressString)) {
- tempAdapter = new OrgBluezAdapter1Interface(
- QStringLiteral("org.bluez"),
- path.path(),
- QDBusConnection::systemBus());
- }
- }
- } else if (iface == QStringLiteral("org.bluez.Device1")) {
- devicesForAdapter.insert(path.path(), ifaceList.value(iface));
- }
- }
- }
- if (!tempAdapter) {
- qCDebug(QT_BT_BLUEZ) << "Cannot find Bluez 5 adapter for device search";
+ bool ok = false;
+ const QString adapterPath = findAdapterForAddress(m_adapterAddress, &ok);
+ if (!ok || adapterPath.isEmpty()) {
+ qCWarning(QT_BT_BLUEZ) << "Cannot find Bluez 5 adapter for device search" << ok;
lastError = QBluetoothDeviceDiscoveryAgent::InputOutputError;
errorString = QBluetoothDeviceDiscoveryAgent::tr("Cannot find valid Bluetooth adapter.");
q->error(lastError);
return;
}
- if (!tempAdapter->powered()) {
+ adapterBluez5 = new OrgBluezAdapter1Interface(QStringLiteral("org.bluez"),
+ adapterPath,
+ QDBusConnection::systemBus());
+
+ if (!adapterBluez5->powered()) {
qCDebug(QT_BT_BLUEZ) << "Aborting device discovery due to offline Bluetooth Adapter";
lastError = QBluetoothDeviceDiscoveryAgent::PoweredOffError;
errorString = QBluetoothDeviceDiscoveryAgent::tr("Device is powered off");
- delete tempAdapter;
+ delete adapterBluez5;
+ adapterBluez5 = 0;
emit q->error(lastError);
return;
}
- adapterBluez5 = tempAdapter;
+
QtBluezDiscoveryManager::instance()->registerDiscoveryInterest(adapterBluez5->path());
QObject::connect(QtBluezDiscoveryManager::instance(), SIGNAL(discoveryInterrupted(QString)),
q, SLOT(_q_discoveryInterrupted(QString)));
// collect initial set of information
- foreach (const QString &path, devicesForAdapter.keys()) {
- if (path.indexOf(adapterBluez5->path()) != 0)
- continue; //devices path doesnt start with same path as adapter
+ QDBusPendingReply<ManagedObjectList> reply = managerBluez5->GetManagedObjects();
+ reply.waitForFinished();
+ if (!reply.isError()) {
+ foreach (const QDBusObjectPath &path, reply.value().keys()) {
+ const InterfaceList ifaceList = reply.value().value(path);
+ foreach (const QString &iface, ifaceList.keys()) {
+ if (iface == QStringLiteral("org.bluez.Device1")) {
+
+ if (path.path().indexOf(adapterBluez5->path()) != 0)
+ continue; //devices whose path doesn't start with same path we skip
- deviceFoundBluez5(path);
+ deviceFoundBluez5(path.path());
+ }
+ }
+ }
}
// wait 20s and sum up what was found
diff --git a/src/bluetooth/qbluetoothlocaldevice.cpp b/src/bluetooth/qbluetoothlocaldevice.cpp
index c5b68645..78899d0a 100644
--- a/src/bluetooth/qbluetoothlocaldevice.cpp
+++ b/src/bluetooth/qbluetoothlocaldevice.cpp
@@ -124,8 +124,16 @@ QBluetoothLocalDevice::~QBluetoothLocalDevice()
}
/*!
- Returns true if the QBluetoothLocalDevice represents an available local Bluetooth device;
+ Returns \c true if the QBluetoothLocalDevice represents an available local Bluetooth device;
otherwise return false.
+
+ If the local Bluetooth adapter represented by an instance of this class
+ is removed from the system (e.g. removal of the underlying Bluetooth dongle)
+ then this instance will become invalid. An already invalid QBluetoothLocalDevice instance
+ remains invalid even if the same Bluetooth adapter is returned to
+ the system.
+
+ \sa allDevices()
*/
bool QBluetoothLocalDevice::isValid() const
{
diff --git a/src/bluetooth/qbluetoothlocaldevice_bluez.cpp b/src/bluetooth/qbluetoothlocaldevice_bluez.cpp
index 98894dff..18493f82 100644
--- a/src/bluetooth/qbluetoothlocaldevice_bluez.cpp
+++ b/src/bluetooth/qbluetoothlocaldevice_bluez.cpp
@@ -286,7 +286,7 @@ static inline OrgBluezDeviceInterface *getDevice(const QBluetoothAddress &addres
void QBluetoothLocalDevice::requestPairing(const QBluetoothAddress &address, Pairing pairing)
{
- if (address.isNull() || !isValid()) {
+ if (!isValid() || address.isNull()) {
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
Q_ARG(QBluetoothLocalDevice::Error,
QBluetoothLocalDevice::PairingError));
@@ -636,6 +636,7 @@ QBluetoothLocalDevicePrivate::QBluetoothLocalDevicePrivate(QBluetoothLocalDevice
adapterProperties(0),
managerBluez5(0),
agent(0),
+ manager(0),
localAddress(address),
pairingTarget(0),
pairingDiscoveryTimer(0),
@@ -700,6 +701,8 @@ QBluetoothLocalDevicePrivate::~QBluetoothLocalDevicePrivate()
delete managerBluez5;
delete agent;
delete pairingTarget;
+ delete manager;
+
qDeleteAll(devices);
qDeleteAll(deviceChangeMonitors);
}
@@ -709,11 +712,12 @@ void QBluetoothLocalDevicePrivate::initializeAdapter()
if (adapter)
return;
- OrgBluezManagerInterface manager(QStringLiteral("org.bluez"), QStringLiteral("/"),
- QDBusConnection::systemBus());
+ QScopedPointer<OrgBluezManagerInterface> man(new OrgBluezManagerInterface(
+ QStringLiteral("org.bluez"), QStringLiteral("/"),
+ QDBusConnection::systemBus()));
if (localAddress == QBluetoothAddress()) {
- QDBusPendingReply<QDBusObjectPath> reply = manager.DefaultAdapter();
+ QDBusPendingReply<QDBusObjectPath> reply = man->DefaultAdapter();
reply.waitForFinished();
if (reply.isError())
return;
@@ -721,7 +725,7 @@ void QBluetoothLocalDevicePrivate::initializeAdapter()
adapter = new OrgBluezAdapterInterface(QStringLiteral("org.bluez"),
reply.value().path(), QDBusConnection::systemBus());
} else {
- QDBusPendingReply<QList<QDBusObjectPath> > reply = manager.ListAdapters();
+ QDBusPendingReply<QList<QDBusObjectPath> > reply = man->ListAdapters();
reply.waitForFinished();
if (reply.isError())
return;
@@ -733,8 +737,10 @@ void QBluetoothLocalDevicePrivate::initializeAdapter()
QDBusPendingReply<QVariantMap> reply = tmpAdapter->GetProperties();
reply.waitForFinished();
- if (reply.isError())
+ if (reply.isError()) {
+ delete tmpAdapter;
continue;
+ }
QBluetoothAddress path_address(reply.value().value(QStringLiteral("Address")).toString());
@@ -747,6 +753,11 @@ void QBluetoothLocalDevicePrivate::initializeAdapter()
}
}
+ // monitor case when local adapter is removed
+ manager = man.take();
+ connect(manager, SIGNAL(AdapterRemoved(QDBusObjectPath)),
+ this, SLOT(adapterRemoved(QDBusObjectPath)));
+
currentMode = static_cast<QBluetoothLocalDevice::HostMode>(-1);
if (adapter) {
connect(adapter, SIGNAL(PropertyChanged(QString, QDBusVariant)),
@@ -775,51 +786,14 @@ void QBluetoothLocalDevicePrivate::initializeAdapterBluez5()
connect(managerBluez5, SIGNAL(InterfacesRemoved(QDBusObjectPath,QStringList)),
SLOT(InterfacesRemoved(QDBusObjectPath,QStringList)));
- QDBusPendingReply<ManagedObjectList> reply = managerBluez5->GetManagedObjects();
- reply.waitForFinished();
- if (reply.isError())
+ bool ok = true;
+ const QString adapterPath = findAdapterForAddress(localAddress, &ok);
+ if (!ok || adapterPath.isEmpty())
return;
- typedef QPair<QString, QBluetoothAddress> AddressForPathType;
- QList<AddressForPathType> localAdapters;
-
- foreach (const QDBusObjectPath &path, reply.value().keys()) {
- const InterfaceList ifaceList = reply.value().value(path);
- foreach (const QString &iface, ifaceList.keys()) {
- if (iface == QStringLiteral("org.bluez.Adapter1")) {
- AddressForPathType pair;
- pair.first = path.path();
- pair.second = QBluetoothAddress(ifaceList.value(iface).value(
- QStringLiteral("Address")).toString());
- if (!pair.second.isNull())
- localAdapters.append(pair);
- break;
- }
- }
- }
-
- if (localAdapters.isEmpty())
- return;
-
- if (localAddress.isNull()) {
- //concept of DefaultAdapter doesn't exist anymore.
- //we define the first adapter as default
- adapterBluez5 = new OrgBluezAdapter1Interface(QStringLiteral("org.bluez"),
- localAdapters.front().first,
- QDBusConnection::systemBus(), this);
- } else {
- foreach (const AddressForPathType &pair, localAdapters) {
- if (pair.second == localAddress) {
- adapterBluez5 = new OrgBluezAdapter1Interface(QStringLiteral("org.bluez"),
- pair.first,
- QDBusConnection::systemBus(), this);
- break;
- }
- }
-
- if (!adapterBluez5) //no match
- return;
- }
+ adapterBluez5 = new OrgBluezAdapter1Interface(QStringLiteral("org.bluez"),
+ adapterPath,
+ QDBusConnection::systemBus(), this);
if (adapterBluez5) {
//hook up propertiesChanged for current adapter
@@ -927,10 +901,11 @@ void QBluetoothLocalDevicePrivate::InterfacesAdded(const QDBusObjectPath &object
}
}
-void QBluetoothLocalDevicePrivate::InterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces)
+void QBluetoothLocalDevicePrivate::InterfacesRemoved(const QDBusObjectPath &object_path,
+ const QStringList &interfaces)
{
if (deviceChangeMonitors.contains(object_path.path())
- && interfaces.contains(QStringLiteral("org.bluez.Device1"))) {
+ && interfaces.contains(QLatin1String("org.bluez.Device1"))) {
//a device was removed
delete deviceChangeMonitors.take(object_path.path());
@@ -944,6 +919,27 @@ void QBluetoothLocalDevicePrivate::InterfacesRemoved(const QDBusObjectPath &obje
if (found)
emit q_ptr->deviceDisconnected(address);
}
+
+ if (adapterBluez5
+ && object_path.path() == adapterBluez5->path()
+ && interfaces.contains(QLatin1String("org.bluez.Adapter1"))) {
+ qCDebug(QT_BT_BLUEZ) << "Adapter" << adapterBluez5->path() << "was removed";
+ // current adapter was removed -> invalidate the instance
+ delete adapterBluez5;
+ adapterBluez5 = 0;
+ managerBluez5->deleteLater();
+ managerBluez5 = 0;
+ delete adapterProperties;
+ adapterProperties = 0;
+
+ delete pairingTarget;
+ pairingTarget = 0;
+
+ // turn off connectivity monitoring
+ qDeleteAll(deviceChangeMonitors);
+ deviceChangeMonitors.clear();
+ connectedDevicesSet.clear();
+ }
}
bool QBluetoothLocalDevicePrivate::isValid() const
@@ -951,6 +947,39 @@ bool QBluetoothLocalDevicePrivate::isValid() const
return adapter || adapterBluez5;
}
+// Bluez 4
+void QBluetoothLocalDevicePrivate::adapterRemoved(const QDBusObjectPath &devicePath)
+{
+ if (!adapter )
+ return;
+
+ if (adapter->path() != devicePath.path())
+ return;
+
+ qCDebug(QT_BT_BLUEZ) << "Adapter" << devicePath.path()
+ << "was removed. Invalidating object.";
+ // the current adapter was removed
+ delete adapter;
+ adapter = 0;
+ manager->deleteLater();
+ manager = 0;
+
+ // stop all pairing related activities
+ if (agent) {
+ QDBusConnection::systemBus().unregisterObject(agent_path);
+ delete agent;
+ agent = 0;
+ }
+
+ delete msgConnection;
+ msgConnection = 0;
+
+ // stop all connectivity monitoring
+ qDeleteAll(devices);
+ devices.clear();
+ connectedDevicesSet.clear();
+}
+
void QBluetoothLocalDevicePrivate::RequestConfirmation(const QDBusObjectPath &in0, uint in1)
{
Q_UNUSED(in0);
diff --git a/src/bluetooth/qbluetoothlocaldevice_p.h b/src/bluetooth/qbluetoothlocaldevice_p.h
index 8edac58c..55086012 100644
--- a/src/bluetooth/qbluetoothlocaldevice_p.h
+++ b/src/bluetooth/qbluetoothlocaldevice_p.h
@@ -61,6 +61,7 @@ class OrgFreedesktopDBusObjectManagerInterface;
class OrgBluezAgentAdaptor;
class OrgBluezDeviceInterface;
class OrgBluezDevice1Interface;
+class OrgBluezManagerInterface;
QT_BEGIN_NAMESPACE
class QDBusPendingCallWatcher;
@@ -137,6 +138,7 @@ public:
OrgFreedesktopDBusObjectManagerInterface *managerBluez5; //Bluez 5
QMap<QString, OrgFreedesktopDBusPropertiesInterface *> deviceChangeMonitors; //Bluez 5
OrgBluezAgentAdaptor *agent;
+ OrgBluezManagerInterface *manager;
QList<QBluetoothAddress> connectedDevices() const;
@@ -167,6 +169,7 @@ public slots:
void _q_deviceRemoved(const QDBusObjectPath &device);
void _q_devicePropertyChanged(const QString &property, const QDBusVariant &value);
bool isValid() const;
+ void adapterRemoved(const QDBusObjectPath &device);
void requestPairingBluez5(const QBluetoothAddress &address,
QBluetoothLocalDevice::Pairing targetPairing);
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp
index 7d2f1b1c..8e5c3aaa 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp
+++ b/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp
@@ -155,38 +155,17 @@ void QBluetoothServiceDiscoveryAgentPrivate::startBluez5(const QBluetoothAddress
if (foundHostAdapterPath.isEmpty()) {
// check that we match adapter addresses or use first if it wasn't specified
- QDBusPendingReply<ManagedObjectList> reply = managerBluez5->GetManagedObjects();
- reply.waitForFinished();
- if (reply.isError()) {
+ bool ok = false;
+ foundHostAdapterPath = findAdapterForAddress(m_deviceAdapterAddress, &ok);
+ if (!ok) {
discoveredDevices.clear();
error = QBluetoothServiceDiscoveryAgent::InputOutputError;
- errorString = reply.error().message();
+ errorString = QBluetoothDeviceDiscoveryAgent::tr("Cannot access adapter during service discovery");
emit q->error(error);
_q_serviceDiscoveryFinished();
return;
}
- const QString desiredAdapter = m_deviceAdapterAddress.toString();
- foreach (const QDBusObjectPath &path, reply.value().keys()) {
- const InterfaceList ifaceList = reply.value().value(path);
- foreach (const QString &iface, ifaceList.keys()) {
- if (iface == QStringLiteral("org.bluez.Adapter1")) {
- if (m_deviceAdapterAddress.isNull()
- || desiredAdapter == ifaceList.value(iface).
- value(QStringLiteral("Address")).toString()) {
- // use first adapter or we just matched one
- foundHostAdapterPath = path.path();
- }
-
- if (!foundHostAdapterPath.isEmpty())
- break;
- }
- }
-
- if (!foundHostAdapterPath.isEmpty())
- break;
- }
-
if (foundHostAdapterPath.isEmpty()) {
// Cannot find a local adapter
// Abort any outstanding discoveries
@@ -551,7 +530,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_discoveredServices(QDBusPendingC
foreach (const QString &record, reply.value()) {
bool isBtleService = false;
- const QBluetoothServiceInfo serviceInfo = parseServiceXml(record, &isBtleService);
+ QBluetoothServiceInfo serviceInfo = parseServiceXml(record, &isBtleService);
if (isBtleService) {
qCDebug(QT_BT_BLUEZ) << "Discovered BLE services" << discoveredDevices.at(0).address().toString()
@@ -566,6 +545,20 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_discoveredServices(QDBusPendingC
// search pattern during DiscoverServices() call
Q_Q(QBluetoothServiceDiscoveryAgent);
+ // Some service uuids are unknown to Bluez. In such cases we fall back
+ // to our own naming resolution.
+ if (serviceInfo.serviceName().isEmpty()
+ && !serviceInfo.serviceClassUuids().isEmpty()) {
+ foreach (const QBluetoothUuid &classUuid, serviceInfo.serviceClassUuids()) {
+ bool ok = false;
+ QBluetoothUuid::ServiceClassUuid clsId
+ = static_cast<QBluetoothUuid::ServiceClassUuid>(classUuid.toUInt16(&ok));
+ if (ok) {
+ serviceInfo.setServiceName(QBluetoothUuid::serviceClassToString(clsId));
+ break;
+ }
+ }
+ }
if (!isDuplicatedService(serviceInfo)) {
discoveredServices.append(serviceInfo);
@@ -878,7 +871,7 @@ QVariant QBluetoothServiceDiscoveryAgentPrivate::readAttributeValue(QXmlStreamRe
}
xml.skipCurrentElement();
return QVariant::fromValue(uuid);
- } else if (xml.name() == QLatin1String("text")) {
+ } else if (xml.name() == QLatin1String("text") || xml.name() == QLatin1String("url")) {
QString value = xml.attributes().value(QStringLiteral("value")).toString();
if (xml.attributes().value(QStringLiteral("encoding")) == QLatin1String("hex"))
value = QString::fromUtf8(QByteArray::fromHex(value.toLatin1()));
diff --git a/src/bluetooth/qbluetoothserviceinfo_bluez.cpp b/src/bluetooth/qbluetoothserviceinfo_bluez.cpp
index 93fe22bf..eb764047 100644
--- a/src/bluetooth/qbluetoothserviceinfo_bluez.cpp
+++ b/src/bluetooth/qbluetoothserviceinfo_bluez.cpp
@@ -44,14 +44,20 @@
#include "bluez/manager_p.h"
#include "bluez/service_p.h"
+#include "bluez/bluez5_helper_p.h"
+#include "bluez/profile1_p.h"
#include <QtCore/QLoggingCategory>
#include <QtCore/QXmlStreamWriter>
+#include <QtCore/QAtomicInt>
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ)
+static const QLatin1String profilePathTemplate("/qt/profile");
+static QAtomicInt pathCounter;
+
static void writeAttribute(QXmlStreamWriter *stream, const QVariant &attribute)
{
const QString unsignedFormat(QStringLiteral("0x%1"));
@@ -171,8 +177,14 @@ static void writeAttribute(QXmlStreamWriter *stream, const QVariant &attribute)
}
QBluetoothServiceInfoPrivate::QBluetoothServiceInfoPrivate()
-: service(0), serviceRecord(0), registered(false)
+: service(0), serviceBluez5(0), serviceRecord(0), registered(false)
{
+ if (isBluez5()) {
+ serviceBluez5 = new OrgBluezProfileManager1Interface(
+ QStringLiteral("org.bluez"),
+ QStringLiteral("/org/bluez"),
+ QDBusConnection::systemBus(), this);
+ }
}
QBluetoothServiceInfoPrivate::~QBluetoothServiceInfoPrivate()
@@ -189,15 +201,30 @@ bool QBluetoothServiceInfoPrivate::unregisterService()
if (!registered)
return false;
- if (!ensureSdpConnection(currentLocalAdapter))
- return false;
+ if (serviceBluez5) { // Bluez 5
+ if (profilePath.isEmpty())
+ return false;
- QDBusPendingReply<> reply = service->RemoveRecord(serviceRecord);
- reply.waitForFinished();
- if (reply.isError())
- return false;
+ QDBusPendingReply<> reply = serviceBluez5->UnregisterProfile(
+ QDBusObjectPath(profilePath));
+ reply.waitForFinished();
+ if (reply.isError()) {
+ qCWarning(QT_BT_BLUEZ) << "Cannot unregister profile:"
+ << profilePath << reply.error().message();
+ return false;
+ }
+ profilePath.clear();
+ } else { // Bluez 4
+ if (!ensureSdpConnection(currentLocalAdapter))
+ return false;
- serviceRecord = 0;
+ QDBusPendingReply<> reply = service->RemoveRecord(serviceRecord);
+ reply.waitForFinished();
+ if (reply.isError())
+ return false;
+
+ serviceRecord = 0;
+ }
registered = false;
return true;
@@ -232,13 +259,18 @@ bool QBluetoothServiceInfoPrivate::ensureSdpConnection(const QBluetoothAddress &
bool QBluetoothServiceInfoPrivate::registerService(const QBluetoothAddress &localAdapter)
{
- //if new adapter unregister previous one first
- if (registered && localAdapter != currentLocalAdapter)
- unregisterService();
+ if (serviceBluez5) { // Bluez 5
+ if (registered)
+ return false;
+ } else { // Bluez 4
+ //if new adapter unregister previous one first
+ if (registered && localAdapter != currentLocalAdapter)
+ unregisterService();
- if (!ensureSdpConnection(localAdapter)) {
- qCWarning(QT_BT_BLUEZ) << "SDP not connected. Cannot register";
- return false;
+ if (!ensureSdpConnection(localAdapter)) {
+ qCWarning(QT_BT_BLUEZ) << "SDP not connected. Cannot register";
+ return false;
+ }
}
QString xmlServiceRecord;
@@ -266,22 +298,84 @@ bool QBluetoothServiceInfoPrivate::registerService(const QBluetoothAddress &loca
stream.writeEndDocument();
- if (!registered) {
- QDBusPendingReply<uint> reply = service->AddRecord(xmlServiceRecord);
- reply.waitForFinished();
- if (reply.isError()) {
- qCWarning(QT_BT_BLUEZ) << "AddRecord returned error" << reply.error();
- return false;
+ if (serviceBluez5) { // Bluez 5
+ // create path
+ profilePath = profilePathTemplate;
+ profilePath.append(QString::fromLatin1("/%1%2/%3").
+ arg(QCoreApplication::applicationName()).
+ arg(QCoreApplication::applicationPid()).
+ arg(pathCounter.fetchAndAddOrdered(1)));
+
+ QVariantMap mapping;
+ mapping.insert(QStringLiteral("ServiceRecord"), xmlServiceRecord);
+
+ // Strategy to pick service uuid
+ // 1.) use serviceUuid()
+ // 2.) use first custom uuid if available
+ // 3.) use first service class uuid
+ QBluetoothUuid profileUuid = attributes.value(QBluetoothServiceInfo::ServiceId)
+ .value<QBluetoothUuid>();
+ QBluetoothUuid firstCustomUuid;
+ if (profileUuid.isNull()) {
+ const QVariant var = attributes.value(QBluetoothServiceInfo::ServiceClassIds);
+ if (var.isValid()) {
+ const QBluetoothServiceInfo::Sequence seq
+ = var.value<QBluetoothServiceInfo::Sequence>();
+ QBluetoothUuid tempUuid;
+
+ for (int i = 0; i < seq.count(); i++) {
+ tempUuid = seq.at(i).value<QBluetoothUuid>();
+ if (tempUuid.isNull())
+ continue;
+
+ int size = tempUuid.minimumSize();
+ if (size == 2 || size == 4) { // Base UUID derived
+ if (profileUuid.isNull())
+ profileUuid = tempUuid;
+ } else if (firstCustomUuid.isNull()){
+ firstCustomUuid = tempUuid;
+ }
+ }
+ }
}
- serviceRecord = reply.value();
- } else {
- QDBusPendingReply<> reply = service->UpdateRecord(serviceRecord, xmlServiceRecord);
+ if (!firstCustomUuid.isNull())
+ profileUuid = firstCustomUuid;
+
+ QString uuidString = profileUuid.toString();
+ uuidString.chop(1); // remove trailing '}'
+ uuidString.remove(0, 1); // remove beginning '{'
+
+ qCDebug(QT_BT_BLUEZ) << "Registering profile under" << profilePath
+ << uuidString;
+
+ QDBusPendingReply<> reply = serviceBluez5->RegisterProfile(
+ QDBusObjectPath(profilePath),
+ uuidString,
+ mapping);
reply.waitForFinished();
if (reply.isError()) {
- qCWarning(QT_BT_BLUEZ) << "UpdateRecord returned error" << reply.error();
+ qCWarning(QT_BT_BLUEZ) << "Cannot register profile" << reply.error().message();
return false;
}
+ } else { // Bluez 4
+ if (!registered) {
+ QDBusPendingReply<uint> reply = service->AddRecord(xmlServiceRecord);
+ reply.waitForFinished();
+ if (reply.isError()) {
+ qCWarning(QT_BT_BLUEZ) << "AddRecord returned error" << reply.error();
+ return false;
+ }
+
+ serviceRecord = reply.value();
+ } else {
+ QDBusPendingReply<> reply = service->UpdateRecord(serviceRecord, xmlServiceRecord);
+ reply.waitForFinished();
+ if (reply.isError()) {
+ qCWarning(QT_BT_BLUEZ) << "UpdateRecord returned error" << reply.error();
+ return false;
+ }
+ }
}
registered = true;
diff --git a/src/bluetooth/qbluetoothserviceinfo_p.h b/src/bluetooth/qbluetoothserviceinfo_p.h
index 46ae84d4..3dc32b5c 100644
--- a/src/bluetooth/qbluetoothserviceinfo_p.h
+++ b/src/bluetooth/qbluetoothserviceinfo_p.h
@@ -51,6 +51,7 @@
#include <QVariant>
class OrgBluezServiceInterface;
+class OrgBluezProfileManager1Interface;
QT_BEGIN_NAMESPACE
@@ -80,8 +81,10 @@ private:
bool ensureSdpConnection(const QBluetoothAddress &localAdapter = QBluetoothAddress());
OrgBluezServiceInterface *service;
+ OrgBluezProfileManager1Interface *serviceBluez5;
quint32 serviceRecord;
QBluetoothAddress currentLocalAdapter;
+ QString profilePath;
#endif
mutable bool registered;
diff --git a/src/bluetooth/qbluetoothsocket.h b/src/bluetooth/qbluetoothsocket.h
index c6a8bd72..f0c45c0e 100644
--- a/src/bluetooth/qbluetoothsocket.h
+++ b/src/bluetooth/qbluetoothsocket.h
@@ -66,6 +66,7 @@ class Q_BLUETOOTH_EXPORT QBluetoothSocket : public QIODevice
public:
+ // TODO Decouple SocketState and SocketError enum values from QAbstractSocket in Qt 6
enum SocketState {
UnconnectedState = QAbstractSocket::UnconnectedState,
ServiceLookupState = QAbstractSocket::HostLookupState,
diff --git a/src/bluetooth/qbluetoothsocket_bluez.cpp b/src/bluetooth/qbluetoothsocket_bluez.cpp
index c4d84211..ba99b889 100644
--- a/src/bluetooth/qbluetoothsocket_bluez.cpp
+++ b/src/bluetooth/qbluetoothsocket_bluez.cpp
@@ -139,7 +139,7 @@ void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address,
int result = -1;
if (socket == -1 && !ensureNativeSocket(socketType)) {
- errorString = QObject::tr("Unknown socket error");
+ errorString = QBluetoothSocket::tr("Unknown socket error");
q->setSocketError(QBluetoothSocket::UnknownSocketError);
return;
}
diff --git a/src/bluetooth/qbluetoothtransferreply.cpp b/src/bluetooth/qbluetoothtransferreply.cpp
index 9acd917d..4dc1d4c8 100644
--- a/src/bluetooth/qbluetoothtransferreply.cpp
+++ b/src/bluetooth/qbluetoothtransferreply.cpp
@@ -63,13 +63,14 @@ QT_BEGIN_NAMESPACE
This enum describes the type of error that occurred
- \value NoError No error.
- \value UnknownError Unknown error, no better enum available
- \value FileNotFoundError Unable to open the file specified
- \value HostNotFoundError Unable to connect to the target host
- \value UserCanceledTransferError User terminated the transfer
- \value IODeviceNotReadableError File was not open before initiating the sending command
- \value ResourceBusyError Unable to access the resource.
+ \value NoError No error.
+ \value UnknownError Unknown error, no better enum available.
+ \value FileNotFoundError Unable to open the file specified.
+ \value HostNotFoundError Unable to connect to the target host.
+ \value UserCanceledTransferError User terminated the transfer.
+ \value IODeviceNotReadableError File was not open before initiating the sending command.
+ \value ResourceBusyError Unable to access the resource..
+ \value SessionError An error occurred during the handling of the session.
*/
diff --git a/src/bluetooth/qbluetoothtransferreply.h b/src/bluetooth/qbluetoothtransferreply.h
index 33910fd9..ccf2d71d 100644
--- a/src/bluetooth/qbluetoothtransferreply.h
+++ b/src/bluetooth/qbluetoothtransferreply.h
@@ -63,7 +63,8 @@ public:
HostNotFoundError,
UserCanceledTransferError,
IODeviceNotReadableError,
- ResourceBusyError
+ ResourceBusyError,
+ SessionError
};
@@ -83,6 +84,7 @@ public Q_SLOTS:
void abort();
Q_SIGNALS:
+ //TODO Remove QBluetoothTransferReply* parameter in Qt 6
void finished(QBluetoothTransferReply *);
void transferProgress(qint64 bytesTransferred, qint64 bytesTotal);
diff --git a/src/bluetooth/qbluetoothtransferreply_bluez.cpp b/src/bluetooth/qbluetoothtransferreply_bluez.cpp
index e4395e2f..4f5eefeb 100644
--- a/src/bluetooth/qbluetoothtransferreply_bluez.cpp
+++ b/src/bluetooth/qbluetoothtransferreply_bluez.cpp
@@ -44,17 +44,23 @@
#include "qbluetoothaddress.h"
#include "bluez/obex_client_p.h"
-#include "bluez/obex_manager_p.h"
#include "bluez/obex_agent_p.h"
#include "bluez/obex_transfer_p.h"
+#include "bluez/bluez5_helper_p.h"
+#include "bluez/obex_client1_bluez5_p.h"
+#include "bluez/obex_objectpush1_bluez5_p.h"
+#include "bluez/obex_transfer1_bluez5_p.h"
+#include "bluez/properties_p.h"
#include "qbluetoothtransferreply.h"
+#include <QtCore/QAtomicInt>
#include <QtCore/QLoggingCategory>
#include <QFuture>
#include <QFutureWatcher>
#include <QtConcurrentRun>
static const QLatin1String agentPath("/qt/agent");
+static QAtomicInt agentPathCounter;
QT_BEGIN_NAMESPACE
@@ -62,26 +68,40 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ)
QBluetoothTransferReplyBluez::QBluetoothTransferReplyBluez(QIODevice *input, const QBluetoothTransferRequest &request,
QBluetoothTransferManager *parent)
-: QBluetoothTransferReply(parent), tempfile(0), source(input),
+: QBluetoothTransferReply(parent),
+ m_client(0), m_agent(0), m_clientBluez(0), m_objectPushBluez(0),
+ m_tempfile(0), m_source(input),
m_running(false), m_finished(false), m_size(0),
m_error(QBluetoothTransferReply::NoError), m_errorStr(), m_transfer_path()
{
setRequest(request);
setManager(parent);
- client = new OrgOpenobexClientInterface(QStringLiteral("org.openobex.client"), QStringLiteral("/"),
- QDBusConnection::sessionBus());
- qsrand(QTime::currentTime().msec());
- m_agent_path = agentPath;
- m_agent_path.append(QString::fromLatin1("/%1").arg(qrand()));
+ qRegisterMetaType<QBluetoothTransferReply*>("QBluetoothTransferReply*");
- agent = new AgentAdaptor(this);
+ if (isBluez5()) {
+ m_clientBluez = new OrgBluezObexClient1Interface(QStringLiteral("org.bluez.obex"),
+ QStringLiteral("/org/bluez/obex"),
+ QDBusConnection::sessionBus(), this);
- bool res = QDBusConnection::sessionBus().registerObject(m_agent_path, this);
- if(!res)
- qCWarning(QT_BT_BLUEZ) << "Failed Creating dbus objects";
- qRegisterMetaType<QBluetoothTransferReply*>("QBluetoothTransferReply*");
+ } else {
+ m_client = new OrgOpenobexClientInterface(QStringLiteral("org.openobex.client"),
+ QStringLiteral("/"),
+ QDBusConnection::sessionBus());
+
+ m_agent_path = agentPath;
+ m_agent_path.append(QStringLiteral("/%1%2/%3").
+ arg(QCoreApplication::applicationName()).
+ arg(QCoreApplication::applicationPid()).
+ arg(agentPathCounter.fetchAndAddOrdered(1)));
+
+ m_agent = new AgentAdaptor(this);
+
+ if (!QDBusConnection::sessionBus().registerObject(m_agent_path, this))
+ qCWarning(QT_BT_BLUEZ) << "Failed creating obex agent dbus objects";
+ }
+
QMetaObject::invokeMethod(this, "start", Qt::QueuedConnection);
m_running = true;
}
@@ -92,19 +112,18 @@ QBluetoothTransferReplyBluez::QBluetoothTransferReplyBluez(QIODevice *input, con
QBluetoothTransferReplyBluez::~QBluetoothTransferReplyBluez()
{
QDBusConnection::sessionBus().unregisterObject(m_agent_path);
- delete client;
+ delete m_client;
}
bool QBluetoothTransferReplyBluez::start()
{
-// qDebug() << "Got a:" << source->metaObject()->className();
- QFile *file = qobject_cast<QFile *>(source);
+ QFile *file = qobject_cast<QFile *>(m_source);
if(!file){
- tempfile = new QTemporaryFile(this );
- tempfile->open();
- qCDebug(QT_BT_BLUEZ) << "Not a QFile, making a copy" << tempfile->fileName();
- if (!source->isReadable()) {
+ m_tempfile = new QTemporaryFile(this );
+ m_tempfile->open();
+ qCDebug(QT_BT_BLUEZ) << "Not a QFile, making a copy" << m_tempfile->fileName();
+ if (!m_source->isReadable()) {
m_errorStr = QBluetoothTransferReply::tr("QIODevice cannot be read."
"Make sure it is open for reading.");
m_error = QBluetoothTransferReply::IODeviceNotReadableError;
@@ -117,7 +136,7 @@ bool QBluetoothTransferReplyBluez::start()
QFutureWatcher<bool> *watcher = new QFutureWatcher<bool>();
QObject::connect(watcher, SIGNAL(finished()), this, SLOT(copyDone()));
- QFuture<bool> results = QtConcurrent::run(QBluetoothTransferReplyBluez::copyToTempFile, tempfile, source);
+ QFuture<bool> results = QtConcurrent::run(QBluetoothTransferReplyBluez::copyToTempFile, m_tempfile, m_source);
watcher->setFuture(results);
}
else {
@@ -158,27 +177,154 @@ bool QBluetoothTransferReplyBluez::copyToTempFile(QIODevice *to, QIODevice *from
return true;
}
+void QBluetoothTransferReplyBluez::cleanupSession()
+{
+ if (!m_objectPushBluez)
+ return;
+
+ QDBusPendingReply<> reply = m_clientBluez->RemoveSession(QDBusObjectPath(m_objectPushBluez->path()));
+ reply.waitForFinished();
+ if (reply.isError())
+ qCWarning(QT_BT_BLUEZ) << "Abort: Cannot remove obex session";
+
+ delete m_objectPushBluez;
+ m_objectPushBluez = 0;
+}
+
void QBluetoothTransferReplyBluez::copyDone()
{
- m_size = tempfile->size();
- startOPP(tempfile->fileName());
+ m_size = m_tempfile->size();
+ startOPP(m_tempfile->fileName());
QObject::sender()->deleteLater();
}
-void QBluetoothTransferReplyBluez::startOPP(QString filename)
+void QBluetoothTransferReplyBluez::sessionCreated(QDBusPendingCallWatcher *watcher)
{
- QVariantMap device;
- QStringList files;
+ QDBusPendingReply<QDBusObjectPath> reply = *watcher;
+ if (reply.isError()) {
+ qCWarning(QT_BT_BLUEZ) << "Failed to create obex session:"
+ << reply.error().name() << reply.reply().errorMessage();
+
+ m_errorStr = QBluetoothTransferReply::tr("Invalid target address");
+ m_error = QBluetoothTransferReply::HostNotFoundError;
+ m_finished = true;
+ m_running = false;
+ QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection,
+ Q_ARG(QBluetoothTransferReply*, this));
+
+ watcher->deleteLater();
+ return;
+ }
+
+ m_objectPushBluez = new OrgBluezObexObjectPush1Interface(QStringLiteral("org.bluez.obex"),
+ reply.value().path(),
+ QDBusConnection::sessionBus(), this);
+ QDBusPendingReply<QDBusObjectPath, QVariantMap> newReply = m_objectPushBluez->SendFile(fileToTranser);
+ QDBusPendingCallWatcher *newWatcher = new QDBusPendingCallWatcher(newReply, this);
+ connect(newWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
+ SLOT(sessionStarted(QDBusPendingCallWatcher*)));
+ watcher->deleteLater();
+}
+
+void QBluetoothTransferReplyBluez::sessionStarted(QDBusPendingCallWatcher *watcher)
+{
+ QDBusPendingReply<QDBusObjectPath, QVariantMap> reply = *watcher;
+ if (reply.isError()) {
+ qCWarning(QT_BT_BLUEZ) << "Failed to start obex session:"
+ << reply.error().name() << reply.reply().errorMessage();
+
+ m_errorStr = QBluetoothTransferReply::tr("Push session cannot be started");
+ m_error = QBluetoothTransferReply::SessionError;
+ m_finished = true;
+ m_running = false;
+
+ cleanupSession();
+
+ QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection,
+ Q_ARG(QBluetoothTransferReply *, this));
+
+ watcher->deleteLater();
+ return;
+ }
- device.insert(QString::fromLatin1("Destination"), request().address().toString());
- files << filename;
+ const QDBusObjectPath path = reply.argumentAt<0>();
+ const QVariantMap map = reply.argumentAt<1>();
+ m_transfer_path = path.path();
- QDBusObjectPath path(m_agent_path);
- QDBusPendingReply<> sendReply = client->SendFiles(device, files, path);
+ //watch the transfer
+ OrgFreedesktopDBusPropertiesInterface *properties = new OrgFreedesktopDBusPropertiesInterface(
+ QStringLiteral("org.bluez.obex"), path.path(),
+ QDBusConnection::sessionBus(), this);
+ connect(properties, SIGNAL(PropertiesChanged(QString,QVariantMap,QStringList)),
+ SLOT(sessionChanged(QString,QVariantMap,QStringList)));
- QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(sendReply, this);
- QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
- this, SLOT(sendReturned(QDBusPendingCallWatcher*)));
+ watcher->deleteLater();
+}
+
+void QBluetoothTransferReplyBluez::sessionChanged(const QString &interface,
+ const QVariantMap &changed_properties,
+ const QStringList &)
+{
+ if (changed_properties.contains(QStringLiteral("Transferred"))) {
+ emit transferProgress(
+ changed_properties.value(QStringLiteral("Transferred")).toULongLong(),
+ m_size);
+ }
+
+ if (changed_properties.contains(QStringLiteral("Status"))) {
+ const QString s = changed_properties.
+ value(QStringLiteral("Status")).toString();
+ if (s == QStringLiteral("complete")
+ || s == QStringLiteral("error")) {
+
+ m_transfer_path.clear();
+ m_finished = true;
+ m_running = false;
+
+ if (s == QStringLiteral("error")) {
+ m_error = QBluetoothTransferReply::UnknownError;
+ m_errorStr = tr("Unknown Error");
+ } else { // complete
+ // allow progress bar to complete
+ emit transferProgress(m_size, m_size);
+ }
+
+ cleanupSession();
+
+ QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection,
+ Q_ARG(QBluetoothTransferReply*, this));
+ } // ignore "active", "queued" & "suspended" status
+ }
+ qCDebug(QT_BT_BLUEZ) << "Transfer update:" << interface << changed_properties;
+}
+
+void QBluetoothTransferReplyBluez::startOPP(const QString &filename)
+{
+ if (m_client) { // Bluez 4
+ QVariantMap device;
+ QStringList files;
+
+ device.insert(QStringLiteral("Destination"), request().address().toString());
+ files << filename;
+
+ QDBusObjectPath path(m_agent_path);
+ QDBusPendingReply<> sendReply = m_client->SendFiles(device, files, path);
+
+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(sendReply, this);
+ connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
+ this, SLOT(sendReturned(QDBusPendingCallWatcher*)));
+ } else { //Bluez 5
+ fileToTranser = filename;
+ QVariantMap mapping;
+ mapping.insert(QStringLiteral("Target"), QStringLiteral("opp"));
+
+ QDBusPendingReply<QDBusObjectPath> reply = m_clientBluez->CreateSession(
+ request().address().toString(), mapping);
+
+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
+ connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
+ SLOT(sessionCreated(QDBusPendingCallWatcher*)));
+ }
}
void QBluetoothTransferReplyBluez::sendReturned(QDBusPendingCallWatcher *watcher)
@@ -278,16 +424,35 @@ bool QBluetoothTransferReplyBluez::isRunning() const
void QBluetoothTransferReplyBluez::abort()
{
- if(!m_transfer_path.isEmpty()){
- OrgOpenobexTransferInterface *xfer = new OrgOpenobexTransferInterface(QStringLiteral("org.openobex.client"),
- m_transfer_path,
- QDBusConnection::sessionBus());
- QDBusPendingReply<> reply = xfer->Cancel();
+ if (m_transfer_path.isEmpty())
+ return;
+
+ if (m_client) {
+ OrgOpenobexTransferInterface xfer(QStringLiteral("org.openobex.client"),
+ m_transfer_path,
+ QDBusConnection::sessionBus());
+
+ QDBusPendingReply<> reply = xfer.Cancel();
reply.waitForFinished();
- if(reply.isError()){
- qCWarning(QT_BT_BLUEZ) << "Failed to abort transfer" << reply.error();
- }
- delete xfer;
+ if (reply.isError())
+ qCWarning(QT_BT_BLUEZ) << "Failed to abort transfer" << reply.error().message();
+
+ } else if (m_clientBluez) {
+ OrgBluezObexTransfer1Interface iface(QStringLiteral("org.bluez.obex"),
+ m_transfer_path,
+ QDBusConnection::sessionBus());
+
+ QDBusPendingReply<> reply = iface.Cancel();
+ reply.waitForFinished();
+ if (reply.isError())
+ qCDebug(QT_BT_BLUEZ) << "Failed to abort transfer" << reply.error().message();
+
+ m_error = QBluetoothTransferReply::UserCanceledTransferError;
+ m_errorStr = tr("Operation canceled");
+
+ cleanupSession();
+
+ emit finished(this);
}
}
diff --git a/src/bluetooth/qbluetoothtransferreply_bluez_p.h b/src/bluetooth/qbluetoothtransferreply_bluez_p.h
index 412959e5..657b550f 100644
--- a/src/bluetooth/qbluetoothtransferreply_bluez_p.h
+++ b/src/bluetooth/qbluetoothtransferreply_bluez_p.h
@@ -51,8 +51,9 @@
#include "qbluetoothtransferreply.h"
class OrgOpenobexClientInterface;
-class OrgOpenobexManagerInterface;
class AgentAdaptor;
+class OrgBluezObexClient1Interface;
+class OrgBluezObexObjectPush1Interface;
QT_BEGIN_NAMESPACE
@@ -75,14 +76,16 @@ private slots:
bool start();
private:
- void startOPP(QString filename);
+ void startOPP(const QString &filename);
- OrgOpenobexClientInterface *client;
- OrgOpenobexManagerInterface *manager;
- AgentAdaptor *agent;
+ OrgOpenobexClientInterface *m_client;
+ AgentAdaptor *m_agent;
+ OrgBluezObexClient1Interface *m_clientBluez;
+ OrgBluezObexObjectPush1Interface *m_objectPushBluez;
- QTemporaryFile *tempfile;
- QIODevice *source;
+
+ QTemporaryFile *m_tempfile;
+ QIODevice *m_source;
bool m_running;
bool m_finished;
@@ -95,11 +98,18 @@ private:
QString m_agent_path;
QString m_transfer_path;
+ QString fileToTranser;
static bool copyToTempFile(QIODevice *to, QIODevice *from);
+ void cleanupSession();
private slots:
void copyDone();
+ void sessionCreated(QDBusPendingCallWatcher *watcher);
+ void sessionStarted(QDBusPendingCallWatcher *watcher);
+ void sessionChanged(const QString &interface,
+ const QVariantMap &changed_properties,
+ const QStringList &invalidated_properties);
public slots:
void abort();