summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dist/changes-5.4.138
-rw-r--r--examples/bluetooth/btchat/chatserver.cpp4
-rw-r--r--examples/bluetooth/btchat/main.cpp2
-rw-r--r--examples/bluetooth/btchat/remoteselector.cpp2
-rw-r--r--src/bluetooth/android/localdevicebroadcastreceiver.cpp4
-rw-r--r--src/bluetooth/bluez/bluez5_helper.cpp16
-rw-r--r--src/bluetooth/bluez/bluez_data_p.h94
-rw-r--r--src/bluetooth/bluez/hcimanager.cpp1
-rw-r--r--src/bluetooth/qbluetoothlocaldevice_android.cpp6
-rw-r--r--src/bluetooth/qbluetoothlocaldevice_bluez.cpp14
-rw-r--r--src/bluetooth/qbluetoothserver.cpp4
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent.cpp5
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent.h6
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp107
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent_p.h6
-rw-r--r--src/bluetooth/qbluetoothsocket_android.cpp65
-rw-r--r--src/bluetooth/qlowenergycontroller_bluez.cpp2
17 files changed, 219 insertions, 157 deletions
diff --git a/dist/changes-5.4.1 b/dist/changes-5.4.1
new file mode 100644
index 00000000..5a4a5dba
--- /dev/null
+++ b/dist/changes-5.4.1
@@ -0,0 +1,38 @@
+Qt 5.4.1 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.4.0.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+ http://doc.qt.io/qt-5.4
+
+The Qt version 5.4 series is binary compatible with the 5.3.x series.
+Applications compiled for 5.3 will continue to run with 5.4.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+ http://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* Library *
+****************************************************************************
+
+QtBluetooth
+-----------
+
+ - General:
+ * Extended documentation with regards to Bluetooth Low Energy. The
+ affected classes were QLowEnergyController and QLowEnergyService.
+ * LowEnergyScanner and chat examples improved.
+
+ - QBluetoothServer:
+ * [QTBUG-43806] Fixed SDP registration of PublicBrowseGroup in BlueZ 5.x.
+
+ - QLowEnergyController:
+ * Fixed blocking of ATT command processing due to a reconnect to the target
+ device.
+
diff --git a/examples/bluetooth/btchat/chatserver.cpp b/examples/bluetooth/btchat/chatserver.cpp
index 6da4b471..6848e2d7 100644
--- a/examples/bluetooth/btchat/chatserver.cpp
+++ b/examples/bluetooth/btchat/chatserver.cpp
@@ -101,8 +101,10 @@ void ChatServer::startServer(const QBluetoothAddress& localAdapter)
//! [Service UUID set]
//! [Service Discoverability]
+ QBluetoothServiceInfo::Sequence publicBrowse;
+ publicBrowse << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup));
serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList,
- QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup));
+ publicBrowse);
//! [Service Discoverability]
//! [Protocol descriptor list]
diff --git a/examples/bluetooth/btchat/main.cpp b/examples/bluetooth/btchat/main.cpp
index ac23a11d..ed362d23 100644
--- a/examples/bluetooth/btchat/main.cpp
+++ b/examples/bluetooth/btchat/main.cpp
@@ -41,9 +41,11 @@
#include "chat.h"
#include <QApplication>
+//#include <QtCore/QLoggingCategory>
int main(int argc, char *argv[])
{
+ //QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
QApplication app(argc, argv);
Chat d;
diff --git a/examples/bluetooth/btchat/remoteselector.cpp b/examples/bluetooth/btchat/remoteselector.cpp
index 79dc0564..913988a2 100644
--- a/examples/bluetooth/btchat/remoteselector.cpp
+++ b/examples/bluetooth/btchat/remoteselector.cpp
@@ -136,6 +136,8 @@ void RemoteSelector::on_remoteDevices_itemActivated(QListWidgetItem *item)
{
qDebug() << "got click" << item->text();
m_service = m_discoveredServices.value(item);
+ if (m_discoveryAgent->isActive())
+ m_discoveryAgent->stop();
accept();
}
diff --git a/src/bluetooth/android/localdevicebroadcastreceiver.cpp b/src/bluetooth/android/localdevicebroadcastreceiver.cpp
index c54c5e32..a3b92252 100644
--- a/src/bluetooth/android/localdevicebroadcastreceiver.cpp
+++ b/src/bluetooth/android/localdevicebroadcastreceiver.cpp
@@ -50,8 +50,8 @@ LocalDeviceBroadcastReceiver::LocalDeviceBroadcastReceiver(QObject *parent) :
addAction(valueForStaticField(JavaNames::BluetoothAdapter, JavaNames::ActionScanModeChanged));
addAction(valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ActionAclConnected));
addAction(valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ActionAclDisconnected));
- if (QtAndroidPrivate::androidSdkVersion() >= 19)
- addAction(valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ActionPairingRequest)); //API 19
+ if (QtAndroidPrivate::androidSdkVersion() >= 15)
+ addAction(valueForStaticField(JavaNames::BluetoothDevice, JavaNames::ActionPairingRequest)); //API 15
//cache integer values for host & bonding mode
//don't use the java fields directly but refer to them by name
diff --git a/src/bluetooth/bluez/bluez5_helper.cpp b/src/bluetooth/bluez/bluez5_helper.cpp
index eebeae9d..0e3c0063 100644
--- a/src/bluetooth/bluez/bluez5_helper.cpp
+++ b/src/bluetooth/bluez/bluez5_helper.cpp
@@ -45,16 +45,16 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ)
typedef enum Bluez5TestResultType
{
- Unknown,
- Bluez4,
- Bluez5
+ BluezVersionUnknown,
+ BluezVersion4,
+ BluezVersion5
} Bluez5TestResult;
-Q_GLOBAL_STATIC_WITH_ARGS(Bluez5TestResult, bluezVersion, (Bluez5TestResult::Unknown));
+Q_GLOBAL_STATIC_WITH_ARGS(Bluez5TestResult, bluezVersion, (BluezVersionUnknown));
bool isBluez5()
{
- if (*bluezVersion() == Bluez5TestResultType::Unknown) {
+ if (*bluezVersion() == BluezVersionUnknown) {
OrgFreedesktopDBusObjectManagerInterface manager(QStringLiteral("org.bluez"),
QStringLiteral("/"),
QDBusConnection::systemBus());
@@ -65,15 +65,15 @@ bool isBluez5()
QDBusPendingReply<ManagedObjectList> reply = manager.GetManagedObjects();
reply.waitForFinished();
if (reply.isError()) {
- *bluezVersion() = Bluez5TestResultType::Bluez4;
+ *bluezVersion() = BluezVersion4;
qCDebug(QT_BT_BLUEZ) << "Bluez 4 detected.";
} else {
- *bluezVersion() = Bluez5TestResultType::Bluez5;
+ *bluezVersion() = BluezVersion5;
qCDebug(QT_BT_BLUEZ) << "Bluez 5 detected.";
}
}
- return (*bluezVersion() == Bluez5TestResultType::Bluez5);
+ return (*bluezVersion() == BluezVersion5);
}
struct AdapterData
diff --git a/src/bluetooth/bluez/bluez_data_p.h b/src/bluetooth/bluez/bluez_data_p.h
index 7c799977..9d2d96b3 100644
--- a/src/bluetooth/bluez/bluez_data_p.h
+++ b/src/bluetooth/bluez/bluez_data_p.h
@@ -75,8 +75,8 @@
#define BT_SECURITY 4
struct bt_security {
- uint8_t level;
- uint8_t key_size;
+ quint8 level;
+ quint8 key_size;
};
#define BT_SECURITY_SDP 0
#define BT_SECURITY_LOW 1
@@ -162,14 +162,14 @@ static inline void ntoh128(const quint128 *src, quint128 *dst)
dst->data[15 - i] = src->data[i];
}
-static inline uint16_t bt_get_le16(const void *ptr)
+static inline quint16 bt_get_le16(const void *ptr)
{
- return bt_get_unaligned((const uint16_t *) ptr);
+ return bt_get_unaligned((const quint16 *) ptr);
}
#elif __BYTE_ORDER == __BIG_ENDIAN
-static inline uint16_t bt_get_le16(const void *ptr)
+static inline quint16 bt_get_le16(const void *ptr)
{
- return bswap_16(bt_get_unaligned((const uint16_t *) ptr));
+ return bswap_16(bt_get_unaligned((const quint16 *) ptr));
}
static inline void btoh128(const quint128 *src, quint128 *dst)
@@ -213,79 +213,79 @@ struct sockaddr_hci {
};
struct hci_dev_req {
- uint16_t dev_id;
- uint32_t dev_opt;
+ quint16 dev_id;
+ quint32 dev_opt;
};
struct hci_dev_list_req {
- uint16_t dev_num;
+ quint16 dev_num;
struct hci_dev_req dev_req[0];
};
struct hci_dev_stats {
- uint32_t err_rx;
- uint32_t err_tx;
- uint32_t cmd_tx;
- uint32_t evt_rx;
- uint32_t acl_tx;
- uint32_t acl_rx;
- uint32_t sco_tx;
- uint32_t sco_rx;
- uint32_t byte_rx;
- uint32_t byte_tx;
+ quint32 err_rx;
+ quint32 err_tx;
+ quint32 cmd_tx;
+ quint32 evt_rx;
+ quint32 acl_tx;
+ quint32 acl_rx;
+ quint32 sco_tx;
+ quint32 sco_rx;
+ quint32 byte_rx;
+ quint32 byte_tx;
};
struct hci_dev_info {
- uint16_t dev_id;
+ quint16 dev_id;
char name[8];
bdaddr_t bdaddr;
- uint32_t flags;
- uint8_t type;
+ quint32 flags;
+ quint8 type;
- uint8_t features[8];
+ quint8 features[8];
- uint32_t pkt_type;
- uint32_t link_policy;
- uint32_t link_mode;
+ quint32 pkt_type;
+ quint32 link_policy;
+ quint32 link_mode;
- uint16_t acl_mtu;
- uint16_t acl_pkts;
- uint16_t sco_mtu;
- uint16_t sco_pkts;
+ quint16 acl_mtu;
+ quint16 acl_pkts;
+ quint16 sco_mtu;
+ quint16 sco_pkts;
struct hci_dev_stats stat;
};
struct hci_conn_info {
- uint16_t handle;
+ quint16 handle;
bdaddr_t bdaddr;
- uint8_t type;
- uint8_t out;
- uint16_t state;
- uint32_t link_mode;
+ quint8 type;
+ quint8 out;
+ quint16 state;
+ quint32 link_mode;
};
struct hci_conn_list_req {
- uint16_t dev_id;
- uint16_t conn_num;
+ quint16 dev_id;
+ quint16 conn_num;
struct hci_conn_info conn_info[0];
};
struct hci_filter {
- uint32_t type_mask;
- uint32_t event_mask[2];
- uint16_t opcode;
+ quint32 type_mask;
+ quint32 event_mask[2];
+ quint16 opcode;
};
static inline void hci_set_bit(int nr, void *addr)
{
- *((uint32_t *) addr + (nr >> 5)) |= (1 << (nr & 31));
+ *((quint32 *) addr + (nr >> 5)) |= (1 << (nr & 31));
}
static inline void hci_clear_bit(int nr, void *addr)
{
- *((uint32_t *) addr + (nr >> 5)) &= ~(1 << (nr & 31));
+ *((quint32 *) addr + (nr >> 5)) &= ~(1 << (nr & 31));
}
static inline void hci_filter_clear(struct hci_filter *f)
{
@@ -317,16 +317,16 @@ static inline void hci_filter_all_events(struct hci_filter *f)
}
typedef struct {
- uint8_t evt;
- uint8_t plen;
+ quint8 evt;
+ quint8 plen;
} __attribute__ ((packed)) hci_event_hdr;
#define HCI_EVENT_HDR_SIZE 2
#define EVT_ENCRYPT_CHANGE 0x08
typedef struct {
- uint8_t status;
- uint16_t handle;
- uint8_t encrypt;
+ quint8 status;
+ quint16 handle;
+ quint8 encrypt;
} __attribute__ ((packed)) evt_encrypt_change;
#define EVT_ENCRYPT_CHANGE_SIZE 4
diff --git a/src/bluetooth/bluez/hcimanager.cpp b/src/bluetooth/bluez/hcimanager.cpp
index 17d54a4b..32450588 100644
--- a/src/bluetooth/bluez/hcimanager.cpp
+++ b/src/bluetooth/bluez/hcimanager.cpp
@@ -38,6 +38,7 @@
#include <QtCore/QLoggingCategory>
+#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
diff --git a/src/bluetooth/qbluetoothlocaldevice_android.cpp b/src/bluetooth/qbluetoothlocaldevice_android.cpp
index 4c1b1d4e..11515743 100644
--- a/src/bluetooth/qbluetoothlocaldevice_android.cpp
+++ b/src/bluetooth/qbluetoothlocaldevice_android.cpp
@@ -376,9 +376,9 @@ void QBluetoothLocalDevice::requestPairing(const QBluetoothAddress &address, Pai
return;
}
- // BluetoothDevice::createBond() requires Android API 19
- if (QtAndroidPrivate::androidSdkVersion() < 19 || !d_ptr->adapter()) {
- qCWarning(QT_BT_ANDROID) << "Unable to pair: requires Android API 19+";
+ // BluetoothDevice::createBond() requires Android API 15
+ if (QtAndroidPrivate::androidSdkVersion() < 15 || !d_ptr->adapter()) {
+ qCWarning(QT_BT_ANDROID) << "Unable to pair: requires Android API 15+";
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
Q_ARG(QBluetoothLocalDevice::Error,
QBluetoothLocalDevice::PairingError));
diff --git a/src/bluetooth/qbluetoothlocaldevice_bluez.cpp b/src/bluetooth/qbluetoothlocaldevice_bluez.cpp
index c7ee556d..0df7cc5d 100644
--- a/src/bluetooth/qbluetoothlocaldevice_bluez.cpp
+++ b/src/bluetooth/qbluetoothlocaldevice_bluez.cpp
@@ -345,6 +345,7 @@ void QBluetoothLocalDevice::requestPairing(const QBluetoothAddress &address, Pai
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
Q_ARG(QBluetoothLocalDevice::Error,
QBluetoothLocalDevice::PairingError));
+ delete device;
return;
}
delete device;
@@ -368,6 +369,7 @@ void QBluetoothLocalDevice::requestPairing(const QBluetoothAddress &address, Pai
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
Q_ARG(QBluetoothLocalDevice::Error,
QBluetoothLocalDevice::PairingError));
+ delete device;
return;
}
delete device;
@@ -579,15 +581,21 @@ QBluetoothLocalDevice::Pairing QBluetoothLocalDevice::pairingStatus(
QDBusPendingReply<QVariantMap> deviceReply = device->GetProperties();
deviceReply.waitForFinished();
- if (deviceReply.isError())
+ if (deviceReply.isError()) {
+ delete device;
return Unpaired;
+ }
QVariantMap map = deviceReply.value();
- if (map.value(QStringLiteral("Trusted")).toBool() && map.value(QStringLiteral("Paired")).toBool())
+ if (map.value(QStringLiteral("Trusted")).toBool() && map.value(QStringLiteral("Paired")).toBool()) {
+ delete device;
return AuthorizedPaired;
- else if (map.value(QStringLiteral("Paired")).toBool())
+ } else if (map.value(QStringLiteral("Paired")).toBool()) {
+ delete device;
return Paired;
+ }
+ delete device;
} else if (d_ptr->adapterBluez5) {
QDBusPendingReply<ManagedObjectList> reply = d_ptr->managerBluez5->GetManagedObjects();
diff --git a/src/bluetooth/qbluetoothserver.cpp b/src/bluetooth/qbluetoothserver.cpp
index 3001a00b..1c4676e0 100644
--- a/src/bluetooth/qbluetoothserver.cpp
+++ b/src/bluetooth/qbluetoothserver.cpp
@@ -204,8 +204,10 @@ QBluetoothServiceInfo QBluetoothServer::listen(const QBluetoothUuid &uuid, const
//! [listen]
QBluetoothServiceInfo serviceInfo;
serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceName, serviceName);
+ QBluetoothServiceInfo::Sequence browseSequence;
+ browseSequence << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup));
serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList,
- QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup));
+ browseSequence);
QBluetoothServiceInfo::Sequence classId;
classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort));
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent.cpp b/src/bluetooth/qbluetoothservicediscoveryagent.cpp
index ef28ef82..7274780a 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent.cpp
+++ b/src/bluetooth/qbluetoothservicediscoveryagent.cpp
@@ -183,6 +183,11 @@ QBluetoothServiceDiscoveryAgent::QBluetoothServiceDiscoveryAgent(const QBluetoot
QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent()
{
+ if (isActive()) {
+ disconnect(); //don't emit any signals due to stop()
+ stop();
+ }
+
delete d_ptr;
}
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent.h b/src/bluetooth/qbluetoothservicediscoveryagent.h
index 787d58e3..d9f005cd 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent.h
+++ b/src/bluetooth/qbluetoothservicediscoveryagent.h
@@ -42,6 +42,10 @@
#include <QtBluetooth/QBluetoothUuid>
#include <QtBluetooth/QBluetoothDeviceDiscoveryAgent>
+#ifdef QT_BLUEZ_BLUETOOTH
+#include <QtCore/qprocess.h>
+#endif
+
QT_BEGIN_NAMESPACE
class QBluetoothAddress;
@@ -108,7 +112,7 @@ private:
#ifdef QT_BLUEZ_BLUETOOTH
Q_PRIVATE_SLOT(d_func(), void _q_discoveredServices(QDBusPendingCallWatcher*))
Q_PRIVATE_SLOT(d_func(), void _q_createdDevice(QDBusPendingCallWatcher*))
- Q_PRIVATE_SLOT(d_func(), void _q_finishSdpScan(QBluetoothServiceDiscoveryAgent::Error, const QString &, const QStringList &))
+ Q_PRIVATE_SLOT(d_func(), void _q_sdpScannerDone(int,QProcess::ExitStatus))
#endif
#ifdef QT_ANDROID_BLUETOOTH
Q_PRIVATE_SLOT(d_func(), void _q_processFetchedUuids(const QBluetoothAddress &address,
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp
index 6958e1b2..90baf1f8 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp
+++ b/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp
@@ -65,7 +65,7 @@ static inline void convertAddress(quint64 from, quint8 (&to)[6])
QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate(const QBluetoothAddress &deviceAdapter)
: error(QBluetoothServiceDiscoveryAgent::NoError), m_deviceAdapterAddress(deviceAdapter), state(Inactive), deviceDiscoveryAgent(0),
mode(QBluetoothServiceDiscoveryAgent::MinimalDiscovery), singleDevice(false),
- manager(0), managerBluez5(0), adapter(0), device(0)
+ manager(0), managerBluez5(0), adapter(0), device(0), sdpScannerProcess(0)
{
if (isBluez5()) {
managerBluez5 = new OrgFreedesktopDBusObjectManagerInterface(
@@ -136,6 +136,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &addr
}
+// Bluez 5
void QBluetoothServiceDiscoveryAgentPrivate::startBluez5(const QBluetoothAddress &address)
{
Q_Q(QBluetoothServiceDiscoveryAgent);
@@ -185,81 +186,64 @@ void QBluetoothServiceDiscoveryAgentPrivate::startBluez5(const QBluetoothAddress
if (DiscoveryMode() == QBluetoothServiceDiscoveryAgent::MinimalDiscovery) {
performMinimalServiceDiscovery(address);
} else {
- // we need to run the discovery in a different thread
- // as it involves blocking calls
- QtConcurrent::run(this, &QBluetoothServiceDiscoveryAgentPrivate::runSdpScan,
- address, QBluetoothAddress(adapter.address()));
+ runExternalSdpScan(address, QBluetoothAddress(adapter.address()));
}
}
-/*
- * This function runs in a different thread. We need to be very careful what we
- * access from here. That's why invokeMethod is used below.
- *
+/* Bluez 5
* src/tools/sdpscanner performs an SDP scan. This is
* done out-of-process to avoid license issues. At this stage Bluez uses GPLv2.
*/
-void QBluetoothServiceDiscoveryAgentPrivate::runSdpScan(
+void QBluetoothServiceDiscoveryAgentPrivate::runExternalSdpScan(
const QBluetoothAddress &remoteAddress, const QBluetoothAddress localAddress)
{
Q_Q(QBluetoothServiceDiscoveryAgent);
- const QString binPath = QLibraryInfo::location(QLibraryInfo::BinariesPath);
-
- QFileInfo fileInfo(binPath, QStringLiteral("sdpscanner"));
- if (!fileInfo.exists() || !fileInfo.isExecutable()) {
- QMetaObject::invokeMethod(q, "_q_finishSdpScan", Qt::QueuedConnection,
- Q_ARG(QBluetoothServiceDiscoveryAgent::Error,
- QBluetoothServiceDiscoveryAgent::InputOutputError),
- Q_ARG(QString,
- QBluetoothServiceDiscoveryAgent::tr("Unable to find sdpscanner")),
- Q_ARG(QStringList, QStringList()));
- qCWarning(QT_BT_BLUEZ) << "Cannot find sdpscanner:"
- << fileInfo.canonicalFilePath();
- return;
+ if (!sdpScannerProcess) {
+ const QString binPath = QLibraryInfo::location(QLibraryInfo::BinariesPath);
+ QFileInfo fileInfo(binPath, QStringLiteral("sdpscanner"));
+ if (!fileInfo.exists() || !fileInfo.isExecutable()) {
+ _q_finishSdpScan(QBluetoothServiceDiscoveryAgent::InputOutputError,
+ QBluetoothServiceDiscoveryAgent::tr("Unable to find sdpscanner"),
+ QStringList());
+ qCWarning(QT_BT_BLUEZ) << "Cannot find sdpscanner:"
+ << fileInfo.canonicalFilePath();
+ return;
+ }
+
+ sdpScannerProcess = new QProcess(q);
+ sdpScannerProcess->setReadChannel(QProcess::StandardOutput);
+ sdpScannerProcess->setProgram(fileInfo.canonicalFilePath());
+ q->connect(sdpScannerProcess, SIGNAL(finished(int,QProcess::ExitStatus)),
+ q, SLOT(_q_sdpScannerDone(int,QProcess::ExitStatus)));
+
}
QStringList arguments;
arguments << remoteAddress.toString() << localAddress.toString();
- QByteArray output;
-
- QProcess process;
- process.setProcessChannelMode(QProcess::ForwardedErrorChannel);
- process.setReadChannel(QProcess::StandardOutput);
- process.start(fileInfo.canonicalFilePath(), arguments);
-
- if (process.waitForStarted(-1)) {
- while (process.waitForReadyRead(-1))
- output += process.readAllStandardOutput();
- }
-
- process.waitForFinished();
+ sdpScannerProcess->setArguments(arguments);
+ sdpScannerProcess->start();
+}
- if (process.exitStatus() != QProcess::NormalExit
- || process.exitCode() != 0) {
- qCWarning(QT_BT_BLUEZ) << "SDP scan failure"
- << process.exitStatus() << process.exitCode()
- << remoteAddress;
+// Bluez 5
+void QBluetoothServiceDiscoveryAgentPrivate::_q_sdpScannerDone(int exitCode, QProcess::ExitStatus status)
+{
+ if (status != QProcess::NormalExit || exitCode != 0) {
+ qCWarning(QT_BT_BLUEZ) << "SDP scan failure" << status << exitCode;
if (singleDevice) {
- QMetaObject::invokeMethod(q, "_q_finishSdpScan", Qt::QueuedConnection,
- Q_ARG(QBluetoothServiceDiscoveryAgent::Error,
- QBluetoothServiceDiscoveryAgent::InputOutputError),
- Q_ARG(QString,
- QBluetoothServiceDiscoveryAgent::tr("Unable to perform SDP scan")),
- Q_ARG(QStringList, QStringList()));
+ _q_finishSdpScan(QBluetoothServiceDiscoveryAgent::InputOutputError,
+ QBluetoothServiceDiscoveryAgent::tr("Unable to perform SDP scan"),
+ QStringList());
} else {
// go to next device
- QMetaObject::invokeMethod(q, "_q_finishSdpScan", Qt::QueuedConnection,
- Q_ARG(QBluetoothServiceDiscoveryAgent::Error,
- QBluetoothServiceDiscoveryAgent::NoError),
- Q_ARG(QString, QString()),
- Q_ARG(QStringList, QStringList()));
+ _q_finishSdpScan(QBluetoothServiceDiscoveryAgent::NoError, QString(), QStringList());
}
return;
}
QStringList xmlRecords;
+ const QByteArray output = sdpScannerProcess->readAllStandardOutput();
const QString decodedData = QString::fromUtf8(QByteArray::fromBase64(output));
// split the various xml docs up
@@ -276,13 +260,10 @@ void QBluetoothServiceDiscoveryAgentPrivate::runSdpScan(
} while ( start != -1);
}
- QMetaObject::invokeMethod(q, "_q_finishSdpScan", Qt::QueuedConnection,
- Q_ARG(QBluetoothServiceDiscoveryAgent::Error,
- QBluetoothServiceDiscoveryAgent::NoError),
- Q_ARG(QString, QString()),
- Q_ARG(QStringList, xmlRecords));
+ _q_finishSdpScan(QBluetoothServiceDiscoveryAgent::NoError, QString(), xmlRecords);
}
+// Bluez 5
void QBluetoothServiceDiscoveryAgentPrivate::_q_finishSdpScan(QBluetoothServiceDiscoveryAgent::Error errorCode,
const QString &errorDescription,
const QStringList &xmlRecords)
@@ -352,8 +333,19 @@ void QBluetoothServiceDiscoveryAgentPrivate::stop()
Q_ASSERT(!device);
}
+
discoveredDevices.clear();
setDiscoveryState(Inactive);
+
+ // must happen after discoveredDevices.clear() above to avoid retrigger of next scan
+ // while waitForFinished() is waiting
+ if (sdpScannerProcess) { // Bluez 5
+ if (sdpScannerProcess->state() != QProcess::NotRunning) {
+ sdpScannerProcess->kill();
+ sdpScannerProcess->waitForFinished();
+ }
+ }
+
Q_Q(QBluetoothServiceDiscoveryAgent);
emit q->canceled();
}
@@ -591,6 +583,7 @@ QBluetoothServiceInfo QBluetoothServiceDiscoveryAgentPrivate::parseServiceXml(
return serviceInfo;
}
+// Bluez 5
void QBluetoothServiceDiscoveryAgentPrivate::performMinimalServiceDiscovery(const QBluetoothAddress &deviceAddress)
{
if (foundHostAdapterPath.isEmpty()) {
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_p.h b/src/bluetooth/qbluetoothservicediscoveryagent_p.h
index ea985627..3b9c0a42 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent_p.h
+++ b/src/bluetooth/qbluetoothservicediscoveryagent_p.h
@@ -58,6 +58,7 @@ class OrgBluezManagerInterface;
class OrgBluezAdapterInterface;
class OrgBluezDeviceInterface;
class OrgFreedesktopDBusObjectManagerInterface;
+#include <QtCore/qprocess.h>
QT_BEGIN_NAMESPACE
class QDBusPendingCallWatcher;
@@ -127,6 +128,7 @@ public:
void _q_discoverGattCharacteristics(QDBusPendingCallWatcher *watcher);
void _q_discoveredGattCharacteristic(QDBusPendingCallWatcher *watcher);
*/
+ void _q_sdpScannerDone(int exitCode, QProcess::ExitStatus status);
void _q_finishSdpScan(QBluetoothServiceDiscoveryAgent::Error errorCode,
const QString &errorDescription,
const QStringList &xmlRecords);
@@ -147,8 +149,9 @@ private:
#ifdef QT_BLUEZ_BLUETOOTH
void startBluez5(const QBluetoothAddress &address);
- void runSdpScan(const QBluetoothAddress &remoteAddress,
+ void runExternalSdpScan(const QBluetoothAddress &remoteAddress,
const QBluetoothAddress localAddress);
+ void sdpScannerDone(int exitCode, QProcess::ExitStatus exitStatus);
QVariant readAttributeValue(QXmlStreamReader &xml);
QBluetoothServiceInfo parseServiceXml(const QString& xml);
void performMinimalServiceDiscovery(const QBluetoothAddress &deviceAddress);
@@ -195,6 +198,7 @@ private:
OrgFreedesktopDBusObjectManagerInterface *managerBluez5;
OrgBluezAdapterInterface *adapter;
OrgBluezDeviceInterface *device;
+ QProcess *sdpScannerProcess;
#endif
#ifdef QT_ANDROID_BLUETOOTH
diff --git a/src/bluetooth/qbluetoothsocket_android.cpp b/src/bluetooth/qbluetoothsocket_android.cpp
index 02440abc..c3380836 100644
--- a/src/bluetooth/qbluetoothsocket_android.cpp
+++ b/src/bluetooth/qbluetoothsocket_android.cpp
@@ -37,6 +37,7 @@
#include "qbluetoothaddress.h"
#include <QtCore/QLoggingCategory>
#include <QtCore/QTime>
+#include <QtCore/private/qjni_p.h>
#include <QtConcurrent/QtConcurrentRun>
#include <QtAndroidExtras/QAndroidJniEnvironment>
@@ -90,32 +91,37 @@ bool QBluetoothSocketPrivate::fallBackConnect(QAndroidJniObject uuid, int channe
qCWarning(QT_BT_ANDROID) << "Falling back to workaround.";
QAndroidJniEnvironment env;
- jclass remoteDeviceClazz = env->GetObjectClass(remoteDevice.object());
- jmethodID getClassMethod = env->GetMethodID(remoteDeviceClazz, "getClass", "()Ljava/lang/Class;");
- if (!getClassMethod) {
- qCWarning(QT_BT_ANDROID) << "BluetoothDevice.getClass method could not be found.";
- return false;
- }
-
- QAndroidJniObject remoteDeviceClass = QAndroidJniObject(env->CallObjectMethod(remoteDevice.object(), getClassMethod));
+ QAndroidJniObject remoteDeviceClass = remoteDevice.callObjectMethod("getClass", "()Ljava/lang/Class;");
if (!remoteDeviceClass.isValid()) {
qCWarning(QT_BT_ANDROID) << "Could not invoke BluetoothDevice.getClass.";
return false;
}
- jclass classClass = env->FindClass("java/lang/Class");
- jclass integerClass = env->FindClass("java/lang/Integer");
- jfieldID integerType = env->GetStaticFieldID(integerClass, "TYPE", "Ljava/lang/Class;");
- jobject integerObject = env->GetStaticObjectField(integerClass, integerType);
- if (!integerObject) {
+ QAndroidJniObject integerObject = QAndroidJniObject::getStaticObjectField<jobject>(
+ "java/lang/Integer", "TYPE", "Ljava/lang/Class;");
+ if (!integerObject.isValid()) {
qCWarning(QT_BT_ANDROID) << "Could not get Integer.TYPE";
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+
return false;
}
- jobjectArray paramTypes = env->NewObjectArray(1, classClass, integerObject);
- if (!paramTypes) {
+ jclass classClass = QJNIEnvironmentPrivate::findClass("java/lang/Class");
+ jobjectArray rawArray = env->NewObjectArray(1, classClass,
+ integerObject.object<jobject>());
+ QAndroidJniObject paramTypes(rawArray);
+ env->DeleteLocalRef(rawArray);
+ if (!paramTypes.isValid()) {
qCWarning(QT_BT_ANDROID) << "Could not create new Class[]{Integer.TYPE}";
+
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
return false;
}
@@ -143,7 +149,7 @@ bool QBluetoothSocketPrivate::fallBackConnect(QAndroidJniObject uuid, int channe
"getMethod",
"(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;",
QAndroidJniObject::fromString(QLatin1String("createRfcommSocket")).object<jstring>(),
- paramTypes);
+ paramTypes.object<jobjectArray>());
if (!method.isValid() || env->ExceptionCheck()) {
qCWarning(QT_BT_ANDROID) << "Could not invoke getMethod";
if (env->ExceptionCheck()) {
@@ -153,29 +159,23 @@ bool QBluetoothSocketPrivate::fallBackConnect(QAndroidJniObject uuid, int channe
return false;
}
- jclass methodClass = env->GetObjectClass(method.object());
- jmethodID invokeMethodId = env->GetMethodID(
- methodClass, "invoke",
- "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
- if (!invokeMethodId) {
- qCWarning(QT_BT_ANDROID) << "Could not invoke method.";
- return false;
- }
+ jclass objectClass = QJNIEnvironmentPrivate::findClass("java/lang/Object");
+ QAndroidJniObject channelObject = QAndroidJniObject::callStaticObjectMethod(
+ "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", channel);
+ rawArray = env->NewObjectArray(1, objectClass, channelObject.object<jobject>());
- jmethodID valueOfMethodId = env->GetStaticMethodID(integerClass, "valueOf", "(I)Ljava/lang/Integer;");
- jclass objectClass = env->FindClass("java/lang/Object");
- jobjectArray invokeParams = env->NewObjectArray(1, objectClass, env->CallStaticObjectMethod(integerClass, valueOfMethodId, channel));
-
-
- jobject invokeResult = env->CallObjectMethod(method.object(), invokeMethodId,
- remoteDevice.object(), invokeParams);
- if (!invokeResult)
+ QAndroidJniObject invokeResult = method.callObjectMethod("invoke",
+ "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;",
+ remoteDevice.object<jobject>(), rawArray);
+ env->DeleteLocalRef(rawArray);
+ if (!invokeResult.isValid())
{
qCWarning(QT_BT_ANDROID) << "Invoke Resulted with error.";
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
env->ExceptionClear();
}
+
return false;
}
@@ -186,7 +186,6 @@ bool QBluetoothSocketPrivate::fallBackConnect(QAndroidJniObject uuid, int channe
env->ExceptionClear();
qCWarning(QT_BT_ANDROID) << "Socket connect via workaround failed.";
-
return false;
}
diff --git a/src/bluetooth/qlowenergycontroller_bluez.cpp b/src/bluetooth/qlowenergycontroller_bluez.cpp
index 63de6edb..ae354bc7 100644
--- a/src/bluetooth/qlowenergycontroller_bluez.cpp
+++ b/src/bluetooth/qlowenergycontroller_bluez.cpp
@@ -41,6 +41,8 @@
#include <QtBluetooth/QBluetoothSocket>
#include <QtBluetooth/QLowEnergyService>
+#include <errno.h>
+
#define ATTRIBUTE_CHANNEL_ID 4
#define ATT_DEFAULT_LE_MTU 23