linux: Remove user-space support for Logitech Unifying devices

All those devices have been supported in the Linux kernel for a number
of years already, so the user-space support has just not been exercised.
This commit is contained in:
Bastien Nocera 2021-06-17 11:54:22 +02:00
parent b09846dbed
commit d2053eff93
7 changed files with 2 additions and 1716 deletions

View file

@ -28,8 +28,6 @@ endif
libupshared_la_SOURCES = \ libupshared_la_SOURCES = \
up-device-supply.c \ up-device-supply.c \
up-device-supply.h \ up-device-supply.h \
up-device-unifying.c \
up-device-unifying.h \
up-device-hid.c \ up-device-hid.c \
up-device-hid.h \ up-device-hid.h \
up-device-wup.c \ up-device-wup.c \
@ -41,25 +39,9 @@ libupshared_la_SOURCES = \
up-backend.c \ up-backend.c \
up-backend-linux-private.h \ up-backend-linux-private.h \
up-native.c \ up-native.c \
hidpp-device.c \
hidpp-device.h \
$(idevice_files) \ $(idevice_files) \
$(BUILT_SOURCES) $(BUILT_SOURCES)
noinst_PROGRAMS = \
hidpp-test
hidpp_test_SOURCES = \
hidpp-device.c \
hidpp-device.h \
hidpp-test.c
hidpp_test_LDADD = \
-lm \
$(GLIB_LIBS) \
$(GIO_LIBS) \
$(GIO_UNIX_LIBS)
hidpp_test_CFLAGS = $(AM_CFLAGS) $(WARNINGFLAGS_C)
EXTRA_DIST = $(libupshared_la_SOURCES) \ EXTRA_DIST = $(libupshared_la_SOURCES) \
integration-test integration-test

File diff suppressed because it is too large Load diff

View file

@ -1,99 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Julien Danjou <julien@danjou.info>
* Copyright (C) 2012 Richard Hughes <richard@hughsie.com>
*
* 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
*
*/
#ifndef __HIDPP_DEVICE_H__
#define __HIDPP_DEVICE_H__
#include <glib-object.h>
#include "hidpp-device.h"
G_BEGIN_DECLS
#define HIDPP_TYPE_DEVICE (hidpp_device_get_type ())
#define HIDPP_DEVICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), HIDPP_TYPE_DEVICE, HidppDevice))
#define HIDPP_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), HIDPP_TYPE_DEVICE, HidppDeviceClass))
#define HIDPP_IS_DEVICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), HIDPP_TYPE_DEVICE))
#define HIDPP_IS_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), HIDPP_TYPE_DEVICE))
#define HIDPP_DEVICE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), HIDPP_TYPE_DEVICE, HidppDeviceClass))
typedef struct HidppDevicePrivate HidppDevicePrivate;
typedef struct
{
GObject parent;
HidppDevicePrivate *priv;
} HidppDevice;
typedef struct
{
GObjectClass parent_class;
} HidppDeviceClass;
typedef enum {
HIDPP_DEVICE_KIND_KEYBOARD,
HIDPP_DEVICE_KIND_MOUSE,
HIDPP_DEVICE_KIND_TOUCHPAD,
HIDPP_DEVICE_KIND_TRACKBALL,
HIDPP_DEVICE_KIND_TABLET,
HIDPP_DEVICE_KIND_UNKNOWN
} HidppDeviceKind;
typedef enum {
HIDPP_DEVICE_BATT_STATUS_CHARGING,
HIDPP_DEVICE_BATT_STATUS_DISCHARGING,
HIDPP_DEVICE_BATT_STATUS_CHARGED,
HIDPP_DEVICE_BATT_STATUS_UNKNOWN
} HidppDeviceBattStatus;
typedef enum {
HIDPP_REFRESH_FLAGS_VERSION = 1,
HIDPP_REFRESH_FLAGS_KIND = 2,
HIDPP_REFRESH_FLAGS_BATTERY = 4,
HIDPP_REFRESH_FLAGS_MODEL = 8,
HIDPP_REFRESH_FLAGS_FEATURES = 16,
HIDPP_REFRESH_FLAGS_SERIAL = 32
} HidppRefreshFlags;
GType hidpp_device_get_type (void);
const gchar *hidpp_device_get_model (HidppDevice *device);
guint hidpp_device_get_batt_percentage (HidppDevice *device);
guint hidpp_device_get_version (HidppDevice *device);
HidppDeviceBattStatus hidpp_device_get_batt_status (HidppDevice *device);
HidppDeviceKind hidpp_device_get_kind (HidppDevice *device);
const gchar *hidpp_device_get_serial (HidppDevice *device);
double hidpp_device_get_luminosity (HidppDevice *device);
void hidpp_device_set_hidraw_device (HidppDevice *device,
const gchar *hidraw_device);
void hidpp_device_set_index (HidppDevice *device,
guint device_idx);
void hidpp_device_set_enable_debug (HidppDevice *device,
gboolean enable_debug);
gboolean hidpp_device_is_reachable (HidppDevice *device);
gboolean hidpp_device_refresh (HidppDevice *device,
HidppRefreshFlags refresh_flags,
GError **error);
HidppDevice *hidpp_device_new (void);
G_END_DECLS
#endif /* __HIDPP_DEVICE_H__ */

