~ubuntu-branches/debian/sid/hal/sid

« back to all changes in this revision

Viewing changes to hald/linux/addons/addon-keyboard.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2007-10-23 12:33:58 UTC
  • Revision ID: james.westby@ubuntu.com-20071023123358-xaf8mjc5n84d5gtz
Tags: upstream-0.5.10
ImportĀ upstreamĀ versionĀ 0.5.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/***************************************************************************
2
 
 * CVSID: $Id$
3
 
 *
4
 
 * addon-keyboard.c : Listen to key events and modify hal device objects
5
 
 *
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>
9
 
 *
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.
14
 
 *
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.
19
 
 *
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
23
 
 *
24
 
 **************************************************************************/
25
 
 
26
 
#ifdef HAVE_CONFIG_H
27
 
#  include <config.h>
28
 
#endif
29
 
 
30
 
#include <stdio.h>
31
 
#include <stdlib.h>
32
 
#include <unistd.h>
33
 
#include <string.h>
34
 
#include <sys/types.h>
35
 
#include <linux/input.h>
36
 
 
37
 
#include "libhal/libhal.h"
38
 
 
39
 
#include "../../logger.h"
40
 
#include "../../util_helper.h"
41
 
 
42
 
static char *udi;
43
 
static int button_state = FALSE;
44
 
static int button_has_state = FALSE;
45
 
 
46
 
