~ubuntu-branches/ubuntu/wily/upower/wily

« back to all changes in this revision

Viewing changes to src/linux/up-device-unifying.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2013-03-19 19:19:51 UTC
  • mfrom: (17.1.4 experimental)
  • Revision ID: package-import@ubuntu.com-20130319191951-2lmdpe40kitm2zbx
Tags: 0.9.20-1
* New upstream release.
* Bump libpolkit-gobject-1-dev build dependency as per upstream
  configure.ac.
* Build with --enable-deprecated, we are not ready yet to drop
  suspend/hibernate functionality.
* Bump Standards-Version to 3.9.4. No changes necessary.
* Add "build" autopkgtest to compile/link/run a simple program against
  libupower-glib.
* Drop unnecessary "needs-root" restriction from upstream-system
  autopkgtest.
* Add no_deprecation_define.patch: Do not require applications to define
  UPOWER_ENABLE_DEPRECATED to access suspend/resume functionality. We are
  not ready to do that yet in Debian.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
 
2
 *
 
3
 * Copyright (C) 2012 Julien Danjou <julien@danjou.info>
 
4
 *
 
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.
 
9
 *
 
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.
 
14
 *
 
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
 
18
 *
 
19
 */
 
20
 
 
21
#ifdef HAVE_CONFIG_H
 
22
#  include "config.h"
 
23
#endif
 
24
 
 
25
#include <glib-object.h>
 
26
#include <gudev/gudev.h>
 
27
 
 
28
#include "hidpp-device.h"
 
29
 
 
30
#include "up-device-unifying.h"
 
31
#include "up-types.h"
 
32
 
 
33
#define UP_DEVICE_UNIFYING_REFRESH_TIMEOUT                      60 /* seconds */
 
34
 
 
35
struct UpDeviceUnifyingPrivate
 
36
{
 
37
        guint                    poll_timer_id;
 
38
        HidppDevice             *hidpp_device;
 
39
};
 
40
 
 
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))
 
43
 
 
44
/**
 
45
 * up_device_unifying_refresh:
 
46
 *
 
47
 * Return %TRUE on success, %FALSE if we failed to refresh or no data
 
48
 **/
 
49
static gboolean
 
50
up_device_unifying_refresh (UpDevice *device)
 
51
{
 
52
        gboolean ret;
 
53
        GError *error = NULL;
 
54
        GTimeVal timeval;
 
55
        UpDeviceState state = UP_DEVICE_STATE_UNKNOWN;
 
56
        UpDeviceUnifying *unifying = UP_DEVICE_UNIFYING (device);
 
57
        UpDeviceUnifyingPrivate *priv = unifying->priv;
 
58
 
 
59
        /* refresh just the battery stats */
 
60
        ret = hidpp_device_refresh (priv->hidpp_device,
 
61
                                    HIDPP_REFRESH_FLAGS_BATTERY,
 
62
                                    &error);
 
63
        if (!ret) {
 
64
                g_warning ("failed to coldplug unifying device: %s",
 
65
                           error->message);
 
66
                g_error_free (error);
 
67
                goto out;
 
68
        }
 
69
        switch (hidpp_device_get_batt_status (priv->hidpp_device)) {
 
70
        case HIDPP_DEVICE_BATT_STATUS_CHARGING:
 
71
                state = UP_DEVICE_STATE_CHARGING;
 
72
                break;
 
73
        case HIDPP_DEVICE_BATT_STATUS_DISCHARGING:
 
74
                state = UP_DEVICE_STATE_DISCHARGING;
 
75
                break;
 
76
        case HIDPP_DEVICE_BATT_STATUS_CHARGED:
 
77
                state = UP_DEVICE_STATE_FULLY_CHARGED;
 
78
                break;
 
79
        default:
 
80
                break;
 
81
        }
 
82
        g_get_current_time (&timeval);
 
83
        g_object_set (device,
 
84
                      "is-present", hidpp_device_get_version (priv->hidpp_device) > 0,
 
85
                      "percentage", (gdouble) hidpp_device_get_batt_percentage (priv->hidpp_device),
 
86
                      "state", state,
 
87
                      "update-time", (guint64) timeval.tv_sec,
 
88
                      NULL);
 
89
out:
 
90
        return TRUE;
 
91
}
 
92
 
 
93
static UpDeviceKind
 
94
up_device_unifying_get_device_kind (UpDeviceUnifying *unifying)
 
95
{
 
96
        UpDeviceKind kind;
 
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;
 
102
                break;
 
103
        case HIDPP_DEVICE_KIND_KEYBOARD:
 
104
                kind = UP_DEVICE_KIND_KEYBOARD;
 
105
                break;
 
106
        case HIDPP_DEVICE_KIND_TABLET:
 
107
                kind = UP_DEVICE_KIND_TABLET;
 
108
                break;
 
109
        default:
 
110
                kind = UP_DEVICE_KIND_UNKNOWN;
 
111
        }
 
112
        return kind;
 
113
}
 