View file

@ -1,81 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Richard Hughes <richard@hughsie.com>
*
* Licensed under the GNU General Public License Version 2
*
* 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include <glib.h>
#include <glib-object.h>
#include "hidpp-device.h"
int
main (int argc, char **argv)
{
// const gchar *model;
// guint batt_percentage;
// guint version;
// HidppDeviceBattStatus batt_status;
HidppDevice *d;
// HidppDeviceKind kind;
gboolean ret;
GError *error = NULL;
#if !defined(GLIB_VERSION_2_36)
g_type_init ();
#endif
g_test_init (&argc, &argv, NULL);
d = hidpp_device_new ();
hidpp_device_set_enable_debug (d, TRUE);
g_assert_cmpint (hidpp_device_get_version (d), ==, 0);
g_assert_cmpstr (hidpp_device_get_model (d), ==, NULL);
g_assert_cmpint (hidpp_device_get_batt_percentage (d), ==, 0);
g_assert_cmpint (hidpp_device_get_batt_status (d), ==, HIDPP_DEVICE_BATT_STATUS_UNKNOWN);
g_assert_cmpint (hidpp_device_get_kind (d), ==, HIDPP_DEVICE_KIND_UNKNOWN);
/* setup */
hidpp_device_set_hidraw_device (d, "/dev/hidraw0");
hidpp_device_set_index (d, 1);
ret = hidpp_device_refresh (d,
HIDPP_REFRESH_FLAGS_VERSION |
HIDPP_REFRESH_FLAGS_KIND |
HIDPP_REFRESH_FLAGS_BATTERY |
HIDPP_REFRESH_FLAGS_MODEL,
&error);
g_assert_no_error (error);
g_assert (ret);
g_assert_cmpint (hidpp_device_get_version (d), !=, 0);
g_assert_cmpstr (hidpp_device_get_model (d), !=, NULL);
g_assert_cmpint (hidpp_device_get_batt_percentage (d), !=, 0);
g_assert_cmpint (hidpp_device_get_batt_status (d), !=, HIDPP_DEVICE_BATT_STATUS_UNKNOWN);
g_assert_cmpint (hidpp_device_get_kind (d), !=, HIDPP_DEVICE_KIND_UNKNOWN);
g_print ("Version:\t\t%i\n", hidpp_device_get_version (d));
g_print ("Kind:\t\t\t%i\n", hidpp_device_get_kind (d));
g_print ("Model:\t\t\t%s\n", hidpp_device_get_model (d));
g_print ("Battery Percentage:\t%i\n", hidpp_device_get_batt_percentage (d));
g_print ("Battery Status:\t\t%i\n", hidpp_device_get_batt_status (d));
g_object_unref (d);
return 0;
}

View file