static char *key_name[KEY_MAX + 1] = {
47
 
        [0 ... KEY_MAX] = NULL,
48
 
        [KEY_STOP] = "stop",
49
 
        [KEY_AGAIN] = "again",
50
 
        [KEY_PROPS] = "props",
51
 
        [KEY_UNDO] = "undo",
52
 
        [KEY_FRONT] = "front",
53
 
        [KEY_COPY] = "copy",
54
 
        [KEY_OPEN] = "open",
55
 
        [KEY_PASTE] = "paste",
56
 
        [KEY_FIND] = "find",
57
 
        [KEY_CUT] = "cut",
58
 
        [KEY_HELP] = "help",
59
 
        [KEY_MENU] = "menu",
60
 
        [KEY_CALC] = "calc",
61
 
        [KEY_SETUP] = "setup",
62
 
        [KEY_SLEEP] = "sleep",
63
 
        [KEY_WAKEUP] = "wake-up",
64
 
        [KEY_FILE] = "file",
65
 
        [KEY_SENDFILE] = "send-file",
66
 
        [KEY_DELETEFILE] = "delete-file",
67
 
        [KEY_XFER] = "xfer",
68
 
        [KEY_PROG1] = "prog1",
69
 
        [KEY_PROG2] = "prog2",
70
 
        [KEY_WWW] = "www",
71
 
        [KEY_MSDOS] = "msdos",
72
 
        [KEY_COFFEE] = "coffee",
73
 
        [KEY_DIRECTION] = "direction",
74
 
        [KEY_CYCLEWINDOWS] = "cycle-windows",
75
 
        [KEY_MAIL] = "mail",
76
 
        [KEY_BOOKMARKS] = "bookmarks",
77
 
        [KEY_COMPUTER] = "computer",
78
 
        [KEY_BACK] = "back",
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",
90
 
        [KEY_ISO] = "iso",
91
 
        [KEY_CONFIG] = "config",
92
 
        [KEY_HOMEPAGE] = "homepage",
93
 
        [KEY_REFRESH] = "refresh",
94
 
        [KEY_EXIT] = "exit",
95
 
        [KEY_MOVE] = "move",
96
 
        [KEY_EDIT] = "edit",
97
 
        [KEY_SCROLLUP] = "scroll-up",
98
 
        [KEY_SCROLLDOWN] = "scroll-down",
99
 
        [KEY_KPLEFTPAREN] = "kp-left-paren",
100
 
        [KEY_KPRIGHTPAREN] = "kp-right-paren",
101
 
        [KEY_F13] = "f13",
102
 
        [KEY_F14] = "f14",
103
 
        [KEY_F15] = "f15",
104
 
        [KEY_F16] = "f16",
105
 
        [KEY_F17] = "f17",
106
 
        [KEY_F18] = "f18",
107
 
        [KEY_F19] = "f19",
108
 
        [KEY_F20] = "f20",
109
 
        [KEY_F21] = "f21",
110
 
        [KEY_F22] = "f22",
111
 
        [KEY_F23] = "f23",
112
 
        [KEY_F24] = "f24",
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",
119
 
        [KEY_PLAY] = "play",
120
 
        [KEY_FASTFORWARD] = "fast-forward",
121
 
        [KEY_BASSBOOST] = "bass-boost",
122
 
        [KEY_PRINT] = "print",
123
 
        [KEY_HP] = "hp",
124
 
        [KEY_CAMERA] = "camera",
125
 
        [KEY_SOUND] = "sound",
126
 
        [KEY_QUESTION] = "question",
127
 
        [KEY_EMAIL] = "email",
128
 
        [KEY_CHAT] = "chat",
129
 
        [KEY_SEARCH] = "search",
130
 
        [KEY_CONNECT] = "connect",
131
 
        [KEY_FINANCE] = "finance",
132
 
        [KEY_SPORT] = "sport",
133
 
        [KEY_SHOP] = "shop",
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",
140
 
        [KEY_MUTE] = "mute",
141
 
        [KEY_VOLUMEDOWN] = "volume-down",
142
 
        [KEY_VOLUMEUP] = "volume-up",
143
 
#ifndef KEY_SWITCHVIDEOMODE
144
 
#define KEY_SWITCHVIDEOMODE     227
145
 
#endif
146
 
        [KEY_SWITCHVIDEOMODE] = "switch-videomode",
147
 
#ifndef KEY_KBDILLUMTOGGLE
148
 
#define KEY_KBDILLUMTOGGLE      228
149
 
#endif
150
 
        [KEY_KBDILLUMTOGGLE] = "kbd-illum-toggle",
151
 
#ifndef KEY_KBDILLUMDOWN
152
 
#define KEY_KBDILLUMDOWN        229
153
 
#endif
154
 
        [KEY_KBDILLUMDOWN] = "kbd-illum-down",
155
 
#ifndef KEY_KBDILLUMUP
156
 
#define KEY_KBDILLUMUP          230
157
 
#endif
158
 
        [KEY_KBDILLUMUP] = "kbd-illum-up",
159
 
#ifndef KEY_BATTERY
160
 
#define KEY_BATTERY 236
161
 
#endif
162
 
        [KEY_BATTERY] = "battery",
163
 
#ifndef KEY_BLUETOOTH
164
 
#define KEY_BLUETOOTH 237
165
 
#endif
166
 
        [KEY_BLUETOOTH] = "bluetooth",
167
 
#ifndef KEY_WLAN
168
 
#define KEY_WLAN 238
169
 
#endif
170
 
        [KEY_WLAN] = "wlan"
171
 
};
172
 
 
173
 
 
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)
181
 
 
182
 
static void
183
 
main_loop (LibHalContext *ctx, FILE* eventfp)
184
 
