1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
3
* Copyright (C) 2009 Pramod Dematagoda <pmd.lotr.gandalf@gmail.com>
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
#endif /* HAVE_CONFIG_H */
27
#include <dbus/dbus-glib.h>
28
#include "devkit-plugin.h"
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"
38
* Info about a single sensor
40
typedef struct _DevInfo{
44
DBusGProxy *sensor_proxy;
47
const gchar *plugin_name = "devkit-disks";
49
GHashTable *devices = NULL;
51
/* This is a global variable for convenience */
52
DBusGConnection *connection;
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);
60
info = g_hash_table_lookup(devices, path);
67
static void devkit_plugin_get_sensors(GList **sensors) {
68
DBusGProxy *proxy, *sensor_proxy;
76
/* This connection will be used for everything, including the obtaining
79
connection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
80
if (connection == NULL)
82
g_printerr("Failed to open connection to DBUS: %s",
88
/* This is the proxy which is only used once during the enumeration of
89
* the device object paths
91
proxy = dbus_g_proxy_new_for_name(connection,
94
DEVKIT_INTERFACE_NAME);
96
/* The object paths of the disks are enumerated and placed in an array
99
if (!dbus_g_proxy_call(proxy, "EnumerateDevices", &error,
101
dbus_g_type_get_collection("GPtrArray",
102
DBUS_TYPE_G_OBJECT_PATH),
106
g_printerr("Failed to enumerate disk devices: %s",
109
g_object_unref(proxy);
110
dbus_g_connection_unref (connection);
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
118
GValue model = {0, }, id = {0, }, smart_time = {0, };
119
gchar *path = (gchar *)g_ptr_array_index(paths, i);
121
sensor_proxy = dbus_g_proxy_new_for_name(connection,
124
DEVKIT_PROPERTIES_INTERFACE);
126
if (dbus_g_proxy_call(sensor_proxy, "Get", &error,
130
"DriveAtaSmartTimeCollected",
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
138
if (!g_value_get_uint64(&smart_time)) {
139
g_object_unref(sensor_proxy);
144
dbus_g_proxy_call(sensor_proxy, "Get", NULL,
145
G_TYPE_STRING, DEVKIT_BUS_NAME,
146
G_TYPE_STRING, "DriveModel",
148
G_TYPE_VALUE, &model,
151
dbus_g_proxy_call(sensor_proxy, "Get", NULL,
152
G_TYPE_STRING, DEVKIT_BUS_NAME,
153
G_TYPE_STRING, "DeviceFile",
158
g_object_unref(sensor_proxy);
160
sensor_proxy = dbus_g_proxy_new_for_name(connection,
163
DEVKIT_DEVICE_INTERFACE_NAME);
165
/* Use the Changed() signal emitted from DeviceKit to
166
* get the temperature without always polling
168
dbus_g_proxy_add_signal(sensor_proxy, "Changed",
171
dbus_g_proxy_connect_signal(sensor_proxy, "Changed",
172
G_CALLBACK(devkit_changed_signal_cb),
175
info = g_malloc(sizeof(DevInfo));
178
devices = g_hash_table_new(g_str_hash,
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
186
info->changed = TRUE;
187
g_hash_table_insert(devices, info->path, info);
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,
199
DEFAULT_GRAPH_COLOR);
203
g_printerr ("Cannot obtain data for device: %s\n"
207
g_error_free (error);
209
g_object_unref(sensor_proxy);
213
g_ptr_array_free(paths, TRUE);
214
g_object_unref(proxy);
216
dbus_g_connection_unref (connection);
219
static gdouble devkit_plugin_get_sensor_value(const gchar *path,
223
GValue smart_blob_val = { 0, };
226
guint64 temperature_placer;
227
DBusGProxy *sensor_proxy;
232
info = (DevInfo *)g_hash_table_lookup(devices, path);
235
g_set_error(error, SENSORS_APPLET_PLUGIN_ERROR, 0,
236
"Error finding disk with path %s", path);
240
/* If the device has changed, we find the new temperature and return
245
sensor_proxy = dbus_g_proxy_new_for_name(connection,
248
DEVKIT_PROPERTIES_INTERFACE);
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,
256
smart_blob = g_value_get_boxed(&smart_blob_val);
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
264
sk_disk_smart_get_temperature (sk_disk, &temperature_placer);
265
temperature = temperature_placer;
267
/* Temperature is in mK, so convert it to K first */
269
info->temp = temperature - 273.15;
270
info->changed = FALSE;
273
g_array_free(smart_blob, TRUE);
275
g_object_unref(sensor_proxy);
280
static GList *devkit_plugin_init(void) {
281
GList *sensors = NULL;
283
devkit_plugin_get_sensors(&sensors);
288
const gchar *sensors_applet_plugin_name(void)
293
GList *sensors_applet_plugin_init(void)
295
return devkit_plugin_init();
298
gdouble sensors_applet_plugin_get_sensor_value(const gchar *path,
302
return devkit_plugin_get_sensor_value(path, id, type, error);