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 | |
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')
127 files changed, 2570 insertions, 5659 deletions
diff --git a/src/android/android.pro b/src/android/android.pro index 07feb78f..f8f5c05e 100644 --- a/src/android/android.pro +++ b/src/android/android.pro @@ -1,2 +1,3 @@ TEMPLATE = subdirs qtHaveModule(bluetooth): SUBDIRS += bluetooth +qtHaveModule(nfc): SUBDIRS += nfc diff --git a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java index f6c41e31..e5711426 100644 --- a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java +++ b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java @@ -133,6 +133,8 @@ public class QtBluetoothLE { resetData(); // reset mBluetoothGatt, reusing same object is not very reliable // sometimes it reconnects and sometimes it does not. + if (mBluetoothGatt != null) + mBluetoothGatt.close(); mBluetoothGatt = null; break; case BluetoothProfile.STATE_CONNECTED: diff --git a/src/android/nfc/AndroidManifest.xml b/src/android/nfc/AndroidManifest.xml new file mode 100644 index 00000000..2ba062ae --- /dev/null +++ b/src/android/nfc/AndroidManifest.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="org.qtproject.qt5.android.nfc" + android:versionCode="1" + android:versionName="1.0"> + <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/> +</manifest> diff --git a/src/android/nfc/bundledjar.pro b/src/android/nfc/bundledjar.pro new file mode 100644 index 00000000..37f7fc82 --- /dev/null +++ b/src/android/nfc/bundledjar.pro @@ -0,0 +1,3 @@ +TARGET = QtNfc-bundled +CONFIG += bundled_jar_file +include(nfc.pri) diff --git a/src/android/nfc/distributedjar.pro b/src/android/nfc/distributedjar.pro new file mode 100644 index 00000000..ed65c50a --- /dev/null +++ b/src/android/nfc/distributedjar.pro @@ -0,0 +1,2 @@ +TARGET = QtNfc +include(nfc.pri) diff --git a/src/android/nfc/nfc.pri b/src/android/nfc/nfc.pri new file mode 100644 index 00000000..65f197ca --- /dev/null +++ b/src/android/nfc/nfc.pri @@ -0,0 +1,13 @@ +CONFIG += java +DESTDIR = $$[QT_INSTALL_PREFIX/get]/jar +API_VERSION = android-10 + +PATHPREFIX = $$PWD/src/org/qtproject/qt5/android/nfc + +JAVACLASSPATH += $$PWD/src/ +JAVASOURCES += \ + $$PWD/src/org/qtproject/qt5/android/nfc/QtNfc.java + +# install +target.path = $$[QT_INSTALL_PREFIX]/jar +INSTALLS += target diff --git a/src/android/nfc/nfc.pro b/src/android/nfc/nfc.pro new file mode 100644 index 00000000..70373fe1 --- /dev/null +++ b/src/android/nfc/nfc.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs +SUBDIRS += bundledjar.pro distributedjar.pro + diff --git a/src/android/nfc/src/org/qtproject/qt5/android/nfc/QtNfc.java b/src/android/nfc/src/org/qtproject/qt5/android/nfc/QtNfc.java new file mode 100644 index 00000000..566489c8 --- /dev/null +++ b/src/android/nfc/src/org/qtproject/qt5/android/nfc/QtNfc.java @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Centria research and development +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtNfc 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$ +** +****************************************************************************/ + +package org.qtproject.qt5.android.nfc; + +import java.lang.Thread; +import java.lang.Runnable; + +import android.os.Parcelable; +import android.os.Looper; +import android.content.Context; +import android.app.Activity; +import android.app.PendingIntent; +import android.content.Intent; +import android.content.IntentFilter; +import android.nfc.NfcAdapter; +import android.content.IntentFilter.MalformedMimeTypeException; +import android.os.Bundle; +import android.util.Log; +import android.content.BroadcastReceiver; + +public class QtNfc +{ + /* static final QtNfc m_nfc = new QtNfc(); */ + static private final String TAG = "QtNfc"; + static public NfcAdapter m_adapter = null; + static public PendingIntent m_pendingIntent = null; + static public IntentFilter[] m_filters; + static public Activity m_activity; + + static public void setActivity(Activity activity, Object activityDelegate) + { + //Log.d(TAG, "setActivity " + activity); + m_activity = activity; + m_adapter = NfcAdapter.getDefaultAdapter(m_activity); + if (m_adapter == null) { + //Log.e(TAG, "No NFC available"); + return; + } + m_pendingIntent = PendingIntent.getActivity( + m_activity, + 0, + new Intent(m_activity, m_activity.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), + 0); + + //Log.d(TAG, "Pending intent:" + m_pendingIntent); + + IntentFilter filter = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED); + + m_filters = new IntentFilter[]{ + filter + }; + + try { + filter.addDataType("*/*"); + } catch(MalformedMimeTypeException e) { + throw new RuntimeException("Fail", e); + } + + //Log.d(TAG, "Thread:" + Thread.currentThread().getId()); + } + + static public boolean start() + { + if (m_adapter == null) return false; + m_activity.runOnUiThread(new Runnable() { + public void run() { + //Log.d(TAG, "Enabling NFC"); + IntentFilter[] filters = new IntentFilter[2]; + filters[0] = new IntentFilter(); + filters[0].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED); + filters[0].addCategory(Intent.CATEGORY_DEFAULT); + try { + filters[0].addDataType("*/*"); + } catch (MalformedMimeTypeException e) { + throw new RuntimeException("Check your mime type."); + } + // some tags will report as tech, even if they are ndef formated/formatable. + filters[1] = new IntentFilter(); + filters[1].addAction(NfcAdapter.ACTION_TECH_DISCOVERED); + String[][] techList = new String[][]{ + {"android.nfc.tech.Ndef"}, + {"android.nfc.tech.NdefFormatable"} + }; + try { + m_adapter.enableForegroundDispatch(m_activity, m_pendingIntent, filters, techList); + } catch(IllegalStateException e) { + // On Android we must call enableForegroundDispatch when the activity is in foreground, only. + Log.d(TAG, "enableForegroundDispatch failed: " + e.toString()); + } + } + }); + return true; + } + + static public boolean stop() + { + if (m_adapter == null) return false; + m_activity.runOnUiThread(new Runnable() { + public void run() { + //Log.d(TAG, "Disabling NFC"); + try { + m_adapter.disableForegroundDispatch(m_activity); + } catch(IllegalStateException e) { + // On Android we must call disableForegroundDispatch when the activity is in foreground, only. + Log.d(TAG, "disableForegroundDispatch failed: " + e.toString()); + } + } + }); + return true; + } + + static public boolean isAvailable() + { + m_adapter = NfcAdapter.getDefaultAdapter(m_activity); + if (m_adapter == null) { + //Log.e(TAG, "No NFC available (Adapter is null)"); + return false; + } + return m_adapter.isEnabled(); + } + + static public Intent getStartIntent() + { + Log.d(TAG, "getStartIntent"); + if (m_activity == null) return null; + Intent intent = m_activity.getIntent(); + if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()) || + NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction()) || + NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) { + return intent; + } else { + return null; + } + } +} 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 diff --git a/src/imports/bluetooth/plugin.cpp b/src/imports/bluetooth/plugin.cpp index 38b464d7..cb9d564f 100644 --- a/src/imports/bluetooth/plugin.cpp +++ b/src/imports/bluetooth/plugin.cpp @@ -67,9 +67,9 @@ public: qmlRegisterType<QDeclarativeBluetoothService >(uri, major, minor, "BluetoothService"); qmlRegisterType<QDeclarativeBluetoothSocket >(uri, major, minor, "BluetoothSocket"); - // Register the 5.5 types - // introduces 5.5 version, other existing 5.2 exports become automatically available under 5.2-5.4 - minor = 5; + // Register the 5.6 types + // introduces 5.6 version, other existing 5.2 exports become automatically available under 5.2-5.5 + minor = 6; qmlRegisterType<QDeclarativeBluetoothDiscoveryModel >(uri, major, minor, "BluetoothDiscoveryModel"); } }; diff --git a/src/imports/bluetooth/plugins.qmltypes b/src/imports/bluetooth/plugins.qmltypes index e9b93e54..82b143df 100644 --- a/src/imports/bluetooth/plugins.qmltypes +++ b/src/imports/bluetooth/plugins.qmltypes @@ -1,19 +1,285 @@ -import QtQuick.tooling 1.1 +import QtQuick.tooling 1.2 // This file describes the plugin-supplied types contained in the library. // It is used for QML tooling purposes only. // // This file was auto-generated by: -// 'qmlplugindump -nonrelocatable QtBluetooth 5.5' +// 'qmlplugindump -nonrelocatable QtBluetooth 5.6' Module { + dependencies: [] + Component { + name: "QAbstractItemModel" + prototype: "QObject" + Enum { + name: "LayoutChangeHint" + values: { + "NoLayoutChangeHint": 0, + "VerticalSortHint": 1, + "HorizontalSortHint": 2 + } + } + Signal { + name: "dataChanged" + Parameter { name: "topLeft"; type: "QModelIndex" } + Parameter { name: "bottomRight"; type: "QModelIndex" } + Parameter { name: "roles"; type: "QVector<int>" } + } + Signal { + name: "dataChanged" + Parameter { name: "topLeft"; type: "QModelIndex" } + Parameter { name: "bottomRight"; type: "QModelIndex" } + } + Signal { + name: "headerDataChanged" + Parameter { name: "orientation"; type: "Qt::Orientation" } + Parameter { name: "first"; type: "int" } + Parameter { name: "last"; type: "int" } + } + Signal { + name: "layoutChanged" + Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" } + Parameter { name: "hint"; type: "QAbstractItemModel::LayoutChangeHint" } + } + Signal { + name: "layoutChanged" + Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" } + } + Signal { name: "layoutChanged" } + Signal { + name: "layoutAboutToBeChanged" + Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" } + Parameter { name: "hint"; type: "QAbstractItemModel::LayoutChangeHint" } + } + Signal { + name: "layoutAboutToBeChanged" + Parameter { name: "parents"; type: "QList<QPersistentModelIndex>" } + } + Signal { name: "layoutAboutToBeChanged" } + Signal { + name: "rowsAboutToBeInserted" + Parameter { name: "parent"; type: "QModelIndex" } + Parameter { name: "first"; type: "int" } + Parameter { name: "last"; type: "int" } + } + Signal { + name: "rowsInserted" + Parameter { name: "parent"; type: "QModelIndex" } + Parameter { name: "first"; type: "int" } + Parameter { name: "last"; type: "int" } + } + Signal { + name: "rowsAboutToBeRemoved" + Parameter { name: "parent"; type: "QModelIndex" } + Parameter { name: "first"; type: "int" } + Parameter { name: "last"; type: "int" } + } + Signal { + name: "rowsRemoved" + Parameter { name: "parent"; type: "QModelIndex" } + Parameter { name: "first"; type: "int" } + Parameter { name: "last"; type: "int" } + } + Signal { + name: "columnsAboutToBeInserted" + Parameter { name: "parent"; type: "QModelIndex" } + Parameter { name: "first"; type: "int" } + Parameter { name: "last"; type: "int" } + } + Signal { + name: "columnsInserted" + Parameter { name: "parent"; type: "QModelIndex" } + Parameter { name: "first"; type: "int" } + Parameter { name: "last"; type: "int" } + } + Signal { + name: "columnsAboutToBeRemoved" + Parameter { name: "parent"; type: "QModelIndex" } + Parameter { name: "first"; type: "int" } + Parameter { name: "last"; type: "int" } + } + Signal { + name: "columnsRemoved" + Parameter { name: "parent"; type: "QModelIndex" } + Parameter { name: "first"; type: "int" } + Parameter { name: "last"; type: "int" } + } + Signal { name: "modelAboutToBeReset" } + Signal { name: "modelReset" } + Signal { + name: "rowsAboutToBeMoved" + Parameter { name: "sourceParent"; type: "QModelIndex" } + Parameter { name: "sourceStart"; type: "int" } + Parameter { name: "sourceEnd"; type: "int" } + Parameter { name: "destinationParent"; type: "QModelIndex" } + Parameter { name: "destinationRow"; type: "int" } + } + Signal { + name: "rowsMoved" + Parameter { name: "parent"; type: "QModelIndex" } + Parameter { name: "start"; type: "int" } + Parameter { name: "end"; type: "int" } + Parameter { name: "destination"; type: "QModelIndex" } + Parameter { name: "row"; type: "int" } + } + Signal { + name: "columnsAboutToBeMoved" + Parameter { name: "sourceParent"; type: "QModelIndex" } + Parameter { name: "sourceStart"; type: "int" } + Parameter { name: "sourceEnd"; type: "int" } + Parameter { name: "destinationParent"; type: "QModelIndex" } + Parameter { name: "destinationColumn"; type: "int" } + } + Signal { + name: "columnsMoved" + Parameter { name: "parent"; type: "QModelIndex" } + Parameter { name: "start"; type: "int" } + Parameter { name: "end"; type: "int" } + Parameter { name: "destination"; type: "QModelIndex" } + Parameter { name: "column"; type: "int" } + } + Method { name: "submit"; type: "bool" } + Method { name: "revert" } + Method { + name: "hasIndex" + type: "bool" + Parameter { name: "row"; type: "int" } + Parameter { name: "column"; type: "int" } + Parameter { name: "parent"; type: "QModelIndex" } + } + Method { + name: "hasIndex" + type: "bool" + Parameter { name: "row"; type: "int" } + Parameter { name: "column"; type: "int" } + } + Method { + name: "index" + type: "QModelIndex" + Parameter { name: "row"; type: "int" } + Parameter { name: "column"; type: "int" } + Parameter { name: "parent"; type: "QModelIndex" } + } + Method { + name: "index" + type: "QModelIndex" + Parameter { name: "row"; type: "int" } + Parameter { name: "column"; type: "int" } + } + Method { + name: "parent" + type: "QModelIndex" + Parameter { name: "child"; type: "QModelIndex" } + } + Method { + name: "sibling" + type: "QModelIndex" + Parameter { name: "row"; type: "int" } + Parameter { name: "column"; type: "int" } + Parameter { name: "idx"; type: "QModelIndex" } + } + Method { + name: "rowCount" + type: "int" + Parameter { name: "parent"; type: "QModelIndex" } + } + Method { name: "rowCount"; type: "int" } + Method { + name: "columnCount" + type: "int" + Parameter { name: "parent"; type: "QModelIndex" } + } + Method { name: "columnCount"; type: "int" } + Method { + name: "hasChildren" + type: "bool" + Parameter { name: "parent"; type: "QModelIndex" } + } + Method { name: "hasChildren"; type: "bool" } + Method { + name: "data" + type: "QVariant" + Parameter { name: "index"; type: "QModelIndex" } + Parameter { name: "role"; type: "int" } + } + Method { + name: "data" + type: "QVariant" + Parameter { name: "index"; type: "QModelIndex" } + } + Method { + name: "setData" + type: "bool" + Parameter { name: "index"; type: "QModelIndex" } + Parameter { name: "value"; type: "QVariant" } + Parameter { name: "role"; type: "int" } + } + Method { + name: "setData" + type: "bool" + Parameter { name: "index"; type: "QModelIndex" } + Parameter { name: "value"; type: "QVariant" } + } + Method { + name: "headerData" + type: "QVariant" + Parameter { name: "section"; type: "int" } + Parameter { name: "orientation"; type: "Qt::Orientation" } + Parameter { name: "role"; type: "int" } + } + Method { + name: "headerData" + type: "QVariant" + Parameter { name: "section"; type: "int" } + Parameter { name: "orientation"; type: "Qt::Orientation" } + } + Method { + name: "fetchMore" + Parameter { name: "parent"; type: "QModelIndex" } + } + Method { + name: "canFetchMore" + type: "bool" + Parameter { name: "parent"; type: "QModelIndex" } + } + Method { + name: "flags" + type: "Qt::ItemFlags" + Parameter { name: "index"; type: "QModelIndex" } + } + Method { + name: "match" + type: "QModelIndexList" + Parameter { name: "start"; type: "QModelIndex" } + Parameter { name: "role"; type: "int" } + Parameter { name: "value"; type: "QVariant" } + Parameter { name: "hits"; type: "int" } + Parameter { name: "flags"; type: "Qt::MatchFlags" } + } + Method { + name: "match" + type: "QModelIndexList" + Parameter { name: "start"; type: "QModelIndex" } + Parameter { name: "role"; type: "int" } + Parameter { name: "value"; type: "QVariant" } + Parameter { name: "hits"; type: "int" } + } + Method { + name: "match" + type: "QModelIndexList" + Parameter { name: "start"; type: "QModelIndex" } + Parameter { name: "role"; type: "int" } + Parameter { name: "value"; type: "QVariant" } + } + } + Component { name: "QAbstractListModel"; prototype: "QAbstractItemModel" } Component { name: "QDeclarativeBluetoothDiscoveryModel" prototype: "QAbstractListModel" exports: [ "QtBluetooth/BluetoothDiscoveryModel 5.0", "QtBluetooth/BluetoothDiscoveryModel 5.2", - "QtBluetooth/BluetoothDiscoveryModel 5.5" + "QtBluetooth/BluetoothDiscoveryModel 5.6" ] exportMetaObjectRevisions: [0, 0, 0] Enum { diff --git a/src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel_p.h b/src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel_p.h index 82a2129b..a06d49c4 100644 --- a/src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel_p.h +++ b/src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel_p.h @@ -64,8 +64,6 @@ class QDeclarativeBluetoothDiscoveryModelPrivate; class QDeclarativeBluetoothDiscoveryModel : public QAbstractListModel, public QQmlParserStatus { Q_OBJECT - Q_ENUMS(DiscoveryMode) - Q_ENUMS(Error) Q_PROPERTY(Error error READ error NOTIFY errorChanged) Q_PROPERTY(DiscoveryMode discoveryMode READ discoveryMode WRITE setDiscoveryMode NOTIFY discoveryModeChanged) Q_PROPERTY(bool running READ running WRITE setRunning NOTIFY runningChanged) @@ -88,6 +86,7 @@ public: FullServiceDiscovery, DeviceDiscovery }; + Q_ENUM(DiscoveryMode) enum Error { @@ -97,6 +96,7 @@ public: UnknownError, InvalidBluetoothAdapterError }; + Q_ENUM(Error) Error error() const; diff --git a/src/imports/bluetooth/qdeclarativebluetoothservice.cpp b/src/imports/bluetooth/qdeclarativebluetoothservice.cpp index 84506ce9..297dfc82 100644 --- a/src/imports/bluetooth/qdeclarativebluetoothservice.cpp +++ b/src/imports/bluetooth/qdeclarativebluetoothservice.cpp @@ -68,7 +68,6 @@ \li deviceName \li serviceDescription \li serviceName - \li servicePort \li serviceProtocol \li serviceUuid \endlist @@ -160,6 +159,7 @@ void QDeclarativeBluetoothService::setDeviceAddress(const QString &newAddress) QBluetoothAddress address(newAddress); QBluetoothDeviceInfo device(address, QString(), QBluetoothDeviceInfo::ComputerDevice); d->m_service->setDevice(device); + emit detailsChanged(); } /*! @@ -177,6 +177,7 @@ QString QDeclarativeBluetoothService::serviceName() const void QDeclarativeBluetoothService::setServiceName(const QString &name) { d->m_service->setServiceName(name); + emit detailsChanged(); } diff --git a/src/imports/bluetooth/qdeclarativebluetoothservice_p.h b/src/imports/bluetooth/qdeclarativebluetoothservice_p.h index 9cb62de9..17611580 100644 --- a/src/imports/bluetooth/qdeclarativebluetoothservice_p.h +++ b/src/imports/bluetooth/qdeclarativebluetoothservice_p.h @@ -66,9 +66,7 @@ class QDeclarativeBluetoothService : public QObject, public QQmlParserStatus Q_PROPERTY(QString serviceUuid READ serviceUuid WRITE setServiceUuid NOTIFY detailsChanged) Q_PROPERTY(Protocol serviceProtocol READ serviceProtocol WRITE setServiceProtocol NOTIFY detailsChanged) Q_PROPERTY(bool registered READ isRegistered WRITE setRegistered NOTIFY registeredChanged) - Q_INTERFACES(QQmlParserStatus) - Q_ENUMS(Protocol) public: /// TODO: Merge/Replace with QBluetoothServiceInfo::Protocol in Qt 6 @@ -77,6 +75,7 @@ public: L2CapProtocol = QBluetoothServiceInfo::L2capProtocol, UnknownProtocol = QBluetoothServiceInfo::UnknownProtocol }; + Q_ENUM(Protocol) explicit QDeclarativeBluetoothService(QObject *parent = 0); explicit QDeclarativeBluetoothService(const QBluetoothServiceInfo &service, diff --git a/src/imports/bluetooth/qdeclarativebluetoothsocket_p.h b/src/imports/bluetooth/qdeclarativebluetoothsocket_p.h index 4ad69f9e..a626c7cf 100644 --- a/src/imports/bluetooth/qdeclarativebluetoothsocket_p.h +++ b/src/imports/bluetooth/qdeclarativebluetoothsocket_p.h @@ -67,11 +67,8 @@ class QDeclarativeBluetoothSocket : public QObject, public QQmlParserStatus Q_PROPERTY(SocketState socketState READ state NOTIFY stateChanged) Q_PROPERTY(QString stringData READ stringData WRITE sendStringData NOTIFY dataAvailable) Q_INTERFACES(QQmlParserStatus) - Q_ENUMS(Error) - Q_ENUMS(SocketState) public: - enum Error { NoError = QBluetoothSocket::NoSocketError, UnknownSocketError = QBluetoothSocket::UnknownSocketError, @@ -80,6 +77,7 @@ public: NetworkError = QBluetoothSocket::NetworkError, UnsupportedProtocolError = QBluetoothSocket::UnsupportedProtocolError }; + Q_ENUM(Error) enum SocketState { Unconnected = QBluetoothSocket::UnconnectedState, @@ -91,6 +89,7 @@ public: Listening = QBluetoothSocket::ListeningState, NoServiceSet = 100 //Leave gap for future enums and to avoid collision with QBluetoothSocket enums }; + Q_ENUM(SocketState) explicit QDeclarativeBluetoothSocket(QObject *parent = 0); explicit QDeclarativeBluetoothSocket(QDeclarativeBluetoothService *service, diff --git a/src/imports/nfc/plugin.cpp b/src/imports/nfc/plugin.cpp index 14f3b280..ff7474f3 100644 --- a/src/imports/nfc/plugin.cpp +++ b/src/imports/nfc/plugin.cpp @@ -83,6 +83,11 @@ public: // Register the 5.5 types minor = 5; qmlRegisterType<QDeclarativeNearField, 1>(uri, major, minor, "NearField"); + + // Register the 5.6 types + minor = 6; + qmlRegisterType<QDeclarativeNearField, 1>(uri, major, minor, "NearField"); + } }; diff --git a/src/imports/nfc/plugins.qmltypes b/src/imports/nfc/plugins.qmltypes index 6abc211d..54459946 100644 --- a/src/imports/nfc/plugins.qmltypes +++ b/src/imports/nfc/plugins.qmltypes @@ -1,12 +1,13 @@ -import QtQuick.tooling 1.1 +import QtQuick.tooling 1.2 // This file describes the plugin-supplied types contained in the library. // It is used for QML tooling purposes only. // // This file was auto-generated by: -// 'qmlplugindump -nonrelocatable QtNfc 5.5' +// 'qmlplugindump -nonrelocatable QtNfc 5.6' Module { + dependencies: [] Component { name: "QDeclarativeNdefFilter" prototype: "QObject" @@ -56,9 +57,10 @@ Module { "QtNfc/NearField 5.0", "QtNfc/NearField 5.2", "QtNfc/NearField 5.4", - "QtNfc/NearField 5.5" + "QtNfc/NearField 5.5", + "QtNfc/NearField 5.6" ] - exportMetaObjectRevisions: [0, 0, 0, 1] + exportMetaObjectRevisions: [0, 0, 0, 1, 1] Property { name: "messageRecords"; type: "QQmlNdefRecord"; isList: true; isReadonly: true } Property { name: "filter"; type: "QDeclarativeNdefFilter"; isList: true; isReadonly: true } Property { name: "orderMatch"; type: "bool" } diff --git a/src/imports/nfc/qdeclarativendeffilter.cpp b/src/imports/nfc/qdeclarativendeffilter.cpp index a3fb1581..508b9d2d 100644 --- a/src/imports/nfc/qdeclarativendeffilter.cpp +++ b/src/imports/nfc/qdeclarativendeffilter.cpp @@ -70,12 +70,18 @@ */ /*! + \qmlproperty QQmlNdefRecord::TypeNameFormat NdefFilter::typeNameFormat + + This property holds the NDEF record name format type \enum QQmlNdefRecord::TypeNameFormat. +*/ + +/*! \qmlproperty int NdefFilter::minimum This property holds the minimum number of records of the given type that must be in the NDEF message for it match. - To match any number of records set both the minimum and maximum properties to -1. + The default minimum is 1. \sa maximum */ @@ -86,13 +92,13 @@ This property holds the maximum number of records of the given type that must be in the NDEF message for it match. - To match any number of records set both the minimum and maximum properties to -1. + The default maximum is UINT_MAX. \sa minimum */ QDeclarativeNdefFilter::QDeclarativeNdefFilter(QObject *parent) -: QObject(parent), m_minimum(-1), m_maximum(-1) +: QObject(parent), m_minimum(1), m_maximum(UINT_MAX) { } diff --git a/src/imports/nfc/qdeclarativendeftextrecord_p.h b/src/imports/nfc/qdeclarativendeftextrecord_p.h index 8a65a951..4699f5a2 100644 --- a/src/imports/nfc/qdeclarativendeftextrecord_p.h +++ b/src/imports/nfc/qdeclarativendeftextrecord_p.h @@ -59,8 +59,6 @@ class QDeclarativeNdefTextRecord : public QQmlNdefRecord Q_PROPERTY(QString locale READ locale WRITE setLocale NOTIFY localeChanged) Q_PROPERTY(LocaleMatch localeMatch READ localeMatch NOTIFY localeMatchChanged) - Q_ENUMS(LocaleMatch) - public: enum LocaleMatch { LocaleMatchedNone, @@ -68,6 +66,7 @@ public: LocaleMatchedLanguage, LocaleMatchedLanguageAndCountry }; + Q_ENUM(LocaleMatch) explicit QDeclarativeNdefTextRecord(QObject *parent = 0); Q_INVOKABLE QDeclarativeNdefTextRecord(const QNdefRecord &record, QObject *parent = 0); diff --git a/src/imports/nfc/qdeclarativenearfield.cpp b/src/imports/nfc/qdeclarativenearfield.cpp index 3e45047b..17e6b177 100644 --- a/src/imports/nfc/qdeclarativenearfield.cpp +++ b/src/imports/nfc/qdeclarativenearfield.cpp @@ -92,6 +92,8 @@ This property indicates whether the order of records should be taken into account when matching messages. This is not supported when using neard. + + The default of orderMatch is false. */ /*! diff --git a/src/nfc/android/androidjninfc.cpp b/src/nfc/android/androidjninfc.cpp new file mode 100644 index 00000000..a95e2f98 --- /dev/null +++ b/src/nfc/android/androidjninfc.cpp @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Centria research and development +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtNfc 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 "androidjninfc_p.h" + +#include <android/log.h> + +#include "androidmainnewintentlistener_p.h" + +#include "qglobal.h" +#include "qbytearray.h" +#include "qdebug.h" + +static const char *nfcClassName = "org/qtproject/qt5/android/nfc/QtNfc"; + +static AndroidNfc::MainNfcNewIntentListener mainListener; + +QT_BEGIN_ANDROIDNFC_NAMESPACE + +bool startDiscovery() +{ + return QAndroidJniObject::callStaticMethod<jboolean>(nfcClassName,"start"); +} + +bool isAvailable() +{ + return QAndroidJniObject::callStaticMethod<jboolean>(nfcClassName,"isAvailable"); +} + +bool stopDiscovery() +{ + return QAndroidJniObject::callStaticMethod<jboolean>(nfcClassName,"stop"); +} + +QAndroidJniObject getStartIntent() +{ + QAndroidJniObject ret = QAndroidJniObject::callStaticObjectMethod(nfcClassName, "getStartIntent", "()Landroid/content/Intent;"); + return ret; +} + +bool registerListener(AndroidNfcListenerInterface *listener) +{ + return mainListener.registerListener(listener); +} + +bool unregisterListener(AndroidNfcListenerInterface *listener) +{ + return mainListener.unregisterListener(listener); +} + +QAndroidJniObject getTag(const QAndroidJniObject &intent) +{ + QAndroidJniObject extraTag = QAndroidJniObject::getStaticObjectField("android/nfc/NfcAdapter", "EXTRA_TAG", "Ljava/lang/String;"); + QAndroidJniObject tag = intent.callObjectMethod("getParcelableExtra", "(Ljava/lang/String;)Landroid/os/Parcelable;", extraTag.object<jstring>()); + Q_ASSERT_X(tag.isValid(), "getTag", "could not get Tag object"); + return tag; +} + +QT_END_ANDROIDNFC_NAMESPACE + +Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /*reserved*/) +{ + JNIEnv* env; + if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { + return -1; + } + + return JNI_VERSION_1_6; +} diff --git a/src/nfc/android/androidjninfc_p.h b/src/nfc/android/androidjninfc_p.h new file mode 100644 index 00000000..fd69412a --- /dev/null +++ b/src/nfc/android/androidjninfc_p.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Centria research and development +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtNfc 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 ANDROIDJNINFC_H +#define ANDROIDJNINFC_H + +#include "qglobal.h" + +#include <QtAndroidExtras/QAndroidJniObject> + +#define QT_USE_ANDROIDNFC_NAMESPACE using namespace ::AndroidNfc; +#define QT_BEGIN_ANDROIDNFC_NAMESPACE namespace AndroidNfc { +#define QT_END_ANDROIDNFC_NAMESPACE } + +QT_BEGIN_ANDROIDNFC_NAMESPACE + +class AndroidNfcListenerInterface +{ +public: + virtual ~AndroidNfcListenerInterface(){} + virtual void newIntent(QAndroidJniObject intent) = 0; +}; + +bool startDiscovery(); +bool stopDiscovery(); +QAndroidJniObject getStartIntent(); +bool isAvailable(); +bool registerListener(AndroidNfcListenerInterface *listener); +bool unregisterListener(AndroidNfcListenerInterface *listener); +QAndroidJniObject getTag(const QAndroidJniObject &intent); + +QT_END_ANDROIDNFC_NAMESPACE + +#endif diff --git a/src/nfc/android/androidmainnewintentlistener.cpp b/src/nfc/android/androidmainnewintentlistener.cpp new file mode 100644 index 00000000..f5b06cbc --- /dev/null +++ b/src/nfc/android/androidmainnewintentlistener.cpp @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2015 BasysKom GmbH +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtNfc 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 "androidmainnewintentlistener_p.h" +#include "qdebug.h" +#include <QtGui/QGuiApplication> +#include <QtAndroidExtras/QAndroidJniObject> + +QT_BEGIN_ANDROIDNFC_NAMESPACE + +MainNfcNewIntentListener::MainNfcNewIntentListener() + : listeners(), listenersLock(), paused(true), receiving(false) +{ + QtAndroidPrivate::registerNewIntentListener(this); + QtAndroidPrivate::registerResumePauseListener(this); +} + +MainNfcNewIntentListener::~MainNfcNewIntentListener() +{ + QtAndroidPrivate::unregisterNewIntentListener(this); + QtAndroidPrivate::unregisterResumePauseListener(this); +} + +bool MainNfcNewIntentListener::handleNewIntent(JNIEnv */*env*/, jobject intent) +{ + listenersLock.lockForRead(); + foreach (AndroidNfc::AndroidNfcListenerInterface *listener, listeners) { + listener->newIntent(QAndroidJniObject(intent)); + } + listenersLock.unlock(); + return true; +} + +bool MainNfcNewIntentListener::registerListener(AndroidNfcListenerInterface *listener) +{ + static bool firstListener = true; + if (firstListener) { + QAndroidJniObject intent = AndroidNfc::getStartIntent(); + if (intent.isValid()) { + listener->newIntent(intent); + } + paused = static_cast<QGuiApplication*>(QGuiApplication::instance())->applicationState() != Qt::ApplicationActive; + } + firstListener = false; + listenersLock.lockForWrite(); + if (!listeners.contains(listener)) + listeners.push_back(listener); + listenersLock.unlock(); + updateReceiveState(); + return true; +} + +bool MainNfcNewIntentListener::unregisterListener(AndroidNfcListenerInterface *listener) +{ + listenersLock.lockForWrite(); + listeners.removeOne(listener); + listenersLock.unlock(); + updateReceiveState(); + return true; +} + +void MainNfcNewIntentListener::handleResume() +{ + paused = false; + updateReceiveState(); +} + +void MainNfcNewIntentListener::handlePause() +{ + paused = true; + updateReceiveState(); +} + +void MainNfcNewIntentListener::updateReceiveState() +{ + if (paused) { + // We were paused while receiving, so we stop receiving. + if (receiving) { + AndroidNfc::stopDiscovery(); + receiving = false; + } + return; + } + + // We reach here, so we are not paused. + listenersLock.lockForRead(); + // We have nfc listeners and do not receive. Switch on. + if (listeners.count() && !receiving) + receiving = AndroidNfc::startDiscovery(); + + // we have no nfc listeners and do receive. Switch off. + if (!listeners.count() && receiving) { + AndroidNfc::stopDiscovery(); + receiving = false; + } + listenersLock.unlock(); +} + +QT_END_ANDROIDNFC_NAMESPACE diff --git a/src/nfc/qnx/qnxnfceventfilter_p.h b/src/nfc/android/androidmainnewintentlistener_p.h index c8a7a9ea..6a016339 100644 --- a/src/nfc/qnx/qnxnfceventfilter_p.h +++ b/src/nfc/android/androidmainnewintentlistener_p.h @@ -1,6 +1,6 @@ -/*************************************************************************** +/**************************************************************************** ** -** Copyright (C) 2012 Research In Motion +** Copyright (C) 2015 BasysKom GmbH ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtNfc module of the Qt Toolkit. @@ -31,48 +31,42 @@ ** ****************************************************************************/ -#ifndef QNXNFCEVENTFILTER_H -#define QNXNFCEVENTFILTER_H +#ifndef ANDROIDMAINNEWINTENTLISTENER_P_H_ +#define ANDROIDMAINNEWINTENTLISTENER_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 <QtCore/private/qjnihelpers_p.h> -#include <QAbstractNativeEventFilter> -#include <QAbstractEventDispatcher> -//#include "qnxnfcmanager_p.h" -#include <bps/navigator.h> -#include "bps/bps.h" -#include "bps/navigator_invoke.h" -#include "../qnfcglobal.h" -#include "../qndefmessage.h" +#include "qlist.h" +#include "qreadwritelock.h" +#include "androidjninfc_p.h" -QT_BEGIN_NAMESPACE +QT_BEGIN_ANDROIDNFC_NAMESPACE -class QNXNFCEventFilter : public QObject, public QAbstractNativeEventFilter +class MainNfcNewIntentListener : public QtAndroidPrivate::NewIntentListener, QtAndroidPrivate::ResumePauseListener { - Q_OBJECT public: - QNXNFCEventFilter(); + MainNfcNewIntentListener(); + ~MainNfcNewIntentListener(); - void installOnEventDispatcher(QAbstractEventDispatcher *dispatcher); - void uninstallEventFilter(); -private: - bool nativeEventFilter(const QByteArray &eventType, void *message, long *result); + //QtAndroidPrivate::NewIntentListener + bool handleNewIntent(JNIEnv *env, jobject intent); + + bool registerListener(AndroidNfcListenerInterface *listener); + bool unregisterListener(AndroidNfcListenerInterface *listener); - QAbstractNativeEventFilter *prevFilter; + //QtAndroidPrivate::ResumePauseListener + void handleResume(); + void handlePause(); -signals: - void ndefEvent(const QNdefMessage &msg); +private: + void updateReceiveState(); +protected: + QList<AndroidNfc::AndroidNfcListenerInterface*> listeners; + QReadWriteLock listenersLock; + bool paused; + bool receiving; }; -QT_END_NAMESPACE +QT_END_ANDROIDNFC_NAMESPACE -#endif // QNXNFCEVENTFILTER_H +#endif /* ANDROIDMAINNEWINTENTLISTENER_P_H_ */ diff --git a/src/nfc/doc/src/nfc-android.qdoc b/src/nfc/doc/src/nfc-android.qdoc new file mode 100644 index 00000000..e7c43423 --- /dev/null +++ b/src/nfc/doc/src/nfc-android.qdoc @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2015 BasysKom GmbH +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! +\ingroup connectivity-nfc +\inmodule QtNfc +\since 5.6 +\page nfc-android.html +\title Qt NFC on Android +\brief Notes on Nfc for Android. + +\section1 Automatically launching NDEF message handlers on Android +Android, the registration of NDEF message handlers is done via the +\l{http://developer.android.com/guide/topics/manifest/manifest-intro.html}{Android manifest file}. +This means the application has to provide an AndroidManifest.xml file with proper +\l{http://developer.android.com/guide/topics/connectivity/nfc/nfc.html#manifest}{NFC intent-filter.} + +\code +<intent-filter> + <action android:name="android.nfc.action.NDEF_DISCOVERED"/> + <category android:name="android.intent.category.DEFAULT"/> + <data android:mimeType="text/plain"/> +</intent-filter> +\endcode + +When the application is started it has to register an message handler with +\l registerNdefMessageHandler(). +The first NDEF message arriving in the handler is the message that started the application. +See the \l {corkboard}{CorkBoard} application for an example. + +\section2 Note: +Supported tag types in Android are +\l{http://developer.android.com/reference/android/nfc/NfcAdapter.html#ACTION_NDEF_DISCOVERED}{NDEF_DISCOVERED} +and +\l{http://developer.android.com/reference/android/nfc/NfcAdapter.html#ACTION_TECH_DISCOVERED}{ACTION_TAG_DISCOVERED} +with +\l{http://developer.android.com/reference/android/nfc/tech/TagTechnology.html}{TagTechnology} +NdefFormatable or Ndef. +If the application register other types in the +\l{http://developer.android.com/guide/topics/manifest/manifest-intro.html}{Android manifest file} +the application will be started, but the tag will never get delivered to the handler. +The handler should be registered as early as possible. If the application has not registered a handler, the application +will be started every time a new tag is in range and the Android device end up running multiple instances of the application. +*/ + diff --git a/src/nfc/doc/src/nfc-index.qdoc b/src/nfc/doc/src/nfc-index.qdoc index 47c158d9..da8833d8 100644 --- a/src/nfc/doc/src/nfc-index.qdoc +++ b/src/nfc/doc/src/nfc-index.qdoc @@ -34,7 +34,8 @@ The NFC API provides connectivity between NFC enabled devices. -Currently the API is supported on \l{Qt for BlackBerry}{BlackBerry 10} and Linux using \l {https://01.org/linux-nfc}{Neard} v0.14 or later. +Currently the API is supported on \l{Qt for Android}{Android}, +and \l{Qt for Linux/X11}{Linux} using \l {https://01.org/linux-nfc}{Neard} v0.14 or later. \section1 Overview diff --git a/src/nfc/nfc.pro b/src/nfc/nfc.pro index 7c6b6ff7..16737e73 100644 --- a/src/nfc/nfc.pro +++ b/src/nfc/nfc.pro @@ -56,51 +56,7 @@ SOURCES += \ qnearfieldsharetarget.cpp \ qnfc.cpp -CONFIG(blackberry) { - NFC_BACKEND_AVAILABLE = yes - DEFINES += QNX_NFC #QQNXNFC_DEBUG - - LIBS += -lnfc - - PRIVATE_HEADERS += \ - qllcpserver_qnx_p.h \ - qllcpsocket_qnx_p.h \ - qnearfieldmanager_qnx_p.h \ - qnx/qnxnfcmanager_p.h \ - qnearfieldtarget_qnx_p.h \ - qnx/qnxnfceventfilter_p.h - - SOURCES += \ - qllcpserver_qnx_p.cpp \ - qllcpsocket_qnx_p.cpp \ - qnearfieldmanager_qnx.cpp \ - qnx/qnxnfcmanager.cpp \ - qnx/qnxnfceventfilter.cpp - - config_libbb2 { - SOURCES += \ - qnearfieldsharemanager_qnx_p.cpp \ - qnearfieldsharetarget_qnx_p.cpp \ - qnx/qnxnfcsharemanager_p.cpp - - PRIVATE_HEADERS += \ - qnearfieldsharemanager_qnx_p.h \ - qnearfieldsharetarget_qnx_p.h \ - qnx/qnxnfcsharemanager_p.h - - LIBS += -l:libbbsystem.so.2 - } else { - SOURCES += \ - qnearfieldsharemanagerimpl_p.cpp \ - qnearfieldsharetargetimpl_p.cpp - - PRIVATE_HEADERS += \ - qnearfieldsharemanagerimpl_p.h \ - qnearfieldsharetargetimpl_p.h - } -} - -linux:qtHaveModule(dbus) { +linux:!android:qtHaveModule(dbus) { NFC_BACKEND_AVAILABLE = yes QT += dbus @@ -123,9 +79,8 @@ linux:qtHaveModule(dbus) { qnearfieldmanager_neard.cpp include(neard/neard.pri) -} -simulator { +} else:simulator { NFC_BACKEND_AVAILABLE = yes QT *= gui @@ -146,6 +101,37 @@ simulator { qllcpserver_simulator_p.cpp \ qnearfieldsharemanagerimpl_p.cpp \ qnearfieldsharetargetimpl_p.cpp +} else:android:!android-no-sdk { + NFC_BACKEND_AVAILABLE = yes + ANDROID_PERMISSIONS = \ + android.permission.NFC + ANDROID_BUNDLED_JAR_DEPENDENCIES = \ + jar/QtNfc-bundled.jar:org.qtproject.qt5.android.nfc.QtNfc + ANDROID_JAR_DEPENDENCIES = \ + jar/QtNfc.jar:org.qtproject.qt5.android.nfc.QtNfc + DEFINES += ANDROID_NFC + QT += core-private gui androidextras + + PRIVATE_HEADERS += \ + qllcpserver_android_p.h \ + qllcpsocket_android_p.h \ + android/androidjninfc_p.h \ + qnearfieldmanager_android_p.h \ + qnearfieldtarget_android_p.h \ + qnearfieldsharemanagerimpl_p.h \ + qnearfieldsharetargetimpl_p.h \ + android/androidmainnewintentlistener_p.h + + + SOURCES += \ + qllcpserver_android_p.cpp \ + qllcpsocket_android_p.cpp \ + android/androidjninfc.cpp \ + qnearfieldmanager_android.cpp \ + qnearfieldtarget_android.cpp \ + qnearfieldsharemanagerimpl_p.cpp \ + qnearfieldsharetargetimpl_p.cpp \ + android/androidmainnewintentlistener.cpp } isEmpty(NFC_BACKEND_AVAILABLE) { diff --git a/src/nfc/qllcpserver.cpp b/src/nfc/qllcpserver.cpp index 4ee26eaf..17fb3369 100644 --- a/src/nfc/qllcpserver.cpp +++ b/src/nfc/qllcpserver.cpp @@ -35,8 +35,6 @@ #if defined(QT_SIMULATOR) #include "qllcpserver_simulator_p.h" -#elif defined(QNX_NFC) -#include "qllcpserver_qnx_p.h" #else #include "qllcpserver_p_p.h" #endif diff --git a/src/nfc/qllcpserver_qnx_p.cpp b/src/nfc/qllcpserver_android_p.cpp index 41168798..ba97bcee 100644 --- a/src/nfc/qllcpserver_qnx_p.cpp +++ b/src/nfc/qllcpserver_android_p.cpp @@ -1,6 +1,6 @@ -/*************************************************************************** +/**************************************************************************** ** -** Copyright (C) 2012 Research In Motion +** Copyright (C) 2013 Centria research and development ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtNfc module of the Qt Toolkit. @@ -31,19 +31,19 @@ ** ****************************************************************************/ -#include "qllcpserver_qnx_p.h" -#include "qnx/qnxnfcmanager_p.h" +#include "qllcpserver_android_p.h" +//#include "qnx/qnxnfcmanager_p.h" QT_BEGIN_NAMESPACE QLlcpServerPrivate::QLlcpServerPrivate(QLlcpServer *q) - : q_ptr(q), m_llcpSocket(0), m_connected(false), m_conListener(0) + : q_ptr(q), m_llcpSocket(0), m_connected(false) { } -bool QLlcpServerPrivate::listen(const QString &serviceUri) +bool QLlcpServerPrivate::listen(const QString &/*serviceUri*/) { - //The server is already listening + /*//The server is already listening if (isListening()) return false; @@ -56,7 +56,7 @@ bool QLlcpServerPrivate::listen(const QString &serviceUri) qWarning() << Q_FUNC_INFO << "Could not register for llcp connection listener"; return false; } - QNXNFCManager::instance()->registerLLCPConnection(m_conListener, this); + QNXNFCManager::instance()->registerLLCPConnection(m_conListener, this);*/ return true; } @@ -67,10 +67,10 @@ bool QLlcpServerPrivate::isListening() const void QLlcpServerPrivate::close() { - nfc_llcp_unregister_connection_listener(m_conListener); + /*nfc_llcp_unregister_connection_listener(m_conListener); QNXNFCManager::instance()->unregisterLLCPConnection(m_conListener); m_serviceUri = QString(); - m_connected = false; + m_connected = false;*/ } QString QLlcpServerPrivate::serviceUri() const @@ -80,10 +80,10 @@ QString QLlcpServerPrivate::serviceUri() const quint8 QLlcpServerPrivate::serverPort() const { - unsigned int sap; + /*unsigned int sap; if (nfc_llcp_get_local_sap(m_target, &sap) == NFC_RESULT_SUCCESS) { return sap; - } + }*/ return -1; } @@ -94,9 +94,10 @@ bool QLlcpServerPrivate::hasPendingConnections() const QLlcpSocket *QLlcpServerPrivate::nextPendingConnection() { - QLlcpSocket *socket = m_llcpSocket; + /*QLlcpSocket *socket = m_llcpSocket; m_llcpSocket = 0; - return socket; + return socket;*/ + return 0; } QLlcpSocket::SocketError QLlcpServerPrivate::serverError() const @@ -104,7 +105,7 @@ QLlcpSocket::SocketError QLlcpServerPrivate::serverError() const return QLlcpSocket::UnknownSocketError; } -void QLlcpServerPrivate::connected(nfc_target_t *target) +/*void QLlcpServerPrivate::connected(nfc_target_t *target) { m_target = target; if (m_llcpSocket != 0) { @@ -113,7 +114,7 @@ void QLlcpServerPrivate::connected(nfc_target_t *target) } m_llcpSocket = new QLlcpSocket(); m_llcpSocket->bind(serverPort()); -} +}*/ QT_END_NAMESPACE diff --git a/src/nfc/qllcpserver_qnx_p.h b/src/nfc/qllcpserver_android_p.h index 16e33784..be725719 100644 --- a/src/nfc/qllcpserver_qnx_p.h +++ b/src/nfc/qllcpserver_android_p.h @@ -1,6 +1,6 @@ -/*************************************************************************** +/**************************************************************************** ** -** Copyright (C) 2013 Research In Motion +** Copyright (C) 2013 Centria research and development ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtNfc module of the Qt Toolkit. @@ -31,22 +31,11 @@ ** ****************************************************************************/ -#ifndef QLLCPSERVER_QNX_P_H -#define QLLCPSERVER_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. -// +#ifndef QLLCPSERVER_ANDROID_P_H +#define QLLCPSERVER_ANDROID_P_H #include "qllcpserver_p.h" -#include "nfc/nfc.h" +//#include "nfc/nfc.h" QT_BEGIN_NAMESPACE @@ -69,18 +58,18 @@ public: QLlcpSocket::SocketError serverError() const; - Q_INVOKABLE void connected(nfc_target_t *); + //Q_INVOKABLE void connected(nfc_target_t *); private: QLlcpServer *q_ptr; QLlcpSocket *m_llcpSocket; //We can not use m_conListener for the connection state bool m_connected; - nfc_llcp_connection_listener_t m_conListener; + //nfc_llcp_connection_listener_t m_conListener; QString m_serviceUri; - nfc_target_t *m_target; + //nfc_target_t *m_target; }; QT_END_NAMESPACE -#endif // QLLCPSERVER_QNX_P_H +#endif // QLLCPSERVER_ANDROID_P_H diff --git a/src/nfc/qllcpsocket.cpp b/src/nfc/qllcpsocket.cpp index ae23f89c..07c0bfbb 100644 --- a/src/nfc/qllcpsocket.cpp +++ b/src/nfc/qllcpsocket.cpp @@ -35,8 +35,6 @@ #if defined(QT_SIMULATOR) #include "qllcpsocket_simulator_p.h" -#elif defined(QNX_NFC) -#include "qllcpsocket_qnx_p.h" #else #include "qllcpsocket_p_p.h" #endif diff --git a/src/nfc/qllcpsocket_qnx_p.cpp b/src/nfc/qllcpsocket_android_p.cpp index 2351a524..0dc425f0 100644 --- a/src/nfc/qllcpsocket_qnx_p.cpp +++ b/src/nfc/qllcpsocket_android_p.cpp @@ -1,6 +1,6 @@ -/*************************************************************************** +/**************************************************************************** ** -** Copyright (C) 2012 Research In Motion +** Copyright (C) 2013 Centria research and development ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtNfc module of the Qt Toolkit. @@ -31,13 +31,13 @@ ** ****************************************************************************/ -#include "qllcpsocket_qnx_p.h" +#include "qllcpsocket_android_p.h" #include <unistd.h> QT_BEGIN_NAMESPACE QLlcpSocketPrivate::QLlcpSocketPrivate(QLlcpSocket *q) - : q_ptr(q), m_conListener(0), m_state(QLlcpSocket::UnconnectedState), m_server(false) + : q_ptr(q), m_state(QLlcpSocket::UnconnectedState), m_server(false) { } @@ -49,7 +49,8 @@ QLlcpSocketPrivate::~QLlcpSocketPrivate() void QLlcpSocketPrivate::connectToService(QNearFieldTarget *target, const QString &serviceUri) { Q_UNUSED(target) - if (m_state != QLlcpSocket::UnconnectedState) { + Q_UNUSED(serviceUri) + /*if (m_state != QLlcpSocket::UnconnectedState) { qWarning() << Q_FUNC_INFO << "socket is already connected"; return; } @@ -64,12 +65,12 @@ void QLlcpSocketPrivate::connectToService(QNearFieldTarget *target, const QStrin QNXNFCManager::instance()->registerLLCPConnection(m_conListener, this); qQNXNFCDebug() << "Connecting client socket" << serviceUri << m_conListener; - connect(QNXNFCManager::instance(), SIGNAL(llcpDisconnected()), this, SLOT(disconnectFromService())); + connect(QNXNFCManager::instance(), SIGNAL(llcpDisconnected()), this, SLOT(disconnectFromService()));*/ } void QLlcpSocketPrivate::disconnectFromService() { - Q_Q(QLlcpSocket); + /*Q_Q(QLlcpSocket); QNXNFCManager::instance()->unregisterTargetLost(this); qQNXNFCDebug() << "Shutting down LLCP socket"; if (!m_server && nfc_llcp_unregister_connection_listener(m_conListener) != NFC_RESULT_SUCCESS) { @@ -80,17 +81,17 @@ void QLlcpSocketPrivate::disconnectFromService() q->disconnected(); m_conListener = 0; - m_state = QLlcpSocket::UnconnectedState; + m_state = QLlcpSocket::UnconnectedState;*/ } bool QLlcpSocketPrivate::bind(quint8 port) { Q_UNUSED(port); - m_state = QLlcpSocket::ConnectedState; + /*m_state = QLlcpSocket::ConnectedState; m_server = true; connect(QNXNFCManager::instance(), SIGNAL(llcpDisconnected()), this, SLOT(disconnectFromService())); - connected(QNXNFCManager::instance()->getLastTarget()); + connected(QNXNFCManager::instance()->getLastTarget());*/ return true; } @@ -164,18 +165,23 @@ QLlcpSocket::SocketState QLlcpSocketPrivate::state() const qint64 QLlcpSocketPrivate::readData(char *data, qint64 maxlen) { + Q_UNUSED(data); + Q_UNUSED(maxlen); if (m_receivedDatagrams.isEmpty()) return 0; - const QByteArray datagram = m_receivedDatagrams.takeFirst(); + /*const QByteArray datagram = m_receivedDatagrams.takeFirst(); qint64 size = qMin(maxlen, qint64(datagram.length())); memcpy(data, datagram.constData(), size); - return size; + return size;*/ + return 0; } qint64 QLlcpSocketPrivate::writeData(const char *data, qint64 len) { - if (socketState != Idle) { + Q_UNUSED(data); + Q_UNUSED(len); + /*if (socketState != Idle) { m_writeQueue.append(QByteArray(data, len)); return len; } else { @@ -189,24 +195,26 @@ qint64 QLlcpSocketPrivate::writeData(const char *data, qint64 len) enteringIdle(); return -1; } - } + }*/ + return -1; } qint64 QLlcpSocketPrivate::bytesAvailable() const { - qint64 available = 0; + /*qint64 available = 0; foreach (const QByteArray &datagram, m_receivedDatagrams) available += datagram.length(); - return available; + return available;*/ + return 0; } bool QLlcpSocketPrivate::canReadLine() const { - foreach (const QByteArray &datagram, m_receivedDatagrams) { + /*foreach (const QByteArray &datagram, m_receivedDatagrams) { if (datagram.contains('\n')) return true; - } + }*/ return false; } @@ -239,7 +247,7 @@ bool QLlcpSocketPrivate::waitForDisconnected(int msecs) return false; } -void QLlcpSocketPrivate::connected(nfc_target_t *target) +/*void QLlcpSocketPrivate::connected(nfc_target_t *target) { Q_Q(QLlcpSocket); m_target = target; @@ -252,33 +260,34 @@ void QLlcpSocketPrivate::connected(nfc_target_t *target) nfc_get_target_connection_id(target, &targetId); QNXNFCManager::instance()->requestTargetLost(this, targetId); enteringIdle(); -} +}*/ void QLlcpSocketPrivate::targetLost() { disconnectFromService(); - qQNXNFCDebug() << "LLCP target lost...socket disconnected"; + //qQNXNFCDebug() << "LLCP target lost...socket disconnected"; } void QLlcpSocketPrivate::dataRead(QByteArray& data) { - Q_Q(QLlcpSocket); + Q_UNUSED(data); + /*Q_Q(QLlcpSocket); if (!data.isEmpty()) { m_receivedDatagrams.append(data); emit q->readyRead(); } socketState = Idle; - enteringIdle(); + enteringIdle();*/ } void QLlcpSocketPrivate::dataWritten() { - enteringIdle(); + //enteringIdle(); } void QLlcpSocketPrivate::read() { - if (socketState != Idle) { + /*if (socketState != Idle) { qQNXNFCDebug() << "Trying to read but socket state not in idle..abort"; return; } @@ -287,12 +296,12 @@ void QLlcpSocketPrivate::read() if (nfc_llcp_read(m_target, 128) != NFC_RESULT_SUCCESS) { qWarning() << Q_FUNC_INFO << "Could not register for reading"; socketState = Idle; - } + }*/ } void QLlcpSocketPrivate::enteringIdle() { - qQNXNFCDebug() << "entering idle; Socket state:" << socketState; + /*qQNXNFCDebug() << "entering idle; Socket state:" << socketState; socketState = Idle; if (m_state == QLlcpSocket::ConnectedState) { if (m_writeQueue.isEmpty()) { @@ -302,7 +311,7 @@ void QLlcpSocketPrivate::enteringIdle() qQNXNFCDebug() << "Write first package in queue"; writeDatagram(m_writeQueue.takeFirst()); } - } + }*/ } QT_END_NAMESPACE diff --git a/src/nfc/qllcpsocket_qnx_p.h b/src/nfc/qllcpsocket_android_p.h index 5e3b2c06..02865823 100644 --- a/src/nfc/qllcpsocket_qnx_p.h +++ b/src/nfc/qllcpsocket_android_p.h @@ -1,6 +1,6 @@ -/*************************************************************************** +/**************************************************************************** ** -** Copyright (C) 2013 Research In Motion +** Copyright (C) 2013 Centria research and development ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtNfc module of the Qt Toolkit. @@ -31,23 +31,12 @@ ** ****************************************************************************/ -#ifndef QLLCPSOCKET_QNX_P_H -#define QLLCPSOCKET_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. -// +#ifndef QLLCPSOCKET_ANDROID_P_H +#define QLLCPSOCKET_ANDROID_P_H #include "qllcpsocket_p.h" -#include "qnearfieldtarget_qnx_p.h" +//#include "qnearfieldtarget_ANDROID_p.h" QT_BEGIN_NAMESPACE @@ -91,21 +80,21 @@ public: bool waitForConnected(int msecs); bool waitForDisconnected(int msecs); - Q_INVOKABLE void connected(nfc_target_t *); + //Q_INVOKABLE void connected(nfc_target_t *); Q_INVOKABLE void targetLost(); void dataRead(QByteArray&); void dataWritten(); -public slots: +public Q_SLOTS: void disconnectFromService(); private: QLlcpSocket *q_ptr; unsigned int m_sap; - nfc_llcp_connection_listener_t m_conListener; + //nfc_llcp_connection_listener_t m_conListener; //NearFieldTarget *m_target; - nfc_target_t *m_target; + //nfc_target_t *m_target; QLlcpSocket::SocketState m_state; @@ -118,11 +107,11 @@ private: Idle, Reading, Writing } socketState; -private slots: +private Q_SLOTS: void read(); void enteringIdle(); }; QT_END_NAMESPACE -#endif // QLLCPSOCKET_QNX_P_H +#endif // QLLCPSOCKET_ANDROID_P_H diff --git a/src/nfc/qllcpsocket_p.h b/src/nfc/qllcpsocket_p.h index db49b4c0..b797ef5b 100644 --- a/src/nfc/qllcpsocket_p.h +++ b/src/nfc/qllcpsocket_p.h @@ -71,6 +71,7 @@ public: BoundState = QAbstractSocket::BoundState, ListeningState = QAbstractSocket::ListeningState }; + Q_ENUM(SocketState) enum SocketError { UnknownSocketError = QAbstractSocket::UnknownSocketError, @@ -78,6 +79,7 @@ public: SocketAccessError = QAbstractSocket::SocketAccessError, SocketResourceError = QAbstractSocket::SocketResourceError }; + Q_ENUM(SocketError) explicit QLlcpSocket(QObject *parent = 0); ~QLlcpSocket(); diff --git a/src/nfc/qndefnfcsmartposterrecord.cpp b/src/nfc/qndefnfcsmartposterrecord.cpp index 9bec5b7a..b71b8ac2 100644 --- a/src/nfc/qndefnfcsmartposterrecord.cpp +++ b/src/nfc/qndefnfcsmartposterrecord.cpp @@ -92,6 +92,18 @@ QNdefNfcSmartPosterRecord::QNdefNfcSmartPosterRecord(const QNdefNfcSmartPosterRe } /*! + Assigns the \a other smart poster record to this record and returns a reference to + this record. +*/ +QNdefNfcSmartPosterRecord &QNdefNfcSmartPosterRecord::operator=(const QNdefNfcSmartPosterRecord &other) +{ + if (this != &other) + d = other.d; + + return *this; +} + +/*! Destroys the smart poster. */ QNdefNfcSmartPosterRecord::~QNdefNfcSmartPosterRecord() diff --git a/src/nfc/qndefnfcsmartposterrecord.h b/src/nfc/qndefnfcsmartposterrecord.h index f390f730..3b813a28 100644 --- a/src/nfc/qndefnfcsmartposterrecord.h +++ b/src/nfc/qndefnfcsmartposterrecord.h @@ -40,10 +40,6 @@ #include <QtNfc/qndefnfctextrecord.h> #include <QtNfc/qndefnfcurirecord.h> -#if 0 -#pragma qt_sync_skip_header_check -#endif - QT_FORWARD_DECLARE_CLASS(QUrl) QT_BEGIN_NAMESPACE @@ -84,6 +80,7 @@ public: QNdefNfcSmartPosterRecord(); QNdefNfcSmartPosterRecord(const QNdefRecord &other); QNdefNfcSmartPosterRecord(const QNdefNfcSmartPosterRecord &other); + QNdefNfcSmartPosterRecord &operator=(const QNdefNfcSmartPosterRecord &other); ~QNdefNfcSmartPosterRecord(); void setPayload(const QByteArray &payload); diff --git a/src/nfc/qnearfieldmanager.cpp b/src/nfc/qnearfieldmanager.cpp index dce1a9f3..d3ebb43f 100644 --- a/src/nfc/qnearfieldmanager.cpp +++ b/src/nfc/qnearfieldmanager.cpp @@ -36,10 +36,10 @@ #if defined(QT_SIMULATOR) #include "qnearfieldmanager_simulator_p.h" -#elif defined(QNX_NFC) -#include "qnearfieldmanager_qnx_p.h" #elif defined(NEARD_NFC) #include "qnearfieldmanager_neard_p.h" +#elif defined(ANDROID_NFC) +#include "qnearfieldmanager_android_p.h" #else #include "qnearfieldmanagerimpl_p.h" #endif @@ -100,20 +100,8 @@ QT_BEGIN_NAMESPACE \snippet doc_src_qtnfc.cpp handleNdefMessage - On BlackBerry the registration for NDEF message handlers is done over the - \l{https://developer.blackberry.com/native/documentation/core/invocation_framework.html}{Invocation Framework}. - This means that the application has to set an invoke target in the bar descriptor xml file when using - \l registerNdefMessageHandler(). - - \code - <invoke-target id="com.myapp.id"> - <type>APPLICATION</type> - <filter> - <action>bb.action.OPEN</action> - <mime-type>application/vnd.rim.nfc.ndef</mime-type> - </filter> - </invoke-target> - \endcode + Automatically launching NDEF message handlers is supported on + \l{nfc-android.html}{Android}. \section3 NFC on Linux The \l{https://01.org/linux-nfc}{Linux NFC project} provides software to support NFC on Linux platforms. diff --git a/src/nfc/qnearfieldmanager.h b/src/nfc/qnearfieldmanager.h index 8dab134f..416c5e91 100644 --- a/src/nfc/qnearfieldmanager.h +++ b/src/nfc/qnearfieldmanager.h @@ -56,6 +56,7 @@ public: NdefWriteTargetAccess = 0x02, TagTypeSpecificTargetAccess = 0x04 }; + Q_ENUM(TargetAccessMode) Q_DECLARE_FLAGS(TargetAccessModes, TargetAccessMode) explicit QNearFieldManager(QObject *parent = 0); diff --git a/src/nfc/qnearfieldmanager_android.cpp b/src/nfc/qnearfieldmanager_android.cpp new file mode 100644 index 00000000..d1434840 --- /dev/null +++ b/src/nfc/qnearfieldmanager_android.cpp @@ -0,0 +1,308 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Centria research and development +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtNfc 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 "qnearfieldmanager_android_p.h" +#include "qnearfieldtarget_android_p.h" + +#include "qndeffilter.h" +#include "qndefmessage.h" +#include "qndefrecord.h" +#include "qbytearray.h" +#include "qcoreapplication.h" +#include "qdebug.h" +#include "qlist.h" + +#include <QtCore/QMetaType> +#include <QtCore/QMetaMethod> + +QT_BEGIN_NAMESPACE + +QNearFieldManagerPrivateImpl::QNearFieldManagerPrivateImpl() : + m_detecting(false), m_handlerID(0) +{ + qRegisterMetaType<QAndroidJniObject>("QAndroidJniObject"); + qRegisterMetaType<QNdefMessage>("QNdefMessage"); + connect(this, SIGNAL(targetDetected(QNearFieldTarget*)), this, SLOT(handlerTargetDetected(QNearFieldTarget*))); + connect(this, SIGNAL(targetLost(QNearFieldTarget*)), this, SLOT(handlerTargetLost(QNearFieldTarget*))); +} + +QNearFieldManagerPrivateImpl::~QNearFieldManagerPrivateImpl() +{ +} + +void QNearFieldManagerPrivateImpl::handlerTargetDetected(QNearFieldTarget *target) +{ + if (ndefMessageHandlers.count() == 0 && ndefFilterHandlers.count() == 0) // if no handler is registered + return; + if (target->hasNdefMessage()) { + connect(target, SIGNAL(ndefMessageRead(const QNdefMessage &, const QNearFieldTarget::RequestId &)), + this, SLOT(handlerNdefMessageRead(const QNdefMessage &, const QNearFieldTarget::RequestId &))); + connect(target, SIGNAL(requestCompleted(const QNearFieldTarget::RequestId &)), + this, SLOT(handlerRequestCompleted(const QNearFieldTarget::RequestId &))); + connect(target, SIGNAL(error(QNearFieldTarget::Error, const QNearFieldTarget::RequestId &)), + this, SLOT(handlerError(QNearFieldTarget::Error, const QNearFieldTarget::RequestId &))); + + QNearFieldTarget::RequestId id = target->readNdefMessages(); + m_idToTarget.insert(id, target); + } +} + +void QNearFieldManagerPrivateImpl::handlerTargetLost(QNearFieldTarget *target) +{ + disconnect(target, SIGNAL(ndefMessageRead(const QNdefMessage &, const QNearFieldTarget::RequestId &)), + this, SLOT(handlerNdefMessageRead(const QNdefMessage &, const QNearFieldTarget::RequestId &))); + disconnect(target, SIGNAL(requestCompleted(const QNearFieldTarget::RequestId &)), + this, SLOT(handlerRequestCompleted(const QNearFieldTarget::RequestId &))); + disconnect(target, SIGNAL(error(QNearFieldTarget::Error, const QNearFieldTarget::RequestId &)), + this, SLOT(handlerError(QNearFieldTarget::Error, const QNearFieldTarget::RequestId &))); + m_idToTarget.remove(m_idToTarget.key(target)); +} + +struct VerifyRecord +{ + QNdefFilter::Record filterRecord; + unsigned int count; +}; + +void QNearFieldManagerPrivateImpl::handlerNdefMessageRead(const QNdefMessage &message, const QNearFieldTarget::RequestId &id) +{ + QNearFieldTarget *target = m_idToTarget.value(id); + //For message handlers without filters + for (int i = 0; i < ndefMessageHandlers.count(); i++) { + ndefMessageHandlers.at(i).second.invoke(ndefMessageHandlers.at(i).first.second, Q_ARG(QNdefMessage, message), Q_ARG(QNearFieldTarget*, target)); + } + + //For message handlers that specified a filter + for (int i = 0; i < ndefFilterHandlers.count(); ++i) { + bool matched = true; + + QNdefFilter filter = ndefFilterHandlers.at(i).second.first; + + QList<VerifyRecord> filterRecords; + for (int j = 0; j < filter.recordCount(); ++j) { + VerifyRecord vr; + vr.count = 0; + vr.filterRecord = filter.recordAt(j); + + filterRecords.append(vr); + } + + foreach (const QNdefRecord &record, message) { + for (int j = 0; matched && (j < filterRecords.count()); ++j) { + VerifyRecord &vr = filterRecords[j]; + + if (vr.filterRecord.typeNameFormat == record.typeNameFormat() && + ( vr.filterRecord.type == record.type() || + vr.filterRecord.type.isEmpty()) ) { + ++vr.count; + break; + } else { + if (filter.orderMatch()) { + if (vr.filterRecord.minimum <= vr.count && + vr.count <= vr.filterRecord.maximum) { + continue; + } else { + matched = false; + } + } + } + } + } + + for (int j = 0; matched && (j < filterRecords.count()); ++j) { + const VerifyRecord &vr = filterRecords.at(j); + + if (vr.filterRecord.minimum <= vr.count && vr.count <= vr.filterRecord.maximum) + continue; + else + matched = false; + } + + if (matched) { + ndefFilterHandlers.at(i).second.second.invoke(ndefFilterHandlers.at(i).first.second, Q_ARG(QNdefMessage, message), Q_ARG(QNearFieldTarget*, target)); + } + } +} + +void QNearFieldManagerPrivateImpl::handlerRequestCompleted(const QNearFieldTarget::RequestId &id) +{ + m_idToTarget.remove(id); +} + +void QNearFieldManagerPrivateImpl::handlerError(QNearFieldTarget::Error error, const QNearFieldTarget::RequestId &id) +{ + Q_UNUSED(error); + m_idToTarget.remove(id); +} + +bool QNearFieldManagerPrivateImpl::isAvailable() const +{ + return AndroidNfc::isAvailable(); +} + +bool QNearFieldManagerPrivateImpl::startTargetDetection() +{ + if (m_detecting) + return false; // Already detecting targets + + m_detecting = true; + updateReceiveState(); + return true; +} + +void QNearFieldManagerPrivateImpl::stopTargetDetection() +{ + m_detecting = false; + updateReceiveState(); +} + +int QNearFieldManagerPrivateImpl::registerNdefMessageHandler(QObject *object, const QMetaMethod &method) +{ + ndefMessageHandlers.append(QPair<QPair<int, QObject *>, QMetaMethod>(QPair<int, QObject *>(m_handlerID, object), method)); + updateReceiveState(); + //Returns the handler ID and increments it afterwards + return m_handlerID++; +} + +int QNearFieldManagerPrivateImpl::registerNdefMessageHandler(const QNdefFilter &filter, + QObject *object, const QMetaMethod &method) +{ + //If no record is set in the filter, we ignore the filter + if (filter.recordCount()==0) + return registerNdefMessageHandler(object, method); + + ndefFilterHandlers.append(QPair<QPair<int, QObject*>, QPair<QNdefFilter, QMetaMethod> > + (QPair<int, QObject*>(m_handlerID, object), QPair<QNdefFilter, QMetaMethod>(filter, method))); + + updateReceiveState(); + + return m_handlerID++; +} + +bool QNearFieldManagerPrivateImpl::unregisterNdefMessageHandler(int handlerId) +{ + for (int i=0; i<ndefMessageHandlers.count(); ++i) { + if (ndefMessageHandlers.at(i).first.first == handlerId) { + ndefMessageHandlers.removeAt(i); + updateReceiveState(); + return true; + } + } + for (int i=0; i<ndefFilterHandlers.count(); ++i) { + if (ndefFilterHandlers.at(i).first.first == handlerId) { + ndefFilterHandlers.removeAt(i); + updateReceiveState(); + return true; + } + } + return false; +} + +void QNearFieldManagerPrivateImpl::requestAccess(QNearFieldManager::TargetAccessModes accessModes) +{ + Q_UNUSED(accessModes); + //Do nothing, because we dont have access modes for the target +} + +void QNearFieldManagerPrivateImpl::releaseAccess(QNearFieldManager::TargetAccessModes accessModes) +{ + Q_UNUSED(accessModes); + //Do nothing, because we dont have access modes for the target +} + +void QNearFieldManagerPrivateImpl::newIntent(QAndroidJniObject intent) +{ + // This function is called from different thread and is used to move intent to main thread. + QMetaObject::invokeMethod(this, "onTargetDiscovered", Qt::QueuedConnection, Q_ARG(QAndroidJniObject, intent)); +} + +QByteArray QNearFieldManagerPrivateImpl::getUid(const QAndroidJniObject &intent) +{ + if (!intent.isValid()) + return QByteArray(); + + QAndroidJniEnvironment env; + QAndroidJniObject tag = AndroidNfc::getTag(intent); + return getUidforTag(tag); +} + +void QNearFieldManagerPrivateImpl::onTargetDiscovered(QAndroidJniObject intent) +{ + // Getting UID + QByteArray uid = getUid(intent); + + // Accepting all targets but only sending signal of requested types. + NearFieldTarget *&target = m_detectedTargets[uid]; + if (target) { + target->setIntent(intent); // Updating existing target + } else { + target = new NearFieldTarget(intent, uid, this); + connect(target, SIGNAL(targetDestroyed(QByteArray)), this, SLOT(onTargetDestroyed(QByteArray))); + connect(target, SIGNAL(targetLost(QNearFieldTarget*)), this, SIGNAL(targetLost(QNearFieldTarget*))); + } + emit targetDetected(target); +} + +void QNearFieldManagerPrivateImpl::onTargetDestroyed(const QByteArray &uid) +{ + m_detectedTargets.remove(uid); +} + +QByteArray QNearFieldManagerPrivateImpl::getUidforTag(const QAndroidJniObject &tag) +{ + if (!tag.isValid()) + return QByteArray(); + + QAndroidJniEnvironment env; + QAndroidJniObject tagId = tag.callObjectMethod("getId", "()[B"); + QByteArray uid; + jsize len = env->GetArrayLength(tagId.object<jbyteArray>()); + uid.resize(len); + env->GetByteArrayRegion(tagId.object<jbyteArray>(), 0, len, reinterpret_cast<jbyte*>(uid.data())); + return uid; +} + +void QNearFieldManagerPrivateImpl::updateReceiveState() +{ + if (m_detecting) { + AndroidNfc::registerListener(this); + } else { + if (ndefMessageHandlers.count() || ndefFilterHandlers.count()) { + AndroidNfc::registerListener(this); + } else { + AndroidNfc::unregisterListener(this); + } + } +} + +QT_END_NAMESPACE diff --git a/src/nfc/qnearfieldmanager_qnx_p.h b/src/nfc/qnearfieldmanager_android_p.h index 6f00041a..3d45b700 100644 --- a/src/nfc/qnearfieldmanager_qnx_p.h +++ b/src/nfc/qnearfieldmanager_android_p.h @@ -1,6 +1,6 @@ -/*************************************************************************** +/**************************************************************************** ** -** Copyright (C) 2012 Research In Motion +** Copyright (C) 2013 Centria research and development ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtNfc module of the Qt Toolkit. @@ -31,29 +31,26 @@ ** ****************************************************************************/ -#ifndef QNEARFIELDMANAGER_QNX_P_H -#define QNEARFIELDMANAGER_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. -// +#ifndef QNEARFIELDMANAGER_ANDROID_P_H +#define QNEARFIELDMANAGER_ANDROID_P_H #include "qnearfieldmanager_p.h" #include "qnearfieldmanager.h" #include "qnearfieldtarget.h" +#include "android/androidjninfc_p.h" -#include "qnx/qnxnfcmanager_p.h" +#include <QHash> +#include <QMap> +#include <QtAndroidExtras/QAndroidJniObject> +#include <QtAndroidExtras/QAndroidJniEnvironment> QT_BEGIN_NAMESPACE -class QNearFieldManagerPrivateImpl : public QNearFieldManagerPrivate +typedef QList<QNdefMessage> QNdefMessageList; + +class NearFieldTarget; +class QByteArray; +class QNearFieldManagerPrivateImpl : public QNearFieldManagerPrivate, public AndroidNfc::AndroidNfcListenerInterface { Q_OBJECT @@ -61,29 +58,34 @@ public: QNearFieldManagerPrivateImpl(); ~QNearFieldManagerPrivateImpl(); - bool isAvailable() const; - - bool startTargetDetection(); - - void stopTargetDetection(); - - int registerNdefMessageHandler(QObject *object, const QMetaMethod &method); - - int registerNdefMessageHandler(const QNdefFilter &filter, QObject *object, const QMetaMethod &method); - - bool unregisterNdefMessageHandler(int handlerId); - - void requestAccess(QNearFieldManager::TargetAccessModes accessModes); - - void releaseAccess(QNearFieldManager::TargetAccessModes accessModes); - -private slots: - void handleMessage(const QNdefMessage&, QNearFieldTarget *); - void newTarget(QNearFieldTarget *target, const QList<QNdefMessage> &); + virtual bool isAvailable() const; + virtual bool startTargetDetection(); + virtual void stopTargetDetection(); + virtual int registerNdefMessageHandler(QObject *object, const QMetaMethod &method); + virtual int registerNdefMessageHandler(const QNdefFilter &filter, QObject *object, const QMetaMethod &method); + virtual bool unregisterNdefMessageHandler(int handlerId); + virtual void requestAccess(QNearFieldManager::TargetAccessModes accessModes); + virtual void releaseAccess(QNearFieldManager::TargetAccessModes accessModes); + virtual void newIntent(QAndroidJniObject intent); + QByteArray getUid(const QAndroidJniObject &intent); + +public slots: + void onTargetDiscovered(QAndroidJniObject intent); + void onTargetDestroyed(const QByteArray &uid); + void handlerTargetDetected(QNearFieldTarget *target); + void handlerTargetLost(QNearFieldTarget *target); + void handlerNdefMessageRead(const QNdefMessage &message, const QNearFieldTarget::RequestId &id); + void handlerRequestCompleted(const QNearFieldTarget::RequestId &id); + void handlerError(QNearFieldTarget::Error error, const QNearFieldTarget::RequestId &id); + +protected: + static QByteArray getUidforTag(const QAndroidJniObject &tag); + void updateReceiveState(); private: - void updateNdefFilter(); - QList<QNearFieldTarget::Type> m_detectTargetTypes; + bool m_detecting; + QHash<QByteArray, NearFieldTarget*> m_detectedTargets; + QMap<QNearFieldTarget::RequestId, QNearFieldTarget*> m_idToTarget; int m_handlerID; QList< QPair<QPair<int, QObject *>, QMetaMethod> > ndefMessageHandlers; @@ -92,4 +94,4 @@ private: QT_END_NAMESPACE -#endif // QNEARFIELDMANAGER_QNX_P_H +#endif // QNEARFIELDMANAGER_ANDROID_P_H diff --git a/src/nfc/qnearfieldmanager_emulator_p.h b/src/nfc/qnearfieldmanager_emulator_p.h index 0fd980f9..a71c9fd5 100644 --- a/src/nfc/qnearfieldmanager_emulator_p.h +++ b/src/nfc/qnearfieldmanager_emulator_p.h @@ -50,7 +50,7 @@ #include "qndeffilter.h" #include <QtCore/QObject> -#include <QtCore/QWeakPointer> +#include <QtCore/QPointer> QT_BEGIN_NAMESPACE @@ -74,7 +74,7 @@ private slots: private: void ndefReceived(const QNdefMessage &message, QNearFieldTarget *target); - QMap<TagBase *, QWeakPointer<QNearFieldTarget> > m_targets; + QMap<TagBase *, QPointer<QNearFieldTarget> > m_targets; }; diff --git a/src/nfc/qnearfieldmanager_qnx.cpp b/src/nfc/qnearfieldmanager_qnx.cpp deleted file mode 100644 index 2c3c7077..00000000 --- a/src/nfc/qnearfieldmanager_qnx.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/*************************************************************************** -** -** Copyright (C) 2012 Research In Motion -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtNfc 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 "qnearfieldmanager_qnx_p.h" -#include <QDebug> -#include "qnearfieldtarget_qnx_p.h" -#include <QMetaMethod> -#include "qndeffilter.h" -#include "qndefrecord.h" - -QT_BEGIN_NAMESPACE - -QNearFieldManagerPrivateImpl::QNearFieldManagerPrivateImpl() : - m_handlerID(0) -{ - QNXNFCManager::instance()->registerForNewInstance(); - connect(QNXNFCManager::instance(), SIGNAL(ndefMessage(QNdefMessage,QNearFieldTarget*)), this, SLOT(handleMessage(QNdefMessage,QNearFieldTarget*))); - - m_requestedModes = QNearFieldManager::NdefWriteTargetAccess; - qQNXNFCDebug() << "Nearfieldmanager created"; -} - -QNearFieldManagerPrivateImpl::~QNearFieldManagerPrivateImpl() -{ - //First, remove all ndef message handlers - QNXNFCManager::instance()->updateNdefFilters(QList<QByteArray>(), this); - QNXNFCManager::instance()->unregisterForInstance(); -} - -bool QNearFieldManagerPrivateImpl::isAvailable() const -{ - return QNXNFCManager::instance()->isAvailable(); -} - -bool QNearFieldManagerPrivateImpl::startTargetDetection() -{ - qQNXNFCDebug() << "Starting targetdetection in nearfieldmanager"; - if (QNXNFCManager::instance()->startTargetDetection()) { - connect(QNXNFCManager::instance(), SIGNAL(targetDetected(QNearFieldTarget*,QList<QNdefMessage>)), - this, SLOT(newTarget(QNearFieldTarget*,QList<QNdefMessage>))); - return true; - } else { - qWarning()<<Q_FUNC_INFO<<"Could not start Target detection"; - return false; - } -} - -void QNearFieldManagerPrivateImpl::stopTargetDetection() -{ - disconnect(QNXNFCManager::instance(), SIGNAL(targetDetected(NearFieldTarget*,QList<QNdefMessage>)), - this, SLOT(newTarget(NearFieldTarget*,QList<QNdefMessage>))); - QNXNFCManager::instance()->unregisterTargetDetection(this); -} - -int QNearFieldManagerPrivateImpl::registerNdefMessageHandler(QObject *object, const QMetaMethod &method) -{ - QList<QByteArray> filterList; - filterList += '*'; - QNXNFCManager::instance()->updateNdefFilters(filterList, this); - - ndefMessageHandlers.append(QPair<QPair<int, QObject *>, QMetaMethod>(QPair<int, QObject *>(m_handlerID, object), method)); - - //Returns the handler ID and increments it afterwards - return m_handlerID++; -} - -int QNearFieldManagerPrivateImpl::registerNdefMessageHandler(const QNdefFilter &filter, - QObject *object, const QMetaMethod &method) -{ - //If no record is set in the filter, we ignore the filter - if (filter.recordCount()==0) - return registerNdefMessageHandler(object, method); - - ndefFilterHandlers.append(QPair<QPair<int, QObject*>, QPair<QNdefFilter, QMetaMethod> > - (QPair<int, QObject*>(m_handlerID, object), QPair<QNdefFilter, QMetaMethod>(filter, method))); - - updateNdefFilter(); - - return m_handlerID++; -} - -bool QNearFieldManagerPrivateImpl::unregisterNdefMessageHandler(int handlerId) -{ - for (int i=0; i<ndefMessageHandlers.count(); i++) { - if (ndefMessageHandlers.at(i).first.first == handlerId) { - ndefMessageHandlers.removeAt(i); - updateNdefFilter(); - return true; - } - } - for (int i=0; i<ndefFilterHandlers.count(); i++) { - if (ndefFilterHandlers.at(i).first.first == handlerId) { - ndefFilterHandlers.removeAt(i); - updateNdefFilter(); - return true; - } - } - return false; -} - -void QNearFieldManagerPrivateImpl::requestAccess(QNearFieldManager::TargetAccessModes accessModes) -{ - Q_UNUSED(accessModes); - //Do nothing, because we don't have access modes for the target -} - -void QNearFieldManagerPrivateImpl::releaseAccess(QNearFieldManager::TargetAccessModes accessModes) -{ - Q_UNUSED(accessModes); - //Do nothing, because we don't have access modes for the target -} - -void QNearFieldManagerPrivateImpl::handleMessage(const QNdefMessage &message, QNearFieldTarget *target) -{ - qQNXNFCDebug() << "Handling message in near field manager. Filtercount:" - << ndefFilterHandlers.count() << message.count(); - //For message handlers without filters - for (int i = 0; i < ndefMessageHandlers.count(); i++) { - ndefMessageHandlers.at(i).second.invoke(ndefMessageHandlers.at(i).first.second, Q_ARG(QNdefMessage, message), Q_ARG(QNearFieldTarget*, target)); - } - - //For message handlers that specified a filter - for (int i = 0; i < ndefFilterHandlers.count(); i++) { - QNdefFilter filter = ndefFilterHandlers.at(i).second.first; - if (filter.recordCount() > message.count()) - continue; - - int j=0; - for (j = 0; j < filter.recordCount();) { - if (message.at(j).typeNameFormat() != filter.recordAt(j).typeNameFormat - || message.at(j).type() != filter.recordAt(j).type ) { - break; - } - j++; - } - if (j == filter.recordCount()) - ndefFilterHandlers.at(i).second.second.invoke(ndefFilterHandlers.at(i).first.second, Q_ARG(QNdefMessage, message), Q_ARG(QNearFieldTarget*, target)); - } -} - -void QNearFieldManagerPrivateImpl::newTarget(QNearFieldTarget *target, const QList<QNdefMessage> &messages) -{ - Q_UNUSED(messages) - qQNXNFCDebug() << "New Target"; - emit targetDetected(target); -} - -void QNearFieldManagerPrivateImpl::updateNdefFilter() -{ - qQNXNFCDebug() << "Updating NDEF filter"; - QList<QByteArray> filterList; - if (ndefMessageHandlers.size() > 0) { ///SUbscribe for all ndef messages - filterList += '*'; - QNXNFCManager::instance()->updateNdefFilters(filterList, this); - } else if (ndefFilterHandlers.size() > 0){ - for (int i = 0; i < ndefFilterHandlers.count(); i++) { - QByteArray filter = "ndef://" + QByteArray::number(ndefFilterHandlers.at(i).second.first.recordAt(0).typeNameFormat) - + '/' + ndefFilterHandlers.at(i).second.first.recordAt(0).type; - if (!filterList.contains(filter)) - filterList.append(filter); - } - QNXNFCManager::instance()->updateNdefFilters(filterList, this); - } else { //Remove all ndef message handlers for this object - QNXNFCManager::instance()->updateNdefFilters(filterList, this); - } -} - - -QT_END_NAMESPACE diff --git a/src/nfc/qnearfieldmanagervirtualbase.cpp b/src/nfc/qnearfieldmanagervirtualbase.cpp index cf25ed2b..b0f77e2f 100644 --- a/src/nfc/qnearfieldmanagervirtualbase.cpp +++ b/src/nfc/qnearfieldmanagervirtualbase.cpp @@ -172,7 +172,8 @@ void QNearFieldManagerPrivateVirtualBase::ndefReceived(const QNdefMessage &messa VerifyRecord &vr = filterRecords[j]; if (vr.filterRecord.typeNameFormat == record.typeNameFormat() && - vr.filterRecord.type == record.type()) { + ( vr.filterRecord.type == record.type() || + vr.filterRecord.type.isEmpty()) ) { ++vr.count; break; } else { diff --git a/src/nfc/qnearfieldsharemanager.cpp b/src/nfc/qnearfieldsharemanager.cpp index e9b70739..c0c031dd 100644 --- a/src/nfc/qnearfieldsharemanager.cpp +++ b/src/nfc/qnearfieldsharemanager.cpp @@ -34,11 +34,7 @@ #include "qnearfieldsharemanager.h" #include "qnearfieldsharemanager_p.h" -#if defined(QNX_NFC) -#include "qnearfieldsharemanager_qnx_p.h" -#else #include "qnearfieldsharemanagerimpl_p.h" -#endif #include "qnearfieldsharetarget.h" diff --git a/src/nfc/qnearfieldsharemanager.h b/src/nfc/qnearfieldsharemanager.h index 330cc621..264e82b6 100644 --- a/src/nfc/qnearfieldsharemanager.h +++ b/src/nfc/qnearfieldsharemanager.h @@ -45,8 +45,6 @@ class QNearFieldShareTarget; class Q_NFC_EXPORT QNearFieldShareManager : public QObject { Q_OBJECT - Q_ENUMS(ShareError) - Q_ENUMS(ShareMode) public: explicit QNearFieldShareManager(QObject *parent = 0); @@ -63,12 +61,14 @@ public: ShareAlreadyInProgressError, SharePermissionDeniedError }; + Q_ENUM(ShareError) enum ShareMode { NoShare = 0x00, NdefShare = 0x01, FileShare = 0x02 }; + Q_ENUM(ShareMode) Q_DECLARE_FLAGS(ShareModes, ShareMode) public: diff --git a/src/nfc/qnearfieldsharemanager_qnx_p.cpp b/src/nfc/qnearfieldsharemanager_qnx_p.cpp deleted file mode 100644 index dd2814d6..00000000 --- a/src/nfc/qnearfieldsharemanager_qnx_p.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/*************************************************************************** - ** - ** Copyright (C) 2013 BlackBerry Limited. All rights reserved. - ** Contact: http://www.qt.io/licensing/ - ** - ** This file is part of the QtNfc 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 "qnearfieldsharemanager_qnx_p.h" -#include "qnearfieldsharetarget.h" -#include "qnx/qnxnfcsharemanager_p.h" - -QT_BEGIN_NAMESPACE - -using namespace bb::system; - -QNearFieldShareManagerPrivateImpl::QNearFieldShareManagerPrivateImpl(QNearFieldShareManager* q) - : QNearFieldShareManagerPrivate(q), q_ptr(q), _manager(0), _target(0), _shareError(QNearFieldShareManager::NoError) -{ - _manager = QNXNFCShareManager::instance(); - _manager->connect(this); -} - -QNearFieldShareManagerPrivateImpl::~QNearFieldShareManagerPrivateImpl() -{ - if (_target) { - delete _target; - } - - _manager->disconnect(this); -} - -void QNearFieldShareManagerPrivateImpl::onShareModeChanged(NfcShareMode::Type mode) -{ - switch (mode) { - case NfcShareMode::DataSnep: { - emit q_ptr->shareModesChanged(QNearFieldShareManager::NdefShare); - break; - } - - case NfcShareMode::File: { - emit q_ptr->shareModesChanged(QNearFieldShareManager::FileShare); - break; - } - - case NfcShareMode::Disabled: { - emit q_ptr->shareModesChanged(QNearFieldShareManager::NoShare); - break; - } - - default: { - } - } -} - -void QNearFieldShareManagerPrivateImpl::onError(NfcShareError::Type error) -{ - _shareError = QNXNFCShareManager::toShareError(error); - - if (_shareError != QNearFieldShareManager::NoError) - emit q_ptr->error(_shareError); -} - -void QNearFieldShareManagerPrivateImpl::onFinished(NfcShareSuccess::Type result) -{ - Q_UNUSED(result) -} - -void QNearFieldShareManagerPrivateImpl::onTargetAcquired() -{ - if (_target) { - delete _target; - _target = 0; - } - - _target = new QNearFieldShareTarget(shareModes(), this); - emit q_ptr->targetDetected(_target); -} - -void QNearFieldShareManagerPrivateImpl::onTargetCancelled() -{ -} - -QNearFieldShareManager::ShareModes QNearFieldShareManagerPrivateImpl::supportedShareModes() -{ - return QNearFieldShareManager::NdefShare | QNearFieldShareManager::FileShare; -} - -void QNearFieldShareManagerPrivateImpl::setShareModes(QNearFieldShareManager::ShareModes modes) -{ - _shareError = QNearFieldShareManager::NoError; - - if (modes == QNearFieldShareManager::NoShare) { - _manager->setShareMode(NfcShareMode::Disabled); - _manager->reset(); - } - - else { - // TODO: Fix NfcShareManager to handle multiple share modes simultaneously - if (modes.testFlag(QNearFieldShareManager::NdefShare)) - _manager->setShareMode(NfcShareMode::DataSnep); - - if (modes.testFlag(QNearFieldShareManager::FileShare)) - _manager->setShareMode(NfcShareMode::File); - } -} - -QNearFieldShareManager::ShareModes QNearFieldShareManagerPrivateImpl::shareModes() const -{ - return QNXNFCShareManager::toShareModes(_manager->shareMode()); -} - -QNearFieldShareManager::ShareError QNearFieldShareManagerPrivateImpl::shareError() const -{ - return _shareError; -} - -QT_END_NAMESPACE diff --git a/src/nfc/qnearfieldsharemanager_qnx_p.h b/src/nfc/qnearfieldsharemanager_qnx_p.h deleted file mode 100644 index c5cea224..00000000 --- a/src/nfc/qnearfieldsharemanager_qnx_p.h +++ /dev/null @@ -1,86 +0,0 @@ -/*************************************************************************** - ** - ** Copyright (C) 2013 BlackBerry Limited. All rights reserved. - ** Contact: http://www.qt.io/licensing/ - ** - ** This file is part of the QtNfc 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 QNEARFIELDSHAREMANAGER_QNX_P_H_ -#define QNEARFIELDSHAREMANAGER_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 "qnearfieldsharemanager_p.h" -#include <bb/system/NfcShareManager> - -QT_BEGIN_NAMESPACE - -class QNXNFCShareManager; - -class QNearFieldShareManagerPrivateImpl : public QNearFieldShareManagerPrivate -{ - Q_OBJECT - -public: - QNearFieldShareManagerPrivateImpl(QNearFieldShareManager* q); - ~QNearFieldShareManagerPrivateImpl(); - - static QNearFieldShareManager::ShareModes supportedShareModes(); - void setShareModes(QNearFieldShareManager::ShareModes modes); - QNearFieldShareManager::ShareModes shareModes() const; - QNearFieldShareManager::ShareError shareError() const; - -private slots: - void onShareModeChanged(bb::system::NfcShareMode::Type mode); - void onError(bb::system::NfcShareError::Type error); - void onFinished(bb::system::NfcShareSuccess::Type result); - void onTargetAcquired(); - void onTargetCancelled(); - -private: - QNearFieldShareManager * const q_ptr; - Q_DECLARE_PUBLIC(QNearFieldShareManager) - - QNXNFCShareManager *_manager; - QNearFieldShareTarget *_target; - QNearFieldShareManager::ShareError _shareError; -}; - -QT_END_NAMESPACE - -#endif /* QNEARFIELDSHAREMANAGER_QNX_P_H_ */ diff --git a/src/nfc/qnearfieldsharetarget.cpp b/src/nfc/qnearfieldsharetarget.cpp index 86c6318e..9e79909b 100644 --- a/src/nfc/qnearfieldsharetarget.cpp +++ b/src/nfc/qnearfieldsharetarget.cpp @@ -34,11 +34,7 @@ #include "qnearfieldsharetarget.h" #include "qnearfieldsharetarget_p.h" -#if defined(QNX_NFC) -#include "qnearfieldsharetarget_qnx_p.h" -#else #include "qnearfieldsharetargetimpl_p.h" -#endif #include "qnearfieldsharemanager.h" diff --git a/src/nfc/qnearfieldsharetarget_qnx_p.cpp b/src/nfc/qnearfieldsharetarget_qnx_p.cpp deleted file mode 100644 index 6dfea8d2..00000000 --- a/src/nfc/qnearfieldsharetarget_qnx_p.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/*************************************************************************** - ** - ** Copyright (C) 2013 BlackBerry Limited. All rights reserved. - ** Contact: http://www.qt.io/licensing/ - ** - ** This file is part of the QtNfc 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 "qnearfieldsharetarget_qnx_p.h" -#include "qnearfieldsharemanager_p.h" -#include "qnx/qnxnfcsharemanager_p.h" - -QT_BEGIN_NAMESPACE - -using namespace bb::system; - -QNearFieldShareTargetPrivateImpl::QNearFieldShareTargetPrivateImpl(QNearFieldShareManager::ShareModes modes, QNearFieldShareTarget *q) -: QNearFieldShareTargetPrivate(modes, q), q_ptr(q), _error(QNearFieldShareManager::NoError) -{ - _manager = QNXNFCShareManager::instance(); - _manager->connect(this); -} - -QNearFieldShareTargetPrivateImpl::~QNearFieldShareTargetPrivateImpl() -{ - _manager->disconnect(this); -} - -QNearFieldShareManager::ShareModes QNearFieldShareTargetPrivateImpl::shareModes() const -{ - return QNXNFCShareManager::toShareModes(_manager->shareMode()); -} - -bool QNearFieldShareTargetPrivateImpl::share(const QNdefMessage &message) -{ - return _manager->shareNdef(message); -} - -bool QNearFieldShareTargetPrivateImpl::share(const QList<QFileInfo> &files) -{ - return _manager->shareFiles(files); -} - -void QNearFieldShareTargetPrivateImpl::cancel() -{ - _manager->cancel(); -} - -bool QNearFieldShareTargetPrivateImpl::isShareInProgress() const -{ - return QNXNFCShareManager::toShareModes(_manager->shareMode()) != QNearFieldShareManager::NoShare; -} - -QNearFieldShareManager::ShareError QNearFieldShareTargetPrivateImpl::shareError() const -{ - return _error; -} - -void QNearFieldShareTargetPrivateImpl::onShareModeChanged(NfcShareMode::Type mode) -{ - Q_UNUSED(mode) -} - -void QNearFieldShareTargetPrivateImpl::onError(NfcShareError::Type error) -{ - _error = QNXNFCShareManager::toShareError(error); - - if (_error != QNearFieldShareManager::NoError) { - emit q_ptr->error(_error); - } -} - -void QNearFieldShareTargetPrivateImpl::onFinished(NfcShareSuccess::Type result) -{ - Q_UNUSED(result) - emit q_ptr->shareFinished(); -} - -void QNearFieldShareTargetPrivateImpl::onTargetAcquired() -{ -} - -void QNearFieldShareTargetPrivateImpl::onTargetCancelled() -{ -} - -QT_END_NAMESPACE diff --git a/src/nfc/qnearfieldsharetarget_qnx_p.h b/src/nfc/qnearfieldsharetarget_qnx_p.h deleted file mode 100644 index 626d2cc1..00000000 --- a/src/nfc/qnearfieldsharetarget_qnx_p.h +++ /dev/null @@ -1,88 +0,0 @@ -/*************************************************************************** - ** - ** Copyright (C) 2013 BlackBerry Limited. All rights reserved. - ** Contact: http://www.qt.io/licensing/ - ** - ** This file is part of the QtNfc 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 QNEARFIELDSHARETARGET_QNX_P_H -#define QNEARFIELDSHARETARGET_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 "qnearfieldsharetarget_p.h" -#include <bb/system/NfcShareManager> - -QT_BEGIN_NAMESPACE - -class QNXNFCShareManager; - -class QNearFieldShareTargetPrivateImpl : public QNearFieldShareTargetPrivate -{ - Q_OBJECT - -public: - QNearFieldShareTargetPrivateImpl(QNearFieldShareManager::ShareModes modes, QNearFieldShareTarget *q); - ~QNearFieldShareTargetPrivateImpl(); - - QNearFieldShareManager::ShareModes shareModes() const; - bool share(const QNdefMessage &message); - bool share(const QList<QFileInfo> &files); - void cancel(); - bool isShareInProgress() const; - QNearFieldShareManager::ShareError shareError() const; - -private slots: - void onShareModeChanged(bb::system::NfcShareMode::Type mode); - void onError(bb::system::NfcShareError::Type error); - void onFinished(bb::system::NfcShareSuccess::Type result); - void onTargetAcquired(); - void onTargetCancelled(); - -private: - QNearFieldShareTarget * const q_ptr; - Q_DECLARE_PUBLIC(QNearFieldShareTarget) - - QNXNFCShareManager *_manager; - QNearFieldShareManager::ShareError _error; -}; - -QT_END_NAMESPACE - -#endif /* QNEARFIELDSHARETARGET_QNX_P_H */ diff --git a/src/nfc/qnearfieldtagtype1_p.h b/src/nfc/qnearfieldtagtype1_p.h index efc757a0..0f5ad26e 100644 --- a/src/nfc/qnearfieldtagtype1_p.h +++ b/src/nfc/qnearfieldtagtype1_p.h @@ -62,6 +62,7 @@ public: EraseAndWrite, WriteOnly }; + Q_ENUM(WriteMode) explicit QNearFieldTagType1(QObject *parent = 0); ~QNearFieldTagType1(); diff --git a/src/nfc/qnearfieldtarget.h b/src/nfc/qnearfieldtarget.h index fef74946..a7abbe25 100644 --- a/src/nfc/qnearfieldtarget.h +++ b/src/nfc/qnearfieldtarget.h @@ -65,6 +65,7 @@ public: NfcTagType4, MifareTag }; + Q_ENUM(Type) enum AccessMethod { UnknownAccess = 0x00, @@ -72,6 +73,7 @@ public: TagTypeSpecificAccess = 0x02, LlcpAccess = 0x04 }; + Q_ENUM(AccessMethod) Q_DECLARE_FLAGS(AccessMethods, AccessMethod) enum Error { @@ -85,6 +87,7 @@ public: NdefReadError, NdefWriteError }; + Q_ENUM(Error) class RequestIdPrivate; class Q_NFC_EXPORT RequestId @@ -158,6 +161,5 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QNearFieldTarget::AccessMethods) QT_END_NAMESPACE Q_DECLARE_METATYPE(QNearFieldTarget::RequestId) -Q_DECLARE_METATYPE(QNearFieldTarget::Error) #endif // QNEARFIELDTARGET_H diff --git a/src/nfc/qnearfieldtarget_android.cpp b/src/nfc/qnearfieldtarget_android.cpp new file mode 100644 index 00000000..891ce3fc --- /dev/null +++ b/src/nfc/qnearfieldtarget_android.cpp @@ -0,0 +1,448 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Centria research and development +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtNfc 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 "qnearfieldtarget_android_p.h" +#include "android/androidjninfc_p.h" +#include "qdebug.h" + +#define NDEFTECHNOLOGY "android.nfc.tech.Ndef" +#define NDEFFORMATABLETECHNOLOGY "android.nfc.tech.NdefFormatable" +#define NFCATECHNOLOGY "android.nfc.tech.NfcA" +#define NFCBTECHNOLOGY "android.nfc.tech.NfcB" +#define NFCFTECHNOLOGY "android.nfc.tech.NfcF" +#define NFCVTECHNOLOGY "android.nfc.tech.NfcV" +#define MIFARECLASSICTECHNOLOGY "android.nfc.tech.MifareClassic" +#define MIFARECULTRALIGHTTECHNOLOGY "android.nfc.tech.MifareUltralight" + +#define MIFARETAG "com.nxp.ndef.mifareclassic" +#define NFCTAGTYPE1 "org.nfcforum.ndef.type1" +#define NFCTAGTYPE2 "org.nfcforum.ndef.type2" +#define NFCTAGTYPE3 "org.nfcforum.ndef.type3" +#define NFCTAGTYPE4 "org.nfcforum.ndef.type4" + +NearFieldTarget::NearFieldTarget(QAndroidJniObject intent, const QByteArray uid, QObject *parent) : + QNearFieldTarget(parent), + m_intent(intent), + m_uid(uid) +{ + updateTechList(); + updateType(); + setupTargetCheckTimer(); +} + +NearFieldTarget::~NearFieldTarget() +{ + releaseIntent(); + emit targetDestroyed(m_uid); +} + +QByteArray NearFieldTarget::uid() const +{ + return m_uid; +} + +QNearFieldTarget::Type NearFieldTarget::type() const +{ + return m_type; +} + +QNearFieldTarget::AccessMethods NearFieldTarget::accessMethods() const +{ + AccessMethods result = NdefAccess; + return result; +} + +bool NearFieldTarget::hasNdefMessage() +{ + return m_techList.contains(QStringLiteral(NDEFTECHNOLOGY)); +} + +QNearFieldTarget::RequestId NearFieldTarget::readNdefMessages() +{ + // Making sure that target has NDEF messages + if (!hasNdefMessage()) + return QNearFieldTarget::RequestId(); + + // Making sure that target is still in range + QNearFieldTarget::RequestId requestId(new QNearFieldTarget::RequestIdPrivate); + if (!m_intent.isValid()) { + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::TargetOutOfRangeError), + Q_ARG(const QNearFieldTarget::RequestId&, requestId)); + return requestId; + } + + // Getting Ndef technology object + QAndroidJniObject ndef = getTagTechnology(QStringLiteral(NDEFTECHNOLOGY)); + if (!ndef.isValid()) { + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::UnsupportedError), + Q_ARG(const QNearFieldTarget::RequestId&, requestId)); + return requestId; + } + + // Connect + ndef.callMethod<void>("connect"); + if (catchJavaExceptions()) { + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::TargetOutOfRangeError), + Q_ARG(const QNearFieldTarget::RequestId&, requestId)); + return requestId; + } + + // Get NdefMessage object + QAndroidJniObject ndefMessage = ndef.callObjectMethod("getNdefMessage", "()Landroid/nfc/NdefMessage;"); + if (catchJavaExceptions()) + ndefMessage = QAndroidJniObject(); + if (!ndefMessage.isValid()) { + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::NdefReadError), + Q_ARG(const QNearFieldTarget::RequestId&, requestId)); + return requestId; + } + + // Convert to byte array + QAndroidJniObject ndefMessageBA = ndefMessage.callObjectMethod("toByteArray", "()[B"); + QByteArray ndefMessageQBA = jbyteArrayToQByteArray(ndefMessageBA.object<jbyteArray>()); + + // Closing connection + ndef.callMethod<void>("close"); + catchJavaExceptions(); // IOException at this point does not matter anymore. + + // Sending QNdefMessage, requestCompleted and exit. + QNdefMessage qNdefMessage = QNdefMessage::fromByteArray(ndefMessageQBA); + QMetaObject::invokeMethod(this, "ndefMessageRead", Qt::QueuedConnection, + Q_ARG(const QNdefMessage&, qNdefMessage)); + QMetaObject::invokeMethod(this, "requestCompleted", Qt::QueuedConnection, + Q_ARG(const QNearFieldTarget::RequestId&, requestId)); + QMetaObject::invokeMethod(this, "ndefMessageRead", Qt::QueuedConnection, + Q_ARG(const QNdefMessage&, qNdefMessage), + Q_ARG(const QNearFieldTarget::RequestId&, requestId)); + return requestId; +} + + +QNearFieldTarget::RequestId NearFieldTarget::sendCommand(const QByteArray &command) +{ + Q_UNUSED(command); + Q_EMIT QNearFieldTarget::error(QNearFieldTarget::UnsupportedError, QNearFieldTarget::RequestId()); + return QNearFieldTarget::RequestId(); + + //Not supported for now + /*if (command.size() == 0) { + Q_EMIT QNearFieldTarget::error(QNearFieldTarget::InvalidParametersError, QNearFieldTarget::RequestId()); + return QNearFieldTarget::RequestId(); + } + + AndroidNfc::AttachedJNIEnv aenv; + JNIEnv *env = aenv.jniEnv; + + jobject tagTech; + if (m_techList.contains(QStringLiteral(NFCATECHNOLOGY))) { + tagTech = getTagTechnology(QStringLiteral(NFCATECHNOLOGY)); + } else if (m_techList.contains(QStringLiteral(NFCBTECHNOLOGY))) { + tagTech = getTagTechnology(QStringLiteral(NFCBTECHNOLOGY)); + } else if (m_techList.contains(QStringLiteral(NFCFTECHNOLOGY))) { + tagTech = getTagTechnology(QStringLiteral(NFCFTECHNOLOGY)); + } else if (m_techList.contains(QStringLiteral(NFCVTECHNOLOGY))) { + tagTech = getTagTechnology(QStringLiteral(NFCVTECHNOLOGY)); + } else { + Q_EMIT QNearFieldTarget::error(QNearFieldTarget::UnsupportedError, QNearFieldTarget::RequestId()); + return QNearFieldTarget::RequestId(); + } + + QByteArray ba(ba); + + jclass techClass = env->GetObjectClass(tagTech); + jmethodID tranceiveMID = env->GetMethodID(techClass, "tranceive", "([B)[B"); + Q_ASSERT_X(tranceiveMID != 0, "sendCommand", "could not find tranceive method"); + + jbyteArray jba = env->NewByteArray(ba.size()); + env->SetByteArrayRegion(jba, 0, ba.size(), reinterpret_cast<jbyte*>(ba.data())); + + jbyteArray rsp = reinterpret_cast<jbyteArray>(env->CallObjectMethod(tagTech, tranceiveMID, jba)); + + jsize len = env->GetArrayLength(rsp); + QByteArray rspQBA; + rspQBA.resize(len); + + env->GetByteArrayRegion(rsp, 0, len, reinterpret_cast<jbyte*>(rspQBA.data())); + + qDebug() << "Send command returned QBA size: " << rspQBA.size(); + + + env->DeleteLocalRef(jba); + + + return QNearFieldTarget::RequestId();*/ +} + +QNearFieldTarget::RequestId NearFieldTarget::sendCommands(const QList<QByteArray> &commands) +{ + QNearFieldTarget::RequestId requestId; + for (int i=0; i < commands.size(); i++){ + requestId = sendCommand(commands.at(i)); + } + return requestId; +} + +QNearFieldTarget::RequestId NearFieldTarget::writeNdefMessages(const QList<QNdefMessage> &messages) +{ + if (messages.size() == 0) + return QNearFieldTarget::RequestId(); + + if (messages.size() > 1) + qWarning("QNearFieldTarget::writeNdefMessages: Android supports writing only one NDEF message per tag."); + + QAndroidJniEnvironment env; + const char *writeMethod; + QAndroidJniObject tagTechnology; + + // Getting write method + if (m_techList.contains(QStringLiteral(NDEFFORMATABLETECHNOLOGY))) { + tagTechnology = getTagTechnology(QStringLiteral(NDEFFORMATABLETECHNOLOGY)); + writeMethod = "format"; + } else if (m_techList.contains(QStringLiteral(NDEFTECHNOLOGY))) { + tagTechnology = getTagTechnology(QStringLiteral(NDEFTECHNOLOGY)); + writeMethod = "writeNdefMessage"; + } else { + // An invalid request id will be returned if the target does not support writing NDEF messages. + return QNearFieldTarget::RequestId(); + } + + // Connecting + QNearFieldTarget::RequestId requestId = QNearFieldTarget::RequestId(new QNearFieldTarget::RequestIdPrivate()); + tagTechnology.callMethod<void>("connect"); + if (catchJavaExceptions()) { + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::TargetOutOfRangeError), + Q_ARG(const QNearFieldTarget::RequestId&, requestId)); + return requestId; + } + + // Making NdefMessage object + const QNdefMessage &message = messages.first(); + QByteArray ba = message.toByteArray(); + QAndroidJniObject jba = env->NewByteArray(ba.size()); + env->SetByteArrayRegion(jba.object<jbyteArray>(), 0, ba.size(), reinterpret_cast<jbyte*>(ba.data())); + QAndroidJniObject jmessage = QAndroidJniObject("android/nfc/NdefMessage", "([B)V", jba.object<jbyteArray>()); + if (catchJavaExceptions()) { + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::UnknownError), + Q_ARG(const QNearFieldTarget::RequestId&, requestId)); + return requestId; + } + + // Writing + tagTechnology.callMethod<void>(writeMethod, "(Landroid/nfc/NdefMessage;)V", jmessage.object<jobject>()); + if (catchJavaExceptions()) { + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::NdefWriteError), + Q_ARG(const QNearFieldTarget::RequestId&, requestId)); + return requestId; + } + + // Closing connection, sending signal and exit + tagTechnology.callMethod<void>("close"); + catchJavaExceptions(); // IOException at this point does not matter anymore. + QMetaObject::invokeMethod(this, "ndefMessagesWritten", Qt::QueuedConnection); + return requestId; +} + +void NearFieldTarget::setIntent(QAndroidJniObject intent) +{ + if (m_intent == intent) + return; + + releaseIntent(); + m_intent = intent; + if (m_intent.isValid()) { + // Updating tech list and type in case of there is another tag with same UID as one before. + updateTechList(); + updateType(); + m_targetCheckTimer->start(); + } +} + +void NearFieldTarget::checkIsTargetLost() +{ + if (!m_intent.isValid() || m_techList.isEmpty()) { + handleTargetLost(); + return; + } + // Using first available technology to check connection + QString techStr = m_techList.first(); + QAndroidJniObject tagTech = getTagTechnology(techStr); + tagTech.callMethod<void>("connect"); + if (catchJavaExceptions()) { + handleTargetLost(); + return; + } + tagTech.callMethod<void>("close"); + if (catchJavaExceptions()) + handleTargetLost(); +} + +void NearFieldTarget::releaseIntent() +{ + m_targetCheckTimer->stop(); + + m_intent = QAndroidJniObject(); +} + +void NearFieldTarget::updateTechList() +{ + if (!m_intent.isValid()) + return; + + // Getting tech list + QAndroidJniEnvironment env; + QAndroidJniObject tag = AndroidNfc::getTag(m_intent); + QAndroidJniObject techListArray = tag.callObjectMethod("getTechList", "()[Ljava/lang/String;"); + if (!techListArray.isValid()) { + handleTargetLost(); + return; + } + + // Converting tech list array to QStringList. + m_techList.clear(); + jsize techCount = env->GetArrayLength(techListArray.object<jobjectArray>()); + for (jsize i = 0; i < techCount; ++i) { + QAndroidJniObject tech = env->GetObjectArrayElement(techListArray.object<jobjectArray>(), i); + m_techList.append(tech.callObjectMethod<jstring>("toString").toString()); + } +} + +void NearFieldTarget::updateType() +{ + m_type = getTagType(); +} + +QNearFieldTarget::Type NearFieldTarget::getTagType() const +{ + QAndroidJniEnvironment env; + + if (m_techList.contains(QStringLiteral(NDEFTECHNOLOGY))) { + QAndroidJniObject ndef = getTagTechnology(QStringLiteral(NDEFTECHNOLOGY)); + QString qtype = ndef.callObjectMethod("getType", "()Ljava/lang/String;").toString(); + + if (qtype.compare(QStringLiteral(MIFARETAG)) == 0) + return MifareTag; + if (qtype.compare(QStringLiteral(NFCTAGTYPE1)) == 0) + return NfcTagType1; + if (qtype.compare(QStringLiteral(NFCTAGTYPE2)) == 0) + return NfcTagType2; + if (qtype.compare(QStringLiteral(NFCTAGTYPE3)) == 0) + return NfcTagType3; + if (qtype.compare(QStringLiteral(NFCTAGTYPE4)) == 0) + return NfcTagType4; + return ProprietaryTag; + } else if (m_techList.contains(QStringLiteral(NFCATECHNOLOGY))) { + if (m_techList.contains(QStringLiteral(MIFARECLASSICTECHNOLOGY))) + return MifareTag; + + // Checking ATQA/SENS_RES + // xxx0 0000 xxxx xxxx: Identifies tag Type 1 platform + QAndroidJniObject nfca = getTagTechnology(QStringLiteral(NFCATECHNOLOGY)); + QAndroidJniObject atqaBA = nfca.callObjectMethod("getAtqa", "()[B"); + QByteArray atqaQBA = jbyteArrayToQByteArray(atqaBA.object<jbyteArray>()); + if (atqaQBA.isEmpty()) + return ProprietaryTag; + if ((atqaQBA[0] & 0x1F) == 0x00) + return NfcTagType1; + + // Checking SAK/SEL_RES + // xxxx xxxx x00x x0xx: Identifies tag Type 2 platform + // xxxx xxxx x01x x0xx: Identifies tag Type 4 platform + jshort sakS = nfca.callMethod<jshort>("getSak"); + if ((sakS & 0x0064) == 0x0000) + return NfcTagType2; + else if ((sakS & 0x0064) == 0x0020) + return NfcTagType4; + return ProprietaryTag; + } else if (m_techList.contains(QStringLiteral(NFCBTECHNOLOGY))) { + return NfcTagType4; + } else if (m_techList.contains(QStringLiteral(NFCFTECHNOLOGY))) { + return NfcTagType3; + } + + return ProprietaryTag; +} + +void NearFieldTarget::setupTargetCheckTimer() +{ + m_targetCheckTimer = new QTimer(this); + m_targetCheckTimer->setInterval(1000); + connect(m_targetCheckTimer, SIGNAL(timeout()), this, SLOT(checkIsTargetLost())); + m_targetCheckTimer->start(); +} + +void NearFieldTarget::handleTargetLost() +{ + releaseIntent(); + emit targetLost(this); +} + +QAndroidJniObject NearFieldTarget::getTagTechnology(const QString &tech) const +{ + QString techClass(tech); + techClass.replace(QLatin1Char('.'), QLatin1Char('/')); + + // Getting requested technology + QAndroidJniObject tag = AndroidNfc::getTag(m_intent); + const QString sig = QString::fromUtf8("(Landroid/nfc/Tag;)L%1;"); + QAndroidJniObject tagtech = QAndroidJniObject::callStaticObjectMethod(techClass.toUtf8().constData(), "get", + sig.arg(techClass).toUtf8().constData(), tag.object<jobject>()); + return tagtech; +} + +QByteArray NearFieldTarget::jbyteArrayToQByteArray(const jbyteArray &byteArray) const +{ + QAndroidJniEnvironment env; + QByteArray resultArray; + jsize len = env->GetArrayLength(byteArray); + resultArray.resize(len); + env->GetByteArrayRegion(byteArray, 0, len, reinterpret_cast<jbyte*>(resultArray.data())); + return resultArray; +} + +bool NearFieldTarget::catchJavaExceptions() const +{ + QAndroidJniEnvironment env; + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + env->ExceptionClear(); + return true; + } + return false; +} diff --git a/src/nfc/qnearfieldtarget_android_p.h b/src/nfc/qnearfieldtarget_android_p.h new file mode 100644 index 00000000..ef9b5fdc --- /dev/null +++ b/src/nfc/qnearfieldtarget_android_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Centria research and development +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtNfc 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 QNEARFIELDTARGET_ANDROID_P_H +#define QNEARFIELDTARGET_ANDROID_P_H + +#include "android/androidjninfc_p.h" +#include "qnearfieldtarget.h" +#include "qnearfieldtarget_p.h" +#include "qndefmessage.h" +#include "qlist.h" +#include "qstringlist.h" +#include <QTimer> + +#include <QtAndroidExtras/QAndroidJniObject> +#include <QtAndroidExtras/QAndroidJniEnvironment> + +QT_BEGIN_NAMESPACE + +class NearFieldTarget : public QNearFieldTarget +{ + Q_OBJECT +public: + NearFieldTarget(QAndroidJniObject intent, + const QByteArray uid, + QObject *parent = 0); + virtual ~NearFieldTarget(); + virtual QByteArray uid() const; + virtual Type type() const; + virtual AccessMethods accessMethods() const; + virtual bool hasNdefMessage(); + virtual RequestId readNdefMessages(); + virtual RequestId sendCommand(const QByteArray &command); + virtual RequestId sendCommands(const QList<QByteArray> &commands); + virtual RequestId writeNdefMessages(const QList<QNdefMessage> &messages); + void setIntent(QAndroidJniObject intent); + +signals: + void targetDestroyed(const QByteArray &tagId); + void targetLost(QNearFieldTarget *target); + void ndefMessageRead(const QNdefMessage &message, const QNearFieldTarget::RequestId &id); + +protected slots: + void checkIsTargetLost(); + +protected: + void releaseIntent(); + void updateTechList(); + void updateType(); + Type getTagType() const; + void setupTargetCheckTimer(); + void handleTargetLost(); + QAndroidJniObject getTagTechnology(const QString &tech) const; + QByteArray jbyteArrayToQByteArray(const jbyteArray &byteArray) const; + bool catchJavaExceptions() const; + +protected: + QAndroidJniObject m_intent; + QByteArray m_uid; + QStringList m_techList; + Type m_type; + QTimer *m_targetCheckTimer; +}; + +QT_END_NAMESPACE + +#endif // QNEARFIELDTARGET_ANDROID_P_H diff --git a/src/nfc/qnearfieldtarget_qnx_p.h b/src/nfc/qnearfieldtarget_qnx_p.h deleted file mode 100644 index eb785d81..00000000 --- a/src/nfc/qnearfieldtarget_qnx_p.h +++ /dev/null @@ -1,227 +0,0 @@ -/*************************************************************************** -** -** Copyright (C) 2012 Research In Motion -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtNfc 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 QNEARFIELDTARGET_QNX_H -#define QNEARFIELDTARGET_QNX_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 <qnearfieldtarget.h> -#include <qnearfieldtarget_p.h> -#include <qndefmessage.h> - -#include <nfc/nfc.h> -#include <nfc/nfc_types.h> - -#include "qnx/qnxnfcmanager_p.h" - -QT_BEGIN_NAMESPACE - -#define TAG_NAME_BUFFER 64 - -template <typename T> -class NearFieldTarget : public T -{ -public: - - NearFieldTarget(QObject *parent, nfc_target_t *target, const QList<QNdefMessage> &messages) - : T(parent), m_target(target) - { - char buf[TAG_NAME_BUFFER]; - size_t bufLength; - - if (nfc_get_tag_name(target, buf, TAG_NAME_BUFFER, &bufLength) != NFC_RESULT_SUCCESS) - qWarning() << Q_FUNC_INFO << "Could not get tag name"; - else - m_tagName = QByteArray(buf, bufLength); - - if (nfc_get_tag_id(target, reinterpret_cast<uchar_t *>(buf), TAG_NAME_BUFFER, &bufLength) != NFC_RESULT_SUCCESS) - qWarning() << Q_FUNC_INFO << "Could not get tag id"; - else - m_tagId = QByteArray(buf,bufLength); - - m_ndefMessages = messages; - } - - ~NearFieldTarget() - { - //Not entierely sure if this is the right place to do that - nfc_destroy_target(m_target); - } - - QByteArray uid() const - { - return m_tagId; - } - - QNearFieldTarget::Type type() const - { - if (m_tagName == QByteArray("Jewel")) - return QNearFieldTarget::NfcTagType1; - else if (m_tagName == QByteArray("Topaz")) - return QNearFieldTarget::NfcTagType1; - else if (m_tagName == QByteArray("Topaz 512")) - return QNearFieldTarget::NfcTagType1; - else if (m_tagName == QByteArray("Mifare UL")) - return QNearFieldTarget::NfcTagType2; - else if (m_tagName == QByteArray("Mifare UL C")) - return QNearFieldTarget::NfcTagType2; - else if (m_tagName == QByteArray("Mifare 1K")) - return QNearFieldTarget::MifareTag; - else if (m_tagName == QByteArray("Kovio")) - return QNearFieldTarget::NfcTagType2; - - return QNearFieldTarget::ProprietaryTag; - } - - QNearFieldTarget::AccessMethods accessMethods() const - { - QNearFieldTarget::AccessMethods result = QNearFieldTarget::NdefAccess; - return result; - } - - bool hasNdefMessage() - { - return m_ndefMessages.count() > 0; - } - - QNearFieldTarget::RequestId readNdefMessages() - { - for (int i = 0; i < m_ndefMessages.size(); i++) { - emit QNearFieldTarget::ndefMessageRead(m_ndefMessages.at(i)); - } - QNearFieldTarget::RequestId requestId = QNearFieldTarget::RequestId(new QNearFieldTarget::RequestIdPrivate()); - QMetaObject::invokeMethod(this, "requestCompleted", Qt::QueuedConnection, - Q_ARG(const QNearFieldTarget::RequestId, requestId)); - return requestId; - } - - QNearFieldTarget::RequestId sendCommand(const QByteArray &command) - { - Q_UNUSED(command); - #if 0 - const int max_nfc_command_length = 256; - //Not tested - bool isSupported; - nfc_tag_supports_tag_type (m_target,TAG_TYPE_ISO_14443_3, &isSupported); - nfc_tag_type_t tagType= TAG_TYPE_ISO_14443_3; - if (!isSupported) { - nfc_tag_supports_tag_type (m_target,TAG_TYPE_ISO_14443_4, &isSupported); - tagType = TAG_TYPE_ISO_14443_4; - if (!isSupported) { - nfc_tag_supports_tag_type (m_target,TAG_TYPE_ISO_15693_3, &isSupported); - tagType = TAG_TYPE_ISO_15693_3; - //We don't support this tag - if (!isSupported) { - emit QNearFieldTarget::error(QNearFieldTarget::UnsupportedError, QNearFieldTarget::RequestId()); - return QNearFieldTarget::RequestId(); - } - } - } - m_cmdRespons = reinterpret_cast<char *> malloc (max_nfc_command_length); - nfc_result_t result = nfc_tag_transceive (m_target, tagType, command.data(), command.length(), m_cmdRespons, max_nfc_command_length, &m_cmdResponseLength); - if (result != NFC_RESULT_SUCCESS) { - emit QNearFieldTarget::error(QNearFieldTarget::UnknownError, QNearFieldTarget::RequestId()); - qWarning() << Q_FUNC_INFO << "nfc_tag_transceive failed" - } - #else - emit QNearFieldTarget::error(QNearFieldTarget::UnsupportedError, QNearFieldTarget::RequestId()); - return QNearFieldTarget::RequestId(); - #endif - } - - QNearFieldTarget::RequestId sendCommands(const QList<QByteArray> &commands) - { - Q_UNUSED(commands); - QNearFieldTarget::RequestId requestId; - for (int i = 0; i < commands.size(); i++) { - requestId = sendCommand(commands.at(i)); //The request id of the last command will be returned - } - return requestId; - } - - QNearFieldTarget::RequestId writeNdefMessages(const QList<QNdefMessage> &messages) - { - for (int i=0; i<messages.count(); i++) { - nfc_ndef_message_t *newMessage; - QByteArray msg = messages.at(i).toByteArray(); - nfc_result_t result = nfc_create_ndef_message_from_bytes(reinterpret_cast<const uchar_t *> (msg.constData()), msg.length(), &newMessage); - if (result != NFC_RESULT_SUCCESS) { - qWarning() << Q_FUNC_INFO << "Could not convert QNdefMessage to byte array" << result; - nfc_delete_ndef_message(newMessage, true); - emit QNearFieldTarget::error(QNearFieldTarget::UnknownError, - QNearFieldTarget::RequestId()); - return QNearFieldTarget::RequestId(); - } - - result = nfc_write_ndef_message_to_tag(m_target, newMessage, i == 0 ? false : true); - nfc_delete_ndef_message(newMessage, true); - - if (result != NFC_RESULT_SUCCESS) { - qWarning() << Q_FUNC_INFO << "Could not write message"; - emit QNearFieldTarget::error(QNearFieldTarget::NdefWriteError, - QNearFieldTarget::RequestId()); - - return QNearFieldTarget::RequestId(); - } - - } - QNearFieldTarget::RequestId requestId = QNearFieldTarget::RequestId(new QNearFieldTarget::RequestIdPrivate()); - QMetaObject::invokeMethod(this, "requestCompleted", Qt::QueuedConnection, - Q_ARG(const QNearFieldTarget::RequestId, requestId)); - return requestId; - } - -protected: - nfc_target_t *m_target; -#if 0 - char m_cmdRespons; - size_t m_cmdResponseLength; -#endif - QByteArray m_tagName; - QByteArray m_tagId; - QList<QNdefMessage> m_ndefMessages; -}; - -QT_END_NAMESPACE - -#endif // QNEARFIELDTARGET_QNX_H diff --git a/src/nfc/qnx/qnxnfceventfilter.cpp b/src/nfc/qnx/qnxnfceventfilter.cpp deleted file mode 100644 index f3d3749a..00000000 --- a/src/nfc/qnx/qnxnfceventfilter.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/*************************************************************************** -** -** Copyright (C) 2012 Research In Motion -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtNfc 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 "qnxnfceventfilter_p.h" -#include <QDebug> -#include "nfc/nfc.h" -#include "qnxnfcmanager_p.h" - -QT_BEGIN_NAMESPACE - -QNXNFCEventFilter::QNXNFCEventFilter() -{ -} - -void QNXNFCEventFilter::installOnEventDispatcher(QAbstractEventDispatcher *dispatcher) -{ - dispatcher->installNativeEventFilter(this); - // start flow of navigator events - navigator_request_events(0); -} - -void QNXNFCEventFilter::uninstallEventFilter() -{ - removeEventFilter(this); -} - -bool QNXNFCEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result) -{ - Q_UNUSED(eventType); - Q_UNUSED(result); - bps_event_t *event = static_cast<bps_event_t *>(message); - - int code = bps_event_get_code(event); - - if (code == NAVIGATOR_INVOKE_TARGET) { - // extract bps request from event - const navigator_invoke_invocation_t *invoke = navigator_invoke_event_get_invocation(event); - const char *uri = navigator_invoke_invocation_get_uri(invoke); - const char *type = navigator_invoke_invocation_get_type(invoke); - int dataLength = navigator_invoke_invocation_get_data_length(invoke); - const char *raw_data = (const char*)navigator_invoke_invocation_get_data(invoke); - QByteArray data(raw_data, dataLength); - - //message.fromByteArray(data); - - //const char* metadata = navigator_invoke_invocation_get_metadata(invoke); - - nfc_ndef_message_t *ndefMessage; - nfc_create_ndef_message_from_bytes(reinterpret_cast<const uchar_t *>(data.data()), - data.length(), &ndefMessage); - - QNdefMessage message = QNXNFCManager::instance()->decodeMessage(ndefMessage); - - unsigned int ndefRecordCount; - nfc_get_ndef_record_count(ndefMessage, &ndefRecordCount); - - qQNXNFCDebug() << "Got Invoke event" << uri << "Type" << type; - - emit ndefEvent(message); - } - - return false; -} - -QT_END_NAMESPACE diff --git a/src/nfc/qnx/qnxnfcmanager.cpp b/src/nfc/qnx/qnxnfcmanager.cpp deleted file mode 100644 index 3db11158..00000000 --- a/src/nfc/qnx/qnxnfcmanager.cpp +++ /dev/null @@ -1,484 +0,0 @@ -/*************************************************************************** -** -** Copyright (C) 2012 Research In Motion -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtNfc 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 "qnxnfcmanager_p.h" -#include <QMetaMethod> -#include <QMetaObject> -#include "../qllcpsocket_qnx_p.h" -#include <QCoreApplication> -#include <QStringList> - -QT_BEGIN_NAMESPACE - -QNXNFCManager *QNXNFCManager::m_instance = 0; - -QNXNFCManager *QNXNFCManager::instance() -{ - if (!m_instance) { - qQNXNFCDebug() << "creating manager instance"; - m_instance = new QNXNFCManager; - } - - return m_instance; -} - -void QNXNFCManager::registerForNewInstance() -{ - m_instanceCount++; -} - -void QNXNFCManager::unregisterForInstance() -{ - if (m_instanceCount>=1) { - m_instanceCount--; - if (m_instanceCount==0) { - delete m_instance; - m_instance = 0; - } - } else { - qWarning() << Q_FUNC_INFO << "instance count below 0"; - } -} - -void QNXNFCManager::unregisterTargetDetection(QObject *obj) -{ - Q_UNUSED(obj) - //TODO another instance of the nearfieldmanager might still - //want to detect targets so we have to do ref counting - nfc_unregister_tag_readerwriter(); -} - -nfc_target_t *QNXNFCManager::getLastTarget() -{ - return m_lastTarget; -} - -bool QNXNFCManager::isAvailable() -{ - return m_available; -} - -void QNXNFCManager::registerLLCPConnection(nfc_llcp_connection_listener_t listener, QObject *obj) -{ - llcpConnections.append(QPair<nfc_llcp_connection_listener_t, QObject*> (listener, obj)); -} - -void QNXNFCManager::unregisterLLCPConnection(nfc_llcp_connection_listener_t listener) -{ - for (int i=0; i<llcpConnections.size(); i++) { - if (llcpConnections.at(i).first == listener) { - llcpConnections.removeAt(i); - } - } -} - -void QNXNFCManager::requestTargetLost(QObject *object, int targetId) -{ - nfcTargets.append(QPair<unsigned int, QObject*> (targetId, object)); -} - -void QNXNFCManager::unregisterTargetLost(QObject *object) -{ - for (int i=0; i<nfcTargets.size(); i++) { - if (nfcTargets.at(i).second == object) { - nfcTargets.removeAt(i); - break; - } - } -} - -QNXNFCManager::QNXNFCManager() - : QObject(), nfcNotifier(0) -{ - nfc_set_verbosity(2); - qQNXNFCDebug() << "Initializing BB NFC"; - - if (nfc_connect() != NFC_RESULT_SUCCESS) { - qWarning() << Q_FUNC_INFO << "Could not connect to NFC system"; - return; - } - - bool nfcStatus; - nfc_get_setting(NFC_SETTING_ENABLED, &nfcStatus); - qQNXNFCDebug() << "NFC status" << nfcStatus; - if (!nfcStatus) { - qWarning() << "NFC not enabled...enabling"; - nfc_set_setting(NFC_SETTING_ENABLED, true); - } - m_available = true; - - if (nfc_get_fd(NFC_CHANNEL_TYPE_PUBLIC, &nfcFD) != NFC_RESULT_SUCCESS) { - qWarning() << Q_FUNC_INFO << "Could not get NFC FD"; - return; - } - - nfcNotifier = new QSocketNotifier(nfcFD, QSocketNotifier::Read); - qQNXNFCDebug() << "Connecting SocketNotifier" << connect(nfcNotifier, SIGNAL(activated(int)), this, SLOT(newNfcEvent(int))); - - ndefEventFilter = new QNXNFCEventFilter(); - ndefEventFilter->installOnEventDispatcher(QAbstractEventDispatcher::instance()); - connect(ndefEventFilter, SIGNAL(ndefEvent(QNdefMessage)), this, SLOT(invokeNdefMessage(QNdefMessage))); -} - -QNXNFCManager::~QNXNFCManager() -{ - nfc_disconnect(); - - if (nfcNotifier) - delete nfcNotifier; - ndefEventFilter->uninstallEventFilter(); -} - -QList<QNdefMessage> QNXNFCManager::decodeTargetMessage(nfc_target_t *target) -{ - unsigned int messageCount; - QList<QNdefMessage> ndefMessages; - - if (nfc_get_ndef_message_count(target, &messageCount) != NFC_RESULT_SUCCESS) - qWarning() << Q_FUNC_INFO << "Could not get ndef message count"; - - for (unsigned int i=0; i<messageCount; i++) { - nfc_ndef_message_t *nextMessage; - if (nfc_get_ndef_message(target, i, &nextMessage) != NFC_RESULT_SUCCESS) { - qWarning() << Q_FUNC_INFO << "Could not get ndef message"; - } else { - QNdefMessage newNdefMessage = decodeMessage(nextMessage); - ndefMessages.append(newNdefMessage); - } - } - return ndefMessages; -} - -void QNXNFCManager::newNfcEvent(int fd) -{ - nfc_event_t *nfcEvent; - nfc_event_type_t nfcEventType; - - if (nfc_read_event(fd, &nfcEvent) != NFC_RESULT_SUCCESS) { - qWarning() << Q_FUNC_INFO << "Could not read NFC event"; - return; - } - - if (nfc_get_event_type(nfcEvent, &nfcEventType) != NFC_RESULT_SUCCESS) { - qWarning() << Q_FUNC_INFO << "Could not get NFC event type"; - return; - } - - switch (nfcEventType) { //TODO handle all the events - case NFC_TAG_READWRITE_EVENT: qQNXNFCDebug() << "NFC read write event"; nfcReadWriteEvent(nfcEvent); break; - case NFC_OFF_EVENT: qQNXNFCDebug() << "NFC is off"; break; - case NFC_ON_EVENT: qQNXNFCDebug() << "NFC is on"; break; - case NFC_HANDOVER_COMPLETE_EVENT: qQNXNFCDebug() << "NFC handover event"; break; - case NFC_HANDOVER_DETECTED_EVENT: qQNXNFCDebug() << "NFC Handover detected"; break; - case NFC_SNEP_CONNECTION_EVENT: qQNXNFCDebug() << "NFC SNEP detected"; break; - case NFC_LLCP_READ_COMPLETE_EVENT: llcpReadComplete(nfcEvent); break; - case NFC_LLCP_WRITE_COMPLETE_EVENT: llcpWriteComplete(nfcEvent); break; - case NFC_LLCP_CONNECTION_EVENT: llcpConnectionEvent(nfcEvent); break; - case NFC_TARGET_LOST_EVENT: targetLostEvent(nfcEvent); break; - default: qQNXNFCDebug() << "Got NFC event" << nfcEventType; break; - } - - nfc_free_event (nfcEvent); -} - -void QNXNFCManager::invokeNdefMessage(const QNdefMessage &msg) -{ - emit ndefMessage(msg, 0); -} - -void QNXNFCManager::llcpReadComplete(nfc_event_t *nfcEvent) -{ - nfc_target_t *target; - if (nfc_get_target(nfcEvent, &target) != NFC_RESULT_SUCCESS) { - qWarning() << Q_FUNC_INFO << "Could not retrieve LLCP NFC target"; - return; - } - nfc_result_t result; - unsigned int bufferLength = -1; - result = nfc_llcp_get_local_miu(target, &bufferLength); - if (result != NFC_RESULT_SUCCESS) { - qWarning() << Q_FUNC_INFO << "could not get local miu"; - } - uchar_t buffer[bufferLength]; - - size_t bytesRead; - - m_lastTarget = target; - unsigned int targetId; - nfc_get_target_connection_id(target, &targetId); - - QByteArray data; - result = nfc_llcp_get_read_result(getLastTarget(), buffer, bufferLength, &bytesRead); - if (result == NFC_RESULT_SUCCESS) { - data = QByteArray(reinterpret_cast<char *> (buffer), bytesRead); - qQNXNFCDebug() << "Read LLCP data" << bytesRead << data; - } else if (result == NFC_RESULT_READ_FAILED) { //This most likely means, that the target has been disconnected - qWarning() << Q_FUNC_INFO << "LLCP read failed"; - nfc_llcp_close(target); - targetLost(targetId); - return; - } else { - qWarning() << Q_FUNC_INFO << "LLCP read unknown error"; - //return; - } - - for (int i=0; i<nfcTargets.size(); i++) { - if (nfcTargets.at(i).first == targetId) { - qobject_cast<QLlcpSocketPrivate*>(nfcTargets.at(i).second)->dataRead(data); - } - } -} - -void QNXNFCManager::llcpWriteComplete(nfc_event_t *nfcEvent) -{ - nfc_target_t *target; - if (nfc_get_target(nfcEvent, &target) != NFC_RESULT_SUCCESS) { - qWarning() << Q_FUNC_INFO << "Could not retrieve LLCP NFC target"; - return; - } - - if (nfc_llcp_get_write_status(target) != NFC_RESULT_SUCCESS) { - qWarning() << Q_FUNC_INFO << "LLCP write failed"; - } else { - qQNXNFCDebug() << "write completed succesfull"; - } - - unsigned int targetId; - nfc_get_target_connection_id(target, &targetId); - - for (int i=0; i<nfcTargets.size(); i++) { - if (nfcTargets.at(i).first == targetId) { - qobject_cast<QLlcpSocketPrivate*>(nfcTargets.at(i).second)->dataWritten(); - } - } -} - -void QNXNFCManager::nfcReadWriteEvent(nfc_event_t *nfcEvent) -{ - nfc_target_t *target; - - if (nfc_get_target(nfcEvent, &target) != NFC_RESULT_SUCCESS) { - qWarning() << Q_FUNC_INFO << "Could not retrieve NFC target"; - return; - } - tag_variant_type_t variant; - nfc_get_tag_variant(target, &variant); - qQNXNFCDebug() << "Variant:" << variant; - - QList<QNdefMessage> targetMessages = decodeTargetMessage(target); - NearFieldTarget<QNearFieldTarget> *bbNFTarget = new NearFieldTarget<QNearFieldTarget>(this, target, targetMessages); - emit targetDetected(bbNFTarget, targetMessages); - for (int i=0; i< targetMessages.count(); i++) { - emit ndefMessage(targetMessages.at(i), reinterpret_cast<QNearFieldTarget *> (bbNFTarget)); - } -} - -void QNXNFCManager::llcpConnectionEvent(nfc_event_t *nfcEvent) -{ - nfc_target_t *target; - - if (nfc_get_target(nfcEvent, &target) != NFC_RESULT_SUCCESS) { - qWarning() << Q_FUNC_INFO << "Could not retrieve NFC target"; - return; - } - nfc_llcp_connection_listener_t conListener; - nfc_llcp_get_connection_status(target, &conListener); - unsigned int lmiu; - nfc_llcp_get_local_miu(target, &lmiu); - m_lastTarget = target; - - qQNXNFCDebug() << "LLCP connection event; local MIU" << lmiu; - for (int i=0; i<llcpConnections.size(); i++) { - if (llcpConnections.at(i).first == conListener) { - //Do we also have to destroy the conn listener afterwards? - QMetaObject::invokeMethod(llcpConnections.at(i).second, "connected", - Q_ARG(nfc_target_t *, target)); - break; - } - } -} -void QNXNFCManager::setupInvokeTarget() { - qQNXNFCDebug() << "Setting up invoke target"; - QByteArray uriFilter; - bool registerAll = false; - - if (!absNdefFilters.isEmpty()) { - uriFilter = "uris="; - } - for (int i=0; i<absNdefFilters.size(); i++) { - if (absNdefFilters.at(i) == "*") { - registerAll = true; - break; - } - uriFilter.append(absNdefFilters.at(i)); - if (i==absNdefFilters.size()-1) - uriFilter += ';'; - else - uriFilter += ','; - } - if (registerAll) { - uriFilter = "uris=ndef://;"; - } - - const char *filters[1]; - QByteArray filter = "actions=bb.action.OPEN;types=application/vnd.rim.nfc.ndef;" + uriFilter; - filters[0] = filter.constData(); - - //Get the correct target-id - QString targetId = QCoreApplication::instance()->arguments().first(); - targetId = targetId.left(targetId.lastIndexOf(QLatin1Char('.'))); - - if (BPS_SUCCESS != navigator_invoke_set_filters("20", targetId.toLatin1().constData(), filters, 1)) { - qWarning() << "NFC Error setting share target filter"; - } else { - qQNXNFCDebug() << "NFC share target filter set" << filters[0] << " Target:" << targetId; - } -} - -void QNXNFCManager::targetLostEvent(nfc_event_t *nfcEvent) -{ - unsigned int targetId; - nfc_get_notification_value(nfcEvent, &targetId); - qQNXNFCDebug() << "Target lost with target ID:" << targetId; - targetLost(targetId); -} - -void QNXNFCManager::targetLost(unsigned int targetId) -{ - for (int i=0; i<nfcTargets.size(); i++) { - if (nfcTargets.at(i).first == targetId) { - QMetaObject::invokeMethod(nfcTargets.at(i).second, "targetLost"); - nfcTargets.removeAt(i); - break; - } - } -} - -bool QNXNFCManager::startTargetDetection() -{ - qQNXNFCDebug() << "Start target detection for all types"; - //TODO handle the target types - if (nfc_register_tag_readerwriter(TAG_TYPE_ALL) == NFC_RESULT_SUCCESS) { - return true; - } else { - qWarning() << Q_FUNC_INFO << "Could not start Target detection"; - return false; - } -} - -void QNXNFCManager::updateNdefFilters(QList<QByteArray> filters, QObject *obj) -{ - qQNXNFCDebug() << Q_FUNC_INFO << "NDEF Filter update"; - //Updating the filters for an object - if (!filters.isEmpty()) { - if (ndefFilters.contains(obj)) { - ndefFilters[obj] = filters; - qQNXNFCDebug() << "Updateing filter list for"<< obj; - } else { - qQNXNFCDebug() << "Appending new filter for"<< obj; - ndefFilters[obj] = filters; - } - } else { - ndefFilters.remove(obj); - } - - //Iterate over all registered object filters and construct a filter list for the application - QList<QByteArray> newFilters; - if (ndefFilters.size() > 0) { - QHash<QObject*, QList<QByteArray> >::const_iterator it=ndefFilters.constBegin(); - do { - foreach (const QByteArray filter, it.value()) { - if (!newFilters.contains(filter)) { - newFilters.append(filter); - qQNXNFCDebug() << "Appending Filter" << filter; - } - } - it++; - } while (it != ndefFilters.constEnd()); - } - - if (newFilters != absNdefFilters) { - absNdefFilters = newFilters; - setupInvokeTarget(); - } -} - -QNdefMessage QNXNFCManager::decodeMessage(nfc_ndef_message_t *nextMessage) -{ - QNdefMessage newNdefMessage; - unsigned int recordCount; - nfc_get_ndef_record_count(nextMessage, &recordCount); - for (unsigned int j=0; j<recordCount; j++) { - nfc_ndef_record_t *newRecord; - char *recordType; - uchar_t *payLoad; - char *recordId; - size_t payLoadSize; - tnf_type_t typeNameFormat; - - nfc_get_ndef_record(nextMessage, j, &newRecord); - - nfc_get_ndef_record_type(newRecord, &recordType); - QNdefRecord newNdefRecord; - newNdefRecord.setType(QByteArray(recordType)); - - nfc_get_ndef_record_payload(newRecord, &payLoad, &payLoadSize); - newNdefRecord.setPayload(QByteArray(reinterpret_cast<const char*>(payLoad), payLoadSize)); - - nfc_get_ndef_record_id(newRecord, &recordId); - newNdefRecord.setId(QByteArray(recordId)); - - nfc_get_ndef_record_tnf(newRecord, &typeNameFormat); - QNdefRecord::TypeNameFormat recordTnf = QNdefRecord::Unknown; - switch (typeNameFormat) { - case NDEF_TNF_WELL_KNOWN: recordTnf = QNdefRecord::NfcRtd; break; - case NDEF_TNF_EMPTY: recordTnf = QNdefRecord::Empty; break; - case NDEF_TNF_MEDIA: recordTnf = QNdefRecord::Mime; break; - case NDEF_TNF_ABSOLUTE_URI: recordTnf = QNdefRecord::Uri; break; - case NDEF_TNF_EXTERNAL: recordTnf = QNdefRecord::ExternalRtd; break; - case NDEF_TNF_UNKNOWN: recordTnf = QNdefRecord::Unknown; break; - //TODO add the rest - case NDEF_TNF_UNCHANGED: recordTnf = QNdefRecord::Unknown; break; - } - - newNdefRecord.setTypeNameFormat(recordTnf); - qQNXNFCDebug() << "Adding NFC record"; - newNdefMessage << newNdefRecord; - delete recordType; - delete payLoad; - delete recordId; - } - return newNdefMessage; -} - -QT_END_NAMESPACE diff --git a/src/nfc/qnx/qnxnfcmanager_p.h b/src/nfc/qnx/qnxnfcmanager_p.h deleted file mode 100644 index 17425198..00000000 --- a/src/nfc/qnx/qnxnfcmanager_p.h +++ /dev/null @@ -1,143 +0,0 @@ -/*************************************************************************** -** -** Copyright (C) 2012 Research In Motion -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtNfc 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 QNXNFCMANAGER_H -#define QNXNFCMANAGER_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 "nfc/nfc_types.h" -#include "nfc/nfc.h" -#include <QSocketNotifier> -#include <QDebug> -#include "../qndefmessage.h" -#include "../qndefrecord.h" -#include <bps/navigator_invoke.h> -#include "../qnearfieldtarget_qnx_p.h" -#include <QTimer> -#include "qnxnfceventfilter_p.h" - -#ifdef QQNXNFC_DEBUG -#define qQNXNFCDebug qDebug -#else -#define qQNXNFCDebug QT_NO_QDEBUG_MACRO -#endif - -QT_BEGIN_NAMESPACE - -class QLlcpSocketPrivate; - -class Q_DECL_EXPORT QNXNFCManager : public QObject -{ - Q_OBJECT -public: - static QNXNFCManager *instance(); - void registerForNewInstance(); - void unregisterForInstance(); - void unregisterTargetDetection(QObject *); - nfc_target_t *getLastTarget(); - bool isAvailable(); - void registerLLCPConnection(nfc_llcp_connection_listener_t, QObject *); - void unregisterLLCPConnection(nfc_llcp_connection_listener_t); - void requestTargetLost(QObject *, int); - void unregisterTargetLost(QObject *); - -private: - QNXNFCManager(); - ~QNXNFCManager(); - - static QNXNFCManager *m_instance; - int m_instanceCount; - - QNXNFCEventFilter *ndefEventFilter; - - int nfcFD; - QSocketNotifier *nfcNotifier; - - QList<QNdefMessage> decodeTargetMessage(nfc_target_t *); - QList<QPair<nfc_llcp_connection_listener_t, QObject *> > llcpConnections; - QList<QPair<unsigned int ,QObject*> > nfcTargets; - - QHash<QObject *, QList<QByteArray> > ndefFilters; - QList<QByteArray> absNdefFilters; - - //QList<QPair<QObject*, QMetaMethod> > ndefMessageHandlers; - - //There can only be one target. The last detected one is saved here - //currently we do not get notified when the target is disconnected. So the target might be invalid - nfc_target_t *m_lastTarget; - bool m_available; - - void llcpReadComplete(nfc_event_t *nfcEvent); - void llcpWriteComplete(nfc_event_t *nfcEvent); - void nfcReadWriteEvent(nfc_event_t *nfcEvent); - void llcpConnectionEvent(nfc_event_t *nfcEvent); - void targetLostEvent(nfc_event_t *nfcEvent); - void targetLost(unsigned int target); - void startBTHandover(); - - void setupInvokeTarget(); - -private slots: - void newNfcEvent(int fd); - void invokeNdefMessage(const QNdefMessage &); - -public: - //TODO add a parameter to only detect a special target for now we are detecting all target types - bool startTargetDetection(); - - void updateNdefFilters(QList<QByteArray>,QObject *); - - QNdefMessage decodeMessage(nfc_ndef_message_t *nextMessage); - -signals: - void newLlcpConnection(nfc_target_t *); - void ndefMessage(const QNdefMessage &, QNearFieldTarget *); - void targetDetected(QNearFieldTarget *, const QList<QNdefMessage> &); - void readResult(QByteArray&, nfc_target_t *); - void llcpDisconnected(); -}; - -QT_END_NAMESPACE - -#endif - diff --git a/src/nfc/qnx/qnxnfcsharemanager_p.cpp b/src/nfc/qnx/qnxnfcsharemanager_p.cpp deleted file mode 100644 index ea6aeb13..00000000 --- a/src/nfc/qnx/qnxnfcsharemanager_p.cpp +++ /dev/null @@ -1,272 +0,0 @@ -/*************************************************************************** - ** - ** Copyright (C) 2013 BlackBerry Limited. All rights reserved. - ** Contact: http://www.qt.io/licensing/ - ** - ** This file is part of the QtNfc 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 "qnxnfcsharemanager_p.h" - -QT_BEGIN_NAMESPACE - -using namespace bb::system; - -const char *QNXNFCShareManager::RECORD_NDEF = "application/vnd.rim.nfc.ndef"; -Q_GLOBAL_STATIC(QNXNFCShareManager, shareStatic) - -QNXNFCShareManager *QNXNFCShareManager::instance() -{ - return shareStatic(); -} - -bool QNXNFCShareManager::shareNdef(const QNdefMessage &message) -{ - bool ok = false; - NfcShareDataContent content; - content.setMimeType(RECORD_NDEF); - content.setData(message.toByteArray()); - - NfcShareSetContentError::Type err = _manager->setShareContent(content); - - switch (err) { - case NfcShareSetContentError::None: { - ok = true; - break; - } - - case NfcShareSetContentError::TransferInProgress: { - emit error(NfcShareError::TransferInProgress); - break; - } - - case NfcShareSetContentError::InvalidShareMode: - case NfcShareSetContentError::InvalidShareRequest: { - emit error(NfcShareError::UnsupportedShareMode); - break; - } - - case NfcShareSetContentError::Unknown: { - emit error(NfcShareError::Unknown); - break; - } - } - - if (ok) - _manager->startTransfer(); - - return ok; -} - -bool QNXNFCShareManager::shareFiles(const QList<QFileInfo> &files) -{ - bool ok = false; - NfcShareFilesContent content; - QList<QUrl> urls; - - for (int i=0; i<files.size(); i++) { - urls.append(QUrl::fromLocalFile(files[i].filePath())); - } - - content.setFileUrls(urls); - - NfcShareSetContentError::Type err = _manager->setShareContent(content); - - switch (err) { - case NfcShareSetContentError::None: { - ok = true; - break; - } - - case NfcShareSetContentError::TransferInProgress: { - emit error(NfcShareError::TransferInProgress); - break; - } - - case NfcShareSetContentError::InvalidShareMode: - case NfcShareSetContentError::InvalidShareRequest: { - emit error(NfcShareError::UnsupportedShareMode); - break; - } - - case NfcShareSetContentError::Unknown: { - emit error(NfcShareError::Unknown); - break; - } - } - - if (ok) - _manager->startTransfer(); - - return ok; -} - -void QNXNFCShareManager::cancel() -{ - _manager->cancelTarget(); -} - -void QNXNFCShareManager::setShareMode(NfcShareMode::Type type) -{ - _manager->setShareMode(type, NfcShareStartTransferMode::OnDemand); -} - -NfcShareMode::Type QNXNFCShareManager::shareMode() const -{ - return _manager->shareMode(); -} - -void QNXNFCShareManager::connect(QObject *obj) -{ - QObject::connect(this, SIGNAL(shareModeChanged(bb::system::NfcShareMode::Type)), - obj, SLOT(onShareModeChanged(bb::system::NfcShareMode::Type))); - QObject::connect(this, SIGNAL(error(bb::system::NfcShareError::Type)), - obj, SLOT(onError(bb::system::NfcShareError::Type))); - QObject::connect(this, SIGNAL(finished(bb::system::NfcShareSuccess::Type)), - obj, SLOT(onFinished(bb::system::NfcShareSuccess::Type))); - QObject::connect(this, SIGNAL(targetAcquired()), - obj, SLOT(onTargetAcquired())); - QObject::connect(this, SIGNAL(targetCancelled()), - obj, SLOT(onTargetCancelled())); -} - -void QNXNFCShareManager::disconnect(QObject *obj) -{ - QObject::disconnect(this, SIGNAL(shareModeChanged(bb::system::NfcShareMode::Type)), - obj, SLOT(onShareModeChanged(bb::system::NfcShareMode::Type))); - QObject::disconnect(this, SIGNAL(error(bb::system::NfcShareError::Type)), - obj, SLOT(onError(bb::system::NfcShareError::Type))); - QObject::disconnect(this, SIGNAL(finished(bb::system::NfcShareSuccess::Type)), - obj, SLOT(onFinished(bb::system::NfcShareSuccess::Type))); - QObject::disconnect(this, SIGNAL(targetAcquired()), - obj, SLOT(onTargetAcquired())); - QObject::disconnect(this, SIGNAL(targetCancelled()), - obj, SLOT(onTargetCancelled())); -} - -void QNXNFCShareManager::reset() -{ - _manager->reset(); -} - -QNXNFCShareManager::QNXNFCShareManager() - : QObject() -{ - _manager = new NfcShareManager(this); - QObject::connect(_manager, SIGNAL(shareModeChanged(bb::system::NfcShareMode::Type)), - this, SIGNAL(shareModeChanged(bb::system::NfcShareMode::Type))); - QObject::connect(_manager, SIGNAL(error(bb::system::NfcShareError::Type)), - this, SIGNAL(error(bb::system::NfcShareError::Type))); - QObject::connect(_manager, SIGNAL(finished(bb::system::NfcShareSuccess::Type)), - this, SIGNAL(finished(bb::system::NfcShareSuccess::Type))); - QObject::connect(_manager, SIGNAL(targetAcquired()), - this, SIGNAL(targetAcquired())); - QObject::connect(_manager, SIGNAL(targetCancelled()), - this, SIGNAL(targetCancelled())); -} - -QNXNFCShareManager::~QNXNFCShareManager() -{ - delete _manager; -} - -QNearFieldShareManager::ShareError QNXNFCShareManager::toShareError(NfcShareError::Type nfcShareError) -{ - QNearFieldShareManager::ShareError shareError = QNearFieldShareManager::NoError; - - switch (nfcShareError) { - case NfcShareError::Unknown: { - shareError = QNearFieldShareManager::UnknownError; - break; - } - - case NfcShareError::NoContentToShare: - case NfcShareError::MessageSize: - case NfcShareError::TagLocked: - case NfcShareError::UnsupportedTagType: { - shareError = QNearFieldShareManager::InvalidShareContentError; - break; - } - - case NfcShareError::RegisterFileSharing: - case NfcShareError::RegisterDataSharing: { - shareError = QNearFieldShareManager::InvalidShareContentError; - break; - } - - case NfcShareError::DataTransferFailed: - case NfcShareError::BluetoothFileTransferFailed: - case NfcShareError::WiFiDirectFileTransferFailed: - case NfcShareError::HandoverFailed: { - shareError = QNearFieldShareManager::ShareInterruptedError; - break; - } - - case NfcShareError::BluetoothFileTransferCancelled: - case NfcShareError::WiFiDirectFileTransferCancelled: { - shareError = QNearFieldShareManager::ShareCanceledError; - break; - } - - case NfcShareError::TransferInProgress: { - shareError = QNearFieldShareManager::ShareAlreadyInProgressError; - break; - } - - case NfcShareError::UnsupportedShareMode: { - shareError = QNearFieldShareManager::UnsupportedShareModeError; - break; - } - - case NfcShareError::NoTransferTarget: { - shareError = QNearFieldShareManager::ShareRejectedError; - break; - } - - default: { - shareError = QNearFieldShareManager::UnknownError; - } - } - - return shareError; -} - -QNearFieldShareManager::ShareModes QNXNFCShareManager::toShareModes(NfcShareMode::Type nfcShareMode) -{ - QNearFieldShareManager::ShareModes modes = QNearFieldShareManager::NoShare; - - if (nfcShareMode == NfcShareMode::DataSnep) - modes |= QNearFieldShareManager::NdefShare; - - else if (nfcShareMode == NfcShareMode::File) - modes |= QNearFieldShareManager::FileShare; - - return modes; -} - -QT_END_NAMESPACE diff --git a/src/nfc/qnx/qnxnfcsharemanager_p.h b/src/nfc/qnx/qnxnfcsharemanager_p.h deleted file mode 100644 index d6774c41..00000000 --- a/src/nfc/qnx/qnxnfcsharemanager_p.h +++ /dev/null @@ -1,93 +0,0 @@ -/*************************************************************************** - ** - ** Copyright (C) 2013 BlackBerry Limited. All rights reserved. - ** Contact: http://www.qt.io/licensing/ - ** - ** This file is part of the QtNfc 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 QNXNFCSHAREMANAGER_P_H -#define QNXNFCSHAREMANAGER_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 "qnearfieldsharemanager.h" -#include <bb/system/NfcShareManager> -#include <QFileInfo> -#include <QNdefMessage> - -QT_BEGIN_NAMESPACE - -class Q_DECL_EXPORT QNXNFCShareManager : public QObject -{ - Q_OBJECT -public: - static QNXNFCShareManager *instance(); - - QNXNFCShareManager(); - ~QNXNFCShareManager(); - - bool shareNdef(const QNdefMessage &message); - bool shareFiles(const QList<QFileInfo> &files); - void cancel(); - - void setShareMode(bb::system::NfcShareMode::Type type); - bb::system::NfcShareMode::Type shareMode() const; - - void connect(QObject *obj); - void disconnect(QObject *obj); - - void reset(); - - static QNearFieldShareManager::ShareError toShareError(bb::system::NfcShareError::Type nfcShareError); - static QNearFieldShareManager::ShareModes toShareModes(bb::system::NfcShareMode::Type nfcShareMode); - -private: - bb::system::NfcShareManager *_manager; - static const char *RECORD_NDEF; - -signals: - void shareModeChanged(bb::system::NfcShareMode::Type); - void error(bb::system::NfcShareError::Type); - void finished(bb::system::NfcShareSuccess::Type); - void targetAcquired(); - void targetCancelled(); -}; - -QT_END_NAMESPACE - -#endif /* QNXNFCSHAREMANAGER_P_H */ diff --git a/src/nfc/qqmlndefrecord.cpp b/src/nfc/qqmlndefrecord.cpp index 280d03a2..278cc583 100644 --- a/src/nfc/qqmlndefrecord.cpp +++ b/src/nfc/qqmlndefrecord.cpp @@ -271,7 +271,7 @@ QString QQmlNdefRecord::type() const } /*! - Sets the record type to \a type if it is not currently equal to \a type; otherwise does + Sets the record type to \a newtype if it is not currently equal to \l type(); otherwise does nothing. If the record type is set the typeChanged() signal will be emitted. \sa QNdefRecord::setType(), QNdefRecord::type() diff --git a/src/nfc/qqmlndefrecord.h b/src/nfc/qqmlndefrecord.h index 71cd5513..dbd947ee 100644 --- a/src/nfc/qqmlndefrecord.h +++ b/src/nfc/qqmlndefrecord.h @@ -52,7 +52,6 @@ class Q_NFC_EXPORT QQmlNdefRecord : public QObject Q_PROPERTY(TypeNameFormat typeNameFormat READ typeNameFormat WRITE setTypeNameFormat NOTIFY typeNameFormatChanged) Q_PROPERTY(QNdefRecord record READ record WRITE setRecord NOTIFY recordChanged) - Q_ENUMS(TypeNameFormat) public: enum TypeNameFormat { Empty = QNdefRecord::Empty, @@ -62,6 +61,7 @@ public: ExternalRtd = QNdefRecord::ExternalRtd, Unknown = QNdefRecord::Unknown }; + Q_ENUM(TypeNameFormat) explicit QQmlNdefRecord(QObject *parent = 0); explicit QQmlNdefRecord(const QNdefRecord &record, QObject *parent = 0); diff --git a/src/tools/sdpscanner/main.cpp b/src/tools/sdpscanner/main.cpp index 1efb6de2..50870651 100644 --- a/src/tools/sdpscanner/main.cpp +++ b/src/tools/sdpscanner/main.cpp @@ -46,9 +46,11 @@ void usage() { fprintf(stderr, "Usage:\n"); - fprintf(stderr, "\tsdpscanner <remote bdaddr> <local bdaddr>\n\n"); + fprintf(stderr, "\tsdpscanner <remote bdaddr> <local bdaddr> [Options]\n\n"); fprintf(stderr, "Performs an SDP scan on remote device, using the SDP server\n" - "represented by the local Bluetooth device.\n"); + "represented by the local Bluetooth device.\n\n" + "Options:\n" + " -p Show scan results in human-readable form\n"); } #define BUFFER_SIZE 1024 @@ -245,7 +247,7 @@ QByteArray parseSdpRecord(sdp_record_t *record) int main(int argc, char **argv) { - if (argc != 3) { + if (argc < 3) { usage(); return RETURN_USAGE; } @@ -266,6 +268,27 @@ int main(int argc, char **argv) return RETURN_INVALPARAM; } + bool showHumanReadable = false; + + for (int i = 3; i < argc; i++) { + if (argv[i][0] != '-') { + usage(); + return RETURN_USAGE; + } + + switch (argv[i][1]) + { + case 'p': + showHumanReadable = true; + break; + default: + fprintf(stderr, "Wrong argument: %s\n", argv[i]); + usage(); + return RETURN_USAGE; + + } + } + sdp_session_t *session = sdp_connect( &local, &remote, SDP_RETRY_IF_BUSY); if (!session) { //try one more time if first time failed @@ -314,7 +337,10 @@ int main(int argc, char **argv) } if (!total.isEmpty()) { - printf("%s", total.toBase64().constData()); + if (showHumanReadable) + printf("%s", total.constData()); + else + printf("%s", total.toBase64().constData()); } sdp_close(session); diff --git a/src/tools/sdpscanner/sdpscanner.pro b/src/tools/sdpscanner/sdpscanner.pro index 6bf0a96c..e4773cae 100644 --- a/src/tools/sdpscanner/sdpscanner.pro +++ b/src/tools/sdpscanner/sdpscanner.pro @@ -12,13 +12,5 @@ load(qt_tool) linux-*: { # bluetooth.h is not standards compliant - contains(QMAKE_CXXFLAGS, -std=c++0x) { - QMAKE_CXXFLAGS -= -std=c++0x - QMAKE_CXXFLAGS += -std=gnu++0x - CONFIG -= c++11 - } - c++11 { - CONFIG -= c++11 - QMAKE_CXXFLAGS += -std=gnu++0x - } + CONFIG -= strict_c++ } |