125 lines
4.2 KiB
C
125 lines
4.2 KiB
C
#include "bluetooth.h"
|
|
#include "../util.h"
|
|
|
|
#include <dirent.h>
|
|
#include <gio/gio.h>
|
|
|
|
static long long powered_devices = 0;
|
|
|
|
static GPtrArray *get_bluetooth_device_paths() {
|
|
DIR *dir = opendir("/sys/class/bluetooth");
|
|
if (!dir) {
|
|
return NULL;
|
|
}
|
|
GPtrArray *arr = g_ptr_array_new();
|
|
struct dirent *current;
|
|
while ((current = readdir(dir))) {
|
|
if (strcmp(current->d_name, ".") != 0 &&
|
|
strcmp(current->d_name, "..") != 0) {
|
|
char *path = g_strdup_printf("/org/bluez/%s", current->d_name);
|
|
g_ptr_array_add(arr, path);
|
|
}
|
|
}
|
|
closedir(dir);
|
|
return arr;
|
|
}
|
|
|
|
static void load_initial_device_states(GDBusConnection *dbus,
|
|
GPtrArray *devices) {
|
|
gsize i;
|
|
for (i = 0; i < devices->len; ++i) {
|
|
const char *path = g_ptr_array_index(devices, i);
|
|
GError *err = NULL;
|
|
GVariant *response = g_dbus_connection_call_sync(
|
|
dbus, "org.bluez", path, "org.freedesktop.DBus.Properties", "Get",
|
|
g_variant_new_parsed("('org.bluez.Adapter1', 'Powered')"),
|
|
(GVariantType *)"(v)", G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
|
|
if (err) {
|
|
qtb_log("checking bluetooth adapter power state failed\n-> %s", err->message);
|
|
g_error_free(err);
|
|
err = NULL;
|
|
qtb_die();
|
|
}
|
|
if (response) {
|
|
GVariant *wrapper = g_variant_get_child_value(response, 0);
|
|
GVariant *value = g_variant_get_child_value(wrapper, 0);
|
|
gboolean powered = g_variant_get_boolean(value);
|
|
if (powered) {
|
|
++powered_devices;
|
|
} /* sice powered_devices is already 0, we dont have to increment it
|
|
if the device is not powered */
|
|
g_variant_unref(value);
|
|
g_variant_unref(wrapper);
|
|
g_variant_unref(response);
|
|
}
|
|
}
|
|
qtb_signal_modules(4);
|
|
}
|
|
|
|
static void device_changed_callback(GDBusConnection *dbus,
|
|
const char *sender_name,
|
|
const char *object_path,
|
|
const char *interface_name,
|
|
const char *signal_name, GVariant *params,
|
|
gpointer user_data) {
|
|
GVariant *changed = g_variant_get_child_value(params, 1);
|
|
GVariant *value_wrapper = g_variant_lookup_value(changed, "Powered", G_VARIANT_TYPE_BOOLEAN);
|
|
if (value_wrapper) {
|
|
gboolean powered = g_variant_get_boolean(value_wrapper);
|
|
if (powered) {
|
|
++powered_devices;
|
|
} else {
|
|
--powered_devices;
|
|
}
|
|
g_variant_unref(value_wrapper);
|
|
}
|
|
g_variant_unref(changed);
|
|
qtb_signal_modules(4);
|
|
}
|
|
|
|
static void subscribe_to_events(GDBusConnection *dbus, GPtrArray *devices) {
|
|
gsize i;
|
|
for (i = 0; i < devices->len; ++i) {
|
|
const char *path = g_ptr_array_index(devices, i);
|
|
g_dbus_connection_signal_subscribe(
|
|
dbus, NULL, "org.freedesktop.DBus.Properties", "PropertiesChanged",
|
|
path, "org.bluez.Adapter1", G_DBUS_SIGNAL_FLAGS_NONE,
|
|
&device_changed_callback, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
static void *thread_action() {
|
|
GMainContext *context = g_main_context_new();
|
|
g_main_context_push_thread_default(context);
|
|
GError *err = NULL;
|
|
GDBusConnection *dbus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
|
|
if (err) {
|
|
qtb_log("could not connect to bluez on the system bus: %s",
|
|
err->message);
|
|
qtb_die();
|
|
}
|
|
GPtrArray *devices = get_bluetooth_device_paths();
|
|
load_initial_device_states(dbus, devices);
|
|
subscribe_to_events(dbus, devices);
|
|
gsize i;
|
|
for (i = 0; i < devices->len; ++i) {
|
|
g_free(g_ptr_array_index(devices, i));
|
|
}
|
|
g_ptr_array_free(devices, TRUE);
|
|
GMainLoop *main_loop = g_main_loop_new(context, FALSE);
|
|
g_main_loop_run(main_loop);
|
|
return NULL;
|
|
}
|
|
|
|
void bluetooth_module_init() {
|
|
g_thread_new("bluetooth-module", &thread_action, NULL);
|
|
}
|
|
|
|
char *bluetooth_module_poll() {
|
|
char *output = NULL;
|
|
if (powered_devices != 0) {
|
|
output = qtb_strdup(" ");
|
|
}
|
|
return output;
|
|
}
|