1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
3
* Copyright (C) 2012 Julien Danjou <julien@danjou.info>
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25
#include <glib-object.h>
26
#include <gudev/gudev.h>
28
#include "hidpp-device.h"
30
#include "up-device-unifying.h"
33
#define UP_DEVICE_UNIFYING_REFRESH_TIMEOUT 60 /* seconds */
35
struct UpDeviceUnifyingPrivate
38
HidppDevice *hidpp_device;
41
G_DEFINE_TYPE (UpDeviceUnifying, up_device_unifying, UP_TYPE_DEVICE)
42
#define UP_DEVICE_UNIFYING_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), UP_TYPE_DEVICE_UNIFYING, UpDeviceUnifyingPrivate))
45
* up_device_unifying_refresh:
47
* Return %TRUE on success, %FALSE if we failed to refresh or no data
50
up_device_unifying_refresh (UpDevice *device)
55
UpDeviceState state = UP_DEVICE_STATE_UNKNOWN;
56
UpDeviceUnifying *unifying = UP_DEVICE_UNIFYING (device);
57
UpDeviceUnifyingPrivate *priv = unifying->priv;
59
/* refresh just the battery stats */
60
ret = hidpp_device_refresh (priv->hidpp_device,
61
HIDPP_REFRESH_FLAGS_BATTERY,
64
g_warning ("failed to coldplug unifying device: %s",
69
switch (hidpp_device_get_batt_status (priv->hidpp_device)) {
70
case HIDPP_DEVICE_BATT_STATUS_CHARGING:
71
state = UP_DEVICE_STATE_CHARGING;
73
case HIDPP_DEVICE_BATT_STATUS_DISCHARGING:
74
state = UP_DEVICE_STATE_DISCHARGING;
76
case HIDPP_DEVICE_BATT_STATUS_CHARGED:
77
state = UP_DEVICE_STATE_FULLY_CHARGED;
82
g_get_current_time (&timeval);
84
"is-present", hidpp_device_get_version (priv->hidpp_device) > 0,
85
"percentage", (gdouble) hidpp_device_get_batt_percentage (priv->hidpp_device),
87
"update-time", (guint64) timeval.tv_sec,
94
up_device_unifying_get_device_kind (UpDeviceUnifying *unifying)
97
switch (hidpp_device_get_kind (unifying->priv->hidpp_device)) {
98
case HIDPP_DEVICE_KIND_MOUSE:
99
case HIDPP_DEVICE_KIND_TOUCHPAD:
100
case HIDPP_DEVICE_KIND_TRACKBALL:
101
kind = UP_DEVICE_KIND_MOUSE;
103
case HIDPP_DEVICE_KIND_KEYBOARD:
104
kind = UP_DEVICE_KIND_KEYBOARD;
106
case HIDPP_DEVICE_KIND_TABLET:
107
kind = UP_DEVICE_KIND_TABLET;
110
kind = UP_DEVICE_KIND_UNKNOWN;
116
* up_device_unifying_coldplug:
118
* Return %TRUE on success, %FALSE if we failed to get data and should be removed
121
up_device_unifying_coldplug (UpDevice *device)
123
const gchar *bus_address;
124
const gchar *device_file;
126
gboolean ret = FALSE;
127
gchar *endptr = NULL;
129
GError *error = NULL;
131
GUdevDevice *parent = NULL;
132
GUdevDevice *receiver = NULL;
133
UpDeviceUnifying *unifying = UP_DEVICE_UNIFYING (device);
134
GUdevClient *client = NULL;
135
GList *hidraw_list = NULL;
138
native = G_UDEV_DEVICE (up_device_get_native (device));
140
/* check if we have the right device */
141
type = g_udev_device_get_property (native, "UPOWER_BATTERY_TYPE");
144
if (g_strcmp0 (type, "unifying") != 0)
147
/* get the device index */
148
unifying->priv->hidpp_device = hidpp_device_new ();
149
bus_address = g_udev_device_get_property (native, "HID_PHYS");
150
tmp = g_strrstr (bus_address, ":");
152
g_debug ("Could not get physical device index");
155
hidpp_device_set_index (unifying->priv->hidpp_device,
156
g_ascii_strtoull (tmp + 1, &endptr, 10));
157
if (endptr != NULL && endptr[0] != '\0') {
158
g_debug ("HID_PHYS malformed: '%s'", bus_address);
162
/* find the hidraw device that matches the parent */
163
parent = g_udev_device_get_parent (native);
164
client = g_udev_client_new (NULL);
165
hidraw_list = g_udev_client_query_by_subsystem (client, "hidraw");
166
for (l = hidraw_list; l != NULL; l = l->next) {
167
if (g_strcmp0 (g_udev_device_get_sysfs_path (parent),
168
g_udev_device_get_sysfs_attr (l->data, "device")) == 0) {
169
receiver = g_object_ref (l->data);
173
if (receiver == NULL) {
174
g_debug ("Unable to find an hidraw device for Unifying receiver");
178
/* connect to the receiver */
179
device_file = g_udev_device_get_device_file (receiver);
180
if (device_file == NULL) {
181
g_debug ("Could not get device file for Unifying receiver device");
184
g_debug ("Using Unifying receiver hidraw device file: %s", device_file);
185
hidpp_device_set_hidraw_device (unifying->priv->hidpp_device,
188
/* coldplug initial parameters */
189
ret = hidpp_device_refresh (unifying->priv->hidpp_device,
190
HIDPP_REFRESH_FLAGS_VERSION |
191
HIDPP_REFRESH_FLAGS_KIND |
192
HIDPP_REFRESH_FLAGS_MODEL,
195
g_warning ("failed to coldplug unifying device: %s",
197
g_error_free (error);
201
/* set some default values */
202
g_object_set (device,
203
"vendor", g_udev_device_get_property (native, "ID_VENDOR"),
204
"type", up_device_unifying_get_device_kind (unifying),
205
"model", hidpp_device_get_model (unifying->priv->hidpp_device),
207
"is-rechargeable", TRUE,
208
"power-supply", FALSE,
211
/* set up a poll to send the magic packet */
212
up_device_unifying_refresh (device);
213
unifying->priv->poll_timer_id = g_timeout_add_seconds (UP_DEVICE_UNIFYING_REFRESH_TIMEOUT,
214
(GSourceFunc) up_device_unifying_refresh,
218
g_list_foreach (hidraw_list, (GFunc) g_object_unref, NULL);
219
g_list_free (hidraw_list);
221
g_object_unref (parent);
222
if (receiver != NULL)
223
g_object_unref (receiver);
225
g_object_unref (client);
230
* up_device_unifying_init:
233
up_device_unifying_init (UpDeviceUnifying *unifying)
235
unifying->priv = UP_DEVICE_UNIFYING_GET_PRIVATE (unifying);
236
unifying->priv->poll_timer_id = 0;
240
* up_device_unifying_finalize:
243
up_device_unifying_finalize (GObject *object)
245
UpDeviceUnifying *unifying;
247
g_return_if_fail (object != NULL);
248
g_return_if_fail (UP_IS_DEVICE_UNIFYING (object));
250
unifying = UP_DEVICE_UNIFYING (object);
251
g_return_if_fail (unifying->priv != NULL);
253
if (unifying->priv->poll_timer_id > 0)
254
g_source_remove (unifying->priv->poll_timer_id);
255
if (unifying->priv->hidpp_device != NULL)
256
g_object_unref (unifying->priv->hidpp_device);
258
G_OBJECT_CLASS (up_device_unifying_parent_class)->finalize (object);
262
* up_device_unifying_class_init:
265
up_device_unifying_class_init (UpDeviceUnifyingClass *klass)
267
GObjectClass *object_class = G_OBJECT_CLASS (klass);
268
UpDeviceClass *device_class = UP_DEVICE_CLASS (klass);
270
object_class->finalize = up_device_unifying_finalize;
271
device_class->coldplug = up_device_unifying_coldplug;
272
device_class->refresh = up_device_unifying_refresh;
274
g_type_class_add_private (klass, sizeof (UpDeviceUnifyingPrivate));
278
* up_device_unifying_new:
281
up_device_unifying_new (void)
283
return g_object_new (UP_TYPE_DEVICE_UNIFYING, NULL);