summaryrefslogtreecommitdiffstats
path: root/bluetooth
diff options
context:
space:
mode:
Diffstat (limited to 'bluetooth')
-rw-r--r--bluetooth/CMakeLists.txt6
-rw-r--r--bluetooth/bluetooth.cpp369
-rw-r--r--bluetooth/bluetooth.h42
-rw-r--r--bluetooth/bluetootheventhandler.cpp121
-rw-r--r--bluetooth/bluetootheventhandler.h71
-rw-r--r--bluetooth/bluetoothmodel.cpp207
-rw-r--r--bluetooth/bluetoothmodel.h20
7 files changed, 520 insertions, 316 deletions
diff --git a/bluetooth/CMakeLists.txt b/bluetooth/CMakeLists.txt
index e514aab..3137e3c 100644
--- a/bluetooth/CMakeLists.txt
+++ b/bluetooth/CMakeLists.txt
@@ -3,16 +3,16 @@ CONFIGURE_FILE("qtappfw-bt.pc.in" "qtappfw-bt.pc" @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qtappfw-bt.pc
DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/pkgconfig)
-add_library(qtappfw-bt SHARED bluetooth.cpp bluetoothmodel.cpp)
+add_library(qtappfw-bt SHARED bluetooth.cpp bluetoothmodel.cpp bluetootheventhandler.cpp)
target_include_directories(qtappfw-bt PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
target_include_directories(qtappfw-bt PRIVATE "${CMAKE_INSTALL_INCLUDEDIR}")
-target_link_libraries(qtappfw-bt qtappfw-core)
+target_link_libraries(qtappfw-bt Qt5::Qml PkgConfig::glib PkgConfig::bluez_glib)
set_target_properties(qtappfw-bt PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION 1
- PUBLIC_HEADER "bluetooth.h;bluetoothmodel.h")
+ PUBLIC_HEADER "bluetooth.h")
install(TARGETS qtappfw-bt
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
diff --git a/bluetooth/bluetooth.cpp b/bluetooth/bluetooth.cpp
index 82ef2f1..c58b64b 100644
--- a/bluetooth/bluetooth.cpp
+++ b/bluetooth/bluetooth.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018-2020 Konsulko Group
+ * Copyright (C) 2018-2021 Konsulko Group
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,301 +16,248 @@
#include <QDebug>
-#include "callmessage.h"
-#include "eventmessage.h"
-#include "responsemessage.h"
-#include "messagefactory.h"
-#include "messageengine.h"
-#include "messageenginefactory.h"
+#include <bluez-glib.h>
+
#include "bluetooth.h"
#include "bluetoothmodel.h"
+#include "bluetootheventhandler.h"
-Bluetooth::Bluetooth (QUrl &url, QQmlContext *context, QObject * parent) :
- QObject(parent),
- m_context(context)
+Bluetooth::Bluetooth (bool register_agent, QQmlContext *context, QObject * parent) :
+ QObject(parent),
+ m_context(context),
+ m_agent(register_agent)
{
- m_mloop = MessageEngineFactory::getInstance().getMessageEngine(url);
- m_bluetooth = new BluetoothModel();
- QObject::connect(m_mloop.get(), &MessageEngine::connected, this, &Bluetooth::onConnected);
- QObject::connect(m_mloop.get(), &MessageEngine::disconnected, this, &Bluetooth::onDisconnected);
- QObject::connect(m_mloop.get(), &MessageEngine::messageReceived, this, &Bluetooth::onMessageReceived);
-
- BluetoothModelFilter *m_model = new BluetoothModelFilter();
- m_model->setSourceModel(m_bluetooth);
- m_model->setFilterFixedString("true");
- context->setContextProperty("BluetoothPairedModel", m_model);
-
- m_model = new BluetoothModelFilter();
- m_model->setSourceModel(m_bluetooth);
- m_model->setFilterFixedString("false");
- context->setContextProperty("BluetoothDiscoveryModel", m_model);
-
- uuids.insert("a2dp", "0000110a-0000-1000-8000-00805f9b34fb");
- uuids.insert("avrcp", "0000110e-0000-1000-8000-00805f9b34fb");
- uuids.insert("hfp", "0000111f-0000-1000-8000-00805f9b34fb");
+ m_bluetooth = new BluetoothModel();
+ BluetoothModelFilter *m_model = new BluetoothModelFilter();
+ m_model->setSourceModel(m_bluetooth);
+ m_model->setFilterFixedString("true");
+ context->setContextProperty("BluetoothPairedModel", m_model);
+
+ m_model = new BluetoothModelFilter();
+ m_model->setSourceModel(m_bluetooth);
+ m_model->setFilterFixedString("false");
+ context->setContextProperty("BluetoothDiscoveryModel", m_model);
+
+ m_event_handler = new BluetoothEventHandler(this, register_agent);
+
+ uuids.insert("a2dp", "0000110a-0000-1000-8000-00805f9b34fb");
+ uuids.insert("avrcp", "0000110e-0000-1000-8000-00805f9b34fb");
+ uuids.insert("hfp", "0000111f-0000-1000-8000-00805f9b34fb");
}
Bluetooth::~Bluetooth()
{
}
-void Bluetooth::send_command(QString verb, QJsonObject parameter)
-{
- std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call);
- if (!msg)
- return;
-
- CallMessage* btmsg = static_cast<CallMessage*>(msg.get());
- btmsg->createRequest("Bluetooth-Manager", verb, parameter);
- m_mloop->sendMessage(std::move(msg));
-}
-
void Bluetooth::setPower(bool state)
{
- QJsonObject parameter;
- parameter.insert("powered", state ? "true" : "false");
- send_command("adapter_state", parameter);
+ bluez_adapter_set_powered(NULL, state ? TRUE : FALSE);
}
void Bluetooth::setDiscoverable(bool state)
{
- QJsonObject parameter;
- parameter.insert("discoverable", state ? "true" : "false");
- send_command("adapter_state", parameter);
+ bluez_adapter_set_discoverable(NULL, state);
- m_discoverable = state;
+ m_discoverable = state;
- emit discoverableChanged();
+ emit discoverableChanged();
}
-void Bluetooth::discovery_command(bool state)
+void Bluetooth::start()
{
- QJsonObject parameter;
- parameter.insert("discovery", state ? "true" : "false");
+ bluez_init(m_agent, m_agent, m_event_handler->init_cb, m_event_handler);
+}
- set_discovery_filter();
+void Bluetooth::discovery_command(bool state)
+{
+ set_discovery_filter();
- send_command("adapter_state", parameter);
+ bluez_adapter_set_discovery(NULL, state ? TRUE : FALSE);
}
void Bluetooth::start_discovery()
{
- discovery_command(true);
-
- // temp workaround to list already discovered devices
- send_command("managed_objects", QJsonObject());
+ discovery_command(true);
}
void Bluetooth::stop_discovery()
{
- discovery_command(false);
+ discovery_command(false);
}
void Bluetooth::remove_device(QString device)
{
- QJsonObject parameter;
- parameter.insert("device", device);
+ QByteArray device_ba = device.toLocal8Bit();
+ const char *device_cstr = device_ba.data();
- send_command("remove_device", parameter);
+ bluez_device_remove(device_cstr);
}
void Bluetooth::pair(QString device)
{
- QJsonObject parameter;
- parameter.insert("device", device);
+ QByteArray device_ba = device.toLocal8Bit();
+ const char *device_cstr = device_ba.data();
- send_command("pair", parameter);
+ bluez_device_pair(device_cstr, m_event_handler->device_pair_cb, m_event_handler);
}
-void Bluetooth::cancel_pair(QString device)
+void Bluetooth::cancel_pair(void)
{
- send_command("cancel_pairing", QJsonObject());
+ bluez_cancel_pairing();
}
void Bluetooth::connect(QString device, QString uuid)
{
- QJsonObject parameter;
- uuid = process_uuid(uuid);
- parameter.insert("device", device);
- parameter.insert("uuid", uuid);
- send_command("connect", parameter);
+ QByteArray device_ba = device.toLocal8Bit();
+ const char *device_cstr = device_ba.data();
+
+ uuid = process_uuid(uuid);
+ QByteArray uuid_ba = uuid.toLocal8Bit();
+ const char *uuid_cstr = uuid_ba.data();
+
+ bluez_device_connect(device_cstr,
+ uuid_cstr,
+ m_event_handler->device_connect_cb,
+ m_event_handler);
}
void Bluetooth::connect(QString device)
{
- QJsonObject parameter;
- parameter.insert("device", device);
- send_command("connect", parameter);
+ QByteArray device_ba = device.toLocal8Bit();
+ const char *device_cstr = device_ba.data();
+
+ bluez_device_connect(device_cstr,
+ NULL,
+ m_event_handler->device_connect_cb,
+ m_event_handler);
}
void Bluetooth::disconnect(QString device, QString uuid)
{
- QJsonObject parameter;
- uuid = process_uuid(uuid);
- parameter.insert("device", device);
- parameter.insert("uuid", uuid);
- send_command("disconnect", parameter);
-}
+ QByteArray device_ba = device.toLocal8Bit();
+ const char *device_cstr = device_ba.data();
-void Bluetooth::disconnect(QString device)
-{
- QJsonObject parameter;
- parameter.insert("device", device);
- send_command("disconnect", parameter);
-}
+ uuid = process_uuid(uuid);
+ QByteArray uuid_ba = uuid.toLocal8Bit();
+ const char *uuid_cstr = uuid_ba.data();
-void Bluetooth::send_confirmation(int pincode)
-{
- QJsonObject parameter;
- parameter.insert("pincode", pincode);
- send_command("confirm_pairing", parameter);
+ bluez_device_disconnect(device_cstr, uuid_cstr);
}
-
-void Bluetooth::set_discovery_filter()
+void Bluetooth::disconnect(QString device)
{
- QStringListIterator eventIterator(uuids.values());
- QJsonObject parameter;
- QJsonArray array;
-
- while (eventIterator.hasNext())
- array.push_back(eventIterator.next());
+ QByteArray device_ba = device.toLocal8Bit();
+ const char *device_cstr = device_ba.data();
- // send inital adapter state + discovery filter
- parameter.insert("filter", array);
- parameter.insert("transport", "bredr");
- send_command("adapter_state", parameter);
+ bluez_device_disconnect(device_cstr, NULL);
}
-void Bluetooth::onConnected()
+void Bluetooth::send_confirmation(int pincode)
{
- QStringListIterator eventIterator(events);
-
- while (eventIterator.hasNext()) {
- QJsonObject parameter;
- parameter.insert("value", eventIterator.next());
- send_command("subscribe", parameter);
- }
+ QString pincode_str;
+ pincode_str.setNum(pincode);
+ QByteArray pincode_ba = pincode_str.toLocal8Bit();
+ const char *pincode_cstr = pincode_ba.data();
- // send initial list
- send_command("managed_objects", QJsonObject());
-
- // get initial power state
- send_command("adapter_state", QJsonObject());
+ bluez_confirm_pairing(pincode_cstr);
}
-void Bluetooth::onDisconnected()
+void Bluetooth::init_adapter_state(QString adapter)
{
- QStringListIterator eventIterator(events);
+ // Get initial power state
+ GVariant *reply = NULL;
+ gboolean rc = bluez_adapter_get_state(NULL, &reply);
+ if (rc && reply) {
+ GVariantDict *props_dict = g_variant_dict_new(reply);
+ gboolean powered = FALSE;
+ if (g_variant_dict_lookup(props_dict, "Powered", "b", &powered)) {
+ if (m_power != powered) {
+ m_power = powered;
+ emit powerChanged(m_power);
+ }
+ }
+ g_variant_dict_unref(props_dict);
+ g_variant_unref(reply);
+ }
- while (eventIterator.hasNext()) {
- QJsonObject parameter;
- parameter.insert("value", eventIterator.next());
- send_command("unsubscribe", parameter);
- }
+ // Get initial device list
+ refresh_device_list();
}
-void Bluetooth::populateDeviceList(QJsonObject data)
+void Bluetooth::refresh_device_list(void)
{
- QJsonArray devices = data.value("devices").toArray();
-
- m_bluetooth->removeAllDevices();
-
- for (auto value : devices) {
- BluetoothDevice *device = m_bluetooth->updateDeviceProperties(nullptr, value.toObject());
- m_bluetooth->addDevice(device);
- }
+ gboolean rc;
+ GVariant *reply = NULL;
+
+ rc = bluez_adapter_get_devices(NULL, &reply);
+ if(!rc)
+ return;
+
+ m_bluetooth->removeAllDevices();
+
+ GVariantIter *array = NULL;
+ g_variant_get(reply, "a{sv}", &array);
+ const gchar *key = NULL;
+ GVariant *var = NULL;
+ while (g_variant_iter_next(array, "{&sv}", &key, &var)) {
+ BluetoothDevice *device = m_bluetooth->updateDeviceProperties(nullptr, key, var);
+ if (device)
+ m_bluetooth->addDevice(device);
+
+ g_variant_unref(var);
+ }
+ g_variant_iter_free(array);
+ g_variant_unref(reply);
}
-void Bluetooth::processDeviceChangesEvent(QJsonObject data)
+void Bluetooth::set_discovery_filter(void)
{
- QString action = data.value("action").toString();
- QString id = data.value("device").toString();
-
- if (id.isEmpty())
- return;
-
- BluetoothDevice *device = m_bluetooth->getDevice(id);
- if (action == "removed") {
- if (device != nullptr)
- m_bluetooth->removeDevice(device);
- return;
- }
-
- BluetoothDevice *ndevice = m_bluetooth->updateDeviceProperties(device, data);
- if (ndevice == nullptr) {
- qDebug() << "bt - failed to create device object with id: " << id;
- return;
- }
- if (device == nullptr) //device not previously in model
- m_bluetooth->addDevice(ndevice);
+ QList<QString> values = uuids.values();
+ QStringListIterator eventIterator(values);
+
+ gchar **uuids_array = (gchar**) g_malloc0((values.count() + 1) * sizeof(gchar*));
+ int i = 0;
+ while (eventIterator.hasNext()) {
+ QByteArray uuid_ba = eventIterator.next().toLocal8Bit();
+ gchar *uuid_cstr = g_strdup(uuid_ba.data());
+ uuids_array[i++] = uuid_cstr;
+ }
+
+ gchar *transport = g_strdup("bredr");
+ bluez_adapter_set_discovery_filter(NULL, uuids_array, transport);
+
+ for (i = 0; i < values.count(); i++)
+ g_free(uuids_array[i]);
+ g_free(uuids_array);
+ g_free(transport);
}
-void Bluetooth::processAdapterChangesEvent(QJsonObject data)
+void Bluetooth::update_adapter_power(bool powered)
{
- QString action = data.value("action").toString();
- if (action != "changed")
- return;
+ if (!powered)
+ m_bluetooth->removeAllDevices();
- QJsonObject properties = data.value("properties").toObject();
- if (!properties.contains("powered"))
- return;
+ if (m_power != powered) {
+ m_power = powered;
+ emit powerChanged(powered);
- bool powered = properties.find("powered").value().toBool();
- if (!powered)
- m_bluetooth->removeAllDevices();
+ if (powered)
+ refresh_device_list();
+ }
- if (m_power != powered) {
- m_power = powered;
- emit powerChanged(powered);
- }
- if (!m_power)
- m_discoverable = false;
+ if (!m_power) {
+ bool discoverable = m_discoverable;
+ m_discoverable = false;
+ if (discoverable != m_discoverable)
+ emit discoverableChanged();
+ }
}
-void Bluetooth::onMessageReceived(std::shared_ptr<Message> msg)
+void Bluetooth::request_confirmation(int pincode)
{
- if (!msg)
- return;
-
- if (msg->isEvent()) {
- std::shared_ptr<EventMessage> emsg = std::static_pointer_cast<EventMessage>(msg);
- QString ename = emsg->eventName();
- QString eapi = emsg->eventApi();
- QJsonObject data = emsg->eventData();
- if (eapi != "Bluetooth-Manager")
- return;
- if (ename == "device_changes") {
- processDeviceChangesEvent(data);
- } else if (ename == "adapter_changes") {
- processAdapterChangesEvent(data);
- } else if (ename == "agent") {
- emit requestConfirmationEvent(data);
- }
- } else if (msg->isReply()) {
- std::shared_ptr<ResponseMessage> rmsg = std::static_pointer_cast<ResponseMessage>(msg);
- QString verb = rmsg->requestVerb();
- QJsonObject data = rmsg->replyData();
- if (rmsg->requestApi() != "Bluetooth-Manager")
- return;
-
- if (rmsg->replyStatus() == "failed") {
- qDebug() << "failed bt verb:" << verb;
- if (rmsg->replyInfo().contains("No adapter")) {
- m_power = false;
- emit powerChanged(m_power);
- }
- }
- else if (verb == "managed_objects") {
- populateDeviceList(data);
- } else if (verb == "adapter_state") {
- bool powered = data.value("powered").toBool();
- if (m_power != powered) {
- m_power = powered;
- emit powerChanged(m_power);
- }
- }
- }
+ QString pincode_str;
+ pincode_str.setNum(pincode);
+ emit requestConfirmationEvent(pincode_str);
}
diff --git a/bluetooth/bluetooth.h b/bluetooth/bluetooth.h
index b79e8f9..c7ef55c 100644
--- a/bluetooth/bluetooth.h
+++ b/bluetooth/bluetooth.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018-2020 Konsulko Group
+ * Copyright (C) 2018-2021 Konsulko Group
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,13 +19,10 @@
#include <memory>
#include <QObject>
-#include <QJsonObject>
-#include <QJsonArray>
#include <QtQml/QQmlContext>
class BluetoothModel;
-class MessageEngine;
-class Message;
+class BluetoothEventHandler;
class Bluetooth : public QObject
{
@@ -34,18 +31,20 @@ class Bluetooth : public QObject
Q_PROPERTY(bool discoverable READ discoverable WRITE setDiscoverable NOTIFY discoverableChanged)
public:
- explicit Bluetooth(QUrl &url, QQmlContext *context, QObject * parent = Q_NULLPTR);
+ explicit Bluetooth(bool register_agent, QQmlContext *context, QObject * parent = Q_NULLPTR);
virtual ~Bluetooth();
void setPower(bool);
void setDiscoverable(bool);
+ Q_INVOKABLE void start(void);
+
Q_INVOKABLE void start_discovery(void);
Q_INVOKABLE void stop_discovery(void);
Q_INVOKABLE void remove_device(QString device);
Q_INVOKABLE void pair(QString device);
- Q_INVOKABLE void cancel_pair(QString device);
+ Q_INVOKABLE void cancel_pair(void);
Q_INVOKABLE void connect(QString device, QString uuid);
Q_INVOKABLE void connect(QString device);
@@ -62,24 +61,21 @@ class Bluetooth : public QObject
void powerChanged(bool state);
void discoverableChanged();
- void connectionEvent(QJsonObject data);
- void requestConfirmationEvent(QJsonObject data);
+ //void connectionEvent(QJsonObject data);
+ void requestConfirmationEvent(QString pincode);
private:
- std::shared_ptr<MessageEngine> m_mloop;
QQmlContext *m_context;
BluetoothModel *m_bluetooth;
- void send_command(QString, QJsonObject);
- void set_discovery_filter();
- void discovery_command(bool);
- void populateDeviceList(QJsonObject data);
- void processDeviceChangesEvent(QJsonObject data);
- void processAdapterChangesEvent(QJsonObject data);
+ BluetoothEventHandler *m_event_handler;
+ bool m_agent;
- // slots
- void onConnected();
- void onDisconnected();
- void onMessageReceived(std::shared_ptr<Message>);
+ void init_adapter_state(QString);
+ void refresh_device_list(void);
+ void set_discovery_filter(void);
+ void discovery_command(bool);
+ void update_adapter_power(bool);
+ void request_confirmation(int);
QString process_uuid(QString uuid) { if (uuid.length() == 36) return uuid; return uuids.value(uuid); };
@@ -89,11 +85,7 @@ class Bluetooth : public QObject
QMap<QString, QString> uuids;
- const QStringList events {
- "adapter_changes",
- "device_changes",
- "agent",
- };
+ friend class BluetoothEventHandler;
};
#endif // BLUETOOTH_H
diff --git a/bluetooth/bluetootheventhandler.cpp b/bluetooth/bluetootheventhandler.cpp
new file mode 100644
index 0000000..0acd5f5
--- /dev/null
+++ b/bluetooth/bluetootheventhandler.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2021 Konsulko Group
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <QDebug>
+#include <bluez-glib.h>
+
+#include "bluetootheventhandler.h"
+#include "bluetooth.h"
+#include "bluetoothmodel.h"
+
+
+BluetoothEventHandler::BluetoothEventHandler (Bluetooth *parent, bool register_agent) :
+ m_parent(parent),
+ m_agent(register_agent)
+{
+ bluez_add_adapter_event_callback(adapter_event_cb, this);
+ bluez_add_device_event_callback(device_event_cb, this);
+ if (register_agent)
+ bluez_add_agent_event_callback(agent_event_cb, this);
+}
+
+BluetoothEventHandler::~BluetoothEventHandler()
+{
+}
+
+void BluetoothEventHandler::handle_init_event(gchar *adapter, gboolean status)
+{
+ if (status)
+ m_parent->init_adapter_state(QString(adapter));
+ else
+ qCritical() << "BlueZ initialization failed";
+}
+
+void BluetoothEventHandler::handle_adapter_event(gchar *adapter,
+ bluez_event_t event,
+ GVariant *properties)
+{
+ if (!adapter || event != BLUEZ_EVENT_CHANGE)
+ return;
+
+ GVariantDict *props_dict = g_variant_dict_new(properties);
+ if (!props_dict)
+ return;
+
+ gboolean powered = FALSE;
+ if (!g_variant_dict_lookup(props_dict, "Powered", "b", &powered)) {
+ g_variant_dict_unref(props_dict);
+ return;
+ }
+
+ g_variant_dict_unref(props_dict);
+
+ m_parent->update_adapter_power(powered);
+}
+
+void BluetoothEventHandler::handle_device_event(gchar *adapter,
+ gchar *device,
+ bluez_event_t event,
+ GVariant *properties)
+{
+ if (!device)
+ return;
+
+ BluetoothDevice *model_device = m_parent->m_bluetooth->getDevice(QString(device));
+ if (event == BLUEZ_EVENT_REMOVE) {
+ if(model_device != nullptr)
+ m_parent->m_bluetooth->removeDevice(model_device);
+
+ return;
+ }
+
+ BluetoothDevice *new_device = m_parent->m_bluetooth->updateDeviceProperties(model_device, device, properties);
+ if (new_device == nullptr) {
+ qCritical() << "Failed to create device object with id: " << QString(device);
+ return;
+ }
+ if (model_device == nullptr && event == BLUEZ_EVENT_ADD) {
+ // device not previously in model
+ m_parent->m_bluetooth->addDevice(new_device);
+ }
+}
+
+void BluetoothEventHandler::handle_agent_event(gchar *device,
+ bluez_agent_event_t event,
+ GVariant *properties)
+{
+ const gchar *path = NULL;
+ int pincode;
+
+ if (event == BLUEZ_AGENT_EVENT_REQUEST_CONFIRMATION) {
+ g_variant_get(properties, "(ou)", &path, &pincode);
+ if (path)
+ m_parent->request_confirmation(pincode);
+ }
+}
+
+void BluetoothEventHandler::handle_connect_event(gchar *device, gboolean status)
+{
+ if (!status)
+ qDebug() << "connect failed";
+}
+
+void BluetoothEventHandler::handle_pair_event(gchar *device, gboolean status)
+{
+ if (!status)
+ qDebug() << "pairing failed";
+}
+
diff --git a/bluetooth/bluetootheventhandler.h b/bluetooth/bluetootheventhandler.h
new file mode 100644
index 0000000..ff970f5
--- /dev/null
+++ b/bluetooth/bluetootheventhandler.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 Konsulko Group
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BLUETOOTH_EVENT_HANDLER_H
+#define BLUETOOTH_EVENT_HANDLER_H
+
+class Bluetooth;
+
+class BluetoothEventHandler
+{
+ public:
+ explicit BluetoothEventHandler(Bluetooth *parent, bool register_agent);
+ virtual ~BluetoothEventHandler();
+
+ static void init_cb(gchar *adapter, gboolean status, gpointer user_data) {
+ if (user_data)
+ ((BluetoothEventHandler*) user_data)->handle_init_event(adapter, status);
+ }
+
+ static void device_connect_cb(gchar *device, gboolean status, gpointer user_data) {
+ if (user_data)
+ ((BluetoothEventHandler*) user_data)->handle_connect_event(device, status);
+ }
+
+ static void device_pair_cb(gchar *device, gboolean status, gpointer user_data) {
+ if (user_data)
+ ((BluetoothEventHandler*) user_data)->handle_pair_event(device, status);
+ }
+
+ private:
+ Bluetooth *m_parent;
+ bool m_agent;
+
+ // Callback functions for bluez-glib hooks
+ static void adapter_event_cb(gchar *adapter, bluez_event_t event, GVariant *properties, gpointer user_data) {
+ if (user_data)
+ ((BluetoothEventHandler*) user_data)->handle_adapter_event(adapter, event, properties);
+ }
+
+ static void device_event_cb(gchar *adapter, gchar *device, bluez_event_t event, GVariant *properties, gpointer user_data) {
+ if (user_data)
+ ((BluetoothEventHandler*) user_data)->handle_device_event(adapter, device, event, properties);
+ }
+
+ static void agent_event_cb(gchar *device, bluez_agent_event_t event, GVariant *properties, gpointer user_data) {
+ if (user_data)
+ ((BluetoothEventHandler*) user_data)->handle_agent_event(device, event, properties);
+ }
+
+ void handle_init_event(gchar *adapter, gboolean status);
+ void handle_adapter_event(gchar *adapter, bluez_event_t event, GVariant *properties);
+ void handle_device_event(gchar *adapter, gchar *device, bluez_event_t event, GVariant *properties);
+ void handle_agent_event(gchar *device, bluez_agent_event_t event, GVariant *properties);
+ void handle_connect_event(gchar *device, gboolean status);
+ void handle_pair_event(gchar *device, gboolean status);
+};
+
+#endif // BLUETOOTH_EVENT_HANDLER_H
diff --git a/bluetooth/bluetoothmodel.cpp b/bluetooth/bluetoothmodel.cpp
index 294b50b..605f950 100644
--- a/bluetooth/bluetoothmodel.cpp
+++ b/bluetooth/bluetoothmodel.cpp
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2019-2021 Konsulko Group
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#include "bluetoothmodel.h"
#include <QDebug>
@@ -13,52 +29,52 @@ BluetoothDevice::BluetoothDevice(const QString &id,
QString BluetoothDevice::id() const
{
- return m_id;
+ return m_id;
}
QString BluetoothDevice::address() const
{
- return m_address;
+ return m_address;
}
QString BluetoothDevice::name() const
{
- return m_name;
+ return m_name;
}
bool BluetoothDevice::paired() const
{
- return m_paired;
+ return m_paired;
}
bool BluetoothDevice::connected() const
{
- return m_connected;
+ return m_connected;
}
void BluetoothDevice::setId(const QString id)
{
- m_id = id;
+ m_id = id;
}
void BluetoothDevice::setAddress(const QString address)
{
- m_address = address;
+ m_address = address;
}
void BluetoothDevice::setName(const QString name)
{
- m_name = name;
+ m_name = name;
}
void BluetoothDevice::setPaired(const bool paired)
{
- m_paired = paired;
+ m_paired = paired;
}
void BluetoothDevice::setConnected(const bool connected)
{
- m_connected = connected;
+ m_connected = connected;
}
BluetoothModel::BluetoothModel(QObject *parent)
@@ -68,117 +84,158 @@ BluetoothModel::BluetoothModel(QObject *parent)
void BluetoothModel::addDevice(BluetoothDevice *device)
{
- beginInsertRows(QModelIndex(), rowCount(), rowCount());
- m_devices << device;
- endInsertRows();
+ if (!device)
+ return;
+
+ beginInsertRows(QModelIndex(), rowCount(), rowCount());
+ m_devices << device;
+ endInsertRows();
}
void BluetoothModel::removeDevice(BluetoothDevice *device)
{
- int row = m_devices.indexOf(device);
- beginRemoveRows(QModelIndex(), row, row);
- m_devices.removeAt(row);
- endRemoveRows();
- delete device;
+ if (!device)
+ return;
+
+ int row = m_devices.indexOf(device);
+ if (row < 0)
+ return;
+ beginRemoveRows(QModelIndex(), row, row);
+ m_devices.removeAt(row);
+ endRemoveRows();
+ delete device;
}
void BluetoothModel::removeAllDevices()
{
- beginRemoveRows(QModelIndex(), 0, m_devices.count() - 1);
- qDeleteAll(m_devices.begin(), m_devices.end());
- m_devices.clear();
- endRemoveRows();
+ if (!m_devices.count())
+ return;
+
+ beginRemoveRows(QModelIndex(), 0, m_devices.count() - 1);
+ qDeleteAll(m_devices.begin(), m_devices.end());
+ m_devices.clear();
+ endRemoveRows();
}
int BluetoothModel::rowCount(const QModelIndex &parent) const
{
- Q_UNUSED(parent);
- return m_devices.count();
+ Q_UNUSED(parent);
+ return m_devices.count();
}
QVariant BluetoothModel::data(const QModelIndex &index, int role) const
{
- if (index.row() < 0 || index.row() >= m_devices.count())
- return QVariant();
+ if (index.row() < 0 || index.row() >= m_devices.count())
+ return QVariant();
- const BluetoothDevice *device = m_devices[index.row()];
+ const BluetoothDevice *device = m_devices[index.row()];
- switch (role) {
+ switch (role) {
case IdRole:
- return device->id();
+ return device->id();
case AddressRole:
- return device->address();
+ return device->address();
case NameRole:
- return device->name();
+ return device->name();
case PairedRole:
- return device->paired();
+ return device->paired();
case ConnectedRole:
- return device->connected();
- }
+ return device->connected();
+ }
- return QVariant();
+ return QVariant();
}
QHash<int, QByteArray> BluetoothModel::roleNames() const {
- QHash<int, QByteArray> roles;
- roles[IdRole] = "id";
- roles[AddressRole] = "address";
- roles[NameRole] = "name";
- roles[PairedRole] = "paired";
- roles[ConnectedRole] = "connected";
+ QHash<int, QByteArray> roles;
+ roles[IdRole] = "id";
+ roles[AddressRole] = "address";
+ roles[NameRole] = "name";
+ roles[PairedRole] = "paired";
+ roles[ConnectedRole] = "connected";
- return roles;
+ return roles;
}
QModelIndex BluetoothModel::indexOf(BluetoothDevice *device)
{
- int row = m_devices.indexOf(device);
+ int row = m_devices.indexOf(device);
- return index(row);
+ return index(row);
}
BluetoothDevice *BluetoothModel::getDevice(QString id)
{
- for (auto device : m_devices) {
- if (device->id() == id)
- return device;
- }
+ for (auto device : m_devices) {
+ if (device->id() == id)
+ return device;
+ }
- return nullptr;
+ return nullptr;
}
-BluetoothDevice *BluetoothModel::updateDeviceProperties(BluetoothDevice *device, QJsonObject data)
+BluetoothDevice *BluetoothModel::updateDeviceProperties(BluetoothDevice *device, const gchar *dev_str, GVariant *properties)
{
- QJsonObject properties = data.value("properties").toObject();
- QString id = data.value("device").toString();
- QString address = properties.value("address").toString();
- QString name = properties.value("name").toString();
- bool paired = properties.value("paired").toBool();
- bool connected = properties.value("connected").toBool();
+ GVariantDict *props_dict = g_variant_dict_new(properties);
+ if (!props_dict)
+ return nullptr;
+
+ QString id(dev_str);
+ if (id.isEmpty()) {
+ g_variant_dict_unref(props_dict);
+ return nullptr;
+ }
+
+ gchar *p = NULL;
+ QString address;
+ if (g_variant_dict_lookup(props_dict, "Address", "s", &p)) {
+ address = QString(p);
+ g_free(p);
+ }
+
+ p = NULL;
+ QString name;
+ if (g_variant_dict_lookup(props_dict, "Name", "s", &p)) {
+ name = QString(p);
+ g_free(p);
+ }
+
+ gboolean paired = FALSE;
+ bool have_paired = false;
+ if (g_variant_dict_lookup(props_dict, "Paired", "b", &paired)) {
+ have_paired = true;
+ }
+
+ gboolean connected = FALSE;
+ bool have_connected = false;
+ if (g_variant_dict_lookup(props_dict, "Connected", "b", &connected)) {
+ have_connected = true;
+ }
- if (id.isEmpty())
- return nullptr;
+ g_variant_dict_unref(props_dict);
- if (device == nullptr)
- return new BluetoothDevice(id, address, name, paired, connected);
+ if (device == nullptr) {
+ // Create new device object
+ return new BluetoothDevice(id, address, name, paired, connected);
+ }
- device->setId(id);
+ device->setId(id);
- if (!address.isEmpty())
- device->setAddress(address);
+ if (!address.isEmpty())
+ device->setAddress(address);
- if (!name.isEmpty())
- device->setName(name);
+ if (!name.isEmpty())
+ device->setName(name);
- if (properties.contains("paired"))
- device->setPaired(paired);
+ if (have_paired)
+ device->setPaired(paired);
- if (properties.contains("connected"))
- device->setConnected(connected);
+ if (have_connected)
+ device->setConnected(connected);
- emit dataChanged(indexOf(device), indexOf(device));
+ emit dataChanged(indexOf(device), indexOf(device));
- return device;
+ return device;
}
BluetoothModelFilter::BluetoothModelFilter(QObject *parent) : QSortFilterProxyModel(parent)
@@ -187,9 +244,9 @@ BluetoothModelFilter::BluetoothModelFilter(QObject *parent) : QSortFilterProxyMo
bool BluetoothModelFilter::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
- BluetoothModel *model = qobject_cast<BluetoothModel *>(sourceModel());
- QModelIndex index = model->index(sourceRow);
- bool paired = model->data(index, BluetoothModel::BluetoothRoles::PairedRole).toBool();
+ BluetoothModel *model = qobject_cast<BluetoothModel *>(sourceModel());
+ QModelIndex index = model->index(sourceRow);
+ bool paired = model->data(index, BluetoothModel::BluetoothRoles::PairedRole).toBool();
- return ((paired ? "true" : "false") == filterRegExp().pattern());
+ return ((paired ? "true" : "false") == filterRegExp().pattern());
}
diff --git a/bluetooth/bluetoothmodel.h b/bluetooth/bluetoothmodel.h
index 0fc07aa..a060ad8 100644
--- a/bluetooth/bluetoothmodel.h
+++ b/bluetooth/bluetoothmodel.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2019,2021 Konsulko Group
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#ifndef BLUETOOTH_MODEL_H
#define BLUETOOTH_MODEL_H
@@ -5,7 +21,7 @@
#include <QSortFilterProxyModel>
#include <QStringList>
#include <QtQml/QQmlContext>
-#include <QJsonObject>
+#include <glib.h>
class BluetoothDevice
{
@@ -53,7 +69,7 @@ class BluetoothModel : public QAbstractListModel
void removeDevice(BluetoothDevice *device);
void removeAllDevices();
BluetoothDevice *getDevice(QString address);
- BluetoothDevice *updateDeviceProperties(BluetoothDevice *device, QJsonObject data);
+ BluetoothDevice *updateDeviceProperties(BluetoothDevice *device, const gchar *dev_str, GVariant *properties);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;