@ -36,7 +36,6 @@
#include "up-device.h" #include "up-device.h"
#include "up-device-supply.h" #include "up-device-supply.h"
#include "up-device-unifying.h"
#include "up-device-wup.h" #include "up-device-wup.h"
#include "up-device-hid.h" #include "up-device-hid.h"
#include "up-device-bluez.h" #include "up-device-bluez.h"
@ -134,16 +133,6 @@ up_backend_device_new (UpBackend *backend, GUdevDevice *native)
/* no valid power supply object */ /* no valid power supply object */
g_clear_object (&device); g_clear_object (&device);
} else if (g_strcmp0 (subsys, "hid") == 0) {
/* see if this is a Unifying mouse or keyboard */
device = UP_DEVICE (up_device_unifying_new ());
ret = up_device_coldplug (device, backend->priv->daemon, G_OBJECT (native));
if (ret)
goto out;
/* no valid power supply object */
g_clear_object (&device);
} else if (g_strcmp0 (subsys, "tty") == 0) { } else if (g_strcmp0 (subsys, "tty") == 0) {
/* see if this is a Watts Up Pro device */ /* see if this is a Watts Up Pro device */
@ -502,8 +491,8 @@ up_backend_coldplug (UpBackend *backend, UpDaemon *daemon)
GList *devices; GList *devices;
GList *l; GList *l;
guint i; guint i;
const gchar *subsystems_wup[] = {"power_supply", "usb", "usbmisc", "tty", "input", "hid", NULL}; const gchar *subsystems_wup[] = {"power_supply", "usb", "usbmisc", "tty", "input", NULL};
const gchar *subsystems[] = {"power_supply", "usb", "usbmisc", "input", "hid", NULL}; const gchar *subsystems[] = {"power_supply", "usb", "usbmisc", "input", NULL};
backend->priv->daemon = g_object_ref (daemon); backend->priv->daemon = g_object_ref (daemon);
backend->priv->device_list = up_daemon_get_device_list (daemon); backend->priv->device_list = up_daemon_get_device_list (daemon);

View file

@ -1,348 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Julien Danjou <julien@danjou.info>
*
* 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 <glib-object.h>
#include <gudev/gudev.h>
#include "hidpp-device.h"
#include "up-device-unifying.h"
#include "up-types.h"
struct UpDeviceUnifyingPrivate
{
HidppDevice *hidpp_device;
};
G_DEFINE_TYPE_WITH_PRIVATE (UpDeviceUnifying, up_device_unifying, UP_TYPE_DEVICE)
/**
* up_device_unifying_refresh:
*
* Return %TRUE on success, %FALSE if we failed to refresh or no data
**/
static gboolean
up_device_unifying_refresh (UpDevice *device)
{
gboolean ret;
GError *error = NULL;
HidppRefreshFlags refresh_flags;
UpDeviceState state = UP_DEVICE_STATE_UNKNOWN;
UpDeviceUnifying *unifying = UP_DEVICE_UNIFYING (device);
UpDeviceUnifyingPrivate *priv = unifying->priv;
double lux;
/* refresh the battery stats */
refresh_flags = HIDPP_REFRESH_FLAGS_BATTERY;
/*
* When a device is initially unreachable, the HID++ version cannot be
* determined. Therefore try determining the HID++ version, otherwise
* battery information cannot be retrieved. Assume that the HID++
* version does not change once detected.
*/
if (hidpp_device_get_version (priv->hidpp_device) == 0)
refresh_flags |= HIDPP_REFRESH_FLAGS_VERSION;
ret = hidpp_device_refresh (priv->hidpp_device,
refresh_flags,
&error);
if (!ret) {
g_warning ("failed to coldplug unifying device: %s",
error->message);
g_error_free (error);
goto out;
}
switch (hidpp_device_get_batt_status (priv->hidpp_device)) {
case HIDPP_DEVICE_BATT_STATUS_CHARGING:
state = UP_DEVICE_STATE_CHARGING;
break;
case HIDPP_DEVICE_BATT_STATUS_DISCHARGING:
state = UP_DEVICE_STATE_DISCHARGING;
break;
case HIDPP_DEVICE_BATT_STATUS_CHARGED:
state = UP_DEVICE_STATE_FULLY_CHARGED;
break;
default:
break;
}
/* if a device is unreachable, some known values do not make sense */
if (!hidpp_device_is_reachable (priv->hidpp_device)) {
state = UP_DEVICE_STATE_UNKNOWN;
}
lux = hidpp_device_get_luminosity (priv->hidpp_device);
if (lux >= 0) {
g_object_set (device, "luminosity", lux, NULL);
}
g_object_set (device,
"is-present", hidpp_device_is_reachable (priv->hidpp_device),
"percentage", (gdouble) hidpp_device_get_batt_percentage (priv->hidpp_device),
"state", state,
"update-time", (guint64) g_get_real_time () / G_USEC_PER_SEC,
NULL);
out:
return TRUE;
}
static UpDeviceKind
up_device_unifying_get_device_kind (UpDeviceUnifying *unifying)
{
UpDeviceKind kind;
switch (hidpp_device_get_kind (unifying->priv->hidpp_device)) {
case HIDPP_DEVICE_KIND_MOUSE:
case HIDPP_DEVICE_KIND_TRACKBALL:
kind = UP_DEVICE_KIND_MOUSE;
break;
case HIDPP_DEVICE_KIND_TOUCHPAD:
kind = UP_DEVICE_KIND_TOUCHPAD;
break;
case HIDPP_DEVICE_KIND_KEYBOARD:
kind = UP_DEVICE_KIND_KEYBOARD;
break;
case HIDPP_DEVICE_KIND_TABLET:
kind = UP_DEVICE_KIND_TABLET;
break;
default:
kind = UP_DEVICE_KIND_UNKNOWN;
}
return kind;
}
/**
* up_device_unifying_coldplug:
*
* Return %TRUE on success, %FALSE if we failed to get data and should be removed
**/
static gboolean
up_device_unifying_coldplug (UpDevice *device)
{
const gchar *bus_address;
const gchar *device_file;
const gchar *type;
const gchar *vendor;
gboolean ret = FALSE;
gchar *endptr = NULL;
gchar *tmp;
GError *error = NULL;
GUdevDevice *native;
GUdevDevice *parent = NULL;
GUdevDevice *receiver = NULL;
UpDeviceUnifying *unifying = UP_DEVICE_UNIFYING (device);
GUdevClient *client = NULL;
GList *hidraw_list = NULL;
GList *l;
native = G_UDEV_DEVICE (up_device_get_native (device));
/* check if we have the right device */
type = g_udev_device_get_property (native, "UPOWER_BATTERY_TYPE");
if (type == NULL)
goto out;
if ((g_strcmp0 (type, "unifying") != 0) && (g_strcmp0 (type, "lg-wireless") != 0))
goto out;
/* get the device index */
unifying->priv->hidpp_device = hidpp_device_new ();
bus_address = g_udev_device_get_property (native, "HID_PHYS");
tmp = g_strrstr (bus_address, ":");
if (tmp == NULL) {
g_debug ("Could not get physical device index");
goto out;
}
if (g_strcmp0 (type, "lg-wireless") == 0)
hidpp_device_set_index (unifying->priv->hidpp_device, 1);
else {
hidpp_device_set_index (unifying->priv->hidpp_device,
g_ascii_strtoull (tmp + 1, &endptr, 10));
if (endptr != NULL && endptr[0] != '\0') {
g_debug ("HID_PHYS malformed: '%s'", bus_address);
goto out;
}
}
/* find the hidraw device that matches */
parent = g_udev_device_get_parent (native);
client = g_udev_client_new (NULL);
hidraw_list = g_udev_client_query_by_subsystem (client, "hidraw");
for (l = hidraw_list; l != NULL; l = l->next) {
gboolean receiver_found = FALSE;
if (g_strcmp0 (type, "lg-wireless") == 0) {
const gchar *filename;
GDir* dir;
GUdevDevice *parent_dev;
parent_dev = g_udev_device_get_parent(l->data);
receiver_found = g_strcmp0 (g_udev_device_get_sysfs_path (native),
g_udev_device_get_sysfs_path(parent_dev)) == 0;
g_object_unref (parent_dev);
if (!receiver_found)
continue;
/* hidraw device which exposes hiddev interface is our receiver */
tmp = g_build_filename (g_udev_device_get_sysfs_path (parent),
"usbmisc", NULL);
dir = g_dir_open (tmp, 0, &error);
g_free(tmp);
if (error) {
g_clear_error(&error);
continue;
}
while ( (filename = g_dir_read_name(dir)) ) {
if (g_ascii_strncasecmp(filename, "hiddev", 6) == 0) {
receiver_found = TRUE;
break;
}
}
g_dir_close(dir);
} else {
GUdevDevice *parent_dev;
/* Unifying devices are located under their receiver */
parent_dev = g_udev_device_get_parent(l->data);
receiver_found = g_strcmp0 (g_udev_device_get_sysfs_path (parent),
g_udev_device_get_sysfs_path(parent_dev)) == 0;
g_object_unref (parent_dev);
}
if (receiver_found) {
receiver = g_object_ref (l->data);
break;
}
}
if (receiver == NULL) {
g_debug ("Unable to find an hidraw device for Unifying receiver");
return FALSE;
}
/* connect to the receiver */
device_file = g_udev_device_get_device_file (receiver);
if (device_file == NULL) {
g_debug ("Could not get device file for Unifying receiver device");
goto out;
}
g_debug ("Using Unifying receiver hidraw device file: %s", device_file);
hidpp_device_set_hidraw_device (unifying->priv->hidpp_device,
device_file);
/* give newly paired devices a chance to complete pairing */
g_usleep(30000);
/* coldplug initial parameters */
ret = hidpp_device_refresh (unifying->priv->hidpp_device,
HIDPP_REFRESH_FLAGS_VERSION |
HIDPP_REFRESH_FLAGS_KIND |
HIDPP_REFRESH_FLAGS_SERIAL |
HIDPP_REFRESH_FLAGS_MODEL,
&error);
if (!ret) {
g_warning ("failed to coldplug unifying device: %s",
error->message);
g_error_free (error);
goto out;
}
vendor = g_udev_device_get_property (native, "UPOWER_VENDOR");
if (vendor == NULL)
vendor = g_udev_device_get_property (native, "ID_VENDOR");
/* set some default values */
g_object_set (device,
"vendor", vendor,
"type", up_device_unifying_get_device_kind (unifying),
"model", hidpp_device_get_model (unifying->priv->hidpp_device),
"serial", hidpp_device_get_serial (unifying->priv->hidpp_device),
"has-history", TRUE,
"is-rechargeable", TRUE,
"power-supply", FALSE,
NULL);
/* set up a poll to send the magic packet */
up_device_unifying_refresh (device);
up_daemon_start_poll (G_OBJECT (device), (GSourceFunc) up_device_unifying_refresh);
ret = TRUE;
out:
g_list_free_full (hidraw_list, (GDestroyNotify) g_object_unref);
g_clear_object (&parent);
g_clear_object (&receiver);
g_clear_object (&client);
return ret;
}
/**
* up_device_unifying_init:
**/
static void
up_device_unifying_init (UpDeviceUnifying *unifying)
{
unifying->priv = up_device_unifying_get_instance_private (unifying);
}
/**
* up_device_unifying_finalize:
**/
static void
up_device_unifying_finalize (GObject *object)
{
UpDeviceUnifying *unifying;
g_return_if_fail (object != NULL);
g_return_if_fail (UP_IS_DEVICE_UNIFYING (object));
unifying = UP_DEVICE_UNIFYING (object);
g_return_if_fail (unifying->priv != NULL);
up_daemon_stop_poll (object);
g_clear_object (&unifying->priv->hidpp_device);
G_OBJECT_CLASS (up_device_unifying_parent_class)->finalize (object);
}
/**
* up_device_unifying_class_init:
**/
static void
up_device_unifying_class_init (UpDeviceUnifyingClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
UpDeviceClass *device_class = UP_DEVICE_CLASS (klass);
object_class->finalize = up_device_unifying_finalize;
device_class->coldplug = up_device_unifying_coldplug;
device_class->refresh = up_device_unifying_refresh;
}
/**
* up_device_unifying_new:
**/
UpDeviceUnifying *
up_device_unifying_new (void)
{
return g_object_new (UP_TYPE_DEVICE_UNIFYING, NULL);
}

View file

@ -1,55 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2012 Julien Danjou <julien@danjou.info>
*
* 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
*
*/
#ifndef __UP_DEVICE_UNIFYING_H__
#define __UP_DEVICE_UNIFYING_H__
#include <glib-object.h>
#include "up-device.h"
G_BEGIN_DECLS
#define UP_TYPE_DEVICE_UNIFYING (up_device_unifying_get_type ())
#define UP_DEVICE_UNIFYING(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), UP_TYPE_DEVICE_UNIFYING, UpDeviceUnifying))
#define UP_DEVICE_UNIFYING_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), UP_TYPE_DEVICE_UNIFYING, UpDeviceUnifyingClass))
#define UP_IS_DEVICE_UNIFYING(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), UP_TYPE_DEVICE_UNIFYING))
#define UP_IS_DEVICE_UNIFYING_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), UP_TYPE_DEVICE_UNIFYING))
#define UP_DEVICE_UNIFYING_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), UP_TYPE_DEVICE_UNIFYING, UpDeviceUnifyingClass))
typedef struct UpDeviceUnifyingPrivate UpDeviceUnifyingPrivate;
typedef struct
{
UpDevice parent;
UpDeviceUnifyingPrivate *priv;
} UpDeviceUnifying;
typedef struct
{
UpDeviceClass parent_class;
} UpDeviceUnifyingClass;
GType up_device_unifying_get_type (void);
UpDeviceUnifying *up_device_unifying_new (void);
G_END_DECLS
#endif /* __UP_DEVICE_UNIFYING_H__ */