diff options
Diffstat (limited to 'src/linux/up-device-bluez.c')
-rw-r--r-- | src/linux/up-device-bluez.c | 182 |
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); +} + |