summaryrefslogtreecommitdiff
path: root/hald-addon-generic-backlight.c
diff options
context:
space:
mode:
Diffstat (limited to 'hald-addon-generic-backlight.c')
-rw-r--r--hald-addon-generic-backlight.c241
1 files changed, 241 insertions, 0 deletions
diff --git a/hald-addon-generic-backlight.c b/hald-addon-generic-backlight.c
new file mode 100644
index 0000000..537ab69
--- /dev/null
+++ b/hald-addon-generic-backlight.c
@@ -0,0 +1,241 @@
1/***************************************************************************
2 *
3 * addon-generic-kbd-backlight.c:
4 * Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
5 *
6 * Based on addon-generic-backlight.c:
7 * Copyright (C) 2008 Danny Kukawka <danny.kukawka@web.de>
8 *
9 * Licensed under the Academic Free License version 2.1
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 **************************************************************************/
26
27#include <string.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <fcntl.h>
31#include <unistd.h>
32#include <stdio.h>
33#include <stdlib.h>
34
35#include "glib-abi.h"
36#include "dbus-abi.h"
37#include "hal-abi.h"
38
39#define HAL_PROPERTY "org.freedesktop.Hal.Device.KeyboardBacklight"
40
41static const char prop_name[] = HAL_PROPERTY;
42static const char prop_invalid[] = HAL_PROPERTY ".Invalid";
43static const char prop_set[] = "SetBrightness";
44static const char prop_get[] = "GetBrightness";
45
46static struct GMainLoop *main_loop;
47static struct LibHalContext *halctx;
48static struct DBusConnection *conn;
49
50static char sysfs_path[512];
51static int levels;
52
53/**
54 * Get keyboard backlight level
55 *
56 * Tries to read from the specified sysfs device, and if successful,
57 * updates the internal keyboard backlight state. Warns if the device
58 * cannot be opened or be read from. Always returns the last succesful
59 * read.
60 */
61static int get_kbd_backlight()
62{
63 static int level;
64 int fd;
65 char buf[64];
66
67 fd = open(sysfs_path, O_RDONLY);
68 if (fd < 0) {
69 HAL_WARNING(("Could not open '%s'", sysfs_path));
70 return level;
71 }
72
73 memset(buf, 0, sizeof(buf));
74 if (read(fd, buf, sizeof(buf)) < 0)
75 HAL_WARNING(("Could not read from '%s'", sysfs_path));
76 else
77 level = atoi(buf);
78
79 close(fd);
80 return level;
81}
82
83/**
84 * Set keyboard backlight level
85 *
86 * Warns if the device cannot be opened or be written to.
87 * Returns bytes written on success, negative value on failure.
88 */
89static int set_kbd_backlight(int level)
90{
91 int fd, ret;
92 char buf[64];
93
94 sprintf(buf, "%d", level);
95
96 fd = open(sysfs_path, O_WRONLY);
97 if (fd < 0) {
98 HAL_WARNING(("Could not open '%s'", sysfs_path));
99 return -1;
100 }
101
102 ret = write(fd, buf, strlen(buf));
103 if (ret < 0)
104 HAL_WARNING(("Could not write '%s' to '%s'", buf, sysfs_path));
105
106 close(fd);
107 return ret;
108}
109
110/* DBus set keyboard backlight level */
111static struct DBusMessage *dbus_get_kbd_backlight(struct DBusMessage *msg)
112{
113 struct DBusError err;
114 struct DBusMessage *reply;
115 int level;
116
117 dbus_error_init(&err);
118 if (!dbus_message_get_args(msg, &err, DBUS_TYPE_INVALID))
119 return dbus_message_new_error(msg, prop_invalid,
120 "Invalid message");
121
122 level = get_kbd_backlight();
123
124 reply = dbus_message_new_method_return(msg);
125 if (reply)
126 dbus_message_append_args(reply, DBUS_TYPE_INT32, &level,
127 DBUS_TYPE_INVALID);
128
129 return reply;
130}
131
132/* DBus set keyboard backlight level */
133static struct DBusMessage *dbus_set_kbd_backlight(struct DBusMessage *msg)
134{
135 struct DBusError err;
136 int level;
137
138 dbus_error_init(&err);
139 if (!dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &level,
140 DBUS_TYPE_INVALID))
141 return dbus_message_new_error(msg, prop_invalid,
142 "Brightness level argument missing");
143
144 if (level < 0 || level > levels - 1)
145 return dbus_message_new_error(msg, prop_invalid,
146 "Brightness level is invalid");
147
148 set_kbd_backlight(level);
149
150 return dbus_message_new_method_return(msg);
151}
152
153/* DBus filter function */
154static DBusHandlerResult filter_function(struct DBusConnection *connection,
155 struct DBusMessage *message,
156 void *userdata)
157{
158 struct DBusMessage *reply = NULL;
159
160 if (dbus_message_is_method_call(message, prop_name, prop_get))
161 reply = dbus_get_kbd_backlight(message);
162 else if (dbus_message_is_method_call(message, prop_name, prop_set))
163 reply = dbus_set_kbd_backlight(message);
164
165 if (reply) {
166 dbus_connection_send(connection, reply, NULL);
167 dbus_message_unref(reply);
168 }
169
170 return DBUS_HANDLER_RESULT_HANDLED;
171}
172
173int main(int argc, char *argv[])
174{
175 struct DBusError err;
176 struct stat fs;
177
178 char *udi = getenv("UDI");
179 char *path = getenv("HAL_PROP_LINUX_SYSFS_PATH");
180 char *level_str = getenv("HAL_PROP_KEYBOARD_BACKLIGHT_NUM_LEVELS");
181
182 setup_logger();
183
184 if (udi == NULL) {
185 HAL_ERROR(("No device specified"));
186 return -2;
187 }
188 if (path == NULL) {
189 HAL_ERROR(("No sysfs path specified"));
190 return -2;
191 }
192 if (level_str == NULL) {
193 HAL_ERROR(("No keyboard_backlight.num_levels defined"));
194 return -2;
195 }
196
197 levels = atoi(level_str);
198 snprintf(sysfs_path, sizeof(sysfs_path), "%s/brightness", path);
199
200 HAL_DEBUG(("udi='%s', path='%s', levels='%d'", udi, path, levels));
201
202 if (stat(sysfs_path, &fs)) {
203 HAL_ERROR(("The sysfs property path does not exist"));
204 return -2;
205 }
206
207 dbus_error_init(&err);
208 halctx = libhal_ctx_init_direct(&err);
209
210 if (halctx == NULL) {
211 HAL_ERROR(("Cannot connect to hald"));
212 return -3;
213 }
214
215 conn = libhal_ctx_get_dbus_connection(halctx);
216 dbus_connection_setup_with_g_main(conn, NULL);
217
218 dbus_connection_add_filter(conn, filter_function, NULL, NULL);
219
220 if (!libhal_device_claim_interface(halctx, udi, prop_name,
221 " <method name=\"GetBrightness\">\n"
222 " <arg name=\"brightness_value\" direction=\"out\" type=\"i\"/>\n"
223 " </method>\n"
224 " <method name=\"SetBrightness\">\n"
225 " <arg name=\"brightness_value\" direction=\"in\" type=\"i\"/>\n"
226 " </method>\n",
227 &err)) {
228 HAL_ERROR(("Cannot claim interface '" HAL_PROPERTY "'"));
229 return -4;
230 }
231
232 dbus_error_init(&err);
233 if (!libhal_device_addon_is_ready(halctx, udi, &err))
234 return -4;
235
236 main_loop = g_main_loop_new(NULL, FALSE);
237 g_main_loop_run(main_loop);
238
239 return 0;
240}
241