114
 
 
115
/**
 
116
 * up_device_unifying_coldplug:
 
117
 *
 
118
 * Return %TRUE on success, %FALSE if we failed to get data and should be removed
 
119
 **/
 
120
static gboolean
 
121
up_device_unifying_coldplug (UpDevice *device)
 
122
{
 
123
        const gchar *bus_address;
 
124
        const gchar *device_file;
 
125
        const gchar *type;
 
126
        gboolean ret = FALSE;
 
127
        gchar *endptr = NULL;
 
128
        gchar *tmp;
 
129
        GError *error = NULL;
 
130
        GUdevDevice *native;
 
131
        GUdevDevice *parent = NULL;
 
132
        GUdevDevice *receiver = NULL;
 
133
        UpDeviceUnifying *unifying = UP_DEVICE_UNIFYING (device);
 
134
        GUdevClient *client = NULL;
 
135
        GList *hidraw_list = NULL;
 
136
        GList *l;
 
137
 
 
138
        native = G_UDEV_DEVICE (up_device_get_native (device));
 
139
 
 
140
        /* check if we have the right device */
 
141
        type = g_udev_device_get_property (native, "UPOWER_BATTERY_TYPE");
 
142
        if (type == NULL)
 
143
                goto out;
 
144
        if (g_strcmp0 (type, "unifying") != 0)
 
145
                goto out;
 
146
 
 
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, ":");
 
151
        if (tmp == NULL) {
 
152
                g_debug ("Could not get physical device index");
 
153
                goto out;
 
154
        }
 
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);
 
159
                goto out;
 
160
        }
 
161
 
 
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);
 
170
                        break;
 
171
                }
 
172
        }
 
173
        if (receiver == NULL) {
 
174
                g_debug ("Unable to find an hidraw device for Unifying receiver");
 
175
                return FALSE;
 
176
        }
 
177
 
 
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");
 
182
                goto out;
 
183
        }
 
184
        g_debug ("Using Unifying receiver hidraw device file: %s", device_file);
 
185
        hidpp_device_set_hidraw_device (unifying->priv->hidpp_device,
 
186
                                        device_file);
 
187
 
 
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,
 
193
                                    &error);
 
194
        if (!ret) {
 
195
                g_warning ("failed to coldplug unifying device: %s",
 
196
                           error->message);
 
197
                g_error_free (error);
 
198
                goto out;
 
199
        }
 
200
 
 
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),
 
206
                      "has-history", TRUE,
 
207
                      "is-rechargeable", TRUE,
 
208
                      "power-supply", FALSE,
 
209
                      NULL);
 
210
 
 
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,
 
215
                                                               device);
 
216
        ret = TRUE;
 
217
out:
 
218
        g_list_foreach (hidraw_list, (GFunc) g_object_unref, NULL);
 
219
        g_list_free (hidraw_list);
 
220
        if (parent != NULL)
 
221
                g_object_unref (parent);
 
222
        if (receiver != NULL)
 
223
                g_object_unref (receiver);
 
224
        if (client != NULL)
 
225
                g_object_unref (client);
 
226
        return ret;
 
227
}
 
228
 
 
229
/**
 
230
 * up_device_unifying_init:
 
231
 **/
 
232
static void
 
233
up_device_unifying_init (UpDeviceUnifying *unifying)
 
234
{
 
235
        unifying->priv = UP_DEVICE_UNIFYING_GET_PRIVATE (unifying);
 
236
        unifying->priv->poll_timer_id = 0;
 
237
}
 
238
 
 
239
/**
 
240
 * up_device_unifying_finalize:
 
241
 **/
 
242
static void
 
243
up_device_unifying_finalize (GObject *object)
 
244
{
 
245
        UpDeviceUnifying *unifying;
 
246
 
 
247
        g_return_if_fail (object != NULL);
 
248
        g_return_if_fail (UP_IS_DEVICE_UNIFYING (object));
 
249
 
 
250
        unifying = UP_DEVICE_UNIFYING (object);
 
251
        g_return_if_fail (unifying->priv != NULL);
 
252
 
 
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);
 
257
 
 
258
        G_OBJECT_CLASS (up_device_unifying_parent_class)->finalize (object);
 
259
}
 
260
 
 
261
/**
 
262
 * up_device_unifying_class_init:
 
263
 **/
 
264
static void
 
265
up_device_unifying_class_init (UpDeviceUnifyingClass *klass)
 
266
{
 
267
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
268
        UpDeviceClass *device_class = UP_DEVICE_CLASS (klass);
 
269
 
 
270
        object_class->finalize = up_device_unifying_finalize;
 
271
        device_class->coldplug = up_device_unifying_coldplug;
 
272
        device_class->refresh = up_device_unifying_refresh;
 
273
 
 
274
        g_type_class_add_private (klass, sizeof (UpDeviceUnifyingPrivate));
 
275
}
 
276
 
 
277
/**
 
278
 * up_device_unifying_new:
 
279
 **/
 
280
UpDeviceUnifying *
 
281
up_device_unifying_new (void)
 
282
{
 
283
        return g_object_new (UP_TYPE_DEVICE_UNIFYING, NULL);
 
284
}