~ubuntu-branches/ubuntu/trusty/sensors-applet/trusty

« back to all changes in this revision

Viewing changes to plugins/devkit-disks/devkit-plugin.c

  • Committer: Bazaar Package Importer
  • Author(s): Nanley Chery
  • Date: 2010-05-22 22:25:13 UTC
  • mfrom: (1.1.13 upstream) (3.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20100522222513-1cg5k0n5hv337u4u
Tags: 2.2.5-4ubuntu1
* Merge from debian testing (LP: #380669, #249955). Remaining changes:
  - debian/rules:
    + Enable nvidia compilation flag.
  - debian/control:
    + Build-depend on nvidia-settings and update description accordingly.

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) 2009 Pramod Dematagoda <pmd.lotr.gandalf@gmail.com>
 
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 */
 
19
 
 
20
#ifdef HAVE_CONFIG_H
 
21
#include "config.h"
 
22
#endif /* HAVE_CONFIG_H */
 
23
 
 
24
#include <stdio.h>
 
25
#include <atasmart.h>
 
26
#include <glib.h>
 
27
#include <dbus/dbus-glib.h>
 
28
#include "devkit-plugin.h"
 
29
 
 
30
#define DEVKIT_BUS_NAME              "org.freedesktop.DeviceKit.Disks"
 
31
#define DEVKIT_DEVICE_INTERFACE_NAME "org.freedesktop.DeviceKit.Disks.Device"
 
32
#define DEVKIT_INTERFACE_NAME        "org.freedesktop.DeviceKit.Disks"
 
33
#define DEVKIT_PROPERTIES_INTERFACE  "org.freedesktop.DBus.Properties"
 
34
#define DEVKIT_OBJECT_PATH           "/org/freedesktop/DeviceKit/Disks"
 
35
 
 
36
 
 
37
/*
 
38
 * Info about a single sensor
 
39
 */
 
40
typedef struct _DevInfo{
 
41
        gchar *path;
 
42
        gboolean changed;
 
43
        gdouble temp;
 
44
        DBusGProxy *sensor_proxy;
 
45
} DevInfo;
 
46
 
 
47
const gchar *plugin_name = "devkit-disks";
 
48
 
 
49
GHashTable *devices = NULL;
 
50
 
 
51
/* This is a global variable for convenience */
 
52
DBusGConnection *connection;
 
53
 
 
54
 
 
55
/* This is the handler for the Changed() signal emitted by DeviceKit-Disks. */
 
56
static void devkit_changed_signal_cb(DBusGProxy *sensor_proxy) {
 
57
        const gchar *path = dbus_g_proxy_get_path(sensor_proxy);
 
58
        DevInfo *info;
 
59
 
 
60
        info = g_hash_table_lookup(devices, path);
 
61
        if (info)
 
62
        {
 
63
                info->changed = TRUE;
 
64
        }
 
65
}
 
66
 
 
67
static void devkit_plugin_get_sensors(GList **sensors) {
 
68
        DBusGProxy *proxy, *sensor_proxy;
 
69
        GError *error = NULL;
 
70
        GPtrArray *paths;
 
71
        guint i;
 
72
        DevInfo *info;
 
73
 
 
74
        g_type_init();
 
75
 
 
76
        /* This connection will be used for everything, including the obtaining
 
77
         * of sensor data
 
78
         */
 
79
        connection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
 
80
        if (connection == NULL)
 
81
        {
 
82
                g_printerr("Failed to open connection to DBUS: %s",
 
83
                           error->message);
 
84
                g_error_free(error);
 
85
                return;
 
86
        }
 
87
 
 
88
        /* This is the proxy which is only used once during the enumeration of
 
89
         * the device object paths
 
90
         */
 
91
        proxy = dbus_g_proxy_new_for_name(connection,
 
92
                                          DEVKIT_BUS_NAME,
 
93
                                          DEVKIT_OBJECT_PATH,
 
94
                                          DEVKIT_INTERFACE_NAME);
 
95
 
 
96
        /* The object paths of the disks are enumerated and placed in an array
 
97
         * of object paths
 
98
         */
 
99
        if (!dbus_g_proxy_call(proxy, "EnumerateDevices", &error,
 
100
                               G_TYPE_INVALID,
 
101
                               dbus_g_type_get_collection("GPtrArray",
 
102
                                                          DBUS_TYPE_G_OBJECT_PATH),
 
103
                               &paths,
 
104
                               G_TYPE_INVALID))
 
105
        {
 
106
                g_printerr("Failed to enumerate disk devices: %s",
 
107
                           error->message);
 
108
                g_error_free(error);
 
109
                g_object_unref(proxy);
 
110
                dbus_g_connection_unref (connection);
 
111
                return;
 
112
        }
 
113
 
 
114
        for (i = 0; i < paths->len; i++) {
 
115
                /* This proxy is used to get the required data in order to build
 
116
                 * up the list of sensors
 
117
                 */
 
118
                GValue model = {0, }, id = {0, }, smart_time = {0, };
 
119
                gchar *path = (gchar *)g_ptr_array_index(paths, i);
 
120
 
 
121
                sensor_proxy = dbus_g_proxy_new_for_name(connection,
 
122
                                                         DEVKIT_BUS_NAME,
 
123
                                                         path,
 
124
                                                         DEVKIT_PROPERTIES_INTERFACE);
 
125
 
 
126
                if (dbus_g_proxy_call(sensor_proxy, "Get", &error,
 
127
                                      G_TYPE_STRING,
 
128
                                      DEVKIT_BUS_NAME,
 
129
                                      G_TYPE_STRING,
 
130
                                      "DriveAtaSmartTimeCollected",
 
131
                                      G_TYPE_INVALID,
 
132
                                      G_TYPE_VALUE, &smart_time, G_TYPE_INVALID)) {
 
133
                        gchar *id_str, *model_str;
 
134
                        /* The DriveAtaSmartTimeCollected property gives the time since
 
135
                         * the Epoch when the last batch of SMART data was collected
 
136
                         * if it is 0 then there is no temperature to get from it anyway
 
137
                         */
 
138
                        if (!g_value_get_uint64(&smart_time)) {
 
139
                                g_object_unref(sensor_proxy);
 
140
                                g_free (path);
 
141
                                continue;
 
142
                        }
 
143
 
 
144
                        dbus_g_proxy_call(sensor_proxy, "Get", NULL,
 
145
                                          G_TYPE_STRING, DEVKIT_BUS_NAME,
 
146
                                          G_TYPE_STRING, "DriveModel",
 
147
                                          G_TYPE_INVALID,
 
148
                                          G_TYPE_VALUE, &model,
 
149
                                          G_TYPE_INVALID);
 
150
 
 
151
                        dbus_g_proxy_call(sensor_proxy, "Get", NULL,
 
152
                                          G_TYPE_STRING, DEVKIT_BUS_NAME,
 
153
                                          G_TYPE_STRING, "DeviceFile",
 
154
                                          G_TYPE_INVALID,
 
155
                                          G_TYPE_VALUE, &id,
 
156
                                          G_TYPE_INVALID);
 
157
 
 
158
                        g_object_unref(sensor_proxy);
 
159
 
 
160
                        sensor_proxy = dbus_g_proxy_new_for_name(connection,
 
161
                                                                 DEVKIT_BUS_NAME,
 
162
                                                                 path,
 
163
                                                                 DEVKIT_DEVICE_INTERFACE_NAME);
 
164
 
 
165
                        /* Use the Changed() signal emitted from DeviceKit to
 
166
                         * get the temperature without always polling
 
167
                         */
 
168
                        dbus_g_proxy_add_signal(sensor_proxy, "Changed",
 
169
                                                G_TYPE_INVALID);
 
170
 
 
171
                        dbus_g_proxy_connect_signal(sensor_proxy, "Changed",
 
172
                                                    G_CALLBACK(devkit_changed_signal_cb),
 
173
                                                    path, NULL);
 
174
 
 
175
                        info = g_malloc(sizeof(DevInfo));
 
176
                        if (devices == NULL)
 
177
                        {
 
178
                                devices = g_hash_table_new(g_str_hash,
 
179
                                                           g_str_equal);
 
180
                        }
 
181
                        info->path = g_strdup(path);
 
182
                        info->sensor_proxy = sensor_proxy;
 
183
                        /* Set the device status changed as TRUE because we need
 
184
                         * to get the initial temperature reading
 
185
                         */
 
186
                        info->changed = TRUE;
 
187
                        g_hash_table_insert(devices, info->path, info);
 
188
 
 
189
                        /* Write the sensor data */
 
190
                        id_str = g_value_get_string(&id);
 
191
                        model_str = g_value_get_string(&model);
 
192
                        sensors_applet_plugin_add_sensor(sensors,
 
193
                                                         path,
 
194
                                                         id_str,
 
195
                                                         model_str,
 
196
                                                         TEMP_SENSOR,
 
197
                                                         FALSE,
 
198
                                                         HDD_ICON,
 
199
                                                         DEFAULT_GRAPH_COLOR);
 
200
                        g_free(id_str);
 
201
                        g_free(model_str);
 
202
                } else {
 
203
                        g_printerr ("Cannot obtain data for device: %s\n"
 
204
                                    "Error: %s\n",
 
205
                                    path,
 
206
                                    error->message);
 
207
                        g_error_free (error);
 
208
                        error = NULL;
 
209
                        g_object_unref(sensor_proxy);
 
210
                }
 
211
                g_free(path);
 
212
        }
 
213
        g_ptr_array_free(paths, TRUE);
 
214
        g_object_unref(proxy);
 
215
        if (devices == NULL)
 
216
                dbus_g_connection_unref (connection);
 
217
}
 
218
 
 
219
static gdouble devkit_plugin_get_sensor_value(const gchar *path,
 
220
                                              const gchar *id,
 
221
                                              SensorType type,
 
222
                                              GError **error) {
 
223
        GValue smart_blob_val = { 0, };
 
224
        GArray *smart_blob;
 
225
        gdouble temperature;
 
226
        guint64 temperature_placer;
 
227
        DBusGProxy *sensor_proxy;
 
228
        guint count;
 
229
        DevInfo *info;
 
230
        SkDisk *sk_disk;
 
231
 
 
232
        info = (DevInfo *)g_hash_table_lookup(devices, path);
 
233
        if (info == NULL)
 
234
        {
 
235
                g_set_error(error, SENSORS_APPLET_PLUGIN_ERROR, 0,
 
236
                            "Error finding disk with path %s", path);
 
237
                return 0.0;
 
238
        }
 
239
 
 
240
        /* If the device has changed, we find the new temperature and return
 
241
         * it
 
242
         */
 
243
        if (info->changed)
 
244
        {
 
245
                sensor_proxy = dbus_g_proxy_new_for_name(connection,
 
246
                                                         DEVKIT_BUS_NAME,
 
247
                                                         path,
 
248
                                                         DEVKIT_PROPERTIES_INTERFACE);
 
249
 
 
250
                if (dbus_g_proxy_call(sensor_proxy, "Get", error,
 
251
                                      G_TYPE_STRING, DEVKIT_BUS_NAME,
 
252
                                      G_TYPE_STRING, "DriveAtaSmartBlob", G_TYPE_INVALID,
 
253
                                      G_TYPE_VALUE, &smart_blob_val,
 
254
                                      G_TYPE_INVALID))
 
255
                {
 
256
                        smart_blob = g_value_get_boxed(&smart_blob_val);
 
257
 
 
258
                        sk_disk_open(NULL, &sk_disk);
 
259
                        sk_disk_set_blob (sk_disk, smart_blob->data, smart_blob->len);
 
260
                        /* Note: A gdouble cannot be passed in through a cast as it is likely that the
 
261
                         * temperature is placed in it purely through memory functions, hence a guint64
 
262
                         * is passed and the number is then placed in a gdouble manually 
 
263
                         */
 
264
                        sk_disk_smart_get_temperature (sk_disk, &temperature_placer);
 
265
                        temperature = temperature_placer;
 
266
 
 
267
                        /* Temperature is in mK, so convert it to K first */
 
268
                        temperature /= 1000;
 
269
                        info->temp = temperature - 273.15;
 
270
                        info->changed = FALSE;
 
271
 
 
272
                        g_free (sk_disk);
 
273
                        g_array_free(smart_blob, TRUE);
 
274
                }
 
275
                g_object_unref(sensor_proxy);
 
276
        }
 
277
        return info->temp;
 
278
}
 
279
 
 
280
static GList *devkit_plugin_init(void) {
 
281
        GList *sensors = NULL;
 
282
 
 
283
        devkit_plugin_get_sensors(&sensors);
 
284
 
 
285
        return sensors;
 
286
}
 
287
 
 
288
const gchar *sensors_applet_plugin_name(void)
 
289
{
 
290
        return plugin_name;
 
291
}
 
292
 
 
293
GList *sensors_applet_plugin_init(void)
 
294
{
 
295
        return devkit_plugin_init();
 
296
}
 
297
 
 
298
gdouble sensors_applet_plugin_get_sensor_value(const gchar *path,
 
299
                                               const gchar *id,
 
300
                                               SensorType type,
 
301
                                               GError **error) {
 
302
        return devkit_plugin_get_sensor_value(path, id, type, error);
 
303
}