Merge remote-tracking branch 'gerrit/5.4.1' into 5.4
Change-Id: I1d15de1e31aeecfe162d700c632ad59cc0d6077d
This commit is contained in:
commit
b398e069ca
|
@ -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.
|
||||
|
|
@ -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]
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,10 @@
|
|||
#include <QtBluetooth/QBluetoothUuid>
|
||||
#include <QtBluetooth/QBluetoothDeviceDiscoveryAgent>
|
||||
|
||||
#ifdef QT_BLUEZ_BLUETOOTH
|
||||
#include <QtCore/qprocess.h>
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QBluetoothAddress;
|
||||
|
@ -106,7 +110,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,
|
||||
|
|
|
@ -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);
|
||||
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)));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
QStringList arguments;
|
||||
arguments << remoteAddress.toString() << localAddress.toString();
|
||||
|
||||
QByteArray output;
|
||||
sdpScannerProcess->setArguments(arguments);
|
||||
sdpScannerProcess->start();
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
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()) {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue