summaryrefslogtreecommitdiff
path: root/src/linux/up-device-bluez.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/linux/up-device-bluez.c')
-rw-r--r--src/linux/up-device-bluez.c182
1 files changed, 182 insertions, 0 deletions
diff --git a/src/linux/up-device-bluez.c b/src/linux/up-device-bluez.c
new file mode 100644
index 0000000..42a8e1b
--- /dev/null
+++ b/src/linux/up-device-bluez.c
@@ -0,0 +1,182 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2017 Bastien Nocera <hadess@hadess.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <gio/gio.h>
+
+#include "up-types.h"
+#include "up-device-bluez.h"
+
+G_DEFINE_TYPE (UpDeviceBluez, up_device_bluez, UP_TYPE_DEVICE)
+#define UP_DEVICE_BLUEZ_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), UP_TYPE_DEVICE_BLUEZ, UpDeviceBluezPrivate))
+
+static UpDeviceKind
+appearance_to_kind (guint16 appearance)
+{
+ switch ((appearance & 0xffc0) >> 6) {
+ case 0x01:
+ return UP_DEVICE_KIND_PHONE;
+ case 0x02:
+ return UP_DEVICE_KIND_COMPUTER;
+ case 0x05:
+ return UP_DEVICE_KIND_MONITOR;
+ case 0x0a:
+ return UP_DEVICE_KIND_MEDIA_PLAYER;
+ case 0x0f: /* HID Generic */
+ switch (appearance & 0x3f) {
+ case 0x01:
+ return UP_DEVICE_KIND_KEYBOARD;
+ case 0x02:
+ return UP_DEVICE_KIND_MOUSE;
+ case 0x03:
+ case 0x04:
+ return UP_DEVICE_KIND_GAMING_INPUT;
+ case 0x05:
+ return UP_DEVICE_KIND_TABLET;
+ }
+ break;
+ }
+
+ return UP_DEVICE_KIND_UNKNOWN;
+}
+
+/**
+ * up_device_bluez_coldplug:
+ *
+ * Return %TRUE on success, %FALSE if we failed to get data and should be removed
+ **/
+static gboolean
+up_device_bluez_coldplug (UpDevice *device)
+{
+ GDBusObjectProxy *object_proxy;
+ GDBusProxy *proxy;
+ GError *error = NULL;
+ UpDeviceKind kind;
+ const char *uuid;
+ const char *model;
+ guint16 appearance;
+ guchar percentage;
+
+ /* Static device properties */
+ object_proxy = G_DBUS_OBJECT_PROXY (up_device_get_native (device));
+ proxy = g_dbus_proxy_new_sync (g_dbus_object_proxy_get_connection (object_proxy),
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.bluez",
+ g_dbus_object_get_object_path (G_DBUS_OBJECT (object_proxy)),
+ "org.bluez.Device1",
+ NULL,
+ &error);
+
+ if (!proxy) {
+ g_warning ("Failed to get proxy for %s (iface org.bluez.Device1)",
+ g_dbus_object_get_object_path (G_DBUS_OBJECT (object_proxy)));
+ return FALSE;
+ }
+
+ appearance = g_variant_get_uint16 (g_dbus_proxy_get_cached_property (proxy, "Appearance"));
+ kind = appearance_to_kind (appearance);
+ uuid = g_variant_get_string (g_dbus_proxy_get_cached_property (proxy, "Address"), NULL);
+ model = g_variant_get_string (g_dbus_proxy_get_cached_property (proxy, "Alias"), NULL);
+
+ /* hardcode some values */
+ g_object_set (device,
+ "type", kind,
+ "serial", uuid,
+ "model", model,
+ "power-supply", FALSE,
+ "has-history", TRUE,
+ NULL);
+
+ g_object_unref (proxy);
+
+ /* Initial battery values */
+ proxy = g_dbus_proxy_new_sync (g_dbus_object_proxy_get_connection (object_proxy),
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.bluez",
+ g_dbus_object_get_object_path (G_DBUS_OBJECT (object_proxy)),
+ "org.bluez.Battery1",
+ NULL,
+ &error);
+
+ if (!proxy) {
+ g_warning ("Failed to get proxy for %s",
+ g_dbus_object_get_object_path (G_DBUS_OBJECT (object_proxy)));
+ return FALSE;
+ }
+
+ percentage = g_variant_get_byte (g_dbus_proxy_get_cached_property (proxy, "Percentage"));
+
+ g_object_set (device,
+ "is-present", TRUE,
+ "percentage", (gdouble) percentage,
+ NULL);
+
+ g_object_unref (proxy);
+
+ return TRUE;
+}
+
+static void
+up_device_bluez_init (UpDeviceBluez *bluez)
+{
+}
+
+void
+up_device_bluez_update (UpDeviceBluez *bluez,
+ GVariant *properties)
+{
+ UpDevice *device = UP_DEVICE (bluez);
+ GVariantIter iter;
+ const gchar *key;
+ GVariant *value;
+
+ g_variant_iter_init (&iter, properties);
+ while (g_variant_iter_next (&iter, "{&sv}", &key, &value)) {
+ if (g_str_equal (key, "Percentage")) {
+ g_object_set (device, "percentage", (gdouble) g_variant_get_byte (value), NULL);
+ } else {
+ char *str = g_variant_print (value, TRUE);
+
+ g_warning ("Unhandled key: %s value: %s", key, str);
+ g_free (str);
+ }
+ g_variant_unref (value);
+ }
+}
+
+static void
+up_device_bluez_class_init (UpDeviceBluezClass *klass)
+{
+ UpDeviceClass *device_class = UP_DEVICE_CLASS (klass);
+
+ device_class->coldplug = up_device_bluez_coldplug;
+}
+
+UpDeviceBluez *
+up_device_bluez_new (void)
+{
+ return g_object_new (UP_TYPE_DEVICE_BLUEZ, NULL);
+}
+