diff options
author | Alex Blasche <alexander.blasche@theqtcompany.com> | 2015-09-24 07:23:23 +0200 |
---|---|---|
committer | Alex Blasche <alexander.blasche@theqtcompany.com> | 2015-09-24 07:23:23 +0200 |
commit | 86a716072ee6ccf59dba8a474d15558eb1438966 (patch) | |
tree | 1d51bd72017c984984f2c08fc22e20b15a8c0e0c /src/bluetooth | |
parent | fba05edde4fd6699da731ffc05660364df613502 (diff) | |
parent | 4ff26a9993b9a797a3e7dcdcd82e13b7b513bc30 (diff) |
Merge branch 'dev' into win
Conflicts:
src/bluetooth/qbluetooth.cpp
src/bluetooth/qbluetoothdevicediscoveryagent_p.h
src/bluetooth/qbluetoothlocaldevice_p.h
Change-Id: I20fa8968db6c6461014899698c17aa86cd969189
Diffstat (limited to 'src/bluetooth')
64 files changed, 615 insertions, 3433 deletions
diff --git a/src/bluetooth/android/serveracceptancethread.cpp b/src/bluetooth/android/serveracceptancethread.cpp index 3a30cacb..c22256c9 100644 --- a/src/bluetooth/android/serveracceptancethread.cpp +++ b/src/bluetooth/android/serveracceptancethread.cpp @@ -38,8 +38,6 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID) -Q_DECLARE_METATYPE(QBluetoothServer::Error) - ServerAcceptanceThread::ServerAcceptanceThread(QObject *parent) : QObject(parent), maxPendingConnections(1) { diff --git a/src/bluetooth/bluetooth.pro b/src/bluetooth/bluetooth.pro index 109b45d1..01cec7ec 100644 --- a/src/bluetooth/bluetooth.pro +++ b/src/bluetooth/bluetooth.pro @@ -97,29 +97,6 @@ config_bluez:qtHaveModule(dbus) { qlowenergycontroller_p.cpp } -} else:CONFIG(blackberry) { - DEFINES += QT_QNX_BLUETOOTH - - include(qnx/qnx.pri) - - LIBS += -lbtapi - config_btapi10_2_1 { - DEFINES += QT_QNX_BT_BLUETOOTH - } - - PRIVATE_HEADERS += \ - qbluetoothtransferreply_qnx_p.h - - SOURCES += \ - qbluetoothdevicediscoveryagent_qnx.cpp \ - qbluetoothlocaldevice_qnx.cpp \ - qbluetoothserviceinfo_qnx.cpp \ - qbluetoothservicediscoveryagent_qnx.cpp \ - qbluetoothsocket_qnx.cpp \ - qbluetoothserver_qnx.cpp \ - qbluetoothtransferreply_qnx.cpp \ - qlowenergycontroller_p.cpp - } else:android:!android-no-sdk { include(android/android.pri) DEFINES += QT_ANDROID_BLUETOOTH diff --git a/src/bluetooth/bluez/bluez5_helper.cpp b/src/bluetooth/bluez/bluez5_helper.cpp index e4cb37d6..384b9979 100644 --- a/src/bluetooth/bluez/bluez5_helper.cpp +++ b/src/bluetooth/bluez/bluez5_helper.cpp @@ -38,6 +38,7 @@ #include "objectmanager_p.h" #include "properties_p.h" #include "adapter1_bluez5_p.h" +#include "manager_p.h" QT_BEGIN_NAMESPACE @@ -47,7 +48,8 @@ typedef enum Bluez5TestResultType { BluezVersionUnknown, BluezVersion4, - BluezVersion5 + BluezVersion5, + BluezNotAvailable } Bluez5TestResult; Q_GLOBAL_STATIC_WITH_ARGS(Bluez5TestResult, bluezVersion, (BluezVersionUnknown)); @@ -65,8 +67,20 @@ bool isBluez5() QDBusPendingReply<ManagedObjectList> reply = manager.GetManagedObjects(); reply.waitForFinished(); if (reply.isError()) { - *bluezVersion() = BluezVersion4; - qCDebug(QT_BT_BLUEZ) << "Bluez 4 detected."; + // not Bluez 5.x + OrgBluezManagerInterface manager_bluez4(QStringLiteral("org.bluez"), + QStringLiteral("/"), + QDBusConnection::systemBus()); + QDBusPendingReply<QList<QDBusObjectPath> > reply + = manager_bluez4.ListAdapters(); + reply.waitForFinished(); + if (reply.isError()) { + *bluezVersion() = BluezNotAvailable; + qWarning() << "Cannot find a running Bluez. Please check the Bluez installation."; + } else { + *bluezVersion() = BluezVersion4; + qCDebug(QT_BT_BLUEZ) << "Bluez 4 detected."; + } } else { *bluezVersion() = BluezVersion5; qCDebug(QT_BT_BLUEZ) << "Bluez 5 detected."; @@ -288,9 +302,14 @@ QString findAdapterForAddress(const QBluetoothAddress &wantedAddress, bool *ok = 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()) { + ManagedObjectList managedObjectList = reply.value(); + for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) { + const QDBusObjectPath &path = it.key(); + const InterfaceList &ifaceList = it.value(); + + for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) { + const QString &iface = jt.key(); + if (iface == QStringLiteral("org.bluez.Adapter1")) { AddressForPathType pair; pair.first = path.path(); diff --git a/src/bluetooth/doc/snippets/doc_src_qtbluetooth.cpp b/src/bluetooth/doc/snippets/doc_src_qtbluetooth.cpp index 0c017e45..1eec9206 100644 --- a/src/bluetooth/doc/snippets/doc_src_qtbluetooth.cpp +++ b/src/bluetooth/doc/snippets/doc_src_qtbluetooth.cpp @@ -190,7 +190,7 @@ void MyClass::characteristicChanged(const QLowEnergyCharacteristic &, const QByt void MyClass::btleSharedData() { - QBluetoothAddress remoteDevice; + QBluetoothDeviceInfo remoteDevice; //! [data_share_qlowenergyservice] QLowEnergyService *first, *second; @@ -213,7 +213,7 @@ void MyClass::btleSharedData() void MyClass::enableCharNotifications() { - QBluetoothAddress remoteDevice; + QBluetoothDeviceInfo remoteDevice; QLowEnergyService *service; QLowEnergyController *control = new QLowEnergyController(remoteDevice, this); control->connectToDevice(); diff --git a/src/bluetooth/doc/src/bluetooth-index.qdoc b/src/bluetooth/doc/src/bluetooth-index.qdoc index f5e76ff0..41b962bf 100644 --- a/src/bluetooth/doc/src/bluetooth-index.qdoc +++ b/src/bluetooth/doc/src/bluetooth-index.qdoc @@ -34,7 +34,7 @@ The Bluetooth API provides connectivity between Bluetooth enabled devices. Currently, the API is supported on the following platforms: \l{Qt for Android}{Android}, -\l{Qt for BlackBerry}{BlackBerry 10}, \l{Qt for iOS}{iOS}, \l{Qt for Linux/X11}{Linux} +\l{Qt for iOS}{iOS}, \l{Qt for Linux/X11}{Linux} (\l{http://www.bluez.org}{BlueZ 4.x/5.x}) and \l{Qt for OS X}{OS X}. \section1 Overview @@ -66,7 +66,7 @@ import statement in your \c .qml file: \section2 Guides \list \li \l {Qt Bluetooth Overview}{Classic Bluetooth Overview} - \li \l {Bluetooth Low Energy Overview} (Tech Preview) + \li \l {Bluetooth Low Energy Overview} \endlist \section2 Reference diff --git a/src/bluetooth/doc/src/bluetooth-le-overview.qdoc b/src/bluetooth/doc/src/bluetooth-le-overview.qdoc index 8cba2f64..909beae2 100644 --- a/src/bluetooth/doc/src/bluetooth-le-overview.qdoc +++ b/src/bluetooth/doc/src/bluetooth-le-overview.qdoc @@ -34,11 +34,9 @@ Low Energy devices. \tableofcontents - \section1 Technology Preview - The Qt Bluetooth Low Energy API was introduced by Qt 5.4. Since Qt 5.5 the API is frozen and a compatibility guarantee is given for future releases. - At the moment, Qt only supports the Bluetooth Low Energy central role. + At the moment, Qt supports the Bluetooth Low Energy central role. For more details on this limitation see below. \section1 What Is Bluetooth Low Energy @@ -166,9 +164,6 @@ Low Energy devices. and writing data stored on the device. The example code below is taken from the \l {heartlistener}{Heart Listener} example. - \note As of Qt 5.4 the Qt Bluetooth Low Energy API is in tech preview mode and supports Linux - with BlueZ 4.101 & 5.x. The minimal Linux kernel version is 3.5. - \section2 Establishing a Connection To be able to read and write the characteristics of the Bluetooth Low Energy peripheral device, diff --git a/src/bluetooth/qbluetooth.cpp b/src/bluetooth/qbluetooth.cpp index 195e4f3e..9ab6728f 100644 --- a/src/bluetooth/qbluetooth.cpp +++ b/src/bluetooth/qbluetooth.cpp @@ -81,7 +81,6 @@ namespace QBluetooth { Q_LOGGING_CATEGORY(QT_BT, "qt.bluetooth") Q_LOGGING_CATEGORY(QT_BT_ANDROID, "qt.bluetooth.android") Q_LOGGING_CATEGORY(QT_BT_BLUEZ, "qt.bluetooth.bluez") -Q_LOGGING_CATEGORY(QT_BT_QNX, "qt.bluetooth.qnx") Q_LOGGING_CATEGORY(QT_BT_WINDOWS, "qt.bluetooth.windows") QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent.h b/src/bluetooth/qbluetoothdevicediscoveryagent.h index aafd8efa..9c481982 100644 --- a/src/bluetooth/qbluetoothdevicediscoveryagent.h +++ b/src/bluetooth/qbluetoothdevicediscoveryagent.h @@ -62,11 +62,13 @@ public: UnsupportedPlatformError, UnknownError = 100 // New errors must be added before Unknown error }; + Q_ENUM(Error) enum InquiryType { GeneralUnlimitedInquiry, LimitedInquiry }; + Q_ENUM(InquiryType) QBluetoothDeviceDiscoveryAgent(QObject *parent = 0); explicit QBluetoothDeviceDiscoveryAgent(const QBluetoothAddress &deviceAdapter, diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp index 9d3387ec..f977c471 100644 --- a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp @@ -201,6 +201,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::processSdpDiscoveryFinished() // start LE scan if supported if (QtAndroidPrivate::androidSdkVersion() < 18) { qCDebug(QT_BT_ANDROID) << "Skipping Bluetooth Low Energy device scan"; + m_active = NoScanActive; emit q->finished(); } else { startLowEnergyScan(); @@ -228,8 +229,8 @@ void QBluetoothDeviceDiscoveryAgentPrivate::processDiscoveredDevices( return; } - // same device found -> avoid duplicates and update info in place - discoveredDevices.replace(i, info); + // same device found -> avoid duplicates and update core configuration + discoveredDevices[i].setCoreConfigurations(discoveredDevices[i].coreConfigurations() | info.coreConfigurations()); emit q->deviceDiscovered(info); return; diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp index 4d296d20..b0fd88d5 100644 --- a/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp @@ -188,6 +188,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start() } QDBusPendingReply<> discoveryReply = adapter->StartDiscovery(); + discoveryReply.waitForFinished(); if (discoveryReply.isError()) { delete adapter; adapter = 0; @@ -238,9 +239,14 @@ void QBluetoothDeviceDiscoveryAgentPrivate::startBluez5() 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()) { + ManagedObjectList managedObjectList = reply.value(); + for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) { + const QDBusObjectPath &path = it.key(); + const InterfaceList &ifaceList = it.value(); + + for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) { + const QString &iface = jt.key(); + if (iface == QStringLiteral("org.bluez.Device1")) { if (path.path().indexOf(adapterBluez5->path()) != 0) @@ -426,6 +432,8 @@ void QBluetoothDeviceDiscoveryAgentPrivate::_q_propertyChanged(const QString &na return; } + QDBusPendingReply<> reply = adapter->StopDiscovery(); + reply.waitForFinished(); adapter->deleteLater(); adapter = 0; emit q->finished(); diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm b/src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm index 85c9f0da..1556c5f9 100644 --- a/src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm @@ -157,7 +157,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start() // We can be here only if we have some kind of // resource allocation error. setError(QBluetoothDeviceDiscoveryAgent::UnknownError, - QCoreApplication::translate(DEV_DISCOVERY, DD_NOT_STARTED); + QCoreApplication::translate(DEV_DISCOVERY, DD_NOT_STARTED)); emit q_ptr->error(lastError); } } diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_p.h b/src/bluetooth/qbluetoothdevicediscoveryagent_p.h index 814f6a37..0d220ef9 100644 --- a/src/bluetooth/qbluetoothdevicediscoveryagent_p.h +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_p.h @@ -71,9 +71,6 @@ class OrgBluezDevice1Interface; QT_BEGIN_NAMESPACE class QDBusVariant; QT_END_NAMESPACE -#elif defined(QT_QNX_BLUETOOTH) -#include "qnx/ppshelpers_p.h" -#include <QTimer> #endif #ifdef Q_OS_WIN32 @@ -85,7 +82,7 @@ QT_END_NAMESPACE QT_BEGIN_NAMESPACE class QBluetoothDeviceDiscoveryAgentPrivate -#if defined(QT_QNX_BLUETOOTH) || defined(QT_ANDROID_BLUETOOTH) || defined(Q_OS_WIN32) +#if defined(QT_ANDROID_BLUETOOTH) || defined(Q_OS_WIN32) : public QObject { Q_OBJECT @@ -157,30 +154,6 @@ private: bool useExtendedDiscovery; QTimer extendedDiscoveryTimer; - -#elif defined(QT_QNX_BLUETOOTH) -private slots: - void finished(); - void remoteDevicesChanged(int); - void controlReply(ppsResult result); - void controlEvent(ppsResult result); - void startDeviceSearch(); - -private: - QSocketNotifier *m_rdNotifier; - QTimer m_finishedTimer; - - int m_rdfd; - bool m_active; - enum Ops { - None, - Cancel, - Start - }; - Ops m_nextOp; - Ops m_currentOp; - void processNextOp(); - bool isFinished; #endif #ifdef Q_OS_WIN32 diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_qnx.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_qnx.cpp deleted file mode 100644 index 8996d71b..00000000 --- a/src/bluetooth/qbluetoothdevicediscoveryagent_qnx.cpp +++ /dev/null @@ -1,296 +0,0 @@ -/*************************************************************************** -** -** Copyright (C) 2012 Research In Motion -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtBluetooth module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qbluetoothdevicediscoveryagent.h" -#include "qbluetoothdevicediscoveryagent_p.h" -#include "qbluetoothaddress.h" -#include "qbluetoothuuid.h" - -#include <QtCore/private/qcore_unix_p.h> - -QT_BEGIN_NAMESPACE - -QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate( - const QBluetoothAddress &deviceAdapter, QBluetoothDeviceDiscoveryAgent *parent) : - QObject(parent), - lastError(QBluetoothDeviceDiscoveryAgent::NoError), - m_rdfd(-1), - m_active(false), - m_nextOp(None), - m_currentOp(None), - q_ptr(parent) -{ - Q_UNUSED(deviceAdapter); - inquiryType = QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry; - ppsRegisterControl(); - ppsRegisterForEvent(QStringLiteral("device_added"), this); - ppsRegisterForEvent(QStringLiteral("device_search"), this); - connect(&m_finishedTimer, SIGNAL(timeout()), this, SLOT(finished())); -} - -QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate() -{ - if (m_active) - stop(); - ppsUnregisterForEvent(QStringLiteral("device_added"), this); - ppsUnregisterForEvent(QStringLiteral("device_search"), this); - ppsUnregisterControl(this); -} - -bool QBluetoothDeviceDiscoveryAgentPrivate::isActive() const -{ - return m_active; -} - -void QBluetoothDeviceDiscoveryAgentPrivate::start() -{ - Q_Q(QBluetoothDeviceDiscoveryAgent); - m_active = true; - isFinished = false; - discoveredDevices.clear(); - - if (m_currentOp == Cancel) { - m_nextOp = Start; - return; - } - if (m_nextOp == Cancel) - m_nextOp = None; - m_currentOp = Start; - - if (m_rdfd != -1) { - qCDebug(QT_BT_QNX) << "RDev FD still open"; - } else if ((m_rdfd - = qt_safe_open("/pps/services/bluetooth/remote_devices/.all", - O_RDONLY)) == -1) { - qCWarning(QT_BT_QNX) << Q_FUNC_INFO - << "rdfd - failed to open /pps/services/bluetooth/remote_devices/.all" - << m_rdfd; - lastError = QBluetoothDeviceDiscoveryAgent::InputOutputError; - errorString = QBluetoothDeviceDiscoveryAgent::tr("Cannot open remote device socket"); - emit q->error(lastError); - stop(); - return; - } else { - m_rdNotifier = new QSocketNotifier(m_rdfd, QSocketNotifier::Read, this); - if (!m_rdNotifier) { - qCWarning(QT_BT_QNX) << Q_FUNC_INFO << "failed to connect to m_rdNotifier"; - lastError = QBluetoothDeviceDiscoveryAgent::InputOutputError; - errorString = QBluetoothDeviceDiscoveryAgent::tr( - "Cannot connect to Bluetooth socket notifier"); - emit q->error(lastError); - stop(); - return; - } - } - - if (ppsSendControlMessage("device_search", this)) { - // If there is no new results after 7 seconds, the device inquire will be stopped - m_finishedTimer.start(10000); - connect(m_rdNotifier, SIGNAL(activated(int)), this, SLOT(remoteDevicesChanged(int))); - } else { - qCWarning(QT_BT_QNX) << "Could not write to control FD"; - m_active = false; - lastError = QBluetoothDeviceDiscoveryAgent::InputOutputError; - errorString = QBluetoothDeviceDiscoveryAgent::tr("Cannot start device inquiry"); - q->error(QBluetoothDeviceDiscoveryAgent::InputOutputError); - return; - } -} - -void QBluetoothDeviceDiscoveryAgentPrivate::stop() -{ - m_active = false; - m_finishedTimer.stop(); - if (m_currentOp == Start) { - m_nextOp = Cancel; - return; - } - m_currentOp = Cancel; - - qCDebug(QT_BT_QNX) << "Stopping device search"; - ppsSendControlMessage("cancel_device_search", this); - - if (m_rdNotifier) { - delete m_rdNotifier; - m_rdNotifier = 0; - } - if (m_rdfd != -1) { - qt_safe_close(m_rdfd); - m_rdfd = -1; - } -} - -void QBluetoothDeviceDiscoveryAgentPrivate::remoteDevicesChanged(int fd) -{ - if (!m_active) - return; - pps_decoder_t ppsDecoder; - pps_decoder_initialize(&ppsDecoder, NULL); - - QBluetoothAddress deviceAddr; - QString deviceName; - - if (!ppsReadRemoteDevice(fd, &ppsDecoder, &deviceAddr, &deviceName)) - return; - - bool paired = false; - int cod = 0; - int dev_type = 0; - int rssi = 0; - bool hasGatt = false; - pps_decoder_get_bool(&ppsDecoder, "paired", &paired); - pps_decoder_get_int(&ppsDecoder, "cod", &cod); - pps_decoder_get_int(&ppsDecoder, "dev_type", &dev_type); - pps_decoder_get_int(&ppsDecoder, "rssi", &rssi); - pps_decoder_push(&ppsDecoder, "gatt_available_services"); - const char *next_service = 0; - - for (int service_count=0; pps_decoder_get_string(&ppsDecoder, 0, &next_service ) == PPS_DECODER_OK; service_count++) { - hasGatt = true; - //qBluetoothDebug() << next_service; - } - pps_decoder_cleanup(&ppsDecoder); - - QBluetoothDeviceInfo deviceInfo(deviceAddr, deviceName, cod); - deviceInfo.setRssi(rssi); - - bool updated = false; - // Prevent a device from being listed twice - for (int i = 0; i < discoveredDevices.size(); i++) { - if (discoveredDevices.at(i).address() == deviceInfo.address()) { - updated = true; - if (discoveredDevices.at(i) == deviceInfo) { - return; - } else { - discoveredDevices.removeAt(i); - break; - } - } - } - // Starts the timer again - m_finishedTimer.start(7000); - if (!deviceAddr.isNull()) { - qCDebug(QT_BT_QNX) << "Device discovered: " << deviceName << deviceAddr.toString(); - /* Looking for device type. Only Low energy devices will be added - * BT_DEVICE_TYPE_LE_PUBLIC is 0 --->LE device - * BT_DEVICE_TYPE_LE_PRIVATE is 1 ---> LE device - * BT_DEVICE_TYPE_REGULAR is 32 - * BT_DEVICE_TYPE_UNKNOWN is 255 - */ - if (dev_type == 0 || dev_type == 1) - deviceInfo.setCoreConfigurations(QBluetoothDeviceInfo::LowEnergyCoreConfiguration); - else{ - if (hasGatt) - deviceInfo.setCoreConfigurations(QBluetoothDeviceInfo::BaseRateAndLowEnergyCoreConfiguration); - else - deviceInfo.setCoreConfigurations(QBluetoothDeviceInfo::BaseRateCoreConfiguration); - } - discoveredDevices.append(deviceInfo); - if (!updated) // We are not allowed to emit a signal with the updated version - emit q_ptr->deviceDiscovered(discoveredDevices.last()); - } -} - -void QBluetoothDeviceDiscoveryAgentPrivate::controlReply(ppsResult result) -{ - Q_Q(QBluetoothDeviceDiscoveryAgent); - if (result.msg == QStringLiteral("device_search") && m_currentOp == Start) { - if (result.dat.size() > 0 && result.dat.first() == QStringLiteral("EOK")) { - // Do nothing. We can not be certain, that the device search is over yet - } else if (result.error == 16) { - qCDebug(QT_BT_QNX) << "Could not start device inquire bc resource is busy"; - if (m_nextOp == None) { // We try again - ppsSendControlMessage("cancel_device_search", this); - QTimer::singleShot(5000, this, SLOT(startDeviceSearch())); - m_finishedTimer.start(20000); - } - return; - } else { - qCWarning(QT_BT_QNX) << "A PPS Bluetooth error occurred:"; - lastError = QBluetoothDeviceDiscoveryAgent::InputOutputError; - errorString = result.errorMsg; - emit q_ptr->error(QBluetoothDeviceDiscoveryAgent::InputOutputError); - stop(); - } - processNextOp(); - } else if (result.msg == QStringLiteral("cancel_device_search") && m_currentOp == Cancel - && !isFinished) { - qCDebug(QT_BT_QNX) << "Cancel device search"; -// if (!result.errorMsg.isEmpty()) { -// lastError = QBluetoothDeviceDiscoveryAgent::InputOutputError; -// errorString = result.errorMsg; -// q_ptr->error(QBluetoothDeviceDiscoveryAgent::InputOutputError); -// } - emit q->canceled(); - processNextOp(); - } -} - -void QBluetoothDeviceDiscoveryAgentPrivate::controlEvent(ppsResult result) -{ - if (result.msg == QStringLiteral("device_added")) - qCDebug(QT_BT_QNX) << "Device was added" << result.dat.first(); -} - -void QBluetoothDeviceDiscoveryAgentPrivate::finished() -{ - if (m_active) { - qCDebug(QT_BT_QNX) << "Device discovery finished"; - isFinished = true; - stop(); - q_ptr->finished(); - } -} - -void QBluetoothDeviceDiscoveryAgentPrivate::startDeviceSearch() -{ - if (m_currentOp == Start) - ppsSendControlMessage("device_search", this); // Try again -} - -void QBluetoothDeviceDiscoveryAgentPrivate::processNextOp() -{ - if (m_currentOp == m_nextOp) { - m_currentOp = None; - m_nextOp = None; - } - m_currentOp = m_nextOp; - m_nextOp = None; - - if (m_currentOp == Start) - start(); - else if (m_currentOp == Cancel) - stop(); -} - -QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothdeviceinfo.h b/src/bluetooth/qbluetoothdeviceinfo.h index b64a9727..e543286d 100644 --- a/src/bluetooth/qbluetoothdeviceinfo.h +++ b/src/bluetooth/qbluetoothdeviceinfo.h @@ -241,6 +241,9 @@ private: Q_DECLARE_PRIVATE(QBluetoothDeviceInfo) }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QBluetoothDeviceInfo::CoreConfigurations) +Q_DECLARE_OPERATORS_FOR_FLAGS(QBluetoothDeviceInfo::ServiceClasses) + QT_END_NAMESPACE Q_DECLARE_METATYPE(QBluetoothDeviceInfo) diff --git a/src/bluetooth/qbluetoothhostinfo.cpp b/src/bluetooth/qbluetoothhostinfo.cpp index 1304f18a..f3671695 100644 --- a/src/bluetooth/qbluetoothhostinfo.cpp +++ b/src/bluetooth/qbluetoothhostinfo.cpp @@ -89,6 +89,29 @@ QBluetoothHostInfo &QBluetoothHostInfo::operator=(const QBluetoothHostInfo &othe } /*! + \since 5.5 + + Returns true if \a other is equal to this QBluetoothHostInfo, otherwise false. +*/ +bool QBluetoothHostInfo::operator==(const QBluetoothHostInfo &other) const +{ + if (d_ptr == other.d_ptr) + return true; + + return d_ptr->m_address == other.d_ptr->m_address && d_ptr->m_name == other.d_ptr->m_name; +} + +/*! + \since 5.5 + + Returns true if \a other is not equal to this QBluetoothHostInfo, otherwise false. +*/ +bool QBluetoothHostInfo::operator!=(const QBluetoothHostInfo &other) const +{ + return !operator==(other); +} + +/*! Returns the Bluetooth address as a QBluetoothAddress. */ QBluetoothAddress QBluetoothHostInfo::address() const diff --git a/src/bluetooth/qbluetoothhostinfo.h b/src/bluetooth/qbluetoothhostinfo.h index 8b0085b0..30e9e249 100644 --- a/src/bluetooth/qbluetoothhostinfo.h +++ b/src/bluetooth/qbluetoothhostinfo.h @@ -49,6 +49,9 @@ public: QBluetoothHostInfo &operator=(const QBluetoothHostInfo &other); + bool operator==(const QBluetoothHostInfo &other) const; + bool operator!=(const QBluetoothHostInfo &other) const; + QBluetoothAddress address() const; void setAddress(const QBluetoothAddress &address); @@ -62,4 +65,6 @@ private: QT_END_NAMESPACE +Q_DECLARE_METATYPE(QBluetoothHostInfo) + #endif diff --git a/src/bluetooth/qbluetoothlocaldevice.cpp b/src/bluetooth/qbluetoothlocaldevice.cpp index 0eb97647..99264962 100644 --- a/src/bluetooth/qbluetoothlocaldevice.cpp +++ b/src/bluetooth/qbluetoothlocaldevice.cpp @@ -281,7 +281,7 @@ bool QBluetoothLocalDevice::isValid() const \fn QBluetoothLocalDevice::requestPairing(const QBluetoothAddress &address, Pairing pairing) Set the \a pairing status with \a address. The results are returned by the signal, pairingFinished(). - On BlackBerry AuthorizedPaired is not possible and will have the same behavior as Paired. + On Android and OS X, AuthorizedPaired is not possible and will have the same behavior as Paired. On OS X, it is not possible to unpair a device. If Unpaired is requested, \l pairingFinished() is immediately emitted although the device remains paired. It is possible to request the pairing diff --git a/src/bluetooth/qbluetoothlocaldevice.h b/src/bluetooth/qbluetoothlocaldevice.h index bcb39bda..40e143ab 100644 --- a/src/bluetooth/qbluetoothlocaldevice.h +++ b/src/bluetooth/qbluetoothlocaldevice.h @@ -49,15 +49,14 @@ class QBluetoothLocalDevicePrivate; class Q_BLUETOOTH_EXPORT QBluetoothLocalDevice : public QObject { Q_OBJECT - Q_ENUMS(Pairing) - Q_ENUMS(HostMode) - Q_ENUMS(Error) + public: enum Pairing { Unpaired, Paired, AuthorizedPaired }; + Q_ENUM(Pairing) enum HostMode { HostPoweredOff, @@ -65,12 +64,15 @@ public: HostDiscoverable, HostDiscoverableLimitedInquiry }; + Q_ENUM(HostMode) enum Error { NoError, PairingError, UnknownError = 100 }; + Q_ENUM(Error) + QBluetoothLocalDevice(QObject *parent = 0); explicit QBluetoothLocalDevice(const QBluetoothAddress &address, QObject *parent = 0); virtual ~QBluetoothLocalDevice(); @@ -111,8 +113,8 @@ private: QT_END_NAMESPACE -Q_DECLARE_METATYPE(QBluetoothLocalDevice::HostMode) Q_DECLARE_METATYPE(QBluetoothLocalDevice::Pairing) +Q_DECLARE_METATYPE(QBluetoothLocalDevice::HostMode) Q_DECLARE_METATYPE(QBluetoothLocalDevice::Error) #endif // QBLUETOOTHLOCALDEVICE_H diff --git a/src/bluetooth/qbluetoothlocaldevice_bluez.cpp b/src/bluetooth/qbluetoothlocaldevice_bluez.cpp index cae21e1b..d2ec70b9 100644 --- a/src/bluetooth/qbluetoothlocaldevice_bluez.cpp +++ b/src/bluetooth/qbluetoothlocaldevice_bluez.cpp @@ -213,17 +213,22 @@ QList<QBluetoothHostInfo> QBluetoothLocalDevice::allDevices() if (reply.isError()) return localDevices; - foreach (const QDBusObjectPath &path, reply.value().keys()) { - const InterfaceList ifaceList = reply.value().value(path); - foreach (const QString &iface, ifaceList.keys()) { + ManagedObjectList managedObjectList = reply.value(); + for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) { + const InterfaceList &ifaceList = it.value(); + + for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) { + const QString &iface = jt.key(); + const QVariantMap &ifaceValues = jt.value(); + if (iface == QStringLiteral("org.bluez.Adapter1")) { QBluetoothHostInfo hostInfo; - const QString temp = ifaceList.value(iface).value(QStringLiteral("Address")).toString(); + const QString temp = ifaceValues.value(QStringLiteral("Address")).toString(); hostInfo.setAddress(QBluetoothAddress(temp)); if (hostInfo.address().isNull()) continue; - hostInfo.setName(ifaceList.value(iface).value(QStringLiteral("Name")).toString()); + hostInfo.setName(ifaceValues.value(QStringLiteral("Name")).toString()); localDevices.append(hostInfo); } } @@ -447,10 +452,13 @@ void QBluetoothLocalDevicePrivate::requestPairingBluez5(const QBluetoothAddress return; } + ManagedObjectList managedObjectList = reply.value(); + for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) { + const QDBusObjectPath &path = it.key(); + const InterfaceList &ifaceList = it.value(); - foreach (const QDBusObjectPath &path, reply.value().keys()) { - const InterfaceList ifaceList = reply.value().value(path); - foreach (const QString &iface, ifaceList.keys()) { + for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) { + const QString &iface = jt.key(); if (iface == QStringLiteral("org.bluez.Device1")) { @@ -603,9 +611,13 @@ QBluetoothLocalDevice::Pairing QBluetoothLocalDevice::pairingStatus( if (reply.isError()) return Unpaired; - foreach (const QDBusObjectPath &path, reply.value().keys()) { - const InterfaceList ifaceList = reply.value().value(path); - foreach (const QString &iface, ifaceList.keys()) { + ManagedObjectList managedObjectList = reply.value(); + for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) { + const QDBusObjectPath &path = it.key(); + const InterfaceList &ifaceList = it.value(); + + for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) { + const QString &iface = jt.key(); if (iface == QStringLiteral("org.bluez.Device1")) { @@ -670,9 +682,16 @@ void QBluetoothLocalDevicePrivate::connectDeviceChanges() return; OrgFreedesktopDBusPropertiesInterface *monitor = 0; - foreach (const QDBusObjectPath &path, reply.value().keys()) { - const InterfaceList ifaceList = reply.value().value(path); - foreach (const QString &iface, ifaceList.keys()) { + + ManagedObjectList managedObjectList = reply.value(); + for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) { + const QDBusObjectPath &path = it.key(); + const InterfaceList &ifaceList = it.value(); + + for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) { + const QString &iface = jt.key(); + const QVariantMap &ifaceValues = jt.value(); + if (iface == QStringLiteral("org.bluez.Device1")) { monitor = new OrgFreedesktopDBusPropertiesInterface(QStringLiteral("org.bluez"), path.path(), @@ -681,7 +700,6 @@ void QBluetoothLocalDevicePrivate::connectDeviceChanges() SLOT(PropertiesChanged(QString,QVariantMap,QStringList))); deviceChangeMonitors.insert(path.path(), monitor); - const QVariantMap ifaceValues = ifaceList.value(QStringLiteral("org.bluez.Device1")); if (ifaceValues.value(QStringLiteral("Connected"), false).toBool()) { QBluetoothAddress address(ifaceValues.value(QStringLiteral("Address")).toString()); connectedDevicesSet.insert(address); diff --git a/src/bluetooth/qbluetoothlocaldevice_p.h b/src/bluetooth/qbluetoothlocaldevice_p.h index 9cf79c86..844be01b 100644 --- a/src/bluetooth/qbluetoothlocaldevice_p.h +++ b/src/bluetooth/qbluetoothlocaldevice_p.h @@ -70,11 +70,8 @@ class OrgBluezManagerInterface; QT_BEGIN_NAMESPACE class QDBusPendingCallWatcher; QT_END_NAMESPACE - -#elif defined(QT_QNX_BLUETOOTH) -#include <QSocketNotifier> -#include "qnx/ppshelpers_p.h" #endif + #ifdef QT_ANDROID_BLUETOOTH #include <jni.h> #include <QtAndroidExtras/QAndroidJniEnvironment> @@ -207,42 +204,6 @@ private: void initializeAdapterBluez5(); }; -#elif defined(QT_QNX_BLUETOOTH) - -class QBluetoothLocalDevicePrivate : public QObject -{ - Q_OBJECT - Q_DECLARE_PUBLIC(QBluetoothLocalDevice) -public: - QBluetoothLocalDevicePrivate(QBluetoothLocalDevice *); - ~QBluetoothLocalDevicePrivate(); - - static QString name(); - static QBluetoothAddress address(); - - void powerOn(); - void powerOff(); - - void setHostMode(QBluetoothLocalDevice::HostMode mode); - QBluetoothLocalDevice::HostMode hostMode() const; - - void requestPairing(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing); - - void setAccess(int); - // This method will be used for emitting signals. - void connectedDevices(); - - Q_INVOKABLE void controlReply(ppsResult res); - Q_INVOKABLE void controlEvent(ppsResult res); - - bool isValid() const; - -private: - QBluetoothLocalDevice *q_ptr; - bool isValidDevice; - QList<QBluetoothAddress> connectedDevicesSet; -}; - #elif defined(Q_OS_WIN32) class QBluetoothLocalDevicePrivate : public QObject diff --git a/src/bluetooth/qbluetoothlocaldevice_qnx.cpp b/src/bluetooth/qbluetoothlocaldevice_qnx.cpp deleted file mode 100644 index c36fb89a..00000000 --- a/src/bluetooth/qbluetoothlocaldevice_qnx.cpp +++ /dev/null @@ -1,398 +0,0 @@ -/*************************************************************************** -** -** Copyright (C) 2012 Research In Motion -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtBluetooth module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qbluetoothlocaldevice.h" -#include "qbluetoothaddress.h" -#include "qbluetoothlocaldevice_p.h" -#include <sys/pps.h> -#include "qnx/ppshelpers_p.h" -#include <QDir> -#include <QtCore/private/qcore_unix_p.h> - -QT_BEGIN_NAMESPACE - -QBluetoothLocalDevice::QBluetoothLocalDevice(QObject *parent) : - QObject(parent) -{ - this->d_ptr = new QBluetoothLocalDevicePrivate(this); - this->d_ptr->isValidDevice = true; // assume single local device on QNX -} - -QBluetoothLocalDevice::QBluetoothLocalDevice(const QBluetoothAddress &address, QObject *parent) : - QObject(parent) -{ - this->d_ptr = new QBluetoothLocalDevicePrivate(this); - - // works since we assume a single local device on QNX - this->d_ptr->isValidDevice = (QBluetoothLocalDevicePrivate::address() == address - || address == QBluetoothAddress()); -} - -QString QBluetoothLocalDevice::name() const -{ - if (this->d_ptr->isValid()) - return this->d_ptr->name(); - return QString(); -} - -QBluetoothAddress QBluetoothLocalDevice::address() const -{ - if (this->d_ptr->isValid()) - return this->d_ptr->address(); - return QBluetoothAddress(); -} - -void QBluetoothLocalDevice::powerOn() -{ - if (hostMode() == QBluetoothLocalDevice::HostPoweredOff) - this->d_ptr->powerOn(); -} - -void QBluetoothLocalDevice::setHostMode(QBluetoothLocalDevice::HostMode mode) -{ - this->d_ptr->setHostMode(mode); -} - -QBluetoothLocalDevice::HostMode QBluetoothLocalDevice::hostMode() const -{ - return this->d_ptr->hostMode(); -} - -QList<QBluetoothAddress> QBluetoothLocalDevice::connectedDevices() const -{ - QList<QBluetoothAddress> devices; - QDir bluetoothDevices(QStringLiteral("/pps/services/bluetooth/remote_devices/")); - QStringList allFiles = bluetoothDevices.entryList(QDir::NoDotAndDotDot| QDir::Files); - for (int i = 0; i < allFiles.size(); i++) { - qCDebug(QT_BT_QNX) << allFiles.at(i); - int fileId; - const char *filePath = QByteArray("/pps/services/bluetooth/remote_devices/").append(allFiles.at( - i).toUtf8().constData()) - .constData(); - if ((fileId = qt_safe_open(filePath, O_RDONLY)) == -1) { - qCWarning(QT_BT_QNX) << "Failed to open remote device file"; - } else { - pps_decoder_t ppsDecoder; - pps_decoder_initialize(&ppsDecoder, 0); - - QBluetoothAddress deviceAddr; - QString deviceName; - - if (!ppsReadRemoteDevice(fileId, &ppsDecoder, &deviceAddr, &deviceName)) { - pps_decoder_cleanup(&ppsDecoder); - qDebug() << "Failed to open remote device file"; - } - - bool connectedDevice = false; - int a = pps_decoder_get_bool(&ppsDecoder, "acl_connected", &connectedDevice); - if (a == PPS_DECODER_OK) { - if (connectedDevice) - devices.append(deviceAddr); - } else if (a == PPS_DECODER_BAD_TYPE) { - qCDebug(QT_BT_QNX) << "Type missmatch"; - } else { - qCDebug(QT_BT_QNX) << "An unknown error occurred while checking connected status."; - } - pps_decoder_cleanup(&ppsDecoder); - } - } - - return devices; -} - -QList<QBluetoothHostInfo> QBluetoothLocalDevice::allDevices() -{ - // We only have one device - QList<QBluetoothHostInfo> localDevices; - QBluetoothHostInfo hostInfo; - hostInfo.setName(QBluetoothLocalDevicePrivate::name()); - hostInfo.setAddress(QBluetoothLocalDevicePrivate::address()); - localDevices.append(hostInfo); - return localDevices; -} - -void QBluetoothLocalDevice::requestPairing(const QBluetoothAddress &address, Pairing pairing) -{ - if (address.isNull()) { - QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, - Q_ARG(QBluetoothLocalDevice::Error, - QBluetoothLocalDevice::PairingError)); - return; - } - - const Pairing current_pairing = pairingStatus(address); - if (current_pairing == pairing) { - QMetaObject::invokeMethod(this, "pairingFinished", Qt::QueuedConnection, - Q_ARG(QBluetoothAddress, address), - Q_ARG(QBluetoothLocalDevice::Pairing, pairing)); - return; - } - d_ptr->requestPairing(address, pairing); -} - -QBluetoothLocalDevice::Pairing QBluetoothLocalDevice::pairingStatus( - const QBluetoothAddress &address) const -{ - if (!isValid()) - return Unpaired; - bool paired = false; - bool btle = false; // Bluetooth Low Energy devices - QByteArray qnxPath("/pps/services/bluetooth/remote_devices/"); - qnxPath.append(address.toString().toUtf8()); - int m_rdfd; - if ((m_rdfd = qt_safe_open(qnxPath.constData(), O_RDONLY)) == -1) { - btle = true; - qnxPath.append("-00"); - if ((m_rdfd = qt_safe_open(qnxPath.constData(), O_RDONLY)) == -1) { - qnxPath.replace((qnxPath.length()-3), 3, "-01"); - if ((m_rdfd = qt_safe_open(qnxPath.constData(), O_RDONLY)) == -1) - return Unpaired; - } - } - - pps_decoder_t ppsDecoder; - pps_decoder_initialize(&ppsDecoder, NULL); - - QBluetoothAddress deviceAddr; - QString deviceName; - - if (!ppsReadRemoteDevice(m_rdfd, &ppsDecoder, &deviceAddr, &deviceName)) - return Unpaired; - bool known = false; - // Paired BTLE devices have only known field set to true. - if (btle) - pps_decoder_get_bool(&ppsDecoder, "known", &known); - pps_decoder_get_bool(&ppsDecoder, "paired", &paired); - pps_decoder_cleanup(&ppsDecoder); - - if (paired) - return Paired; - else if (btle && known) - return Paired; - else - return Unpaired; -} - -void QBluetoothLocalDevice::pairingConfirmation(bool confirmation) -{ - Q_UNUSED(confirmation); -} - -QBluetoothLocalDevicePrivate::QBluetoothLocalDevicePrivate(QBluetoothLocalDevice *q) : - q_ptr(q) -{ - ppsRegisterControl(); - ppsRegisterForEvent(QStringLiteral("access_changed"), this); - ppsRegisterForEvent(QStringLiteral("pairing_complete"), this); - ppsRegisterForEvent(QStringLiteral("device_deleted"), this); - ppsRegisterForEvent(QStringLiteral("radio_shutdown"), this); -} - -QBluetoothLocalDevicePrivate::~QBluetoothLocalDevicePrivate() -{ - ppsUnregisterControl(this); - ppsUnregisterForEvent(QStringLiteral("access_changed"), this); - ppsUnregisterForEvent(QStringLiteral("pairing_complete"), this); - ppsUnregisterForEvent(QStringLiteral("device_deleted"), this); - ppsUnregisterForEvent(QStringLiteral("radio_shutdown"), this); -} - -bool QBluetoothLocalDevicePrivate::isValid() const -{ - return isValidDevice; -} - -QBluetoothAddress QBluetoothLocalDevicePrivate::address() -{ - return QBluetoothAddress(ppsReadSetting("btaddr").toString()); -} - -QString QBluetoothLocalDevicePrivate::name() -{ - return ppsReadSetting("name").toString(); -} - -void QBluetoothLocalDevicePrivate::powerOn() -{ - if (isValid()) - ppsSendControlMessage("radio_init", this); -} - -void QBluetoothLocalDevicePrivate::powerOff() -{ - if (isValid()) - ppsSendControlMessage("radio_shutdown", this); -} - -void QBluetoothLocalDevicePrivate::setHostMode(QBluetoothLocalDevice::HostMode mode) -{ - if (!isValid()) - return; - - QBluetoothLocalDevice::HostMode currentHostMode = hostMode(); - if (currentHostMode == mode) - return; - // If the device is in PowerOff state and the profile is changed then the power has to be turned on - if (currentHostMode == QBluetoothLocalDevice::HostPoweredOff) { - qCDebug(QT_BT_QNX) << "Powering on"; - powerOn(); - } - - if (mode == QBluetoothLocalDevice::HostPoweredOff) - powerOff(); - else if (mode == QBluetoothLocalDevice::HostDiscoverable) // General discoverable and connectable. - setAccess(1); - else if (mode == QBluetoothLocalDevice::HostConnectable) // Connectable but not discoverable. - setAccess(3); - else if (mode == QBluetoothLocalDevice::HostDiscoverableLimitedInquiry) // Limited discoverable and connectable. - setAccess(2); -} - -void QBluetoothLocalDevicePrivate::requestPairing(const QBluetoothAddress &address, - QBluetoothLocalDevice::Pairing pairing) -{ - if (pairing == QBluetoothLocalDevice::Paired - || pairing == QBluetoothLocalDevice::AuthorizedPaired) { - ppsSendControlMessage("initiate_pairing", - QStringLiteral("{\"addr\":\"%1\"}").arg(address.toString()), - this); - } else { - ppsSendControlMessage("remove_device", - QStringLiteral("{\"addr\":\"%1\"}").arg(address.toString()), - this); - } -} - -QBluetoothLocalDevice::HostMode QBluetoothLocalDevicePrivate::hostMode() const -{ - if (!isValid()) - return QBluetoothLocalDevice::HostPoweredOff; - - if (!ppsReadSetting("enabled").toBool()) - return QBluetoothLocalDevice::HostPoweredOff; - - int hostMode = ppsReadSetting("accessibility").toInt(); - - if (hostMode == 1) // General discoverable and connectable. - return QBluetoothLocalDevice::HostDiscoverable; - else if (hostMode == 3) // Connectable but not discoverable. - return QBluetoothLocalDevice::HostConnectable; - else if (hostMode == 2) // Limited discoverable and connectable. - return QBluetoothLocalDevice::HostDiscoverableLimitedInquiry; - else - return QBluetoothLocalDevice::HostPoweredOff; -} - -extern int __newHostMode; - -void QBluetoothLocalDevicePrivate::setAccess(int access) -{ - if (!ppsReadSetting("enabled").toBool()) // We cannot set the host mode until BT is fully powered up - __newHostMode = access; - else - ppsSendControlMessage("set_access", QStringLiteral("{\"access\":%1}").arg(access), 0); -} - -void QBluetoothLocalDevicePrivate::connectedDevices() -{ - QList<QBluetoothAddress> devices = q_ptr->connectedDevices(); - for (int i = 0; i < devices.size(); i++) { - if (!connectedDevicesSet.contains(devices.at(i))) { - QBluetoothAddress addr = devices.at(i); - connectedDevicesSet.append(addr); - emit q_ptr->deviceConnected(devices.at(i)); - } - } - - for (int i = 0; i < connectedDevicesSet.size(); i++) { - if (!devices.contains(connectedDevicesSet.at(i))) { - QBluetoothAddress addr = connectedDevicesSet.at(i); - emit q_ptr->deviceDisconnected(addr); - connectedDevicesSet.removeOne(addr); - } - } -} - -void QBluetoothLocalDevicePrivate::controlReply(ppsResult result) -{ - qCDebug(QT_BT_QNX) << Q_FUNC_INFO << result.msg << result.dat; - if (!result.errorMsg.isEmpty()) { - qCWarning(QT_BT_QNX) << Q_FUNC_INFO << result.errorMsg; - if (result.msg == QStringLiteral("initiate_pairing")) - q_ptr->error(QBluetoothLocalDevice::PairingError); - else - q_ptr->error(QBluetoothLocalDevice::UnknownError); - } -} - -void QBluetoothLocalDevicePrivate::controlEvent(ppsResult result) -{ - qCDebug(QT_BT_QNX) << Q_FUNC_INFO << "Control Event" << result.msg; - if (result.msg == QStringLiteral("access_changed")) { - if (__newHostMode == -1 && result.dat.size() > 1 - && result.dat.first() == QStringLiteral("level")) { - QBluetoothLocalDevice::HostMode newHostMode = hostMode(); - qCDebug(QT_BT_QNX) << "New Host mode" << newHostMode; - connectedDevices(); - emit q_ptr->hostModeStateChanged(newHostMode); - } - } else if (result.msg == QStringLiteral("pairing_complete")) { - qCDebug(QT_BT_QNX) << "pairing completed"; - if (result.dat.contains(QStringLiteral("addr"))) { - const QBluetoothAddress address = QBluetoothAddress( - result.dat.at(result.dat.indexOf(QStringLiteral("addr")) + 1)); - - QBluetoothLocalDevice::Pairing pairingStatus = QBluetoothLocalDevice::Paired; - - if (result.dat.contains(QStringLiteral("trusted")) - && result.dat.at(result.dat.indexOf(QStringLiteral("trusted")) + 1) - == QStringLiteral("true")) { - pairingStatus = QBluetoothLocalDevice::AuthorizedPaired; - } - qCDebug(QT_BT_QNX) << "pairing completed" << address.toString(); - emit q_ptr->pairingFinished(address, pairingStatus); - } - } else if (result.msg == QStringLiteral("device_deleted")) { - qCDebug(QT_BT_QNX) << "device deleted"; - if (result.dat.contains(QStringLiteral("addr"))) { - const QBluetoothAddress address = QBluetoothAddress( - result.dat.at(result.dat.indexOf(QStringLiteral("addr")) + 1)); - emit q_ptr->pairingFinished(address, QBluetoothLocalDevice::Unpaired); - } - } else if (result.msg == QStringLiteral("radio_shutdown")) { - qCDebug(QT_BT_QNX) << "radio shutdown"; - emit q_ptr->hostModeStateChanged(QBluetoothLocalDevice::HostPoweredOff); - } -} - -QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothserver.cpp b/src/bluetooth/qbluetoothserver.cpp index 01f6fc37..be198950 100644 --- a/src/bluetooth/qbluetoothserver.cpp +++ b/src/bluetooth/qbluetoothserver.cpp @@ -126,8 +126,6 @@ QT_BEGIN_NAMESPACE Sets the maximum number of pending connections to \a numConnections. If the number of pending sockets exceeds this limit new sockets will be rejected. - QNX platform supports only one device at the time and it will ignore this value. - \sa maxPendingConnections() */ @@ -152,7 +150,7 @@ QT_BEGIN_NAMESPACE /*! \fn quint16 QBluetoothServer::serverPort() const - Returns the server port number. On BlackBerry, this port might not correspond to the real RFCOMM port. + Returns the server port number. */ /*! @@ -253,10 +251,7 @@ bool QBluetoothServer::isListening() const { Q_D(const QBluetoothServer); -#ifdef QT_QNX_BLUETOOTH - if (!d->socket) - return false; -#elif defined(QT_ANDROID_BLUETOOTH) +#ifdef QT_ANDROID_BLUETOOTH return d->isListening(); #endif @@ -285,7 +280,7 @@ int QBluetoothServer::maxPendingConnections() const \l QBluetooth::NoSecurity the server object will not employ any authentication or encryption. Any other security flag combination will trigger a secure Bluetooth connection. - On BlackBerry, security flags are not supported and will be ignored. + On OS X, security flags are not supported and will be ignored. */ /*! diff --git a/src/bluetooth/qbluetoothserver.h b/src/bluetooth/qbluetoothserver.h index 951b47f4..752780a5 100644 --- a/src/bluetooth/qbluetoothserver.h +++ b/src/bluetooth/qbluetoothserver.h @@ -62,6 +62,8 @@ public: ServiceAlreadyRegisteredError, UnsupportedProtocolError }; + Q_ENUM(Error) + QBluetoothServer(QBluetoothServiceInfo::Protocol serverType, QObject *parent = 0); ~QBluetoothServer(); diff --git a/src/bluetooth/qbluetoothserver_bluez.cpp b/src/bluetooth/qbluetoothserver_bluez.cpp index d5cdb440..6b538447 100644 --- a/src/bluetooth/qbluetoothserver_bluez.cpp +++ b/src/bluetooth/qbluetoothserver_bluez.cpp @@ -57,8 +57,8 @@ static inline void convertAddress(quint64 from, quint8 (&to)[6]) } QBluetoothServerPrivate::QBluetoothServerPrivate(QBluetoothServiceInfo::Protocol sType) - : maxPendingConnections(1), serverType(sType), m_lastError(QBluetoothServer::NoError), - socketNotifier(0) + : maxPendingConnections(1), securityFlags(QBluetooth::Authorization), serverType(sType), + m_lastError(QBluetoothServer::NoError), socketNotifier(0) { if (sType == QBluetoothServiceInfo::RfcommProtocol) socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol); @@ -81,6 +81,57 @@ void QBluetoothServerPrivate::_q_newConnection() emit q_ptr->newConnection(); } +void QBluetoothServerPrivate::setSocketSecurityLevel( + QBluetooth::SecurityFlags requestedSecLevel, int *errnoCode) +{ + if (requestedSecLevel == QBluetooth::NoSecurity) { + qCWarning(QT_BT_BLUEZ) << "Cannot set NoSecurity on server socket"; + return; + } + + struct bt_security security; + memset(&security, 0, sizeof(security)); + + // ignore QBluetooth::Authentication -> not used anymore + if (requestedSecLevel & QBluetooth::Authorization) + security.level = BT_SECURITY_LOW; + if (requestedSecLevel & QBluetooth::Encryption) + security.level = BT_SECURITY_MEDIUM; + if (requestedSecLevel & QBluetooth::Secure) + security.level = BT_SECURITY_HIGH; + + if (setsockopt(socket->socketDescriptor(), SOL_BLUETOOTH, BT_SECURITY, + &security, sizeof(security)) != 0) { + if (errnoCode) + *errnoCode = errno; + } +} + +QBluetooth::SecurityFlags QBluetoothServerPrivate::socketSecurityLevel() const +{ + struct bt_security security; + memset(&security, 0, sizeof(security)); + socklen_t length = sizeof(security); + + if (getsockopt(socket->socketDescriptor(), SOL_BLUETOOTH, BT_SECURITY, + &security, &length) != 0) { + qCWarning(QT_BT_BLUEZ) << "Failed to get security flags" << qt_error_string(errno); + return QBluetooth::NoSecurity; + } + + switch (security.level) { + case BT_SECURITY_LOW: + return QBluetooth::Authorization; + case BT_SECURITY_MEDIUM: + return QBluetooth::Encryption; + case BT_SECURITY_HIGH: + return QBluetooth::Secure; + default: + qCWarning(QT_BT_BLUEZ) << "Unknown server socket security level" << security.level; + return QBluetooth::NoSecurity; + } +} + void QBluetoothServer::close() { Q_D(QBluetoothServer); @@ -178,6 +229,8 @@ bool QBluetoothServer::listen(const QBluetoothAddress &address, quint16 port) } } + d->setSocketSecurityLevel(d->securityFlags, 0); + if (::listen(sock, d->maxPendingConnections) < 0) { d->m_lastError = InputOutputError; emit error(d->m_lastError); @@ -269,95 +322,31 @@ void QBluetoothServer::setSecurityFlags(QBluetooth::SecurityFlags security) { Q_D(QBluetoothServer); - int lm = 0; - if (security == QBluetooth::NoSecurity) - lm = 0; - - if (d->serverType == QBluetoothServiceInfo::RfcommProtocol) { - if (security.testFlag(QBluetooth::Authorization)) - lm |= RFCOMM_LM_AUTH; - if (security.testFlag(QBluetooth::Authentication)) - lm |= RFCOMM_LM_TRUSTED; - if (security.testFlag(QBluetooth::Encryption)) - lm |= RFCOMM_LM_ENCRYPT; - if (security.testFlag(QBluetooth::Secure)) - lm |= RFCOMM_LM_SECURE; - - qCDebug(QT_BT_BLUEZ) << hex << "Setting lm to" << lm << security; - - if (setsockopt(d->socket->socketDescriptor(), SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm)) < 0){ - qCWarning(QT_BT_BLUEZ) << "Failed to set socket option, closing socket for safety" << errno; - qCWarning(QT_BT_BLUEZ) << "Error: " << qt_error_string(errno); - d->m_lastError = InputOutputError; - emit error(d->m_lastError); - d->socket->close(); - } - } else { - if (security.testFlag(QBluetooth::Authorization)) - lm |= L2CAP_LM_AUTH; - if (security.testFlag(QBluetooth::Authentication)) - lm |= L2CAP_LM_TRUSTED; - if (security.testFlag(QBluetooth::Encryption)) - lm |= L2CAP_LM_ENCRYPT; - if (security.testFlag(QBluetooth::Secure)) - lm |= L2CAP_LM_SECURE; - - if (setsockopt(d->socket->socketDescriptor(), SOL_L2CAP, L2CAP_LM, &lm, sizeof(lm)) < 0){ - qCWarning(QT_BT_BLUEZ) << "Failed to set socket option, closing socket for safety" << errno; - qCWarning(QT_BT_BLUEZ) << "Error: " << qt_error_string(errno); - d->m_lastError = InputOutputError; - emit error(d->m_lastError); - d->socket->close(); - } + if (d->socket->state() == QBluetoothSocket::UnconnectedState) { + // nothing to set beyond the fact to remember the sec level for the next listen() + d->securityFlags = security; + return; } + int errorCode = 0; + d->setSocketSecurityLevel(security, &errorCode); + if (errorCode) { + qCWarning(QT_BT_BLUEZ) << "Failed to set socket option, closing socket for safety" << errorCode; + qCWarning(QT_BT_BLUEZ) << "Error: " << qt_error_string(errorCode); + d->m_lastError = InputOutputError; + emit error(d->m_lastError); + d->socket->close(); + } } QBluetooth::SecurityFlags QBluetoothServer::securityFlags() const { Q_D(const QBluetoothServer); - int lm = 0; - int len = sizeof(lm); - int security = QBluetooth::NoSecurity; - - if (d->serverType == QBluetoothServiceInfo::RfcommProtocol) { - if (getsockopt(d->socket->socketDescriptor(), SOL_RFCOMM, RFCOMM_LM, &lm, (socklen_t *)&len) < 0) { - qCWarning(QT_BT_BLUEZ) << "Failed to get security flags" << qt_error_string(errno); - return QBluetooth::NoSecurity; - } - - if (lm & RFCOMM_LM_SECURE) - security |= QBluetooth::Secure; - - if (lm & RFCOMM_LM_ENCRYPT) - security |= QBluetooth::Encryption; - - if (lm & RFCOMM_LM_TRUSTED) - security |= QBluetooth::Authentication; - - if (lm & RFCOMM_LM_AUTH) - security |= QBluetooth::Authorization; - } else { - if (getsockopt(d->socket->socketDescriptor(), SOL_L2CAP, L2CAP_LM, &lm, (socklen_t *)&len) < 0) { - qCWarning(QT_BT_BLUEZ) << "Failed to get security flags" << qt_error_string(errno); - return QBluetooth::NoSecurity; - } - - if (lm & L2CAP_LM_SECURE) - security |= QBluetooth::Secure; - - if (lm & L2CAP_LM_ENCRYPT) - security |= QBluetooth::Encryption; - - if (lm & L2CAP_LM_TRUSTED) - security |= QBluetooth::Authentication; - - if (lm & L2CAP_LM_AUTH) - security |= QBluetooth::Authorization; - } + if (d->socket->state() == QBluetoothSocket::UnconnectedState) + return d->securityFlags; - return static_cast<QBluetooth::Security>(security); + return d->socketSecurityLevel(); } QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothserver_p.h b/src/bluetooth/qbluetoothserver_p.h index 090d8860..2516c3d3 100644 --- a/src/bluetooth/qbluetoothserver_p.h +++ b/src/bluetooth/qbluetoothserver_p.h @@ -51,10 +51,6 @@ #include "qbluetoothserver.h" #include "qbluetooth.h" -#ifdef QT_QNX_BLUETOOTH -#include "qnx/ppshelpers_p.h" -#endif - #ifdef QT_BLUEZ_BLUETOOTH QT_FORWARD_DECLARE_CLASS(QSocketNotifier) #endif @@ -77,13 +73,7 @@ class QBluetoothServer; #ifndef QT_OSX_BLUETOOTH class QBluetoothServerPrivate -#ifdef QT_QNX_BLUETOOTH -: public QObject -{ - Q_OBJECT -#else { -#endif Q_DECLARE_PUBLIC(QBluetoothServer) public: @@ -92,6 +82,8 @@ public: #ifdef QT_BLUEZ_BLUETOOTH void _q_newConnection(); + void setSocketSecurityLevel(QBluetooth::SecurityFlags requestedSecLevel, int *errnoCode); + QBluetooth::SecurityFlags socketSecurityLevel() const; #endif public: @@ -101,31 +93,12 @@ public: QBluetooth::SecurityFlags securityFlags; QBluetoothServiceInfo::Protocol serverType; -#ifdef QT_QNX_BLUETOOTH -#ifdef QT_QNX_BT_BLUETOOTH - static void btCallback(long param, int socket); - Q_INVOKABLE void setBtCallbackParameters(int receivedSocket); -#endif - QList<QBluetoothSocket *> activeSockets; - QString m_serviceName; -#endif - protected: QBluetoothServer *q_ptr; private: QBluetoothServer::Error m_lastError; -#ifdef QT_QNX_BLUETOOTH - QBluetoothUuid m_uuid; - bool serverRegistered; - QString nextClientAddress; - -private slots: -#ifndef QT_QNX_BT_BLUETOOTH - void controlReply(ppsResult result); - void controlEvent(ppsResult result); -#endif -#elif defined(QT_BLUEZ_BLUETOOTH) +#if defined(QT_BLUEZ_BLUETOOTH) QSocketNotifier *socketNotifier; #elif defined(QT_ANDROID_BLUETOOTH) ServerAcceptanceThread *thread; diff --git a/src/bluetooth/qbluetoothserver_qnx.cpp b/src/bluetooth/qbluetoothserver_qnx.cpp deleted file mode 100644 index d23ea55a..00000000 --- a/src/bluetooth/qbluetoothserver_qnx.cpp +++ /dev/null @@ -1,304 +0,0 @@ -/*************************************************************************** -** -** Copyright (C) 2012 - 2013 BlackBerry Limited. All rights reserved. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtBluetooth module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qbluetoothserver.h" -#include "qbluetoothserver_p.h" -#include "qbluetoothsocket.h" -#include "qbluetoothsocket_p.h" -#include "qbluetoothlocaldevice.h" - -#include <QSocketNotifier> - -#include <QCoreApplication> -#ifdef QT_QNX_BT_BLUETOOTH -#include <btapi/btspp.h> -#endif -QT_BEGIN_NAMESPACE - -extern QHash<QBluetoothServerPrivate*, int> __fakeServerPorts; - -QBluetoothServerPrivate::QBluetoothServerPrivate(QBluetoothServiceInfo::Protocol sType) - : socket(0),maxPendingConnections(1), securityFlags(QBluetooth::NoSecurity), serverType(sType), - m_lastError(QBluetoothServer::NoError) -{ - ppsRegisterControl(); -} - -QBluetoothServerPrivate::~QBluetoothServerPrivate() -{ - Q_Q(QBluetoothServer); - q->close(); - __fakeServerPorts.remove(this); - ppsUnregisterControl(this); - qDeleteAll(activeSockets); - activeSockets.clear(); -} - -#ifdef QT_QNX_BT_BLUETOOTH -void QBluetoothServerPrivate::btCallback(long param, int socket) -{ - QBluetoothServerPrivate *impl = reinterpret_cast<QBluetoothServerPrivate*>(param); - QMetaObject::invokeMethod(impl, "setBtCallbackParameters", - Qt::BlockingQueuedConnection, - Q_ARG(int, socket)); -} - -void QBluetoothServerPrivate::setBtCallbackParameters(int receivedSocket) -{ - Q_Q(QBluetoothServer); - if (receivedSocket == -1) { - qCDebug(QT_BT_QNX) << "Socket error: " << qt_error_string(errno); - m_lastError = QBluetoothServer::InputOutputError; - emit q->error(m_lastError); - return; - } - socket->setSocketDescriptor(receivedSocket, QBluetoothServiceInfo::RfcommProtocol, - QBluetoothSocket::ConnectedState, - QBluetoothSocket::ReadWrite); - char addr[18]; - if (bt_spp_get_address(receivedSocket, addr) == -1) { - qCDebug(QT_BT_QNX) << "Could not obtain the remote address. " - << qt_error_string(errno); - m_lastError = QBluetoothServer::InputOutputError; - emit q->error(m_lastError); - return; - } - socket->d_ptr->m_peerAddress = QBluetoothAddress(addr); - activeSockets.append(socket); - socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol, this); - socket->setSocketState(QBluetoothSocket::ListeningState); - emit q->newConnection(); -} -#else -void QBluetoothServerPrivate::controlReply(ppsResult result) -{ - Q_Q(QBluetoothServer); - - if (result.msg == QStringLiteral("register_server")) { - qCDebug(QT_BT_QNX) << "SPP: Server registration succesfull"; - - } else if (result.msg == QStringLiteral("get_mount_point_path")) { - qCDebug(QT_BT_QNX) << "SPP: Mount point for server" << result.dat.first(); - - int socketFD = ::open(result.dat.first().toStdString().c_str(), O_RDWR | O_NONBLOCK); - if (socketFD == -1) { - m_lastError = QBluetoothServer::InputOutputError; - emit q->error(m_lastError); - qCWarning(QT_BT_QNX) << Q_FUNC_INFO << "RFCOMM Server: Could not open socket FD" << errno; - } else { - if (!socket) { // Should never happen - qCWarning(QT_BT_QNX) << "Socket not valid"; - m_lastError = QBluetoothServer::UnknownError; - emit q->error(m_lastError); - return; - } - - socket->setSocketDescriptor(socketFD, QBluetoothServiceInfo::RfcommProtocol, - QBluetoothSocket::ConnectedState); - socket->d_ptr->m_peerAddress = QBluetoothAddress(nextClientAddress); - socket->d_ptr->m_uuid = m_uuid; - activeSockets.append(socket); - socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol, this); - socket->setSocketState(QBluetoothSocket::ListeningState); - emit q->newConnection(); - } - } -} - -void QBluetoothServerPrivate::controlEvent(ppsResult result) -{ - Q_Q(QBluetoothServer); - if (result.msg == QStringLiteral("service_connected")) { - qCDebug(QT_BT_QNX) << "SPP: Server: Sending request for mount point path"; - qCDebug(QT_BT_QNX) << result.dat; - for (int i=0; i<result.dat.size(); i++) { - qCDebug(QT_BT_QNX) << result.dat.at(i); - } - - if (result.dat.contains(QStringLiteral("addr")) && result.dat.contains(QStringLiteral("uuid")) - && result.dat.contains(QStringLiteral("subtype"))) { - nextClientAddress = result.dat.at(result.dat.indexOf(QStringLiteral("addr")) + 1); - m_uuid = QBluetoothUuid(result.dat.at(result.dat.indexOf(QStringLiteral("uuid")) + 1)); - int subtype = result.dat.at(result.dat.indexOf(QStringLiteral("subtype")) + 1).toInt(); - qCDebug(QT_BT_QNX) << "Getting mount point path" << m_uuid << nextClientAddress<< subtype; - ppsSendControlMessage("get_mount_point_path", 0x1101, m_uuid, nextClientAddress, - m_serviceName, this, BT_SPP_SERVER_SUBTYPE); - } else { - m_lastError = QBluetoothServer::InputOutputError; - emit q->error(m_lastError); - qCWarning(QT_BT_QNX) << Q_FUNC_INFO << "address not specified in service connect reply"; - } - } -} -#endif - -void QBluetoothServer::close() -{ - Q_D(QBluetoothServer); - if (!d->activeSockets.isEmpty()) { - for (int i = 0; i < d->activeSockets.size(); i++) - d->activeSockets.at(i)->close(); - qDeleteAll(d->activeSockets); - d->activeSockets.clear(); - } - if (d->socket) { - d->socket->close(); - if (__fakeServerPorts.contains(d)) { -#ifdef QT_QNX_BT_BLUETOOTH - QByteArray b_uuid = d->m_uuid.toByteArray(); - b_uuid = b_uuid.mid(1, b_uuid.length()-2); - bt_spp_close_server(b_uuid.data()); -#else - ppsSendControlMessage("deregister_server", 0x1101, d->m_uuid, - QString(), QString(), 0); -#endif - __fakeServerPorts.remove(d); - } - delete d->socket; - d->socket = 0; - } -} - -bool QBluetoothServer::listen(const QBluetoothAddress &address, quint16 port) -{ - Q_UNUSED(address) - Q_D(QBluetoothServer); - if (serverType() != QBluetoothServiceInfo::RfcommProtocol) { - d->m_lastError = UnsupportedProtocolError; - emit error(d->m_lastError); - return false; - } - - QBluetoothLocalDevice device(address); - if (!device.isValid()) { - qCWarning(QT_BT_QNX) << "Device does not support Bluetooth or" - << address.toString() << "is not a valid local adapter"; - d->m_lastError = QBluetoothServer::UnknownError; - emit error(d->m_lastError); - return false; - } - - QBluetoothLocalDevice::HostMode hostMode= device.hostMode(); - if (hostMode == QBluetoothLocalDevice::HostPoweredOff) { - d->m_lastError = QBluetoothServer::PoweredOffError; - emit error(d->m_lastError); - qCWarning(QT_BT_QNX) << "Bluetooth device is powered off"; - return false; - } - - // listen has already been called before - if (!d->socket) - d->socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol); - else if (d->socket->state() == QBluetoothSocket::ListeningState) - return false; - - //We can not register an actual Rfcomm port, because the platform does not allow it - //but we need a way to associate a server with a service - - if (port == 0) { //Try to assign a non taken port id - for (int i=1; ; i++){ - if (__fakeServerPorts.key(i) == 0) { - port = i; - break; - } - } - } - - if (__fakeServerPorts.key(port) == 0) { - __fakeServerPorts[d] = port; - qCDebug(QT_BT_QNX) << "Port" << port << "registered"; - } else { - qCWarning(QT_BT_QNX) << "server with port" << port << "already registered or port invalid"; - d->m_lastError = ServiceAlreadyRegisteredError; - emit error(d->m_lastError); - return false; - } - -#ifndef QT_QNX_BT_BLUETOOTH - ppsRegisterForEvent(QStringLiteral("service_connected"),d); -#endif - d->socket->setSocketState(QBluetoothSocket::ListeningState); - return true; -} - -void QBluetoothServer::setMaxPendingConnections(int numConnections) -{ - Q_D(QBluetoothServer); - //QNX supports only one device at the time -} - -QBluetoothAddress QBluetoothServer::serverAddress() const -{ - Q_D(const QBluetoothServer); - if (d->socket) - return d->socket->localAddress(); - else - return QBluetoothAddress(); -} - -quint16 QBluetoothServer::serverPort() const -{ - //Currently we do not have access to the port - Q_D(const QBluetoothServer); - return __fakeServerPorts.value((QBluetoothServerPrivate*)d); -} - -bool QBluetoothServer::hasPendingConnections() const -{ - Q_D(const QBluetoothServer); - return !d->activeSockets.isEmpty(); -} - -QBluetoothSocket *QBluetoothServer::nextPendingConnection() -{ - Q_D(QBluetoothServer); - if (d->activeSockets.isEmpty()) - return 0; - - return d->activeSockets.takeFirst(); -} - -void QBluetoothServer::setSecurityFlags(QBluetooth::SecurityFlags security) -{ - Q_D(QBluetoothServer); - d->securityFlags = security; //not used -} - -QBluetooth::SecurityFlags QBluetoothServer::securityFlags() const -{ - Q_D(const QBluetoothServer); - return d->securityFlags; //not used -} - -QT_END_NAMESPACE - diff --git a/src/bluetooth/qbluetoothservicediscoveryagent.cpp b/src/bluetooth/qbluetoothservicediscoveryagent.cpp index a285a557..9f2b87cc 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent.cpp +++ b/src/bluetooth/qbluetoothservicediscoveryagent.cpp @@ -257,8 +257,9 @@ QList<QBluetoothUuid> QBluetoothServiceDiscoveryAgent::uuidFilter() const address can only be set while there is no service discovery in progress; otherwise this function returns false. - On some platforms such as Blackberry the service discovery might lead to pairing requests. + On some platforms the service discovery might lead to pairing requests. Therefore it is not recommended to do service discoveries on all devices. + This function can be used to restrict the service discovery to a particular device. \sa remoteAddress() */ @@ -289,7 +290,7 @@ QBluetoothAddress QBluetoothServiceDiscoveryAgent::remoteAddress() const /*! Starts service discovery. \a mode specifies the type of service discovery to perform. - On BlackBerry devices, device discovery may lead to pairing requests. + On some platforms, device discovery may lead to pairing requests. \sa DiscoveryMode */ diff --git a/src/bluetooth/qbluetoothservicediscoveryagent.h b/src/bluetooth/qbluetoothservicediscoveryagent.h index d15a1d8d..984a4084 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent.h +++ b/src/bluetooth/qbluetoothservicediscoveryagent.h @@ -66,11 +66,13 @@ public: //New Errors must be added after Unknown Error the space before UnknownError is reserved //for future device discovery errors }; + Q_ENUM(Error) enum DiscoveryMode { MinimalDiscovery, FullDiscovery }; + Q_ENUM(DiscoveryMode) QBluetoothServiceDiscoveryAgent(QObject *parent = 0); explicit QBluetoothServiceDiscoveryAgent(const QBluetoothAddress &deviceAdapter, QObject *parent = 0); @@ -112,6 +114,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_foundDevice(QDBusPendingCallWatcher*)) Q_PRIVATE_SLOT(d_func(), void _q_sdpScannerDone(int,QProcess::ExitStatus)) #endif #ifdef QT_ANDROID_BLUETOOTH @@ -124,6 +127,4 @@ private: QT_END_NAMESPACE -Q_DECLARE_METATYPE(QBluetoothServiceDiscoveryAgent::Error) - #endif diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp index f66603a9..ae51d681 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp +++ b/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp @@ -127,13 +127,12 @@ void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &addr } } - QDBusPendingReply<QDBusObjectPath> deviceObjectPath = adapter->CreateDevice(address.toString()); + QDBusPendingReply<QDBusObjectPath> deviceObjectPath = adapter->FindDevice(address.toString()); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(deviceObjectPath, q); watcher->setProperty("_q_BTaddress", QVariant::fromValue(address)); QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), - q, SLOT(_q_createdDevice(QDBusPendingCallWatcher*))); - + q, SLOT(_q_foundDevice(QDBusPendingCallWatcher*))); } // Bluez 5 @@ -352,30 +351,65 @@ void QBluetoothServiceDiscoveryAgentPrivate::stop() emit q->canceled(); } -void QBluetoothServiceDiscoveryAgentPrivate::_q_createdDevice(QDBusPendingCallWatcher *watcher) +void QBluetoothServiceDiscoveryAgentPrivate::_q_foundDevice(QDBusPendingCallWatcher *watcher) { - if (!adapter) + if (!adapter) { + watcher->deleteLater(); return; + } Q_Q(QBluetoothServiceDiscoveryAgent); const QBluetoothAddress &address = watcher->property("_q_BTaddress").value<QBluetoothAddress>(); - qCDebug(QT_BT_BLUEZ) << Q_FUNC_INFO << "created" << address.toString(); + qCDebug(QT_BT_BLUEZ) << Q_FUNC_INFO << "found" << address.toString(); QDBusPendingReply<QDBusObjectPath> deviceObjectPath = *watcher; + watcher->deleteLater(); if (deviceObjectPath.isError()) { - if (deviceObjectPath.error().name() != QStringLiteral("org.bluez.Error.AlreadyExists")) { + if (deviceObjectPath.error().name() != QStringLiteral("org.bluez.Error.DoesNotExist")) { + qCDebug(QT_BT_BLUEZ) << "Find device failed Error: " << error << deviceObjectPath.error().name(); delete adapter; adapter = 0; + if (singleDevice) { + error = QBluetoothServiceDiscoveryAgent::InputOutputError; + errorString = QBluetoothServiceDiscoveryAgent::tr("Unable to access device"); + emit q->error(error); + } _q_serviceDiscoveryFinished(); - qCDebug(QT_BT_BLUEZ) << "Create device failed Error: " << error << deviceObjectPath.error().name(); return; } - deviceObjectPath = adapter->FindDevice(address.toString()); - deviceObjectPath.waitForFinished(); - if (deviceObjectPath.isError()) { + deviceObjectPath = adapter->CreateDevice(address.toString()); + watcher = new QDBusPendingCallWatcher(deviceObjectPath, q); + watcher->setProperty("_q_BTaddress", QVariant::fromValue(address)); + QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + q, SLOT(_q_createdDevice(QDBusPendingCallWatcher*))); + return; + } + + qCDebug(QT_BT_BLUEZ) << Q_FUNC_INFO << "path" << deviceObjectPath.value().path(); + discoverServices(deviceObjectPath.value().path()); +} + +void QBluetoothServiceDiscoveryAgentPrivate::_q_createdDevice(QDBusPendingCallWatcher *watcher) +{ + Q_Q(QBluetoothServiceDiscoveryAgent); + + if (!adapter) { + watcher->deleteLater(); + return; + } + + const QBluetoothAddress &address = watcher->property("_q_BTaddress").value<QBluetoothAddress>(); + + qCDebug(QT_BT_BLUEZ) << Q_FUNC_INFO << "created" << address.toString(); + + QDBusPendingReply<QDBusObjectPath> deviceObjectPath = *watcher; + watcher->deleteLater(); + if (deviceObjectPath.isError()) { + if (deviceObjectPath.error().name() != QLatin1String("org.bluez.Error.AlreadyExists")) { + qCDebug(QT_BT_BLUEZ) << "Create device failed Error: " << error << deviceObjectPath.error().name(); delete adapter; adapter = 0; if (singleDevice) { @@ -384,13 +418,20 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_createdDevice(QDBusPendingCallWa emit q->error(error); } _q_serviceDiscoveryFinished(); - qCDebug(QT_BT_BLUEZ) << "Can't find device after creation Error: " << error << deviceObjectPath.error().name(); return; } } + qCDebug(QT_BT_BLUEZ) << Q_FUNC_INFO << "path" << deviceObjectPath.value().path(); + discoverServices(deviceObjectPath.value().path()); +} + +void QBluetoothServiceDiscoveryAgentPrivate::discoverServices(const QString deviceObjectPath) +{ + Q_Q(QBluetoothServiceDiscoveryAgent); + device = new OrgBluezDeviceInterface(QStringLiteral("org.bluez"), - deviceObjectPath.value().path(), + deviceObjectPath, QDBusConnection::systemBus()); delete adapter; adapter = 0; @@ -479,7 +520,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_createdDevice(QDBusPendingCallWa qCDebug(QT_BT_BLUEZ) << Q_FUNC_INFO << "Discover restrictions:" << pattern; QDBusPendingReply<ServiceMap> discoverReply = device->DiscoverServices(pattern); - watcher = new QDBusPendingCallWatcher(discoverReply, q); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(discoverReply, q); QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), q, SLOT(_q_discoveredServices(QDBusPendingCallWatcher*))); } @@ -488,8 +529,10 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_createdDevice(QDBusPendingCallWa // Bluez 4 void QBluetoothServiceDiscoveryAgentPrivate::_q_discoveredServices(QDBusPendingCallWatcher *watcher) { - if (!device) + if (!device) { + watcher->deleteLater(); return; + } qCDebug(QT_BT_BLUEZ) << Q_FUNC_INFO; Q_Q(QBluetoothServiceDiscoveryAgent); @@ -609,14 +652,18 @@ void QBluetoothServiceDiscoveryAgentPrivate::performMinimalServiceDiscovery(cons } QStringList uuidStrings; - foreach (const QDBusObjectPath &path, reply.value().keys()) { - const InterfaceList ifaceList = reply.value().value(path); - foreach (const QString &iface, ifaceList.keys()) { + + ManagedObjectList managedObjectList = reply.value(); + for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) { + const InterfaceList &ifaceList = it.value(); + + for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) { + const QString &iface = jt.key(); + const QVariantMap &ifaceValues = jt.value(); + if (iface == QStringLiteral("org.bluez.Device1")) { - const QVariantMap details = ifaceList.value(iface); - if (deviceAddress.toString() - == details.value(QStringLiteral("Address")).toString()) { - uuidStrings = details.value(QStringLiteral("UUIDs")).toStringList(); + if (deviceAddress.toString() == ifaceValues.value(QStringLiteral("Address")).toString()) { + uuidStrings = ifaceValues.value(QStringLiteral("UUIDs")).toStringList(); break; } } diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_osx.mm b/src/bluetooth/qbluetoothservicediscoveryagent_osx.mm index 64723dd1..0cf77d9d 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent_osx.mm +++ b/src/bluetooth/qbluetoothservicediscoveryagent_osx.mm @@ -495,9 +495,6 @@ QList<QBluetoothUuid> QBluetoothServiceDiscoveryAgent::uuidFilter() const address can only be set while there is no service discovery in progress; otherwise this function returns false. - On some platforms such as Blackberry the service discovery might lead to pairing requests. - Therefore it is not recommended to do service discoveries on all devices. - \sa remoteAddress() */ bool QBluetoothServiceDiscoveryAgent::setRemoteAddress(const QBluetoothAddress &address) diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_p.h b/src/bluetooth/qbluetoothservicediscoveryagent_p.h index 9f2c501a..c4d5017a 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent_p.h +++ b/src/bluetooth/qbluetoothservicediscoveryagent_p.h @@ -66,14 +66,6 @@ class QXmlStreamReader; QT_END_NAMESPACE #endif -#ifdef QT_QNX_BLUETOOTH -#include "qnx/ppshelpers_p.h" -#include <fcntl.h> -#include <unistd.h> -#include <QTimer> -#include <btapi/btdevice.h> -#endif - QT_BEGIN_NAMESPACE class QBluetoothDeviceDiscoveryAgent; @@ -85,13 +77,7 @@ class LocalDeviceBroadcastReceiver; #endif class QBluetoothServiceDiscoveryAgentPrivate -#ifdef QT_QNX_BLUETOOTH -: public QObject -{ - Q_OBJECT -#else { -#endif Q_DECLARE_PUBLIC(QBluetoothServiceDiscoveryAgent) public: @@ -122,6 +108,7 @@ public: #ifdef QT_BLUEZ_BLUETOOTH void _q_discoveredServices(QDBusPendingCallWatcher *watcher); void _q_createdDevice(QDBusPendingCallWatcher *watcher); + void _q_foundDevice(QDBusPendingCallWatcher *watcher); //Slots below are used for discovering Bluetooth Low Energy devices. It will be used with Bluez 5.x version. /* void _g_discoveredGattService(); @@ -155,24 +142,7 @@ private: QVariant readAttributeValue(QXmlStreamReader &xml); QBluetoothServiceInfo parseServiceXml(const QString& xml); void performMinimalServiceDiscovery(const QBluetoothAddress &deviceAddress); -#endif - -#ifdef QT_QNX_BLUETOOTH -private slots: - void remoteDevicesChanged(int fd); - void controlReply(ppsResult result); - void controlEvent(ppsResult result); - void queryTimeout(); -#ifdef QT_QNX_BT_BLUETOOTH - static void deviceServicesDiscoveryCallback(bt_sdp_list_t *, void *, uint8_t); -#endif - -private: - int m_rdfd; - QSocketNotifier *rdNotifier; - QTimer m_queryTimer; - bool m_btInitialized; - bool m_serviceScanDone; + void discoverServices(const QString deviceObjectPath); #endif public: diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_qnx.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_qnx.cpp deleted file mode 100644 index 32d6d2c2..00000000 --- a/src/bluetooth/qbluetoothservicediscoveryagent_qnx.cpp +++ /dev/null @@ -1,433 +0,0 @@ -/*************************************************************************** -** -** Copyright (C) 2012 Research In Motion -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtBluetooth module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qbluetoothservicediscoveryagent.h" -#include "qbluetoothservicediscoveryagent_p.h" - -#include "qbluetoothdeviceinfo.h" -#include "qbluetoothdevicediscoveryagent.h" - -#include <QStringList> -#include "qbluetoothuuid.h" -#include <stdio.h> -#include <unistd.h> -#include <sys/pps.h> -#ifdef QT_QNX_BT_BLUETOOTH -#include <errno.h> -#include <QPointer> -#endif -#include <QFile> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -#include <QtCore/private/qcore_unix_p.h> - -QT_BEGIN_NAMESPACE - -#ifdef QT_QNX_BT_BLUETOOTH -void QBluetoothServiceDiscoveryAgentPrivate::deviceServicesDiscoveryCallback(bt_sdp_list_t *result, void *user_data, uint8_t error) -{ - if (error != 0) - qCWarning(QT_BT_QNX) << "Error received in callback: " << errno << strerror(errno); - QPointer<QBluetoothServiceDiscoveryAgentPrivate> *classPointer = static_cast<QPointer<QBluetoothServiceDiscoveryAgentPrivate> *>(user_data); - if (classPointer->isNull()) { - qCDebug(QT_BT_QNX) << "Pointer received in callback is null"; - return; - } - QBluetoothServiceDiscoveryAgentPrivate *p = classPointer->data(); - if ( result == 0) { - qCDebug(QT_BT_QNX) << "Result received in callback is null."; - p->errorString = QBluetoothServiceDiscoveryAgent::tr("Result received in callback is null"); - p->error = QBluetoothServiceDiscoveryAgent::InputOutputError; - p->q_ptr->error(p->error); - p->_q_serviceDiscoveryFinished(); - return; - } - - for (int i = 0; i < result->num_records; i++) { - bt_sdp_record_t rec = result->record[i]; - QBluetoothServiceInfo serviceInfo; - serviceInfo.setDevice(p->discoveredDevices.at(0)); - serviceInfo.setServiceName(rec.name); - serviceInfo.setServiceDescription(rec.description); - //serviceInfo.setServiceAvailability(rec.availability); - serviceInfo.setServiceProvider(QString(rec.provider)); - QBluetoothServiceInfo::Sequence protocolDescriptorList; - for ( int j = 0; j < rec.num_protocol; j++) { - bt_sdp_prot_t protoc = rec.protocol[j]; - QString protocolUuid(protoc.uuid); - protocolUuid = QStringLiteral("0x") + protocolUuid; - QBluetoothUuid pUuid(protocolUuid.toUShort(0,0)); - protocolDescriptorList << QVariant::fromValue(pUuid); - for ( int k = 0; k < 2; k++) - protocolDescriptorList << QVariant::fromValue(QString::fromLatin1(protoc.parm[k])); - } - serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, protocolDescriptorList); - qCDebug(QT_BT_QNX) << "Service name " << rec.name << " Description: " << rec.description << "uuid " << rec.serviceId << "provider: " << rec.provider; - qCDebug(QT_BT_QNX) << "num protocol " << rec.num_protocol << "record handle " << rec.record_handle << "class id" << rec.num_classId << "availability " << rec.availability << rec.num_language; - - QList<QBluetoothUuid> serviceClassId; - - for (int j = 0; j < rec.num_classId; j++) { - bt_sdp_class_t uuid = rec.classId[j]; - qCDebug(QT_BT_QNX) << "uuid: " << uuid.uuid; - QString protocolUuid(uuid.uuid); - protocolUuid = QStringLiteral("0x") + protocolUuid; - QBluetoothUuid Uuid(protocolUuid.toUShort(0,0)); - if (j == 0) { - serviceInfo.setServiceUuid(Uuid); - //Check if the UUID is in the uuidFilter - if (!p->uuidFilter.isEmpty() && !p->uuidFilter.contains(Uuid)) - continue; - } - serviceClassId << Uuid; - } - serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, QVariant::fromValue(serviceClassId)); - serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList, - QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup)); - p->q_ptr->serviceDiscovered(serviceInfo); - } - p->_q_serviceDiscoveryFinished(); - //delete p; - //delete classPointer; -} -#endif - -QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate(const QBluetoothAddress &deviceAdapter) - : m_rdfd(-1), rdNotifier(0), m_btInitialized(false), error(QBluetoothServiceDiscoveryAgent::NoError), deviceAddress(deviceAdapter), state(Inactive), - deviceDiscoveryAgent(0), mode(QBluetoothServiceDiscoveryAgent::MinimalDiscovery) -{ - ppsRegisterControl(); - connect(&m_queryTimer, SIGNAL(timeout()), this, SLOT(queryTimeout())); - ppsRegisterForEvent(QStringLiteral("service_updated"), this); - //Needed for connecting signals and slots from static function - qRegisterMetaType<QBluetoothServiceInfo>(); - qRegisterMetaType<QBluetoothServiceDiscoveryAgent::Error>(); -} - -QBluetoothServiceDiscoveryAgentPrivate::~QBluetoothServiceDiscoveryAgentPrivate() -{ - ppsUnregisterForEvent(QStringLiteral("service_updated"), this); - ppsUnregisterControl(this); -} - -void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &address) -{ - Q_Q(QBluetoothServiceDiscoveryAgent); -#ifdef QT_QNX_BT_BLUETOOTH - errno = 0; - if (!m_btInitialized) { - if (bt_device_init( 0 ) < 0) { - qCWarning(QT_BT_QNX) << "Failed to initialize Bluetooth stack."; - error = QBluetoothServiceDiscoveryAgent::InputOutputError; - errorString = QBluetoothServiceDiscoveryAgent::tr("Failed to initialize Bluetooth stack"); - q->error(error); - _q_serviceDiscoveryFinished(); - return; - } - } - m_btInitialized = true; - errno = 0; - bt_remote_device_t *remoteDevice = bt_rdev_get_device(address.toString().toLocal8Bit().constData()); - int deviceType = bt_rdev_get_type(remoteDevice); - if (deviceType == -1) { - qCWarning(QT_BT_QNX) << "Could not retrieve remote device address (address is 00:00:00:00:00:00)."; - error = QBluetoothServiceDiscoveryAgent::InputOutputError; - errorString = QBluetoothServiceDiscoveryAgent::tr("Could not retrieve remote device address"); - q->error(error); - _q_serviceDiscoveryFinished(); - return; - } - /* - * In case remote device is LE device, calling bt_rdev_sdp_search_async will cause memory fault. - */ - - if ( deviceType >1) { - errno = 0; - QPointer<QBluetoothServiceDiscoveryAgentPrivate> *classPointer = new QPointer<QBluetoothServiceDiscoveryAgentPrivate>(this); - int b = bt_rdev_sdp_search_async(remoteDevice, 0, &(this->deviceServicesDiscoveryCallback), classPointer); - if ( b != 0 ) { - qCWarning(QT_BT_QNX) << "Failed to run search on device: " << address.toString(); - error = QBluetoothServiceDiscoveryAgent::InputOutputError; - errorString = QBluetoothServiceDiscoveryAgent::tr(strerror(errno)); - q->error(error); - _q_serviceDiscoveryFinished(); - return; - } - } - else - _q_serviceDiscoveryFinished(); -#else - qCDebug(QT_BT_QNX) << "Starting Service discovery for" << address.toString(); - const QString filePath = QStringLiteral("/pps/services/bluetooth/remote_devices/").append(address.toString()); - bool hasError = false; - if ((m_rdfd = qt_safe_open(filePath.toLocal8Bit().constData(), O_RDONLY)) == -1) { - if (QFile::exists(filePath + QStringLiteral("-00")) || - QFile::exists(filePath + QStringLiteral("-01"))) - { - qCDebug(QT_BT_QNX) << "LE device discovered...skipping"; - QString lePath = filePath + QStringLiteral("-00"); - if ((m_rdfd = qt_safe_open(lePath.toLocal8Bit().constData(), O_RDONLY)) == -1) { - lePath = filePath + QStringLiteral("-01"); - if ((m_rdfd = qt_safe_open(lePath.toLocal8Bit().constData(), O_RDONLY)) == -1) - hasError = true; - } - } else { - hasError = true; - } - } - if (hasError) { - qCWarning(QT_BT_QNX) << "Failed to open " << filePath; - error = QBluetoothServiceDiscoveryAgent::InputOutputError; - errorString = QBluetoothServiceDiscoveryAgent::tr("Failed to open remote device file"); - q->error(error); - _q_serviceDiscoveryFinished(); - return; - } - - if (rdNotifier) - delete rdNotifier; - rdNotifier = new QSocketNotifier(m_rdfd, QSocketNotifier::Read, this); - if (rdNotifier) { - connect(rdNotifier, SIGNAL(activated(int)), this, SLOT(remoteDevicesChanged(int))); - } else { - qWarning() << "Service Discovery: Failed to connect to rdNotifier"; - error = QBluetoothServiceDiscoveryAgent::InputOutputError; - errorString = QStringLiteral("Failed to connect to rdNotifier"); - q->error(error); - _q_serviceDiscoveryFinished(); - return; - } - - m_queryTimer.start(10000); - ppsSendControlMessage("service_query", QStringLiteral("{\"addr\":\"%1\"}").arg(address.toString()), this); -#endif -} - -void QBluetoothServiceDiscoveryAgentPrivate::stop() -{ - m_queryTimer.stop(); - discoveredDevices.clear(); - setDiscoveryState(Inactive); - Q_Q(QBluetoothServiceDiscoveryAgent); - emit q->canceled(); - if (rdNotifier) - delete rdNotifier; - rdNotifier = 0; - if (m_rdfd != -1) { - qt_safe_close (m_rdfd); - m_rdfd = -1; - } -} - -void QBluetoothServiceDiscoveryAgentPrivate::remoteDevicesChanged(int fd) -{ - if (discoveredDevices.count() == 0) - return; - pps_decoder_t ppsDecoder; - pps_decoder_initialize(&ppsDecoder, 0); - - QBluetoothAddress deviceAddr; - QString deviceName; - - if (!ppsReadRemoteDevice(fd, &ppsDecoder, &deviceAddr, &deviceName)) { - pps_decoder_cleanup(&ppsDecoder); - return; - } - // Checking for standard Bluetooth services - pps_decoder_push(&ppsDecoder, "available_services"); - bool standardService = false; - const char *next_service = 0; - for (int service_count=0; pps_decoder_get_string(&ppsDecoder, 0, &next_service ) == PPS_DECODER_OK; service_count++) { - if (next_service == 0) - break; - standardService = true; - qCDebug(QT_BT_QNX) << Q_FUNC_INFO << "Service" << next_service; - - QBluetoothServiceInfo serviceInfo; - serviceInfo.setDevice(discoveredDevices.at(0)); - - QBluetoothServiceInfo::Sequence protocolDescriptorList; - QBluetoothServiceInfo::Sequence l2cpProtocol; - l2cpProtocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::L2cap)); - protocolDescriptorList.append(QVariant::fromValue(l2cpProtocol)); - - bool ok; - QBluetoothUuid suuid(QByteArray(next_service).toUInt(&ok,16)); - if (!ok) { - QList<QByteArray> serviceName = QByteArray(next_service).split(':'); - if (serviceName.size() == 2) { - serviceInfo.setServiceUuid(QBluetoothUuid(QLatin1String(serviceName.last()))); - suuid = QBluetoothUuid((quint16)(serviceName.first().toUInt(&ok,16))); - if (suuid == QBluetoothUuid::SerialPort) { - QBluetoothServiceInfo::Sequence protocol; - protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm)) - << QVariant::fromValue(0); - protocolDescriptorList.append(QVariant::fromValue(protocol)); - } - } - } else { - //We do not have anything better, so we set the service class UUID as service UUID - serviceInfo.setServiceUuid(suuid); - } - - //Check if the UUID is in the uuidFilter - if (!uuidFilter.isEmpty() && !uuidFilter.contains(serviceInfo.serviceUuid())) - continue; - - serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, protocolDescriptorList); - - QList<QBluetoothUuid> serviceClassId; - serviceClassId << suuid; - serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, QVariant::fromValue(serviceClassId)); - - serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList, - QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup)); - - //Did we already discover this service? - if (!isDuplicatedService(serviceInfo)) { - qCDebug(QT_BT_QNX) << "Adding service" << next_service << " " << serviceInfo.socketProtocol(); - discoveredServices << serviceInfo; - q_ptr->serviceDiscovered(serviceInfo); - } - } - - if (standardService) // we need to pop back for the LE service scan - pps_decoder_pop(&ppsDecoder); - //Checking for Bluetooth Low Energy services - pps_decoder_push(&ppsDecoder, "gatt_available_services"); - - for (int service_count=0; pps_decoder_get_string(&ppsDecoder, 0, &next_service ) == PPS_DECODER_OK; service_count++) { - if (next_service == 0) - break; - - QString lowEnergyUuid(next_service); - qCDebug(QT_BT_QNX) << "LE Service: " << lowEnergyUuid << next_service; - QBluetoothUuid leUuid; - - //In case of custom UUIDs (e.g. Texas Instruments SenstorTag LE Device) - if ( lowEnergyUuid.length() > 4 ) { - leUuid = QBluetoothUuid(lowEnergyUuid); - } - else {// Official UUIDs are presented in 4 characters (for instance 180A) - lowEnergyUuid = QStringLiteral("0x") + lowEnergyUuid; - leUuid = QBluetoothUuid(lowEnergyUuid.toUShort(0,0)); - } - - //Check if the UUID is in the uuidFilter - if (!uuidFilter.isEmpty() && !uuidFilter.contains(leUuid)) - continue; - - QBluetoothServiceInfo lowEnergyService; - lowEnergyService.setDevice(discoveredDevices.at(0)); - - bool ok = false; - quint16 serviceClass = leUuid.toUInt16(&ok); - if (ok) - lowEnergyService.setServiceName(QBluetoothUuid::serviceClassToString( - static_cast<QBluetoothUuid::ServiceClassUuid>(serviceClass))); - - QBluetoothServiceInfo::Sequence classId; - classId << QVariant::fromValue(leUuid); - lowEnergyService.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId); - - QBluetoothServiceInfo::Sequence protocolDescriptorList; - { - QBluetoothServiceInfo::Sequence protocol; - protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::L2cap)); - protocolDescriptorList.append(QVariant::fromValue(protocol)); - } - { - QBluetoothServiceInfo::Sequence protocol; - protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Att)); - protocolDescriptorList.append(QVariant::fromValue(protocol)); - } - lowEnergyService.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, protocolDescriptorList); - - qCDebug(QT_BT_QNX) << "Adding Low Energy service" << leUuid; - - q_ptr->serviceDiscovered(lowEnergyService); - } - - pps_decoder_cleanup(&ppsDecoder); - //Deleting notifier since services will not change. - delete rdNotifier; - rdNotifier = 0; -} - -void QBluetoothServiceDiscoveryAgentPrivate::controlReply(ppsResult result) -{ - qCDebug(QT_BT_QNX) << "Control reply" << result.msg << result.dat; - if (!m_queryTimer.isActive()) - return; - m_queryTimer.stop(); - Q_Q(QBluetoothServiceDiscoveryAgent); - if (!result.errorMsg.isEmpty()) { - qCWarning(QT_BT_QNX) << Q_FUNC_INFO << result.errorMsg; - errorString = result.errorMsg; - if (errorString == QBluetoothServiceDiscoveryAgent::tr("Operation canceled")) - _q_serviceDiscoveryFinished(); - error = QBluetoothServiceDiscoveryAgent::InputOutputError; - q->error(error); - } else { - _q_serviceDiscoveryFinished(); - } -} - -void QBluetoothServiceDiscoveryAgentPrivate::controlEvent(ppsResult result) -{ - qCDebug(QT_BT_QNX) << "Control event" << result.msg << result.dat; - if (!m_queryTimer.isActive()) - return; - m_queryTimer.stop(); - Q_Q(QBluetoothServiceDiscoveryAgent); - if (!result.errorMsg.isEmpty()) { - qCWarning(QT_BT_QNX) << Q_FUNC_INFO << result.errorMsg; - errorString = result.errorMsg; - error = QBluetoothServiceDiscoveryAgent::InputOutputError; - q->error(error); - } else { - _q_serviceDiscoveryFinished(); - } -} - -void QBluetoothServiceDiscoveryAgentPrivate::queryTimeout() -{ - Q_Q(QBluetoothServiceDiscoveryAgent); - error = QBluetoothServiceDiscoveryAgent::UnknownError; - errorString = QBluetoothServiceDiscoveryAgent::tr("Service query timed out"); - q->error(error); - _q_serviceDiscoveryFinished(); -} -QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothserviceinfo.cpp b/src/bluetooth/qbluetoothserviceinfo.cpp index 445d64b4..fefb2549 100644 --- a/src/bluetooth/qbluetoothserviceinfo.cpp +++ b/src/bluetooth/qbluetoothserviceinfo.cpp @@ -135,7 +135,7 @@ QT_BEGIN_NAMESPACE \value UnknownProtocol The service uses an unknown socket protocol. \value L2capProtocol The service uses the L2CAP socket protocol. This protocol is not supported - for direct socket connections on Android and BlackBerry. + for direct socket connections on Android. \value RfcommProtocol The service uses the RFCOMM socket protocol. */ @@ -375,7 +375,7 @@ bool QBluetoothServiceInfo::isValid() const */ bool QBluetoothServiceInfo::isComplete() const { - return d_ptr->attributes.keys().contains(ProtocolDescriptorList); + return d_ptr->attributes.contains(ProtocolDescriptorList); } /*! diff --git a/src/bluetooth/qbluetoothserviceinfo_osx.mm b/src/bluetooth/qbluetoothserviceinfo_osx.mm index 743fb377..d79156e2 100644 --- a/src/bluetooth/qbluetoothserviceinfo_osx.mm +++ b/src/bluetooth/qbluetoothserviceinfo_osx.mm @@ -309,7 +309,7 @@ bool QBluetoothServiceInfo::isValid() const bool QBluetoothServiceInfo::isComplete() const { - return d_ptr->attributes.keys().contains(ProtocolDescriptorList); + return d_ptr->attributes.contains(ProtocolDescriptorList); } QBluetoothDeviceInfo QBluetoothServiceInfo::device() const diff --git a/src/bluetooth/qbluetoothserviceinfo_qnx.cpp b/src/bluetooth/qbluetoothserviceinfo_qnx.cpp deleted file mode 100644 index 6d5f678e..00000000 --- a/src/bluetooth/qbluetoothserviceinfo_qnx.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/*************************************************************************** -** -** Copyright (C) 2012 Research In Motion -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtBluetooth module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qbluetoothserviceinfo.h" -#include "qbluetoothserviceinfo_p.h" - -#include "qbluetoothserver_p.h" -#include "qbluetoothserver.h" - -#ifdef QT_QNX_BT_BLUETOOTH -#include <btapi/btspp.h> -#include <errno.h> -#endif - -QT_BEGIN_NAMESPACE - -QBluetoothServiceInfoPrivate::QBluetoothServiceInfoPrivate() -: registered(false) -{ -} - -QBluetoothServiceInfoPrivate::~QBluetoothServiceInfoPrivate() -{ -} - -bool QBluetoothServiceInfoPrivate::isRegistered() const -{ - return registered; -} - -extern QHash<QBluetoothServerPrivate*, int> __fakeServerPorts; - -bool QBluetoothServiceInfoPrivate::unregisterService() -{ - if (!registered) - return false; - if (serverChannel() == -1) - return false; - if ( __fakeServerPorts.key(serverChannel()) != 0) { -#ifdef QT_QNX_BT_BLUETOOTH - QByteArray b_uuid = attributes.value(QBluetoothServiceInfo::ServiceId). - value<QBluetoothUuid>().toByteArray(); - b_uuid = b_uuid.mid(1, b_uuid.length() - 2); - if (bt_spp_close_server(b_uuid.data()) == -1) - return false; -#else - if (!ppsSendControlMessage("deregister_server", 0x1101, attributes.value(QBluetoothServiceInfo::ServiceId).value<QBluetoothUuid>(), QString(), - attributes.value(QBluetoothServiceInfo::ServiceName).toString(), - __fakeServerPorts.key(serverChannel()), BT_SPP_SERVER_SUBTYPE)) { - return false; - } -#endif - else { - __fakeServerPorts.remove(__fakeServerPorts.key(serverChannel())); - registered = false; - return true; - } - } - else { - return false; - } -} - -bool QBluetoothServiceInfoPrivate::registerService(const QBluetoothAddress& localAdapter) -{ - Q_UNUSED(localAdapter); //QNX always uses default local adapter - if (protocolDescriptor(QBluetoothUuid::Rfcomm).isEmpty()) { - qCWarning(QT_BT_QNX) << Q_FUNC_INFO << "Only SPP services can be registered on QNX"; - return false; - } - - if (serverChannel() == -1) - return false; - - if (__fakeServerPorts.key(serverChannel()) != 0) { -#ifdef QT_QNX_BT_BLUETOOTH - QByteArray b_uuid = attributes.value(QBluetoothServiceInfo::ServiceId) - .value<QBluetoothUuid>().toByteArray(); - b_uuid = b_uuid.mid(1, b_uuid.length() - 2); - qCDebug(QT_BT_QNX) << "Registering server. " << b_uuid.data() - << attributes.value(QBluetoothServiceInfo::ServiceName) - .toString(); - if (bt_spp_open_server(attributes.value(QBluetoothServiceInfo::ServiceName) - .toString().toUtf8().data(), - b_uuid.data(), true, &QBluetoothServerPrivate::btCallback, - reinterpret_cast<long>(__fakeServerPorts.key(serverChannel()))) == -1) { - qCDebug(QT_BT_QNX) << "Could not open the server. " - << qt_error_string(errno) << errno; - bt_spp_close_server(b_uuid.data()); - return false; - } -#else - if (!ppsSendControlMessage("register_server", 0x1101, attributes.value(QBluetoothServiceInfo::ServiceId).value<QBluetoothUuid>(), QString(), - attributes.value(QBluetoothServiceInfo::ServiceName).toString(), - __fakeServerPorts.key(serverChannel()), BT_SPP_SERVER_SUBTYPE)) - return false; -#endif - //The server needs to know the service name for the socket mount point path - __fakeServerPorts.key(serverChannel())->m_serviceName = attributes.value(QBluetoothServiceInfo::ServiceName).toString(); - } else { - return false; - } - - registered = true; - return true; -} - -QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothsocket.cpp b/src/bluetooth/qbluetoothsocket.cpp index 56428544..97ee7dc2 100644 --- a/src/bluetooth/qbluetoothsocket.cpp +++ b/src/bluetooth/qbluetoothsocket.cpp @@ -46,7 +46,6 @@ QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(QT_BT) -Q_DECLARE_LOGGING_CATEGORY(QT_BT_QNX) /*! \class QBluetoothSocket @@ -60,7 +59,7 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT_QNX) \l {QBluetoothServiceInfo::RfcommProtocol}{RFCOMM}. \l {QBluetoothServiceInfo::L2capProtocol}{L2CAP} is a low level datagram-oriented Bluetooth socket. - Android and BlackBerry do not support \l {QBluetoothServiceInfo::L2capProtocol}{L2CAP} for socket + Android does not support \l {QBluetoothServiceInfo::L2capProtocol}{L2CAP} for socket connections. \l {QBluetoothServiceInfo::RfcommProtocol}{RFCOMM} is a reliable, stream-oriented socket. RFCOMM @@ -199,7 +198,7 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT_QNX) Although some platforms may differ the socket must generally be connected to guarantee the return of a valid port number. - On BlackBerry, Android and OS X, this feature is not supported and returns 0. + On Android and OS X, this feature is not supported and returns 0. */ /*! @@ -218,7 +217,7 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT_QNX) \fn quint16 QBluetoothSocket::peerPort() const Return the port number of the peer socket if available, otherwise returns 0. - On BlackBerry and Android, this feature is not supported. + On Android, this feature is not supported. */ /*! @@ -322,7 +321,7 @@ void QBluetoothSocket::connectToService(const QBluetoothServiceInfo &service, Op setSocketError(QBluetoothSocket::OperationError); return; } -#if defined(QT_QNX_BLUETOOTH) || defined(QT_ANDROID_BLUETOOTH) +#if defined(QT_ANDROID_BLUETOOTH) if (!d->ensureNativeSocket(service.socketProtocol())) { d->errorString = tr("Socket type not supported"); setSocketError(QBluetoothSocket::UnsupportedProtocolError); @@ -367,8 +366,8 @@ void QBluetoothSocket::connectToService(const QBluetoothServiceInfo &service, Op ConnectingState, and attempts to connect to \a address. If a connection is established, QBluetoothSocket enters Connected State and emits connected(). - On BlackBerry and Android, the service connection can directly be established - using the UUID of the remote service. Therefore these platforms do not require + On Android, the service connection can directly be established + using the UUID of the remote service. Therefore the platforms does not require the \l ServiceLookupState and \l socketType() is always set to \l QBluetoothServiceInfo::RfcommProtocol. @@ -390,7 +389,7 @@ void QBluetoothSocket::connectToService(const QBluetoothAddress &address, const return; } -#if defined(QT_QNX_BLUETOOTH) || defined(QT_ANDROID_BLUETOOTH) +#if defined(QT_ANDROID_BLUETOOTH) if (!d->ensureNativeSocket(QBluetoothServiceInfo::RfcommProtocol)) { d->errorString = tr("Socket type not supported"); setSocketError(QBluetoothSocket::UnsupportedProtocolError); @@ -416,7 +415,7 @@ void QBluetoothSocket::connectToService(const QBluetoothAddress &address, const At any point, the socket can emit error() to signal that an error occurred. - On BlackBerry and Android, a connection to a service can not be established using a port. Calling this function + On Android, a connection to a service can not be established using a port. Calling this function will emit a \l {QBluetoothSocket::ServiceNotFoundError}{ServiceNotFoundError} Note that most platforms require a pairing prior to connecting to the remote device. Otherwise @@ -427,7 +426,7 @@ void QBluetoothSocket::connectToService(const QBluetoothAddress &address, const void QBluetoothSocket::connectToService(const QBluetoothAddress &address, quint16 port, OpenMode openMode) { Q_D(QBluetoothSocket); -#if defined(QT_QNX_BLUETOOTH) || defined(QT_ANDROID_BLUETOOTH) +#if defined(QT_ANDROID_BLUETOOTH) Q_UNUSED(port); Q_UNUSED(openMode); Q_UNUSED(address); @@ -451,7 +450,7 @@ void QBluetoothSocket::connectToService(const QBluetoothAddress &address, quint1 Returns the socket type. The socket automatically adjusts to the protocol offered by the remote service. - Blackberry and Android only support \l{QBluetoothServiceInfo::RfcommProtocol}{RFCOMM} + Android only support \l{QBluetoothServiceInfo::RfcommProtocol}{RFCOMM} based sockets. */ QBluetoothServiceInfo::Protocol QBluetoothSocket::socketType() const @@ -488,6 +487,60 @@ QString QBluetoothSocket::errorString() const } /*! + Sets the preferred security parameter for the connection attempt to + \a flags. This value is incorporated when calling \l connectToService(). + Therefore it is required to reconnect to change this parameter for an + existing connection. + + On Bluez this property is set to QBluetooth::Authorization by default. + + On OS X, this value is ignored as the platform does not permit access + to the security parameter of the socket. By default the platform prefers + secure/encrypted connections though and therefore this function always + returns \l QBluetooth::Secure. + + Android only supports two levels of security (secure and non-secure). If this flag is set to + \l QBluetooth::NoSecurity the socket object will not employ any authentication or encryption. + Any other security flag combination will trigger a secure Bluetooth connection. + This flag is set to \l QBluetooth::Secure by default. + + \note A secure connection requires a pairing between the two devices. On + some platforms, the pairing is automatically initiated during the establishment + of the connection. Other platforms require the application to manually trigger + the pairing before attempting to connect. + + \sa preferredSecurityFlags() + + \since 5.6 +*/ +void QBluetoothSocket::setPreferredSecurityFlags(QBluetooth::SecurityFlags flags) +{ + Q_D(QBluetoothSocket); + if (d->secFlags != flags) + d->secFlags = flags; +} + +/*! + Returns the security parameters used for the initial connection + attempt. + + The security parameters may be renegotiated between the two parties + during or after the connection has been established. If such a change happens + it is not reflected in the value of this flag. + + On OS X, this flag is always set to \l QBluetooth::Secure. + + \sa setPreferredSecurityFlags() + + \since 5.6 +*/ +QBluetooth::SecurityFlags QBluetoothSocket::preferredSecurityFlags() const +{ + Q_D(const QBluetoothSocket); + return d->secFlags; +} + +/*! Sets the socket state to \a state. */ void QBluetoothSocket::setSocketState(QBluetoothSocket::SocketState state) diff --git a/src/bluetooth/qbluetoothsocket.h b/src/bluetooth/qbluetoothsocket.h index b073ada3..5d686d7f 100644 --- a/src/bluetooth/qbluetoothsocket.h +++ b/src/bluetooth/qbluetoothsocket.h @@ -36,12 +36,13 @@ #include <QtBluetooth/qbluetoothglobal.h> -#include <QtBluetooth/QBluetoothAddress> -#include <QtBluetooth/QBluetoothUuid> -#include <QtBluetooth/QBluetoothServiceInfo> +#include <QtBluetooth/qbluetooth.h> +#include <QtBluetooth/qbluetoothaddress.h> +#include <QtBluetooth/qbluetoothuuid.h> +#include <QtBluetooth/qbluetoothserviceinfo.h> -#include <QtCore/QIODevice> -#include <QtNetwork/QAbstractSocket> +#include <QtCore/qiodevice.h> +#include <QtNetwork/qabstractsocket.h> QT_BEGIN_NAMESPACE @@ -67,6 +68,7 @@ public: ClosingState = QAbstractSocket::ClosingState, ListeningState = QAbstractSocket::ListeningState }; + Q_ENUM(SocketState) enum SocketError { NoSocketError = -2, @@ -78,6 +80,7 @@ public: OperationError = QAbstractSocket::OperationError //19 //New enums (independent of QAbstractSocket) should be added from 100 onwards }; + Q_ENUM(SocketError) explicit QBluetoothSocket(QBluetoothServiceInfo::Protocol socketType, QObject *parent = 0); // create socket of type socketType QBluetoothSocket(QObject *parent = 0); // create a blank socket @@ -127,6 +130,9 @@ public: //bool waitForDisconnected(int msecs = 30000); //virtual bool waitForReadyRead(int msecs = 30000); + void setPreferredSecurityFlags(QBluetooth::SecurityFlags flags); + QBluetooth::SecurityFlags preferredSecurityFlags() const; + Q_SIGNALS: void connected(); void disconnected(); @@ -161,7 +167,4 @@ Q_BLUETOOTH_EXPORT QDebug operator<<(QDebug, QBluetoothSocket::SocketState); QT_END_NAMESPACE -Q_DECLARE_METATYPE(QBluetoothSocket::SocketError) -Q_DECLARE_METATYPE(QBluetoothSocket::SocketState) - #endif diff --git a/src/bluetooth/qbluetoothsocket_android.cpp b/src/bluetooth/qbluetoothsocket_android.cpp index 990ab378..1a5f70b0 100644 --- a/src/bluetooth/qbluetoothsocket_android.cpp +++ b/src/bluetooth/qbluetoothsocket_android.cpp @@ -173,6 +173,7 @@ QBluetoothSocketPrivate::QBluetoothSocketPrivate() socketError(QBluetoothSocket::NoSocketError), connecting(false), discoveryAgent(0), + secFlags(QBluetooth::Secure), inputThread(0) { adapter = QAndroidJniObject::callStaticObjectMethod("android/bluetooth/BluetoothAdapter", @@ -257,11 +258,22 @@ bool QBluetoothSocketPrivate::fallBackConnect(QAndroidJniObject uuid, int channe } } - QAndroidJniObject method = remoteDeviceClass.callObjectMethod( + QAndroidJniObject method; + if (secFlags == QBluetooth::NoSecurity) { + qCDebug(QT_BT_ANDROID) << "Connnecting via insecure rfcomm"; + method = remoteDeviceClass.callObjectMethod( + "getMethod", + "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", + QAndroidJniObject::fromString(QLatin1String("createInsecureRfcommSocket")).object<jstring>(), + paramTypes.object<jobjectArray>()); + } else { + qCDebug(QT_BT_ANDROID) << "Connnecting via secure rfcomm"; + method = remoteDeviceClass.callObjectMethod( "getMethod", "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", QAndroidJniObject::fromString(QLatin1String("createRfcommSocket")).object<jstring>(), paramTypes.object<jobjectArray>()); + } if (!method.isValid() || env->ExceptionCheck()) { qCWarning(QT_BT_ANDROID) << "Could not invoke getMethod"; if (env->ExceptionCheck()) { @@ -371,9 +383,17 @@ void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address, "(Ljava/lang/String;)Ljava/util/UUID;", inputString.object<jstring>()); - socketObject = remoteDevice.callObjectMethod("createRfcommSocketToServiceRecord", + if (secFlags == QBluetooth::NoSecurity) { + qCDebug(QT_BT_ANDROID) << "Connnecting via insecure rfcomm"; + socketObject = remoteDevice.callObjectMethod("createInsecureRfcommSocketToServiceRecord", "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;", uuidObject.object<jobject>()); + } else { + qCDebug(QT_BT_ANDROID) << "Connnecting via secure rfcomm"; + socketObject = remoteDevice.callObjectMethod("createRfcommSocketToServiceRecord", + "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;", + uuidObject.object<jobject>()); + } if (env->ExceptionCheck()) { env->ExceptionDescribe(); diff --git a/src/bluetooth/qbluetoothsocket_bluez.cpp b/src/bluetooth/qbluetoothsocket_bluez.cpp index c18ce279..71f26296 100644 --- a/src/bluetooth/qbluetoothsocket_bluez.cpp +++ b/src/bluetooth/qbluetoothsocket_bluez.cpp @@ -64,6 +64,7 @@ QBluetoothSocketPrivate::QBluetoothSocketPrivate() connectWriteNotifier(0), connecting(false), discoveryAgent(0), + secFlags(QBluetooth::Authorization), lowEnergySocketType(0) { } @@ -132,6 +133,27 @@ void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address, return; } + // apply preferred security level + // ignore QBluetooth::Authentication -> not used anymore by kernel + struct bt_security security; + memset(&security, 0, sizeof(security)); + + if (secFlags & QBluetooth::Authorization) + security.level = BT_SECURITY_LOW; + if (secFlags & QBluetooth::Encryption) + security.level = BT_SECURITY_MEDIUM; + if (secFlags & QBluetooth::Secure) + security.level = BT_SECURITY_HIGH; + + if (setsockopt(socket, SOL_BLUETOOTH, BT_SECURITY, + &security, sizeof(security)) != 0) { + qCWarning(QT_BT_BLUEZ) << "Failed to set socket option, closing socket for safety" << errno; + qCWarning(QT_BT_BLUEZ) << "Error: " << qt_error_string(errno); + errorString = QBluetoothSocket::tr("Cannot set connection security level"); + q->setSocketError(QBluetoothSocket::UnknownSocketError); + return; + } + if (socketType == QBluetoothServiceInfo::RfcommProtocol) { sockaddr_rc addr; @@ -362,13 +384,17 @@ QString QBluetoothSocketPrivate::peerName() const if (reply.isError()) return QString(); - foreach (const QDBusObjectPath &path, reply.value().keys()) { - const InterfaceList ifaceList = reply.value().value(path); - foreach (const QString &iface, ifaceList.keys()) { + ManagedObjectList managedObjectList = reply.value(); + for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) { + const InterfaceList &ifaceList = it.value(); + + for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) { + const QString &iface = jt.key(); + const QVariantMap &ifaceValues = jt.value(); + if (iface == QStringLiteral("org.bluez.Device1")) { - if (ifaceList.value(iface).value(QStringLiteral("Address")).toString() - == peerAddress) - return ifaceList.value(iface).value(QStringLiteral("Alias")).toString(); + if (ifaceValues.value(QStringLiteral("Address")).toString() == peerAddress) + return ifaceValues.value(QStringLiteral("Alias")).toString(); } } } @@ -385,13 +411,13 @@ QString QBluetoothSocketPrivate::peerName() const OrgBluezAdapterInterface adapter(QStringLiteral("org.bluez"), reply.value().path(), QDBusConnection::systemBus()); - QDBusPendingReply<QDBusObjectPath> deviceObjectPath = adapter.CreateDevice(peerAddress); + QDBusPendingReply<QDBusObjectPath> deviceObjectPath = adapter.FindDevice(peerAddress); deviceObjectPath.waitForFinished(); if (deviceObjectPath.isError()) { - if (deviceObjectPath.error().name() != QStringLiteral("org.bluez.Error.AlreadyExists")) + if (deviceObjectPath.error().name() != QStringLiteral("org.bluez.Error.DoesNotExist")) return QString(); - deviceObjectPath = adapter.FindDevice(peerAddress); + deviceObjectPath = adapter.CreateDevice(peerAddress); deviceObjectPath.waitForFinished(); if (deviceObjectPath.isError()) return QString(); diff --git a/src/bluetooth/qbluetoothsocket_osx.mm b/src/bluetooth/qbluetoothsocket_osx.mm index 490c1bed..91393138 100644 --- a/src/bluetooth/qbluetoothsocket_osx.mm +++ b/src/bluetooth/qbluetoothsocket_osx.mm @@ -712,6 +712,18 @@ int QBluetoothSocket::socketDescriptor() const return -1; } +/* not supported on OS X */ +void QBluetoothSocket::setPreferredSecurityFlags(QBluetooth::SecurityFlags flags) +{ + Q_UNUSED(flags) +} + +/* not supported on OS X - platform always uses encryption */ +QBluetooth::SecurityFlags QBluetoothSocket::preferredSecurityFlags() const +{ + return QBluetooth::Secure; +} + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug debug, QBluetoothSocket::SocketError error) diff --git a/src/bluetooth/qbluetoothsocket_p.cpp b/src/bluetooth/qbluetoothsocket_p.cpp index e18c985b..13b32045 100644 --- a/src/bluetooth/qbluetoothsocket_p.cpp +++ b/src/bluetooth/qbluetoothsocket_p.cpp @@ -40,7 +40,8 @@ QBluetoothSocketPrivate::QBluetoothSocketPrivate() : socket(-1), socketType(QBluetoothServiceInfo::UnknownProtocol), state(QBluetoothSocket::UnconnectedState), - socketError(QBluetoothSocket::NoSocketError) + socketError(QBluetoothSocket::NoSocketError), + secFlags(QBluetooth::NoSecurity) { } diff --git a/src/bluetooth/qbluetoothsocket_p.h b/src/bluetooth/qbluetoothsocket_p.h index e5ddf798..23f3cf72 100644 --- a/src/bluetooth/qbluetoothsocket_p.h +++ b/src/bluetooth/qbluetoothsocket_p.h @@ -47,9 +47,6 @@ #include "qbluetoothsocket.h" -#ifdef QT_QNX_BLUETOOTH -#include "qnx/ppshelpers_p.h" -#endif #ifdef QT_ANDROID_BLUETOOTH #include <QtAndroidExtras/QAndroidJniObject> #include <QtCore/QPointer> @@ -95,8 +92,8 @@ public: QBluetoothSocketPrivate(); ~QBluetoothSocketPrivate(); -//On QNX and Android we connect using the uuid not the port -#if defined(QT_QNX_BLUETOOTH) || defined(QT_ANDROID_BLUETOOTH) +//On Android we connect using the uuid not the port +#if defined(QT_ANDROID_BLUETOOTH) void connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid, QIODevice::OpenMode openMode); #else @@ -151,6 +148,7 @@ public: QBluetoothServiceDiscoveryAgent *discoveryAgent; QBluetoothSocket::OpenMode openMode; + QBluetooth::SecurityFlags secFlags; // QByteArray rxBuffer; @@ -179,7 +177,7 @@ signals: #endif -#if defined(QT_QNX_BLUETOOTH) || defined(QT_BLUEZ_BLUETOOTH) +#if defined(QT_BLUEZ_BLUETOOTH) private slots: void _q_readNotify(); void _q_writeNotify(); @@ -189,15 +187,6 @@ protected: QBluetoothSocket *q_ptr; private: -#ifdef QT_QNX_BLUETOOTH - QBluetoothAddress m_peerAddress; - QBluetoothUuid m_uuid; - bool isServerSocket; - -private slots: - void controlReply(ppsResult result); - void controlEvent(ppsResult result); -#endif #ifdef QT_BLUEZ_BLUETOOTH public: diff --git a/src/bluetooth/qbluetoothsocket_qnx.cpp b/src/bluetooth/qbluetoothsocket_qnx.cpp deleted file mode 100644 index 125a5595..00000000 --- a/src/bluetooth/qbluetoothsocket_qnx.cpp +++ /dev/null @@ -1,420 +0,0 @@ -/*************************************************************************** -** -** Copyright (C) 2012 Research In Motion -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtBluetooth module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qbluetoothsocket.h" -#include "qbluetoothsocket_p.h" -#include "qbluetoothlocaldevice.h" -#include <sys/stat.h> -#ifdef QT_QNX_BT_BLUETOOTH -#include <errno.h> -#include <btapi/btspp.h> -#endif - -QT_BEGIN_NAMESPACE -#ifdef QT_QNX_BT_BLUETOOTH -static int initCounter = 0; -#endif - -QBluetoothSocketPrivate::QBluetoothSocketPrivate() - : socket(-1), - socketType(QBluetoothServiceInfo::UnknownProtocol), - state(QBluetoothSocket::UnconnectedState), - socketError(QBluetoothSocket::NoSocketError), - readNotifier(0), - connectWriteNotifier(0), - connecting(false), - discoveryAgent(0), - isServerSocket(false) -{ -#ifdef QT_QNX_BT_BLUETOOTH - if (!initCounter && (bt_spp_init() == -1)) - qCDebug(QT_BT_QNX) << "Could not initialize Bluetooth library. " - << qt_error_string(errno); - - initCounter++; -#else - ppsRegisterControl(); -#endif -} - -QBluetoothSocketPrivate::~QBluetoothSocketPrivate() -{ -#ifdef QT_QNX_BT_BLUETOOTH - if (initCounter == 1 && (bt_spp_deinit() == -1)) - qCDebug(QT_BT_QNX) << "Could not deinitialize Bluetooth library." - "SPP connection is still open."; - - initCounter--; -#else - ppsUnregisterControl(this); -#endif - close(); -} - -bool QBluetoothSocketPrivate::ensureNativeSocket(QBluetoothServiceInfo::Protocol type) -{ - socketType = type; - if (socketType == QBluetoothServiceInfo::RfcommProtocol) - return true; - - return false; -} - -void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address, - const QBluetoothUuid &uuid, - QIODevice::OpenMode openMode) -{ - Q_Q(QBluetoothSocket); - Q_UNUSED(openMode); - qCDebug(QT_BT_QNX) << "Connecting socket"; - - m_peerAddress = address; -#ifdef QT_QNX_BT_BLUETOOTH - QByteArray b_uuid = uuid.toByteArray(); - b_uuid = b_uuid.mid(1, b_uuid.length() - 2); - socket = bt_spp_open(address.toString().toUtf8().data(), b_uuid.data(), false); - if (socket == -1) { - qCWarning(QT_BT_QNX) << "Could not connect to" << address.toString() << b_uuid << qt_error_string(errno); - errorString = qt_error_string(errno); - q->setSocketError(QBluetoothSocket::NetworkError); - return; - } - - delete readNotifier; - delete connectWriteNotifier; - - readNotifier = new QSocketNotifier(socket, QSocketNotifier::Read); - QObject::connect(readNotifier, SIGNAL(activated(int)), this, SLOT(_q_readNotify())); - connectWriteNotifier = new QSocketNotifier(socket, QSocketNotifier::Write, q); - QObject::connect(connectWriteNotifier, SIGNAL(activated(int)), this, SLOT(_q_writeNotify())); - - connecting = true; - q->setOpenMode(openMode); -#else - m_uuid = uuid; - if (isServerSocket) - return; - - if (state != QBluetoothSocket::UnconnectedState) { - qCDebug(QT_BT_QNX) << "Socket already connected"; - return; - } - - ppsSendControlMessage("connect_service", 0x1101, uuid, address.toString(), QString(), this, BT_SPP_CLIENT_SUBTYPE); - ppsRegisterForEvent(QStringLiteral("service_connected"),this); - ppsRegisterForEvent(QStringLiteral("get_mount_point_path"),this); -#endif - q->setSocketState(QBluetoothSocket::ConnectingState); -} - -void QBluetoothSocketPrivate::_q_writeNotify() -{ - Q_Q(QBluetoothSocket); - if (connecting && state == QBluetoothSocket::ConnectingState){ - q->setSocketState(QBluetoothSocket::ConnectedState); - emit q->connected(); - - connectWriteNotifier->setEnabled(false); - connecting = false; - } else { - if (txBuffer.size() == 0) { - connectWriteNotifier->setEnabled(false); - return; - } - - char buf[1024]; - Q_Q(QBluetoothSocket); - - int size = txBuffer.read(buf, 1024); - - if (::write(socket, buf, size) != size) { - errorString = QBluetoothSocket::tr("Network Error"); - q->setSocketError(QBluetoothSocket::NetworkError); - } - else { - emit q->bytesWritten(size); - } - - if (txBuffer.size()) { - connectWriteNotifier->setEnabled(true); - } - else if (state == QBluetoothSocket::ClosingState) { - connectWriteNotifier->setEnabled(false); - this->close(); - } - } -} - -void QBluetoothSocketPrivate::_q_readNotify() -{ - Q_Q(QBluetoothSocket); - char *writePointer = buffer.reserve(QPRIVATELINEARBUFFER_BUFFERSIZE); - int readFromDevice = ::read(socket, writePointer, QPRIVATELINEARBUFFER_BUFFERSIZE); - if (readFromDevice <= 0){ - int errsv = errno; - readNotifier->setEnabled(false); - connectWriteNotifier->setEnabled(false); - qCWarning(QT_BT_QNX) << Q_FUNC_INFO << socket << " error:" << readFromDevice << errorString; //TODO Try if this actually works - errorString = qt_error_string(errsv); - q->setSocketError(QBluetoothSocket::UnknownSocketError); - - q->disconnectFromService(); - q->setSocketState(QBluetoothSocket::UnconnectedState); - } else { - buffer.chop(QPRIVATELINEARBUFFER_BUFFERSIZE - (readFromDevice < 0 ? 0 : readFromDevice)); - - emit q->readyRead(); - } -} - -void QBluetoothSocketPrivate::abort() -{ - Q_Q(QBluetoothSocket); - qCDebug(QT_BT_QNX) << "Disconnecting service"; -#ifdef QT_QNX_BT_BLUETOOTH - if (isServerSocket) - bt_spp_close_server(m_uuid.toString().toUtf8().data()); - else - bt_spp_close(socket); -#else - if (q->state() != QBluetoothSocket::ClosingState) - ppsSendControlMessage("disconnect_service", 0x1101, m_uuid, m_peerAddress.toString(), QString(), 0, - isServerSocket ? BT_SPP_SERVER_SUBTYPE : BT_SPP_CLIENT_SUBTYPE); -#endif - delete readNotifier; - readNotifier = 0; - delete connectWriteNotifier; - connectWriteNotifier = 0; - - ::close(socket); - - isServerSocket = false; -} - -QString QBluetoothSocketPrivate::localName() const -{ - QBluetoothLocalDevice ld; - return ld.name(); -} - -QBluetoothAddress QBluetoothSocketPrivate::localAddress() const -{ - QBluetoothLocalDevice ld; - return ld.address(); -} - -quint16 QBluetoothSocketPrivate::localPort() const -{ - return 0; -} - -QString QBluetoothSocketPrivate::peerName() const -{ - return QString(); -} - -QBluetoothAddress QBluetoothSocketPrivate::peerAddress() const -{ - return m_peerAddress; -} - -quint16 QBluetoothSocketPrivate::peerPort() const -{ - return 0; -} - -qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize) -{ - Q_Q(QBluetoothSocket); - - if (state != QBluetoothSocket::ConnectedState) { - errorString = QBluetoothSocket::tr("Cannot write while not connected"); - q->setSocketError(QBluetoothSocket::OperationError); - return -1; - } - - if (q->openMode() & QIODevice::Unbuffered) { - if (::write(socket, data, maxSize) != maxSize) { - errorString = QBluetoothSocket::tr("Network Error"); - q->setSocketError(QBluetoothSocket::NetworkError); - qCWarning(QT_BT_QNX) << Q_FUNC_INFO << "Socket error"; - return -1; - } - - emit q->bytesWritten(maxSize); - - return maxSize; - } else { - if (!connectWriteNotifier) - return -1; - - if (txBuffer.size() == 0) { - connectWriteNotifier->setEnabled(true); - QMetaObject::invokeMethod(this, "_q_writeNotify", Qt::QueuedConnection); - } - - char *txbuf = txBuffer.reserve(maxSize); - memcpy(txbuf, data, maxSize); - - return maxSize; - } -} - -qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize) -{ - Q_Q(QBluetoothSocket); - - if (state != QBluetoothSocket::ConnectedState) { - errorString = QBluetoothSocket::tr("Cannot read while not connected"); - q->setSocketError(QBluetoothSocket::OperationError); - return -1; - } - - if (!buffer.isEmpty()) { - int i = buffer.read(data, maxSize); - return i; - } - return 0; -} - -void QBluetoothSocketPrivate::close() -{ - abort(); -} - -bool QBluetoothSocketPrivate::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType_, - QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode) -{ - Q_Q(QBluetoothSocket); - delete readNotifier; - readNotifier = 0; - delete connectWriteNotifier; - connectWriteNotifier = 0; - - socket = socketDescriptor; - socketType = socketType_; - - readNotifier = new QSocketNotifier(socket, QSocketNotifier::Read); - QObject::connect(readNotifier, SIGNAL(activated(int)), this, SLOT(_q_readNotify())); - connectWriteNotifier = new QSocketNotifier(socket, QSocketNotifier::Write, q); - QObject::connect(connectWriteNotifier, SIGNAL(activated(int)), this, SLOT(_q_writeNotify())); - - q->setSocketState(socketState); - q->setOpenMode(openMode); - - if (openMode == QBluetoothSocket::ConnectedState) - emit q->connected(); - - isServerSocket = true; -#ifndef QT_QNX_BT_BLUETOOTH - ppsRegisterForEvent(QStringLiteral("service_disconnected"),this); -#endif - - return true; -} - -qint64 QBluetoothSocketPrivate::bytesAvailable() const -{ - return buffer.size(); -} - -void QBluetoothSocketPrivate::controlReply(ppsResult result) -{ -#ifndef QT_QNX_BT_BLUETOOTH - Q_Q(QBluetoothSocket); - - if (result.msg == QStringLiteral("connect_service")) { - if (!result.errorMsg.isEmpty()) { - qCWarning(QT_BT_QNX) << Q_FUNC_INFO << "Error connecting to service:" << result.errorMsg; - errorString = result.errorMsg; - q->setSocketError(QBluetoothSocket::UnknownSocketError); - q->setSocketState(QBluetoothSocket::UnconnectedState); - return; - } else { - qCDebug(QT_BT_QNX) << Q_FUNC_INFO << "Sending request for mount point"; - ppsSendControlMessage("get_mount_point_path", 0x1101, m_uuid, m_peerAddress.toString(), QString(), this, BT_SPP_CLIENT_SUBTYPE); - } - } else if (result.msg == QStringLiteral("get_mount_point_path")) { - QString path; - path = result.dat.first(); - qCDebug(QT_BT_QNX) << Q_FUNC_INFO << "PATH is" << path; - - if (!result.errorMsg.isEmpty()) { - qCWarning(QT_BT_QNX) << Q_FUNC_INFO << result.errorMsg; - errorString = result.errorMsg; - q->setSocketError(QBluetoothSocket::UnknownSocketError); - q->setSocketState(QBluetoothSocket::UnconnectedState); - return; - } else { - qCDebug(QT_BT_QNX) << "Mount point path is:" << path; - socket = ::open(path.toStdString().c_str(), O_RDWR); - if (socket == -1) { - errorString = qt_error_string(errno); - q->setSocketError(QBluetoothSocket::UnknownSocketError); - qCWarning(QT_BT_QNX) << Q_FUNC_INFO << socket << " error:" << errno << errorString; //TODO Try if this actually works - - q->disconnectFromService(); - q->setSocketState(QBluetoothSocket::UnconnectedState); - return; - } - - Q_Q(QBluetoothSocket); - readNotifier = new QSocketNotifier(socket, QSocketNotifier::Read); - QObject::connect(readNotifier, SIGNAL(activated(int)), this, SLOT(_q_readNotify())); - connectWriteNotifier = new QSocketNotifier(socket, QSocketNotifier::Write, q); - QObject::connect(connectWriteNotifier, SIGNAL(activated(int)), this, SLOT(_q_writeNotify())); - - connectWriteNotifier->setEnabled(true); - readNotifier->setEnabled(true); - q->setOpenMode(QIODevice::ReadWrite); - state = QBluetoothSocket::ConnectedState; - emit q->connected(); - ppsRegisterForEvent(QStringLiteral("service_disconnected"),this); - } - } -#endif -} - -void QBluetoothSocketPrivate::controlEvent(ppsResult result) -{ -#ifndef QT_QNX_BT_BLUETOOTH - Q_Q(QBluetoothSocket); - if (result.msg == QStringLiteral("service_disconnected")) { - q->setSocketState(QBluetoothSocket::ClosingState); - close(); - } -#endif -} - -QT_END_NAMESPACE - diff --git a/src/bluetooth/qbluetoothtransfermanager.cpp b/src/bluetooth/qbluetoothtransfermanager.cpp index 4c40fe72..de7693d7 100644 --- a/src/bluetooth/qbluetoothtransfermanager.cpp +++ b/src/bluetooth/qbluetoothtransfermanager.cpp @@ -36,8 +36,6 @@ #include "qbluetoothtransferreply.h" #ifdef QT_BLUEZ_BLUETOOTH #include "qbluetoothtransferreply_bluez_p.h" -#elif QT_QNX_BLUETOOTH -#include "qbluetoothtransferreply_qnx_p.h" #elif QT_OSX_BLUETOOTH #include "qbluetoothtransferreply_osx_p.h" #endif @@ -108,10 +106,6 @@ QBluetoothTransferReply *QBluetoothTransferManager::put(const QBluetoothTransfer QBluetoothTransferReplyBluez *rep = new QBluetoothTransferReplyBluez(data, request, this); connect(rep, SIGNAL(finished(QBluetoothTransferReply*)), this, SIGNAL(finished(QBluetoothTransferReply*))); return rep; -#elif QT_QNX_BLUETOOTH - QBluetoothTransferReplyQnx *reply = new QBluetoothTransferReplyQnx(data, request, this); - connect(reply, SIGNAL(finished(QBluetoothTransferReply*)), this, SIGNAL(finished(QBluetoothTransferReply*))); - return reply; #elif QT_OSX_BLUETOOTH QBluetoothTransferReply *reply = new QBluetoothTransferReplyOSX(data, request, this); connect(reply, SIGNAL(finished(QBluetoothTransferReply*)), this, SIGNAL(finished(QBluetoothTransferReply*))); diff --git a/src/bluetooth/qbluetoothtransferreply.h b/src/bluetooth/qbluetoothtransferreply.h index 081b7002..755b9caa 100644 --- a/src/bluetooth/qbluetoothtransferreply.h +++ b/src/bluetooth/qbluetoothtransferreply.h @@ -58,7 +58,7 @@ public: ResourceBusyError, SessionError }; - + Q_ENUM(TransferError) ~QBluetoothTransferReply(); diff --git a/src/bluetooth/qbluetoothtransferreply_qnx.cpp b/src/bluetooth/qbluetoothtransferreply_qnx.cpp deleted file mode 100644 index fa8992d2..00000000 --- a/src/bluetooth/qbluetoothtransferreply_qnx.cpp +++ /dev/null @@ -1,291 +0,0 @@ -/*************************************************************************** -** -** Copyright (C) 2013 Research In Motion -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtBluetooth module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "qbluetoothtransferreply_qnx_p.h" -#include "qbluetoothaddress.h" - -#include "qbluetoothtransferreply.h" - -#include <QFuture> -#include <QFutureWatcher> -#include <QtConcurrentRun> - -#include "qnx/ppshelpers_p.h" -#include <QSocketNotifier> -#include <QtCore/QVector> - -#include <QtCore/private/qcore_unix_p.h> - -#include <QTime> -#include <QDir> -#include <QCoreApplication> - -static const QString agentPath(QStringLiteral("/accounts/1000/shared/misc/")); -static bool busy; - -QT_BEGIN_NAMESPACE - -QBluetoothTransferReplyQnx::QBluetoothTransferReplyQnx(QIODevice *input, const QBluetoothTransferRequest &request, - QBluetoothTransferManager *parent) -: QBluetoothTransferReply(parent), tempfile(0), source(input), - m_running(false), m_finished(false), - m_error(QBluetoothTransferReply::NoError), m_errorStr() -{ - setRequest(request); - setManager(parent); - - if (!input) { - qCWarning(QT_BT_QNX) << "Invalid input device (null)"; - m_errorStr = QBluetoothTransferReply::tr("Invalid input device (null)"); - m_error = QBluetoothTransferReply::FileNotFoundError; - m_finished = true; - return; - } - - ppsRegisterControl(); - //qsrand(QTime::currentTime().msec()); - //m_agent_path = agentPath; - //m_agent_path.append(QString::fromLatin1("/%1").arg(qrand())); - ppsRegisterForEvent(QStringLiteral("opp_update"), this); - ppsRegisterForEvent(QStringLiteral("opp_complete"), this); - ppsRegisterForEvent(QStringLiteral("opp_cancelled"), this); - - QMetaObject::invokeMethod(this, "start", Qt::QueuedConnection); - m_running = true; -} - -/*! - Destroys the QBluetoothTransferReply object. -*/ -QBluetoothTransferReplyQnx::~QBluetoothTransferReplyQnx() -{ - removeTempFile(); - delete tempfile; - ppsUnregisterControl(this); -} - -bool QBluetoothTransferReplyQnx::start() -{ - m_error = QBluetoothTransferReply::NoError; - m_errorStr = QString(); - - QFile *file = qobject_cast<QFile *>(source); - - if (!file){ - // Deleting temporary files in case of app crash - QDir directory(agentPath); - QString appName = QStringLiteral("Qt5OPP_tmp") + QCoreApplication::applicationName(); - if (directory.exists(appName) && !busy) { - QFile file(agentPath + appName); - file.remove(); - } - else if (directory.exists(appName) && busy) { - m_errorStr = QBluetoothTransferReply::tr("Resource busy."); - m_error = QBluetoothTransferReply::ResourceBusyError; - m_finished = true; - m_running = false; - emit QBluetoothTransferReply::error(m_error); - emit finished(this); - return false; - } - if (!source->isReadable()) { - m_errorStr = QBluetoothTransferReply::tr("QIODevice cannot be read. " - "Make sure it is open for reading."); - m_error = QBluetoothTransferReply::IODeviceNotReadableError; - m_finished = true; - m_running = false; - emit QBluetoothTransferReply::error(m_error); - emit finished(this); - return false; - } - QString fileName = agentPath + QStringLiteral("Qt5OPP_tmp"); - tempfile = new QFile(fileName); - tempfile->open(QIODevice::WriteOnly); - - QFutureWatcher<bool> *watcher = new QFutureWatcher<bool>(); - QObject::connect(watcher, SIGNAL(finished()), this, SLOT(copyDone())); - QFuture<bool> results = QtConcurrent::run(QBluetoothTransferReplyQnx::copyToTempFile, tempfile, source); - watcher->setFuture(results); - busy = true; - - } else { - if (!file->exists()) { - m_errorStr = QBluetoothTransferReply::tr("Source file does not exist"); - m_error = QBluetoothTransferReply::FileNotFoundError; - m_finished = true; - m_running = false; - emit QBluetoothTransferReply::error(m_error); - emit finished(this); - return false; - } - if (request().address().isNull()) { - m_errorStr = QBluetoothTransferReply::tr("Invalid target address"); - m_error = QBluetoothTransferReply::HostNotFoundError; - m_finished = true; - m_running = false; - emit QBluetoothTransferReply::error(m_error); - emit finished(this); - return false; - } - startOPP(file->fileName()); - } - return true; -} - -bool QBluetoothTransferReplyQnx::copyToTempFile(QIODevice *to, QIODevice *from) -{ - QVector<char> block(4096); - int size; - - while ((size = from->read(block.data(), block.size())) > 0) { - if (size != to->write(block.data(), size)) - return false; - } - - return true; -} - -void QBluetoothTransferReplyQnx::copyDone() -{ - startOPP(tempfile->fileName()); - QObject::sender()->deleteLater(); -} - -void QBluetoothTransferReplyQnx::startOPP(QString filename) -{ - qCDebug(QT_BT_QNX) << "Sending push object command" - << request().address().toString() << filename; - ppsSendOpp("push_object", filename.toUtf8(), request().address(), this); -} - -QBluetoothTransferReply::TransferError QBluetoothTransferReplyQnx::error() const -{ - return m_error; -} - -QString QBluetoothTransferReplyQnx::errorString() const -{ - return m_errorStr; -} - -void QBluetoothTransferReplyQnx::controlReply(ppsResult result) -{ - if (!result.errorMsg.isEmpty()) { - m_errorStr = result.errorMsg; - m_error = QBluetoothTransferReply::UnknownError; - emit QBluetoothTransferReply::error(m_error); - emit finished(this); - } -} - -void QBluetoothTransferReplyQnx::controlEvent(ppsResult result) -{ - if (result.msg == QStringLiteral("opp_cancelled")) { - qCDebug(QT_BT_QNX) << "opp cancelled" << result.errorMsg << result.error; - removeTempFile(); - if (m_running) - return; - m_finished = true; - m_running = false; -// bool ok; -// int reason = result.dat.at(result.dat.indexOf(QStringLiteral("reason")) + 1).toInt(&ok); -// if (ok) { -// switch (reason) { -// case 1: m_error = QBluetoothTransferReply::UserCanceledTransferError; -// case 3: m_error = QBluetoothTransferReply::UserCanceledTransferError; -// } -// } else { - m_errorStr = result.errorMsg; - m_error = QBluetoothTransferReply::UnknownError; - emit QBluetoothTransferReply::error(m_error); -// } - emit finished(this); - } else if (result.msg == QStringLiteral("opp_update")) { - bool ok; - qint64 sentBytes = result.dat.at(result.dat.indexOf(QStringLiteral("sent")) + 1).toDouble(&ok); - if (!ok) { - qCWarning(QT_BT_QNX) << "Could not convert sent bytes"; - return; - } - qint64 totalBytes = result.dat.at(result.dat.indexOf(QStringLiteral("total")) + 1).toDouble(&ok); - if (!ok) { - qCWarning(QT_BT_QNX) << "Could not convert total bytes"; - return; - } - qCDebug(QT_BT_QNX) << "opp update" << sentBytes << totalBytes; - emit transferProgress(sentBytes, totalBytes); - } else if (result.msg == QStringLiteral("opp_complete")) { - qCDebug(QT_BT_QNX) << "opp complete"; - removeTempFile(); - m_finished = true; - m_running = false; - emit finished(this); - } -} - -/*! - Returns true if this reply has finished; otherwise returns false. -*/ -bool QBluetoothTransferReplyQnx::isFinished() const -{ - return m_finished; -} - -/*! - Returns true if this reply is running; otherwise returns false. -*/ -bool QBluetoothTransferReplyQnx::isRunning() const -{ - return m_running; -} - -void QBluetoothTransferReplyQnx::abort() -{ - //not supported yet -} - -void QBluetoothTransferReplyQnx::removeTempFile() -{ - if (tempfile) { - if (tempfile->exists()) { - tempfile->remove(); - busy = false; - } - } -} - -#include "moc_qbluetoothtransferreply_qnx_p.cpp" - -QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothtransferreply_qnx_p.h b/src/bluetooth/qbluetoothtransferreply_qnx_p.h deleted file mode 100644 index 138672c5..00000000 --- a/src/bluetooth/qbluetoothtransferreply_qnx_p.h +++ /dev/null @@ -1,104 +0,0 @@ -/*************************************************************************** -** -** Copyright (C) 2013 Research In Motion -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtBluetooth module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef QBLUETOOTHTRANSFERREPLY_QNX_P_H -#define QBLUETOOTHTRANSFERREPLY_QNX_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <qbluetoothtransferrequest.h> -#include <qbluetoothtransfermanager.h> - -#include "qbluetoothtransferreply.h" - -#include "qnx/ppshelpers_p.h" - -QT_FORWARD_DECLARE_CLASS(QFile) -QT_FORWARD_DECLARE_CLASS(QIODevice) - -QT_BEGIN_NAMESPACE - -class Q_BLUETOOTH_EXPORT QBluetoothTransferReplyQnx : public QBluetoothTransferReply -{ - Q_OBJECT - -public: - explicit QBluetoothTransferReplyQnx(QIODevice *input, const QBluetoothTransferRequest &request, - QBluetoothTransferManager *parent = 0); - ~QBluetoothTransferReplyQnx(); - - bool isFinished() const; - bool isRunning() const; - - QBluetoothTransferReply::TransferError error() const; - QString errorString() const; - -private slots: - void controlReply(ppsResult result); - void controlEvent(ppsResult result); - void copyDone(); - bool start(); - -private: - void startOPP(QString filename); - void removeTempFile(); - QFile *tempfile; - QIODevice *source; - - bool m_running; - bool m_finished; - - QBluetoothTransferReply::TransferError m_error; - QString m_errorStr; - - //QString m_agent_path; - - static bool copyToTempFile(QIODevice *to, QIODevice *from); - -public slots: - void abort(); -}; - -QT_END_NAMESPACE - -#endif // QBLUETOOTHTRANSFERREPLY_QNX_P_H diff --git a/src/bluetooth/qbluetoothuuid.cpp b/src/bluetooth/qbluetoothuuid.cpp index bbb9f652..cfce871c 100644 --- a/src/bluetooth/qbluetoothuuid.cpp +++ b/src/bluetooth/qbluetoothuuid.cpp @@ -587,9 +587,12 @@ QBluetoothUuid::QBluetoothUuid(quint32 uuid) */ QBluetoothUuid::QBluetoothUuid(quint128 uuid) { +QT_WARNING_PUSH +QT_WARNING_DISABLE_GCC("-Wstrict-aliasing") data1 = qFromBigEndian<quint32>(*reinterpret_cast<quint32 *>(&uuid.data[0])); data2 = qFromBigEndian<quint16>(*reinterpret_cast<quint16 *>(&uuid.data[4])); data3 = qFromBigEndian<quint16>(*reinterpret_cast<quint16 *>(&uuid.data[6])); +QT_WARNING_POP memcpy(data4, &uuid.data[8], 8); } diff --git a/src/bluetooth/qlowenergycharacteristic.cpp b/src/bluetooth/qlowenergycharacteristic.cpp index f0b78243..885b1337 100644 --- a/src/bluetooth/qlowenergycharacteristic.cpp +++ b/src/bluetooth/qlowenergycharacteristic.cpp @@ -64,9 +64,6 @@ QT_BEGIN_NAMESPACE format or range information specifying how the characteristic's value is to be\ interpreted. - \note This class is provided by Qt 5.4 as part of a Bluetooth Low Energy Tech Preview. - Some API elements may change until the final release of the feature. - \sa QLowEnergyService, QLowEnergyDescriptor */ @@ -341,11 +338,18 @@ QLowEnergyDescriptor QLowEnergyCharacteristic::descriptor(const QBluetoothUuid & if (d_ptr.isNull() || !data) return QLowEnergyDescriptor(); - QList<QLowEnergyHandle> descriptorKeys = d_ptr->characteristicList[data->handle]. - descriptorList.keys(); - foreach (const QLowEnergyHandle descHandle, descriptorKeys) { - if (uuid == d_ptr->characteristicList[data->handle].descriptorList[descHandle].uuid) - return QLowEnergyDescriptor(d_ptr, data->handle, descHandle); + CharacteristicDataMap::const_iterator charIt = d_ptr->characteristicList.constFind(data->handle); + if (charIt != d_ptr->characteristicList.constEnd()) { + const QLowEnergyServicePrivate::CharData &charDetails = charIt.value(); + + DescriptorDataMap::const_iterator descIt = charDetails.descriptorList.constBegin(); + for ( ; descIt != charDetails.descriptorList.constEnd(); ++descIt) { + const QLowEnergyHandle descHandle = descIt.key(); + const QLowEnergyServicePrivate::DescData &descDetails = descIt.value(); + + if (descDetails.uuid == uuid) + return QLowEnergyDescriptor(d_ptr, data->handle, descHandle); + } } return QLowEnergyDescriptor(); diff --git a/src/bluetooth/qlowenergycontroller.cpp b/src/bluetooth/qlowenergycontroller.cpp index 79359345..99a3724e 100644 --- a/src/bluetooth/qlowenergycontroller.cpp +++ b/src/bluetooth/qlowenergycontroller.cpp @@ -93,9 +93,6 @@ QT_BEGIN_NAMESPACE connection becomes invalid as soon as the controller disconnects from the remote Bluetooth Low Energy device. - \note This class is provided by Qt 5.4 as part of a Bluetooth Low Energy Tech Preview. - Some API elements may change until the final release of the feature. - \sa QLowEnergyService, QLowEnergyCharacteristic, QLowEnergyDescriptor */ @@ -342,13 +339,18 @@ quint16 QLowEnergyControllerPrivate::updateValueOfCharacteristic( QLowEnergyHandle charHandle,const QByteArray &value, bool appendValue) { QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(charHandle); - if (!service.isNull() && service->characteristicList.contains(charHandle)) { - if (appendValue) - service->characteristicList[charHandle].value += value; - else - service->characteristicList[charHandle].value = value; + if (!service.isNull()) { + CharacteristicDataMap::iterator charIt = service->characteristicList.find(charHandle); + if (charIt != service->characteristicList.end()) { + QLowEnergyServicePrivate::CharData &charDetails = charIt.value(); + + if (appendValue) + charDetails.value += value; + else + charDetails.value = value; - return service->characteristicList[charHandle].value.size(); + return charDetails.value.size(); + } } return 0; @@ -362,18 +364,26 @@ quint16 QLowEnergyControllerPrivate::updateValueOfDescriptor( const QByteArray &value, bool appendValue) { QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(charHandle); - if (service.isNull() || !service->characteristicList.contains(charHandle)) - return 0; - - if (!service->characteristicList[charHandle].descriptorList.contains(descriptorHandle)) - return 0; - - if (appendValue) - service->characteristicList[charHandle].descriptorList[descriptorHandle].value += value; - else - service->characteristicList[charHandle].descriptorList[descriptorHandle].value = value; + if (!service.isNull()) { + CharacteristicDataMap::iterator charIt = service->characteristicList.find(charHandle); + if (charIt != service->characteristicList.end()) { + QLowEnergyServicePrivate::CharData &charDetails = charIt.value(); + + DescriptorDataMap::iterator descIt = charDetails.descriptorList.find(descriptorHandle); + if (descIt != charDetails.descriptorList.end()) { + QLowEnergyServicePrivate::DescData &descDetails = descIt.value(); + + if (appendValue) + descDetails.value += value; + else + descDetails.value = value; + + return descDetails.value.size(); + } + } + } - return service->characteristicList[charHandle].descriptorList[descriptorHandle].value.size(); + return 0; } /*! @@ -385,6 +395,8 @@ quint16 QLowEnergyControllerPrivate::updateValueOfDescriptor( The controller uses the local default Bluetooth adapter for the connection management. + + \obsolete */ QLowEnergyController::QLowEnergyController( const QBluetoothAddress &remoteDevice, @@ -420,6 +432,7 @@ QLowEnergyController::QLowEnergyController( d->remoteDevice = remoteDeviceInfo.address(); d->localAdapter = QBluetoothLocalDevice().address(); d->addressType = QLowEnergyController::PublicAddress; + d->remoteName = remoteDeviceInfo.name(); } /*! @@ -434,6 +447,8 @@ QLowEnergyController::QLowEnergyController( \a localDevice specifies a local device that is not a local Bluetooth adapter, \l error() is set to \l InvalidBluetoothAdapterError once \l connectToDevice() is called. + + \obsolete */ QLowEnergyController::QLowEnergyController( const QBluetoothAddress &remoteDevice, @@ -480,6 +495,16 @@ QBluetoothAddress QLowEnergyController::remoteAddress() const } /*! + Returns the name of the remote Bluetooth Low Energy device. + + \since 5.5 + */ +QString QLowEnergyController::remoteName() const +{ + return d_ptr->remoteName; +} + +/*! Returns the current state of the controller. \sa stateChanged() @@ -629,11 +654,15 @@ QLowEnergyService *QLowEnergyController::createServiceObject( const QBluetoothUuid &serviceUuid, QObject *parent) { Q_D(QLowEnergyController); - if (!d->serviceList.contains(serviceUuid)) - return 0; - QLowEnergyService *service = new QLowEnergyService( - d->serviceList.value(serviceUuid), parent); + QLowEnergyService *service = Q_NULLPTR; + + ServiceDataMap::const_iterator it = d->serviceList.constFind(serviceUuid); + if (it != d->serviceList.constEnd()) { + const QSharedPointer<QLowEnergyServicePrivate> &serviceData = it.value(); + + service = new QLowEnergyService(serviceData, parent); + } return service; } diff --git a/src/bluetooth/qlowenergycontroller.h b/src/bluetooth/qlowenergycontroller.h index 1d29502b..be729dda 100644 --- a/src/bluetooth/qlowenergycontroller.h +++ b/src/bluetooth/qlowenergycontroller.h @@ -55,6 +55,7 @@ public: InvalidBluetoothAdapterError, ConnectionError }; + Q_ENUM(Error) enum ControllerState { UnconnectedState = 0, @@ -64,24 +65,28 @@ public: DiscoveredState, ClosingState }; + Q_ENUM(ControllerState) enum RemoteAddressType { PublicAddress = 0, RandomAddress }; + Q_ENUM(RemoteAddressType) explicit QLowEnergyController(const QBluetoothAddress &remoteDevice, - QObject *parent = 0); + QObject *parent = 0); // TODO Qt 6 remove ctor explicit QLowEnergyController(const QBluetoothDeviceInfo &remoteDevice, QObject *parent = 0); explicit QLowEnergyController(const QBluetoothAddress &remoteDevice, const QBluetoothAddress &localDevice, - QObject *parent = 0); + QObject *parent = 0); // TODO Qt 6 remove ctor ~QLowEnergyController(); QBluetoothAddress localAddress() const; QBluetoothAddress remoteAddress() const; + QString remoteName() const; + ControllerState state() const; RemoteAddressType remoteAddressType() const; @@ -114,7 +119,8 @@ private: QT_END_NAMESPACE -Q_DECLARE_METATYPE(QLowEnergyController::ControllerState) Q_DECLARE_METATYPE(QLowEnergyController::Error) +Q_DECLARE_METATYPE(QLowEnergyController::ControllerState) +Q_DECLARE_METATYPE(QLowEnergyController::RemoteAddressType) #endif // QLOWENERGYCONTROLLER_H diff --git a/src/bluetooth/qlowenergycontroller_android.cpp b/src/bluetooth/qlowenergycontroller_android.cpp index f48c0e85..b04ddedd 100644 --- a/src/bluetooth/qlowenergycontroller_android.cpp +++ b/src/bluetooth/qlowenergycontroller_android.cpp @@ -453,9 +453,11 @@ void QLowEnergyControllerPrivate::descriptorRead( serviceList.value(serviceUuid); bool entryUpdated = false; - foreach (QLowEnergyHandle charHandle, service->characteristicList.keys()) { - QLowEnergyServicePrivate::CharData &charDetails = - service->characteristicList[charHandle]; + + CharacteristicDataMap::iterator charIt = service->characteristicList.begin(); + for ( ; charIt != service->characteristicList.end(); ++charIt) { + QLowEnergyServicePrivate::CharData &charDetails = charIt.value(); + if (charDetails.uuid != charUuid) continue; diff --git a/src/bluetooth/qlowenergycontroller_bluez.cpp b/src/bluetooth/qlowenergycontroller_bluez.cpp index bb490ba9..a7b2e794 100644 --- a/src/bluetooth/qlowenergycontroller_bluez.cpp +++ b/src/bluetooth/qlowenergycontroller_bluez.cpp @@ -478,7 +478,7 @@ QLowEnergyHandle parseReadByTypeCharDiscovery( QLowEnergyHandle attributeHandle = bt_get_le16(&data[0]); charData->properties = - (QLowEnergyCharacteristic::PropertyTypes)data[2]; + (QLowEnergyCharacteristic::PropertyTypes)(data[2] & 0xff); charData->valueHandle = bt_get_le16(&data[3]); if (elementLength == 7) // 16 bit uuid @@ -672,6 +672,7 @@ void QLowEnergyControllerPrivate::processReply( lastHandle = parseReadByTypeCharDiscovery( &characteristic, &data[offset], elementLength); p->characteristicList[lastHandle] = characteristic; + offset += elementLength; } else if (attributeType == GATT_INCLUDED_SERVICE) { QList<QBluetoothUuid> includedServices; lastHandle = parseReadByTypeIncludeDiscovery( @@ -1150,12 +1151,11 @@ void QLowEnergyControllerPrivate::readServiceValues( // Create list of attribute handles which need to be read QList<QPair<QLowEnergyHandle, quint32> > targetHandles; - const QList<QLowEnergyHandle> keys = service->characteristicList.keys(); - for (int i = 0; i < keys.count(); i++) { - const QLowEnergyHandle charHandle = keys[i]; - const QLowEnergyServicePrivate::CharData &charDetails = - service->characteristicList[charHandle]; + CharacteristicDataMap::const_iterator charIt = service->characteristicList.constBegin(); + for ( ; charIt != service->characteristicList.constEnd(); ++charIt) { + const QLowEnergyHandle charHandle = charIt.key(); + const QLowEnergyServicePrivate::CharData &charDetails = charIt.value(); if (readCharacteristics) { // Collect handles of all characteristic value attributes @@ -1170,7 +1170,10 @@ void QLowEnergyControllerPrivate::readServiceValues( } else { // Collect handles of all descriptor attributes - foreach (QLowEnergyHandle descriptorHandle, charDetails.descriptorList.keys()) { + DescriptorDataMap::const_iterator descIt = charDetails.descriptorList.constBegin(); + for ( ; descIt != charDetails.descriptorList.constEnd(); ++descIt) { + const QLowEnergyHandle descriptorHandle = descIt.key(); + pair.first = descriptorHandle; pair.second = (charHandle | (descriptorHandle << 16)); targetHandles.append(pair); @@ -1222,7 +1225,7 @@ void QLowEnergyControllerPrivate::readServiceValues( starting the next read request. */ void QLowEnergyControllerPrivate::readServiceValuesByOffset( - quint16 handleData, quint16 offset, bool isLastValue) + uint handleData, quint16 offset, bool isLastValue) { const QLowEnergyHandle charHandle = (handleData & 0xffff); const QLowEnergyHandle descriptorHandle = ((handleData >> 16) & 0xffff); @@ -1269,15 +1272,15 @@ void QLowEnergyControllerPrivate::discoverServiceDescriptors( qCDebug(QT_BT_BLUEZ) << "Discovering descriptor values for" << serviceUuid.toString(); QSharedPointer<QLowEnergyServicePrivate> service = serviceList.value(serviceUuid); - // start handle of all known characteristics - QList<QLowEnergyHandle> keys = service->characteristicList.keys(); - if (keys.isEmpty()) { // service has no characteristics + if (service->characteristicList.isEmpty()) { // service has no characteristics // implies that characteristic & descriptor discovery can be skipped service->setState(QLowEnergyService::ServiceDiscovered); return; } + // start handle of all known characteristics + QList<QLowEnergyHandle> keys = service->characteristicList.keys(); std::sort(keys.begin(), keys.end()); discoverNextDescriptor(service, keys, keys[0]); diff --git a/src/bluetooth/qlowenergycontroller_osx.mm b/src/bluetooth/qlowenergycontroller_osx.mm index e3cf57b1..d0d65248 100644 --- a/src/bluetooth/qlowenergycontroller_osx.mm +++ b/src/bluetooth/qlowenergycontroller_osx.mm @@ -151,6 +151,7 @@ QLowEnergyControllerPrivateOSX::QLowEnergyControllerPrivateOSX(QLowEnergyControl const QBluetoothDeviceInfo &deviceInfo) : q_ptr(q), deviceUuid(deviceInfo.deviceUuid()), + deviceName(deviceInfo.name()), isConnecting(false), lastError(QLowEnergyController::NoError), controllerState(QLowEnergyController::UnconnectedState), @@ -276,7 +277,9 @@ void QLowEnergyControllerPrivateOSX::serviceDiscoveryFinished(LEServices service qCDebug(QT_BT_OSX) << Q_FUNC_INFO << "no services found"; } - foreach (const QBluetoothUuid &uuid, discoveredServices.keys()) { + for (ServiceMap::const_iterator it = discoveredServices.constBegin(); it != discoveredServices.constEnd(); ++it) { + const QBluetoothUuid &uuid = it.key(); + QMetaObject::invokeMethod(q_ptr, "serviceDiscovered", Qt::QueuedConnection, Q_ARG(QBluetoothUuid, uuid)); } @@ -641,13 +644,18 @@ quint16 QLowEnergyControllerPrivateOSX::updateValueOfCharacteristic(QLowEnergyHa bool appendValue) { QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(charHandle); - if (!service.isNull() && service->characteristicList.contains(charHandle)) { - if (appendValue) - service->characteristicList[charHandle].value += value; - else - service->characteristicList[charHandle].value = value; + if (!service.isNull()) { + CharacteristicDataMap::iterator charIt = service->characteristicList.find(charHandle); + if (charIt != service->characteristicList.end()) { + QLowEnergyServicePrivate::CharData &charData = charIt.value(); + + if (appendValue) + charData.value += value; + else + charData.value = value; - return service->characteristicList[charHandle].value.size(); + return charData.value.size(); + } } return 0; @@ -692,19 +700,27 @@ void QLowEnergyControllerPrivateOSX::writeDescriptor(QSharedPointer<QLowEnergySe quint16 QLowEnergyControllerPrivateOSX::updateValueOfDescriptor(QLowEnergyHandle charHandle, QLowEnergyHandle descHandle, const QByteArray &value, bool appendValue) { - ServicePrivate service(serviceForHandle(charHandle)); - if (service.isNull() || !service->characteristicList.contains(charHandle)) - return 0; + QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(charHandle); + if (!service.isNull()) { + CharacteristicDataMap::iterator charIt = service->characteristicList.find(charHandle); + if (charIt != service->characteristicList.end()) { + QLowEnergyServicePrivate::CharData &charData = charIt.value(); - if (!service->characteristicList[charHandle].descriptorList.contains(descHandle)) - return 0; + DescriptorDataMap::iterator descIt = charData.descriptorList.find(descHandle); + if (descIt != charData.descriptorList.end()) { + QLowEnergyServicePrivate::DescData &descDetails = descIt.value(); - if (appendValue) - service->characteristicList[charHandle].descriptorList[descHandle].value += value; - else - service->characteristicList[charHandle].descriptorList[descHandle].value = value; + if (appendValue) + descDetails.value += value; + else + descDetails.value = value; + + return descDetails.value.size(); + } + } + } - return service->characteristicList[charHandle].descriptorList[descHandle].value.size(); + return 0; } QSharedPointer<QLowEnergyServicePrivate> QLowEnergyControllerPrivateOSX::serviceForHandle(QLowEnergyHandle handle) @@ -855,6 +871,13 @@ QBluetoothAddress QLowEnergyController::remoteAddress() const return osx_d_ptr->remoteAddress; } +QString QLowEnergyController::remoteName() const +{ + OSX_D_PTR; + + return osx_d_ptr->deviceName; +} + QLowEnergyController::ControllerState QLowEnergyController::state() const { OSX_D_PTR; @@ -944,10 +967,16 @@ QLowEnergyService *QLowEnergyController::createServiceObject(const QBluetoothUui { OSX_D_PTR; - if (!osx_d_ptr->discoveredServices.contains(serviceUuid)) - return Q_NULLPTR; + QLowEnergyService *service = Q_NULLPTR; + + QLowEnergyControllerPrivateOSX::ServiceMap::const_iterator it = osx_d_ptr->discoveredServices.constFind(serviceUuid); + if (it != osx_d_ptr->discoveredServices.constEnd()) { + const QSharedPointer<QLowEnergyServicePrivate> &serviceData = it.value(); + + service = new QLowEnergyService(serviceData, parent); + } - return new QLowEnergyService(osx_d_ptr->discoveredServices.value(serviceUuid), parent); + return service; } QLowEnergyController::Error QLowEnergyController::error() const diff --git a/src/bluetooth/qlowenergycontroller_osx_p.h b/src/bluetooth/qlowenergycontroller_osx_p.h index 96af6db0..1a4d5707 100644 --- a/src/bluetooth/qlowenergycontroller_osx_p.h +++ b/src/bluetooth/qlowenergycontroller_osx_p.h @@ -131,6 +131,7 @@ private: QLowEnergyController *q_ptr; QBluetoothUuid deviceUuid; + QString deviceName; // To be sure we set controller's state correctly // (Connecting or Connected) we have to know if we're // still inside connectToDevice - this is important, diff --git a/src/bluetooth/qlowenergycontroller_p.h b/src/bluetooth/qlowenergycontroller_p.h index d40c0b6b..6d81316d 100644 --- a/src/bluetooth/qlowenergycontroller_p.h +++ b/src/bluetooth/qlowenergycontroller_p.h @@ -138,6 +138,8 @@ public: QBluetoothAddress remoteDevice; QBluetoothAddress localAdapter; + QString remoteName; + QLowEnergyController::ControllerState state; QLowEnergyController::Error error; QString errorString; @@ -177,7 +179,7 @@ private: void sendReadValueRequest(QLowEnergyHandle attributeHandle, bool isDescriptor); void readServiceValues(const QBluetoothUuid &service, bool readCharacteristics); - void readServiceValuesByOffset(quint16 handleData, quint16 offset, + void readServiceValuesByOffset(uint handleData, quint16 offset, bool isLastValue); void discoverServiceDescriptors(const QBluetoothUuid &serviceUuid); diff --git a/src/bluetooth/qlowenergydescriptor.cpp b/src/bluetooth/qlowenergydescriptor.cpp index 16b5b02b..cf1f46fa 100644 --- a/src/bluetooth/qlowenergydescriptor.cpp +++ b/src/bluetooth/qlowenergydescriptor.cpp @@ -57,9 +57,6 @@ QT_BEGIN_NAMESPACE The \l {QLowEnergyService::descriptorWritten()} signal is emitted upon success. The cahced \l value() of this object is updated accordingly. - \note This class is provided by Qt 5.4 as part of a Bluetooth Low Energy Tech Preview. - Some API elements may change until the final release of the feature. - \sa QLowEnergyService, QLowEnergyCharacteristic */ diff --git a/src/bluetooth/qlowenergyservice.cpp b/src/bluetooth/qlowenergyservice.cpp index f7a73326..9fb8e47c 100644 --- a/src/bluetooth/qlowenergyservice.cpp +++ b/src/bluetooth/qlowenergyservice.cpp @@ -159,9 +159,6 @@ QT_BEGIN_NAMESPACE related \l QLowEnergyController disconnecting from the device are shared the same way. - \note This class is provided by Qt 5.4 as part of a Bluetooth Low Energy Tech Preview. - Some API elements may change until the final release of the feature. - \sa QLowEnergyController, QLowEnergyCharacteristic, QLowEnergyDescriptor */ @@ -352,6 +349,8 @@ QLowEnergyService::QLowEnergyService(QSharedPointer<QLowEnergyServicePrivate> p, { qRegisterMetaType<QLowEnergyService::ServiceState>(); qRegisterMetaType<QLowEnergyService::ServiceError>(); + qRegisterMetaType<QLowEnergyService::ServiceType>(); + qRegisterMetaType<QLowEnergyService::WriteMode>(); connect(p.data(), SIGNAL(error(QLowEnergyService::ServiceError)), this, SIGNAL(error(QLowEnergyService::ServiceError))); @@ -455,9 +454,13 @@ QLowEnergyService::ServiceTypes QLowEnergyService::type() const */ QLowEnergyCharacteristic QLowEnergyService::characteristic(const QBluetoothUuid &uuid) const { - foreach (const QLowEnergyHandle handle, d_ptr->characteristicList.keys()) { - if (d_ptr->characteristicList[handle].uuid == uuid) - return QLowEnergyCharacteristic(d_ptr, handle); + CharacteristicDataMap::const_iterator charIt = d_ptr->characteristicList.constBegin(); + for ( ; charIt != d_ptr->characteristicList.constEnd(); ++charIt) { + const QLowEnergyHandle charHandle = charIt.key(); + const QLowEnergyServicePrivate::CharData &charDetails = charIt.value(); + + if (charDetails.uuid == uuid) + return QLowEnergyCharacteristic(d_ptr, charHandle); } return QLowEnergyCharacteristic(); @@ -598,9 +601,7 @@ void QLowEnergyService::readCharacteristic( { Q_D(QLowEnergyService); - if (!contains(characteristic) - || state() != ServiceDiscovered - || !d->controller) { + if (d->controller == Q_NULLPTR || state() != ServiceDiscovered || !contains(characteristic)) { d->setError(QLowEnergyService::OperationError); return; } @@ -649,9 +650,7 @@ void QLowEnergyService::writeCharacteristic( //TODO check behavior when writing to WriteSigned characteristic Q_D(QLowEnergyService); - if (!contains(characteristic) - || state() != ServiceDiscovered - || !d->controller) { + if (d->controller == Q_NULLPTR || state() != ServiceDiscovered || !contains(characteristic)) { d->setError(QLowEnergyService::OperationError); return; } @@ -717,9 +716,7 @@ void QLowEnergyService::readDescriptor( { Q_D(QLowEnergyService); - if (!contains(descriptor) - || state() != ServiceDiscovered - || !d->controller) { + if (d->controller == Q_NULLPTR || state() != ServiceDiscovered || !contains(descriptor)) { d->setError(QLowEnergyService::OperationError); return; } @@ -751,9 +748,7 @@ void QLowEnergyService::writeDescriptor(const QLowEnergyDescriptor &descriptor, { Q_D(QLowEnergyService); - if (!contains(descriptor) - || state() != ServiceDiscovered - || !d->controller) { + if (d->controller == Q_NULLPTR || state() != ServiceDiscovered || !contains(descriptor)) { d->setError(QLowEnergyService::OperationError); return; } diff --git a/src/bluetooth/qlowenergyservice.h b/src/bluetooth/qlowenergyservice.h index 9b6e73f4..524650c9 100644 --- a/src/bluetooth/qlowenergyservice.h +++ b/src/bluetooth/qlowenergyservice.h @@ -50,6 +50,7 @@ public: PrimaryService = 0x0001, IncludedService = 0x0002 }; + Q_ENUM(ServiceType) Q_DECLARE_FLAGS(ServiceTypes, ServiceType) enum ServiceError { @@ -61,6 +62,7 @@ public: CharacteristicReadError, DescriptorReadError }; + Q_ENUM(ServiceError) enum ServiceState { InvalidService = 0, @@ -69,11 +71,13 @@ public: DiscoveringServices,// discoverDetails() called and running ServiceDiscovered // all details have been synchronized }; + Q_ENUM(ServiceState) enum WriteMode { WriteWithResponse = 0, WriteWithoutResponse }; + Q_ENUM(WriteMode) ~QLowEnergyService(); @@ -126,9 +130,13 @@ private: QObject *parent = 0); }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QLowEnergyService::ServiceTypes) + QT_END_NAMESPACE -Q_DECLARE_METATYPE(QLowEnergyService::ServiceState) Q_DECLARE_METATYPE(QLowEnergyService::ServiceError) +Q_DECLARE_METATYPE(QLowEnergyService::ServiceState) +Q_DECLARE_METATYPE(QLowEnergyService::ServiceType) +Q_DECLARE_METATYPE(QLowEnergyService::WriteMode) #endif // QLOWENERGYSERVICE_H diff --git a/src/bluetooth/qlowenergyservice_osx.mm b/src/bluetooth/qlowenergyservice_osx.mm index b424dc96..da1636cb 100644 --- a/src/bluetooth/qlowenergyservice_osx.mm +++ b/src/bluetooth/qlowenergyservice_osx.mm @@ -104,9 +104,13 @@ QLowEnergyService::ServiceState QLowEnergyService::state() const QLowEnergyCharacteristic QLowEnergyService::characteristic(const QBluetoothUuid &uuid) const { - foreach (const QLowEnergyHandle handle, d_ptr->characteristicList.keys()) { - if (d_ptr->characteristicList[handle].uuid == uuid) - return QLowEnergyCharacteristic(d_ptr, handle); + CharacteristicDataMap::const_iterator charIt = d_ptr->characteristicList.constBegin(); + for ( ; charIt != d_ptr->characteristicList.constEnd(); ++charIt) { + const QLowEnergyHandle charHandle = charIt.key(); + const QLowEnergyServicePrivate::CharData &charDetails = charIt.value(); + + if (charDetails.uuid == uuid) + return QLowEnergyCharacteristic(d_ptr, charHandle); } return QLowEnergyCharacteristic(); @@ -185,7 +189,7 @@ bool QLowEnergyService::contains(const QLowEnergyCharacteristic &characteristic) void QLowEnergyService::readCharacteristic(const QLowEnergyCharacteristic &characteristic) { QLowEnergyControllerPrivateOSX *const controller = qt_mac_le_controller(d_ptr); - if (!contains(characteristic) || state() != ServiceDiscovered || !controller) { + if (controller == Q_NULLPTR || state() != ServiceDiscovered || !contains(characteristic)) { d_ptr->setError(OperationError); return; } @@ -198,8 +202,7 @@ void QLowEnergyService::writeCharacteristic(const QLowEnergyCharacteristic &ch, WriteMode mode) { QLowEnergyControllerPrivateOSX *const controller = qt_mac_le_controller(d_ptr); - - if (!contains(ch) || state() != ServiceDiscovered || !controller) { + if (controller == Q_NULLPTR || state() != ServiceDiscovered || !contains(ch)) { d_ptr->setError(QLowEnergyService::OperationError); return; } @@ -234,7 +237,7 @@ bool QLowEnergyService::contains(const QLowEnergyDescriptor &descriptor) const void QLowEnergyService::readDescriptor(const QLowEnergyDescriptor &descriptor) { QLowEnergyControllerPrivateOSX *const controller = qt_mac_le_controller(d_ptr); - if (!contains(descriptor) || state() != ServiceDiscovered || !controller) { + if (controller == Q_NULLPTR || state() != ServiceDiscovered || !contains(descriptor)) { d_ptr->setError(OperationError); return; } @@ -246,7 +249,7 @@ void QLowEnergyService::writeDescriptor(const QLowEnergyDescriptor &descriptor, const QByteArray &newValue) { QLowEnergyControllerPrivateOSX *const controller = qt_mac_le_controller(d_ptr); - if (!contains(descriptor) || state() != ServiceDiscovered || !controller) { + if (controller == Q_NULLPTR || state() != ServiceDiscovered || !contains(descriptor)) { d_ptr->setError(OperationError); return; } diff --git a/src/bluetooth/qlowenergyserviceprivate_p.h b/src/bluetooth/qlowenergyserviceprivate_p.h index a020341f..0232b912 100644 --- a/src/bluetooth/qlowenergyserviceprivate_p.h +++ b/src/bluetooth/qlowenergyserviceprivate_p.h @@ -104,6 +104,9 @@ public: QPointer<QLowEnergyControllerPrivate> controller; }; +typedef QHash<QLowEnergyHandle, QLowEnergyServicePrivate::CharData> CharacteristicDataMap; +typedef QHash<QLowEnergyHandle, QLowEnergyServicePrivate::DescData> DescriptorDataMap; + QT_END_NAMESPACE Q_DECLARE_METATYPE(QSharedPointer<QLowEnergyServicePrivate>) diff --git a/src/bluetooth/qnx/ppshelpers.cpp b/src/bluetooth/qnx/ppshelpers.cpp deleted file mode 100644 index 215839cc..00000000 --- a/src/bluetooth/qnx/ppshelpers.cpp +++ /dev/null @@ -1,449 +0,0 @@ -/*************************************************************************** -** -** Copyright (C) 2012 Research In Motion -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtBluetooth module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "ppshelpers_p.h" -#include <QtCore/private/qcore_unix_p.h> -#include <QDebug> -#include "../qbluetoothserver_p.h" -#include <QTimer> - -QT_BEGIN_NAMESPACE - -static int count = 0; - -static int ppsCtrlFD = -1; - -static QSocketNotifier *ppsCtrlNotifier = 0; - -static const char btControlFDPath[] = "/pps/services/bluetooth/public/control"; -static const char btSettingsFDPath[] = "/pps/services/bluetooth/settings"; -static const char btRemoteDevFDPath[] = "/pps/services/bluetooth/remote_devices/"; -static const char btMediaFDPath[] = "/pps/services/bluetooth/media/control"; - -static const int ppsBufferSize = 1024; - -static int ctrlId = 20; - -static QList<QPair<int, QObject*> > waitingCtrlMsgs; - -static BBSocketNotifier bbSocketNotifier; - -QHash<QBluetoothServerPrivate*, int> __fakeServerPorts; - -QList<QPair<QString, QObject*> > evtRegistration; - -void BBSocketNotifier::distribute() -{ - ppsDecodeControlResponse(); -} - -void BBSocketNotifier::closeControlFD() -{ - if (count <= 0) { - delete ppsCtrlNotifier; - qt_safe_close(ppsCtrlFD); - ppsCtrlFD = -1; - ppsCtrlNotifier = 0; - } -} - -QPair<int, QObject*> takeObjectInWList(int id) -{ - for (int i=0; i<waitingCtrlMsgs.size(); i++) { - if (waitingCtrlMsgs.at(i).first == id) - return waitingCtrlMsgs.takeAt(i); - } - return QPair<int, QObject*>(-1,0); -} - -void ppsRegisterControl() -{ - count++; - if (count == 1) { - if (ppsCtrlFD != -1) { - qCDebug(QT_BT_QNX) << "PPS control FD not properly deinitialized"; - return; - } - ppsCtrlFD = qt_safe_open(btControlFDPath, O_RDWR | O_SYNC); - if (ppsCtrlFD == -1) { - qCWarning(QT_BT_QNX) << Q_FUNC_INFO << "ppsCtrlFD - failed to qt_safe_open" << btControlFDPath; - } else { - ppsCtrlNotifier = new QSocketNotifier(ppsCtrlFD, QSocketNotifier::Read); - QObject::connect(ppsCtrlNotifier, SIGNAL(activated(int)), &bbSocketNotifier, SLOT(distribute())); - } - } -} - -void ppsUnregisterControl(QObject *obj) -{ - count--; - if (count == 0) { - //QMetaObject::invokeMethod(&bbSocketNotifier, "closeControlFD",Qt::QueuedConnection); - //We need to postpone the closing of the file descriptor, otherwise the last message - //might not have gone through...a queued connection is not enough here - QTimer::singleShot(5, &bbSocketNotifier, SLOT(closeControlFD())); - } - for (int i = waitingCtrlMsgs.size()-1; i >= 0 ; i--) { - if (waitingCtrlMsgs.at(i).second == obj) - waitingCtrlMsgs.removeAt(i); - } -} - -pps_encoder_t *beginCtrlMessage(const char *msg, QObject *sender) -{ - pps_encoder_t *encoder= new pps_encoder_t; - pps_encoder_initialize(encoder, 0); - pps_encoder_add_string(encoder, "msg", msg); - ctrlId++; - pps_encoder_add_string(encoder, "id", QString::number(ctrlId).toStdString().c_str() ); - waitingCtrlMsgs.append(QPair<int, QObject*>(ctrlId, sender)); - return encoder; -} - -bool endCtrlMessage(pps_encoder_t *encoder) -{ - qCDebug(QT_BT_QNX) << "writing" << pps_encoder_buffer(encoder); - if (pps_encoder_buffer(encoder) != 0) { - int res = qt_safe_write(ppsCtrlFD, pps_encoder_buffer(encoder), pps_encoder_length(encoder)); - if (res == -1) { - qCWarning(QT_BT_QNX) << Q_FUNC_INFO << "Error when writing to control FD. Is Bluetooth powerd on?" - << errno << ppsCtrlFD << count; - return false; - } - } - - pps_encoder_cleanup( encoder ); - return true; -} - -bool ppsSendControlMessage(const char *msg, int service, const QBluetoothUuid &uuid, const QString &address, const QString &serviceName, QObject *sender, const int &subtype) -{ - pps_encoder_t *encoder = beginCtrlMessage(msg, sender); - pps_encoder_start_object(encoder, "dat"); - pps_encoder_add_int(encoder, "service", service); - if (subtype != -1) - pps_encoder_add_int(encoder, "subtype", subtype); - - pps_encoder_add_string(encoder, "uuid", uuid.toString().mid(1,36).toUtf8().constData()); - - if (!serviceName.isEmpty()) { - pps_encoder_add_string(encoder, "name", serviceName.toUtf8().constData()); - } - if (!address.isEmpty()) { - pps_encoder_add_string(encoder, "addr", address.toUtf8().constData()); - } - - pps_encoder_error_t rese = pps_encoder_end_object(encoder); - - if (rese != PPS_ENCODER_OK) { - errno = EPERM; - return false; - } - - return endCtrlMessage(encoder); -} - -bool ppsSendControlMessage(const char *msg, const QString &dat, QObject *sender) -{ - pps_encoder_t *encoder = beginCtrlMessage(msg, sender); - pps_encoder_add_json(encoder, "dat", dat.toUtf8().constData()); - return endCtrlMessage(encoder); -} - -bool ppsSendControlMessage(const char *msg, QObject *sender) -{ - pps_encoder_t *encoder = beginCtrlMessage(msg, sender); - return endCtrlMessage(encoder); -} - -int __newHostMode = -1; - -void ppsDecodeControlResponse() -{ - ppsResult result; - ResultType resType = UNKNOWN; - - if (ppsCtrlFD != -1) { - char buf[ppsBufferSize]; - qt_safe_read(ppsCtrlFD, &buf, sizeof(buf) ); - if (buf[0] != '@') - return; - qCDebug(QT_BT_QNX) << "CTRL Response" << buf; - - pps_decoder_t ppsDecoder; - pps_decoder_initialize(&ppsDecoder, 0); - if (pps_decoder_parse_pps_str(&ppsDecoder, buf) == PPS_DECODER_OK) { - pps_decoder_push(&ppsDecoder, 0); - const char *buf; - - //The pps response can either be of type 'res', 'msg' or 'evt' - if (pps_decoder_get_string(&ppsDecoder, "res", &buf) == PPS_DECODER_OK) { - result.msg = QString::fromUtf8(buf); - resType = RESPONSE; - } else if (pps_decoder_get_string(&ppsDecoder, "msg", &buf) == PPS_DECODER_OK) { - result.msg = QString::fromUtf8(buf); - resType = MESSAGE; - } else if (pps_decoder_get_string(&ppsDecoder, "evt", &buf) == PPS_DECODER_OK) { - result.msg = QString::fromUtf8(buf); - resType = EVENT; - } - - if (pps_decoder_get_string(&ppsDecoder, "id", &buf) == PPS_DECODER_OK) - result.id = QString::fromUtf8(buf).toInt(); - - //read out the error message if there is one - if (pps_decoder_get_string(&ppsDecoder, "errstr", &buf) == PPS_DECODER_OK) - result.errorMsg = QString::fromUtf8(buf); - - int dat; - if (pps_decoder_get_int(&ppsDecoder, "err", &dat) == PPS_DECODER_OK) { - result.error = dat; - } - - //The dat object can be either a string or a array - pps_node_type_t nodeType = pps_decoder_type(&ppsDecoder,"dat"); - if (nodeType == PPS_TYPE_STRING) { - pps_decoder_get_string(&ppsDecoder,"dat",&buf); - result.dat << QString::fromUtf8(buf); - } else if (nodeType == PPS_TYPE_OBJECT || nodeType == PPS_TYPE_ARRAY) { - pps_decoder_push(&ppsDecoder,"dat"); - pps_decoder_goto_index(&ppsDecoder, 0); - int len = pps_decoder_length(&ppsDecoder); - - for (int i = 0; i < len; ++i) { - switch ( pps_decoder_type(&ppsDecoder, 0)) { - case PPS_TYPE_STRING: - result.dat << QString::fromUtf8(pps_decoder_name(&ppsDecoder)); - pps_decoder_get_string(&ppsDecoder, 0, &buf); - result.dat << QString::fromUtf8(buf); - break; - case PPS_TYPE_NUMBER: - result.dat << QString::fromUtf8(pps_decoder_name(&ppsDecoder)); - double dvalue; - pps_decoder_get_double(&ppsDecoder, 0, &dvalue); - result.dat << QString::number(dvalue); - break; - default: - pps_decoder_next(&ppsDecoder); - } - } - } else { - qCDebug(QT_BT_QNX) << "Control Response: No node type" << result.msg; - } - } - pps_decoder_cleanup(&ppsDecoder); - } - - if (result.msg == QStringLiteral("radio_init")) { - qCDebug(QT_BT_QNX) << "Radio initialized"; - } else if (result.msg == QStringLiteral("access_changed") && __newHostMode != -1) { - qCDebug(QT_BT_QNX) << "Access changed after radio init"; - ppsSendControlMessage("set_access", QStringLiteral("{\"access\":%1}").arg(__newHostMode), 0); - __newHostMode = -1; - } - - if (resType == RESPONSE) { - QPair<int, QObject*> wMessage = takeObjectInWList(result.id); - if (wMessage.second != 0) - wMessage.second->metaObject()->invokeMethod(wMessage.second, "controlReply", Q_ARG(ppsResult, result)); - } else if (resType == EVENT) { - //qCDebug(QT_BT_QNX) << "Distributing event" << result.msg; - for (int i=0; i < evtRegistration.size(); i++) { - if (result.msg == evtRegistration.at(i).first) - evtRegistration.at(i).second->metaObject()->invokeMethod(evtRegistration.at(i).second, "controlEvent", Q_ARG(ppsResult, result)); - } - } -} - -void ppsSendOpp(const char *msg, const QByteArray &url, const QBluetoothAddress &address, QObject *sender) -{ - pps_encoder_t *encoder = beginCtrlMessage(msg, sender); - - pps_encoder_start_object(encoder, "dat"); - pps_encoder_add_string(encoder, "address", address.toString().toUtf8().constData()); - pps_encoder_start_array(encoder, "urls"); - pps_encoder_add_string(encoder, 0, url.constData()); - pps_encoder_end_array(encoder); - pps_encoder_end_object(encoder); - - endCtrlMessage(encoder); -} - -QVariant ppsReadSetting(const char *property) -{ - int settingsFD; - char buf[ppsBufferSize]; - if ((settingsFD = qt_safe_open(btSettingsFDPath, O_RDONLY)) == -1) { - qCWarning(QT_BT_QNX) << Q_FUNC_INFO << "failed to open "<< btSettingsFDPath; - return QVariant(); - } - - QVariant result; - - qt_safe_read( settingsFD, &buf, sizeof(buf)); - pps_decoder_t decoder; - pps_decoder_initialize(&decoder, 0); - - if (pps_decoder_parse_pps_str(&decoder, buf) == PPS_DECODER_OK) { - pps_decoder_push(&decoder, 0); - pps_node_type_t nodeType = pps_decoder_type(&decoder, property); - if (nodeType == PPS_TYPE_STRING) { - const char *dat; - if (pps_decoder_get_string(&decoder, property, &dat) == PPS_DECODER_OK) { - result = QString::fromUtf8(dat); - qCDebug(QT_BT_QNX) << "Read setting" << result; - } else { - qCWarning(QT_BT_QNX) << Q_FUNC_INFO << "could not read"<< property; - return QVariant(); - } - } else if (nodeType == PPS_TYPE_BOOL) { - bool dat; - if (pps_decoder_get_bool(&decoder, property, &dat) == PPS_DECODER_OK) { - result = dat; - qCDebug(QT_BT_QNX) << "Read setting" << result; - } else { - qCWarning(QT_BT_QNX) << Q_FUNC_INFO << "could not read"<< property; - return QVariant(); - } - } else if (nodeType == PPS_TYPE_NUMBER) { - int dat; - if (pps_decoder_get_int(&decoder, property, &dat) == PPS_DECODER_OK) { - result = dat; - qCDebug(QT_BT_QNX) << "Read setting" << result; - } else { - qCWarning(QT_BT_QNX) << Q_FUNC_INFO << "could not read"<< property; - return QVariant(); - } - } else { - qCDebug(QT_BT_QNX) << Q_FUNC_INFO << "unrecognized entry for settings"; - } - } - pps_decoder_cleanup(&decoder); - qt_safe_close(settingsFD); - return result; -} - -QVariant ppsRemoteDeviceStatus(const QByteArray &address, const char *property) -{ - int rmFD; - char buf[ppsBufferSize]; - QByteArray filename = btRemoteDevFDPath; - filename.append(address); - - if ((rmFD = qt_safe_open(filename.constData(), O_RDONLY)) < 0) { - qCWarning(QT_BT_QNX) << Q_FUNC_INFO << "failed to open "<< btRemoteDevFDPath << address; - return false; - } - - QVariant res; - - qt_safe_read(rmFD, &buf, sizeof(buf)); - pps_decoder_t ppsDecoder; - pps_decoder_initialize(&ppsDecoder, 0); - if (pps_decoder_parse_pps_str(&ppsDecoder, buf) == PPS_DECODER_OK) { - pps_decoder_push(&ppsDecoder, 0); - - //Find out about the node type - pps_node_type_t nodeType = pps_decoder_type(&ppsDecoder, property); - if (nodeType == PPS_TYPE_STRING) { - const char *dat; - pps_decoder_get_string(&ppsDecoder,property,&dat); - res = QString::fromUtf8(dat); - } else if (nodeType == PPS_TYPE_BOOL) { - bool dat; - pps_decoder_get_bool(&ppsDecoder,property,&dat); - res = QVariant(dat); - } else { - qCDebug(QT_BT_QNX) << "RDStatus: No node type" << property; - } - } - pps_decoder_cleanup(&ppsDecoder); - qt_safe_close(rmFD); - return res; -} - -bool ppsReadRemoteDevice(int fd, pps_decoder_t *decoder, QBluetoothAddress *btAddr, QString *deviceName) -{ - char buf[ppsBufferSize * 2]; - char addr_buf[18]; - - addr_buf[17] = '\0'; - - if (qt_safe_read(fd, &buf, sizeof(buf)) == -1) { - qCWarning(QT_BT_QNX) << Q_FUNC_INFO << "Could not qt_safe_read from pps remote device file"; - return false; - } - - qCDebug(QT_BT_QNX) << "Remote device" << buf; - - //the address of the BT device is stored at the beginning of the qt_safe_read - if (buf[0] != '-') { - memcpy(&addr_buf, &buf[1], 17); - } else { //The device was removed - memcpy(&addr_buf, &buf[2], 17); - return false; - } - - *btAddr = QBluetoothAddress(QString::fromUtf8(addr_buf)); - - if (pps_decoder_parse_pps_str(decoder, buf) == PPS_DECODER_OK) { - const char* name; - pps_decoder_push(decoder, 0); - - if (pps_decoder_get_string(decoder, "name", &name) == PPS_DECODER_OK) - (*deviceName) = QString::fromUtf8(name); - - return true; - } - return false; -} - -void ppsRegisterForEvent(const QString &evt, QObject *obj) -{ - //If the event was already registered, we don't register it again - for (int i = 0; i < evtRegistration.size(); i++) { - if (evtRegistration.at(i).first == evt && evtRegistration.at(i).second == obj ) - return; - } - evtRegistration.append(QPair<QString, QObject*>(evt,obj)); -} - -void ppsUnregisterForEvent(const QString &str, QObject *obj) -{ - for (int i=evtRegistration.size()-1; i >= 0; --i) { - if (evtRegistration.at(i).first == str && evtRegistration.at(i).second == obj) - evtRegistration.removeAt(i); - } -} - -QT_END_NAMESPACE diff --git a/src/bluetooth/qnx/ppshelpers_p.h b/src/bluetooth/qnx/ppshelpers_p.h deleted file mode 100644 index 0a3a1033..00000000 --- a/src/bluetooth/qnx/ppshelpers_p.h +++ /dev/null @@ -1,121 +0,0 @@ -/*************************************************************************** -** -** Copyright (C) 2012 Research In Motion -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtBluetooth module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PPSHELPERS_H -#define PPSHELPERS_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <fcntl.h> -#include <errno.h> -#include <sys/pps.h> - -#include <QtCore/QLoggingCategory> -#include <QtCore/QSocketNotifier> -#include <QtCore/QStringList> - -#include <QtBluetooth/qbluetoothuuid.h> -#include <QtBluetooth/qbluetoothaddress.h> - -#define BT_SPP_SERVER_SUBTYPE 1 -#define BT_SPP_CLIENT_SUBTYPE 2 - -QT_BEGIN_NAMESPACE - -Q_DECLARE_LOGGING_CATEGORY(QT_BT_QNX) - -class BBSocketNotifier : public QObject -{ - Q_OBJECT -public slots: - void distribute(); - void closeControlFD(); -}; - -enum ResultType {UNKNOWN, EVENT, MESSAGE, RESPONSE}; - -struct ppsResult { - ppsResult() : success(false), error(0) {} - - bool success; - int id; - QString msg; - QStringList dat; - QString errorMsg; - int error; -}; - -QPair<int, QObject*> takeObjectInWList(int id); - -void ppsRegisterControl(); - -void ppsUnregisterControl(QObject *obj); - -pps_encoder_t *beginCtrlMessage(const char *msg, QObject *sender); - -bool endCtrlMessage(pps_encoder_t *encoder); - -bool ppsSendControlMessage(const char *msg, int service, const QBluetoothUuid &uuid, const QString &address, const QString &serviceName, QObject *sender=0, const int &subtype=-1); - -bool ppsSendControlMessage(const char *msg, const QString &dat, QObject *sender=0); - -bool ppsSendControlMessage(const char *msg, QObject *sender=0); - -void ppsDecodeControlResponse(); - -int openOPPControl(); - -void ppsSendOpp(const char *msg, const QByteArray &filename, const QBluetoothAddress &address, QObject *sender); - -QVariant ppsReadSetting(const char *property); - -QVariant ppsRemoteDeviceStatus(const QByteArray &address, const char *property); - -bool ppsReadRemoteDevice(int fd, pps_decoder_t *decoder, QBluetoothAddress *btAddr, QString *deviceName); - -void ppsRegisterForEvent(const QString &evt, QObject *obj); - -void ppsUnregisterForEvent(const QString &evt, QObject *obj); - -QT_END_NAMESPACE - -#endif // PPSHELPERS_H diff --git a/src/bluetooth/qnx/qnx.pri b/src/bluetooth/qnx/qnx.pri deleted file mode 100644 index ec0b4dab..00000000 --- a/src/bluetooth/qnx/qnx.pri +++ /dev/null @@ -1,6 +0,0 @@ -QT += core-private - -HEADERS += \ - qnx/ppshelpers_p.h - -SOURCES += qnx/ppshelpers.cpp |