summaryrefslogtreecommitdiffstats
path: root/core/btdiscovery.cpp
diff options
context:
space:
mode:
authorGravatar Dirk Hohndel <dirk@hohndel.org>2017-06-05 19:41:57 -0700
committerGravatar Dirk Hohndel <dirk@hohndel.org>2017-06-11 13:55:41 -0700
commitb14a522f4f308aed41ab49b5529cc10c05168716 (patch)
tree2b3540e4aeefbe9c21ab9d3af1af2b07a4f503e0 /core/btdiscovery.cpp
parent3b993fbaad0738efe54e797b60e4f49270951323 (diff)
downloadsubsurface-b14a522f4f308aed41ab49b5529cc10c05168716.tar.gz
QML UI: move BT handling into core code
This shouldn't be part of the UI (qmlmanager), but part of our overall handling of dive computers and BT devices. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Diffstat (limited to 'core/btdiscovery.cpp')
-rw-r--r--core/btdiscovery.cpp165
1 files changed, 165 insertions, 0 deletions
diff --git a/core/btdiscovery.cpp b/core/btdiscovery.cpp
new file mode 100644
index 000000000..cf68bf8eb
--- /dev/null
+++ b/core/btdiscovery.cpp
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include "btdiscovery.h"
+#include "downloadfromdcthread.h"
+#include <QDebug>
+
+BTDiscovery *BTDiscovery::m_instance = NULL;
+
+BTDiscovery::BTDiscovery(QObject *parent)
+{
+ Q_UNUSED(parent)
+ if (m_instance) {
+ qDebug() << "trying to create an additional BTDiscovery object";
+ return;
+ }
+ m_instance = this;
+#if defined(BT_SUPPORT)
+ if (localBtDevice.isValid() &&
+ localBtDevice.hostMode() == QBluetoothLocalDevice::HostConnectable) {
+ btPairedDevices.clear();
+ qDebug() << "localDevice " + localBtDevice.name() + " is valid, starting discovery";
+#if defined(Q_OS_LINUX)
+ discoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);
+ connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &BTDiscovery::btDeviceDiscovered);
+ discoveryAgent->start();
+#endif
+#if defined(Q_OS_ANDROID) && defined(BT_SUPPORT)
+ getBluetoothDevices();
+#endif
+ for (int i = 0; i < btPairedDevices.length(); i++) {
+ qDebug() << "Paired =" << btPairedDevices[i].name << btPairedDevices[i].address.toString();
+ }
+#if defined(Q_OS_LINUX)
+ discoveryAgent->stop();
+#endif
+ } else {
+ qDebug() << "localBtDevice isn't valid";
+ }
+#endif
+}
+
+BTDiscovery::~BTDiscovery()
+{
+ m_instance = NULL;
+#if defined(BT_SUPPORT)
+ free(discoveryAgent);
+#endif
+}
+
+BTDiscovery *BTDiscovery::instance()
+{
+ if (!m_instance)
+ m_instance = new BTDiscovery();
+ return m_instance;
+}
+
+#if defined(BT_SUPPORT)
+
+extern void addBtUuid(QBluetoothUuid uuid);
+extern QHash<QString, QStringList> productList;
+extern QStringList vendorList;
+
+void BTDiscovery::btDeviceDiscovered(const QBluetoothDeviceInfo &device)
+{
+ btPairedDevice this_d;
+ this_d.address = device.address();
+ this_d.name = device.name();
+ btPairedDevices.append(this_d);
+
+ QString newDevice = device.name();
+
+ // all the HW OSTC BT computers show up as "OSTC" + some other text, depending on model
+ if (newDevice.startsWith("OSTC"))
+ newDevice = "OSTC 3";
+ QList<QBluetoothUuid> serviceUuids = device.serviceUuids();
+ foreach (QBluetoothUuid id, serviceUuids) {
+ addBtUuid(id);
+ qDebug() << id.toByteArray();
+ }
+ qDebug() << "Found new device " + newDevice + " (" + device.address().toString() + ")";
+ QString vendor, product;
+ foreach (vendor, productList.keys()) {
+ if (productList[vendor].contains(newDevice)) {
+ qDebug() << "this could be a " + vendor + " " +
+ (newDevice == "OSTC 3" ? "OSTC family" : newDevice);
+ struct btVendorProduct btVP;
+ btVP.btdi = device;
+ btVP.vendorIdx = vendorList.indexOf(vendor);
+ btVP.productIdx = productList[vendor].indexOf(newDevice);
+ qDebug() << "adding new btDCs entry" << newDevice << btVP.vendorIdx << btVP.productIdx;
+ btDCs << btVP;
+ }
+ }
+}
+
+QList <struct btVendorProduct> BTDiscovery::getBtDcs()
+{
+ return btDCs;
+}
+
+
+// Android: As Qt is not able to pull the pairing data from a device, i
+// a lengthy discovery process is needed to see what devices are paired. On
+// https://forum.qt.io/topic/46075/solved-bluetooth-list-paired-devices
+// user s.frings74 does, however, present a solution to this using JNI.
+// Currently, this code is taken "as is".
+
+#if defined(Q_OS_ANDROID)
+void BTDiscovery::getBluetoothDevices()
+{
+ struct BTDiscovery::btPairedDevice result;
+ // Query via Android Java API.
+
+ // returns a BluetoothAdapter
+ QAndroidJniObject adapter=QAndroidJniObject::callStaticObjectMethod("android/bluetooth/BluetoothAdapter","getDefaultAdapter","()Landroid/bluetooth/BluetoothAdapter;");
+ if (checkException("BluetoothAdapter.getDefaultAdapter()", &adapter)) {
+ return;
+ }
+ // returns a Set<BluetoothDevice>
+ QAndroidJniObject pairedDevicesSet=adapter.callObjectMethod("getBondedDevices","()Ljava/util/Set;");
+ if (checkException("BluetoothAdapter.getBondedDevices()", &pairedDevicesSet)) {
+ return;
+ }
+ jint size=pairedDevicesSet.callMethod<jint>("size");
+ checkException("Set<BluetoothDevice>.size()", &pairedDevicesSet);
+ if (size > 0) {
+ // returns an Iterator<BluetoothDevice>
+ QAndroidJniObject iterator=pairedDevicesSet.callObjectMethod("iterator","()Ljava/util/Iterator;");
+ if (checkException("Set<BluetoothDevice>.iterator()", &iterator)) {
+ return;
+ }
+ for (int i = 0; i < size; i++) {
+ // returns a BluetoothDevice
+ QAndroidJniObject dev=iterator.callObjectMethod("next","()Ljava/lang/Object;");
+ if (checkException("Iterator<BluetoothDevice>.next()", &dev)) {
+ continue;
+ }
+
+ result.address = QBluetoothAddress(dev.callObjectMethod("getAddress","()Ljava/lang/String;").toString());
+ result.name = dev.callObjectMethod("getName", "()Ljava/lang/String;").toString();
+
+ btPairedDevices.append(result);
+ }
+ }
+}
+
+bool BTDiscovery::checkException(const char* method, const QAndroidJniObject *obj)
+{
+ static QAndroidJniEnvironment env;
+ bool result = false;
+
+ if (env->ExceptionCheck()) {
+ qCritical("Exception in %s", method);
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ result=true;
+ }
+ if (!(obj == NULL || obj->isValid())) {
+ qCritical("Invalid object returned by %s", method);
+ result=true;
+ }
+ return result;
+}
+#endif // Q_OS_ANDROID
+#endif // BT_SUPPORT