{
185
 
        DBusError error;
186
 
        struct input_event event;
187
 
 
188
 
 
189
 
        while (fread (&event, sizeof(event), 1, eventfp)) {
190
 
 
191
 
                if (button_has_state && event.type == EV_SW) {
192
 
                        char *name = NULL;
193
 
 
194
 
                        HAL_INFO (("%s: event.value=%d ; event.code=%d (0x%02x)", 
195
 
                                   udi, event.value, event.code, event.code));
196
 
 
197
 
 
198
 
                        switch (event.code) {
199
 
                        case SW_LID:
200
 
                                name = "lid";
201
 
                                break;
202
 
                        case SW_TABLET_MODE:
203
 
                                name = "tablet_mode";
204
 
                                break;
205
 
                        case SW_HEADPHONE_INSERT:
206
 
                                name = "headphone_insert";
207
 
                                break;
208
 
                        }
209
 
                        if (name != NULL) {
210
 
                                long bitmask[NBITS(SW_MAX)];
211
 
 
212
 
                                /* check switch state - cuz apparently we get spurious events (or I don't know
213
 
                                 * how to use the input layer correctly)
214
 
                                 *
215
 
                                 * Lid close:
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)
218
 
                                 *
219
 
                                 * Lid open:
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)
226
 
                                 */
227
 
 
228
 
                                if (ioctl (fileno (eventfp), EVIOCGSW(sizeof (bitmask)), bitmask) < 0) {
229
 
                                        HAL_DEBUG (("ioctl EVIOCGSW failed"));
230
 
                                } else {
231
 
                                        int new_state = test_bit (event.code, bitmask);
232
 
                                        if (new_state != button_state) {
233
 
                                                button_state = new_state;
234
 
                                                
235
 
                                                dbus_error_init (&error);
236
 
                                                libhal_device_set_property_bool (ctx, udi, "button.state.value", 
237
 
                                                                                 button_state, &error);
238
 
                                                
239
 
                                                dbus_error_init (&error);
240
 
                                                libhal_device_emit_condition (ctx, udi, 
241
 
                                                                              "ButtonPressed",
242
 
                                                                              name,
243
 
                                                                              &error);
244
 
                                        }
245
 
                                }
246
 
                        }
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, 
250
 
                                                      "ButtonPressed",
251
 
                                                      key_name[event.code],
252
 
                                                      &error);
253
 
                }
254
 
        }
255
 
        
256
 
        dbus_error_free (&error);
257
 
}
258
 
 
259
 
int
260
 
main (int argc, char **argv)
261
 
{
262
 
        LibHalContext *ctx = NULL;
263
 
        DBusError error;
264
 
        char *device_file;
265
 
        FILE *eventfp;
266
 
        char *s;
267
 
 
268
 
        hal_set_proc_title_init (argc, argv);
269
 
 
270
 
        /* setup_logger (); */
271
 
 
272
 
        dbus_error_init (&error);
273
 
 
274
 
        if ((udi = getenv ("UDI")) == NULL)
275
 
                goto out;
276
 
        
277
 
        if ((device_file = getenv ("HAL_PROP_INPUT_DEVICE")) == NULL)
278
 
                goto out;
279
 
 
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)
284
 
                        goto out;
285
 
                button_state = (strcmp (s, "true") == 0);
286
 
        }
287
 
 
288
 
        if ((ctx = libhal_ctx_init_direct (&error)) == NULL)
289
 
                goto out;
290
 
 
291
 
        dbus_error_init (&error);
292
 
        if (!libhal_device_addon_is_ready (ctx, udi, &error)) {
293
 
                goto out;
294
 
        }
295
 
 
296
 
        eventfp = fopen(device_file, "r");      
297
 
 
298
 
        if (!eventfp)
299
 
                goto out;
300
 
 
301
 
        drop_privileges (0);
302
 
 
303
 
        hal_set_proc_title ("hald-addon-keyboard: listening on %s", device_file);
304
 
 
305
 
        while (1)
306
 
        {
307
 
                main_loop (ctx, eventfp);
308
 
                
309
 
                /* If main_loop exits sleep for 5s and try to reconnect (again). */
310
 
                sleep (5);
311
 
        }
312
 
        
313
 
        return 0;
314
 
 
315
 
 out:
316
 
        if (ctx != NULL) {
317
 
                dbus_error_init (&error);
318
 
                libhal_ctx_shutdown (ctx, &error);
319
 
                libhal_ctx_free (ctx);
320
 
        }
321
 
        
322
 
        return 0;
323
 
}
324
 
 
325
 
/* vim:set sw=8 noet: */