1
/***************************************************************************
4
* addon-keyboard.c : Listen to key events and modify hal device objects
6
* Copyright (C) 2005 David Zeuthen, <david@fubar.dk>
7
* Copyright (C) 2005 Ryan Lortie <desrt@desrt.ca>
8
* Copyright (C) 2006 Matthew Garrett <mjg59@srcf.ucam.org>
10
* This program is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License as published by
12
* the Free Software Foundation; either version 2 of the License, or
13
* (at your option) any later version.
15
* This program is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU General Public License for more details.
20
* You should have received a copy of the GNU General Public License
21
* along with this program; if not, write to the Free Software
22
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24
**************************************************************************/
34
#include <sys/types.h>
35
#include <linux/input.h>
37
#include "libhal/libhal.h"
39
#include "../../logger.h"
40
#include "../../util_helper.h"
43
static int button_state = FALSE;
44
static int button_has_state = FALSE;
46
static char *key_name[KEY_MAX + 1] = {
47
[0 ... KEY_MAX] = NULL,
49
[KEY_AGAIN] = "again",
50
[KEY_PROPS] = "props",
52
[KEY_FRONT] = "front",
55
[KEY_PASTE] = "paste",
61
[KEY_SETUP] = "setup",
62
[KEY_SLEEP] = "sleep",
63
[KEY_WAKEUP] = "wake-up",
65
[KEY_SENDFILE] = "send-file",
66
[KEY_DELETEFILE] = "delete-file",
68
[KEY_PROG1] = "prog1",
69
[KEY_PROG2] = "prog2",
71
[KEY_MSDOS] = "msdos",
72
[KEY_COFFEE] = "coffee",
73
[KEY_DIRECTION] = "direction",
74
[KEY_CYCLEWINDOWS] = "cycle-windows",
76
[KEY_BOOKMARKS] = "bookmarks",
77
[KEY_COMPUTER] = "computer",
79
[KEY_FORWARD] = "forward",
80
[KEY_CLOSECD] = "close-cd",
81
[KEY_EJECTCD] = "eject-cd",
82
[KEY_EJECTCLOSECD] = "eject-close-cd",
83
[KEY_NEXTSONG] = "next-song",
84
[KEY_PLAYPAUSE] = "play-pause",
85
[KEY_PREVIOUSSONG] = "previous-song",
86
[KEY_STOPCD] = "stop-cd",
87
[KEY_RECORD] = "record",
88
[KEY_REWIND] = "rewind",
89
[KEY_PHONE] = "phone",
91
[KEY_CONFIG] = "config",
92
[KEY_HOMEPAGE] = "homepage",
93
[KEY_REFRESH] = "refresh",
97
[KEY_SCROLLUP] = "scroll-up",
98
[KEY_SCROLLDOWN] = "scroll-down",
99
[KEY_KPLEFTPAREN] = "kp-left-paren",
100
[KEY_KPRIGHTPAREN] = "kp-right-paren",
113
[KEY_PLAYCD] = "play-cd",
114
[KEY_PAUSECD] = "pause-cd",
115
[KEY_PROG3] = "prog3",
116
[KEY_PROG4] = "prog4",
117
[KEY_SUSPEND] = "hibernate",
118
[KEY_CLOSE] = "close",
120
[KEY_FASTFORWARD] = "fast-forward",
121
[KEY_BASSBOOST] = "bass-boost",
122
[KEY_PRINT] = "print",
124
[KEY_CAMERA] = "camera",
125
[KEY_SOUND] = "sound",
126
[KEY_QUESTION] = "question",
127
[KEY_EMAIL] = "email",
129
[KEY_SEARCH] = "search",
130
[KEY_CONNECT] = "connect",
131
[KEY_FINANCE] = "finance",
132
[KEY_SPORT] = "sport",
134
[KEY_ALTERASE] = "alt-erase",
135
[KEY_CANCEL] = "cancel",
136
[KEY_BRIGHTNESSDOWN] = "brightness-down",
137
[KEY_BRIGHTNESSUP] = "brightness-up",
138
[KEY_MEDIA] = "media",
139
[KEY_POWER] = "power",
141
[KEY_VOLUMEDOWN] = "volume-down",
142
[KEY_VOLUMEUP] = "volume-up",
143
#ifndef KEY_SWITCHVIDEOMODE
144
#define KEY_SWITCHVIDEOMODE 227
146
[KEY_SWITCHVIDEOMODE] = "switch-videomode",
147
#ifndef KEY_KBDILLUMTOGGLE
148
#define KEY_KBDILLUMTOGGLE 228
150
[KEY_KBDILLUMTOGGLE] = "kbd-illum-toggle",
151
#ifndef KEY_KBDILLUMDOWN
152
#define KEY_KBDILLUMDOWN 229
154
[KEY_KBDILLUMDOWN] = "kbd-illum-down",
155
#ifndef KEY_KBDILLUMUP
156
#define KEY_KBDILLUMUP 230
158
[KEY_KBDILLUMUP] = "kbd-illum-up",
160
#define KEY_BATTERY 236
162
[KEY_BATTERY] = "battery",
163
#ifndef KEY_BLUETOOTH
164
#define KEY_BLUETOOTH 237
166
[KEY_BLUETOOTH] = "bluetooth",
174
/* we must use this kernel-compatible implementation */
175
#define BITS_PER_LONG (sizeof(long) * 8)
176
#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
177
#define OFF(x) ((x)%BITS_PER_LONG)
178
#define BIT(x) (1UL<<OFF(x))
179
#define LONG(x) ((x)/BITS_PER_LONG)
180
#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
183
main_loop (LibHalContext *ctx, FILE* eventfp)
186
struct input_event event;
189
while (fread (&event, sizeof(event), 1, eventfp)) {
191
if (button_has_state && event.type == EV_SW) {
194
HAL_INFO (("%s: event.value=%d ; event.code=%d (0x%02x)",
195
udi, event.value, event.code, event.code));
198
switch (event.code) {
203
name = "tablet_mode";
205
case SW_HEADPHONE_INSERT:
206
name = "headphone_insert";
210
long bitmask[NBITS(SW_MAX)];
212
/* check switch state - cuz apparently we get spurious events (or I don't know
213
* how to use the input layer correctly)
216
* 19:08:22.911 [I] event.value=1 ; event.code=0 (0x00)
217
* 19:08:22.914 [I] event.value=0 ; event.code=0 (0x00)
220
* 19:08:26.772 [I] event.value=0 ; event.code=0 (0x00)
221
* 19:08:26.776 [I] event.value=0 ; event.code=0 (0x00)
222
* 19:08:26.863 [I] event.value=1 ; event.code=0 (0x00)
223
* 19:08:26.868 [I] event.value=0 ; event.code=0 (0x00)
224
* 19:08:26.955 [I] event.value=0 ; event.code=0 (0x00)
225
* 19:08:26.960 [I] event.value=0 ; event.code=0 (0x00)
228
if (ioctl (fileno (eventfp), EVIOCGSW(sizeof (bitmask)), bitmask) < 0) {
229
HAL_DEBUG (("ioctl EVIOCGSW failed"));
231
int new_state = test_bit (event.code, bitmask);
232
if (new_state != button_state) {
233
button_state = new_state;
235
dbus_error_init (&error);
236
libhal_device_set_property_bool (ctx, udi, "button.state.value",
237
button_state, &error);
239
dbus_error_init (&error);
240
libhal_device_emit_condition (ctx, udi,
247
} else if (event.type == EV_KEY && key_name[event.code] != NULL && event.value == 1) {
248
dbus_error_init (&error);
249
libhal_device_emit_condition (ctx, udi,
251
key_name[event.code],
256
dbus_error_free (&error);
260
main (int argc, char **argv)
262
LibHalContext *ctx = NULL;
268
hal_set_proc_title_init (argc, argv);
270
/* setup_logger (); */
272
dbus_error_init (&error);
274
if ((udi = getenv ("UDI")) == NULL)
277
if ((device_file = getenv ("HAL_PROP_INPUT_DEVICE")) == NULL)
280
s = getenv ("HAL_PROP_BUTTON_HAS_STATE");
281
if (s != NULL && strcmp (s, "true") == 0) {
282
button_has_state = TRUE;
283
if ((s = getenv ("HAL_PROP_BUTTON_STATE_VALUE")) == NULL)
285
button_state = (strcmp (s, "true") == 0);
288
if ((ctx = libhal_ctx_init_direct (&error)) == NULL)
291
dbus_error_init (&error);
292
if (!libhal_device_addon_is_ready (ctx, udi, &error)) {
296
eventfp = fopen(device_file, "r");
303
hal_set_proc_title ("hald-addon-keyboard: listening on %s", device_file);
307
main_loop (ctx, eventfp);
309
/* If main_loop exits sleep for 5s and try to reconnect (again). */
317
dbus_error_init (&error);
318
libhal_ctx_shutdown (ctx, &error);
319
libhal_ctx_free (ctx);
325
/* vim:set sw=8 noet: */