2 * input_layer - Kernel ACPI Event Input Layer Interface
4 * Handles the details of getting kernel ACPI events from the input
5 * layer (/dev/input/event*).
7 * Inspired by (and in some cases blatantly lifted from) Vojtech Pavlik's
10 * Copyright (C) 2008-2009, Ted Felix (www.tedfelix.com)
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34 #include <linux/input.h>
43 #include "connection_list.h"
46 #define DIM(a) (sizeof(a) / sizeof(a[0]))
49 struct input_event event;
53 /* Event Table: Events we are interested in and their strings. Use
54 evtest.c, acpi_genl, or kacpimon to find new events to add to this
56 static struct evtab_entry evtab[] = {
57 {{{0,0}, EV_KEY, KEY_POWER, 1}, "button/power PBTN 00000080 00000000"},
58 {{{0,0}, EV_KEY, KEY_SUSPEND, 1},
59 "button/suspend SUSP 00000080 00000000"},
60 {{{0,0}, EV_SW, SW_LID, 1}, "button/lid LID close"},
61 {{{0,0}, EV_SW, SW_LID, 0}, "button/lid LID open"},
62 /* blue access IBM button on Thinkpad T42p*/
63 {{{0,0}, EV_KEY, KEY_PROG1, 1}, "button/prog1 PROG1 00000080 00000000"},
64 {{{0,0}, EV_KEY, KEY_VENDOR, 1}, "button/vendor VNDR 00000080 00000000"},
65 {{{0,0}, EV_KEY, KEY_FN_F1, 1}, "button/fnf1 FNF1 00000080 00000000"},
66 {{{0,0}, EV_KEY, KEY_FN_F2, 1}, "button/fnf2 FNF2 00000080 00000000"},
67 /* Fn-F2 produces KEY_BATTERY on Thinkpad T42p */
68 {{{0,0}, EV_KEY, KEY_BATTERY, 1},
69 "button/battery BAT 00000080 00000000"},
70 {{{0,0}, EV_KEY, KEY_SCREENLOCK, 1},
71 "button/screenlock SCRNLCK 00000080 00000000"},
72 {{{0,0}, EV_KEY, KEY_COFFEE, 1}, "button/coffee CFEE 00000080 00000000"},
73 {{{0,0}, EV_KEY, KEY_SLEEP, 1}, "button/sleep SBTN 00000080 00000000"},
74 {{{0,0}, EV_KEY, KEY_WLAN, 1}, "button/wlan WLAN 00000080 00000000"},
75 {{{0,0}, EV_KEY, KEY_FN_F6, 1}, "button/fnf6 FNF6 00000080 00000000"},
76 /* procfs on Thinkpad 600X reports "video VID0 00000080 00000000" */
77 /* typical events file has "video.* 00000080" */
78 {{{0,0}, EV_KEY, KEY_SWITCHVIDEOMODE, 1},
79 "video/switchmode VMOD 00000080 00000000"},
80 {{{0,0}, EV_KEY, KEY_FN_F9, 1}, "button/fnf9 FNF9 00000080 00000000"},
81 {{{0,0}, EV_KEY, KEY_FN_F10, 1}, "button/fnf10 FF10 00000080 00000000"},
82 {{{0,0}, EV_KEY, KEY_FN_F11, 1}, "button/fnf11 FF11 00000080 00000000"},
83 /* Fn-F9 produces KEY_F24 on Thinkpad T42p */
84 {{{0,0}, EV_KEY, KEY_F24, 1}, "button/f24 F24 00000080 00000000"},
87 /* These "EV_MSC, 4, x" events cause trouble. They are triggered */
88 /* by unexpected keys on the keyboard. */
89 /* The 4 is MSC_SCAN, so these are actually scan code events. */
91 /* EV_MSC, MSC_SCAN, KEY_MINUS This is triggered by the minus key. */
92 {{{0,0}, EV_MSC, 4, 12}, "button/fnbs FNBS 00000080 00000000"},
94 /* EV_MSC, MSC_SCAN, KEY_EQUAL Triggered by the equals key. */
95 {{{0,0}, EV_MSC, 4, 13}, "button/fnins FNINS 00000080 00000000"},
97 /* EV_MSC, MSC_SCAN, KEY_BACKSPACE Triggered by the backspace key. */
98 {{{0,0}, EV_MSC, 4, 14}, "button/fndel FNDEL 00000080 00000000"},
100 /* EV_MSC, MSC_SCAN, KEY_E Triggered by the 'E' key. */
101 {{{0,0}, EV_MSC, 4, 18}, "button/fnpgdown FNPGDOWN 00000080 00000000"},
104 {{{0,0}, EV_KEY, KEY_ZOOM, 1}, "button/zoom ZOOM 00000080 00000000"},
105 /* typical events file has "video.* 00000087" */
106 {{{0,0}, EV_KEY, KEY_BRIGHTNESSDOWN, 1},
107 "video/brightnessdown BRTDN 00000087 00000000"},
108 /* typical events file has "video.* 00000086" */
109 {{{0,0}, EV_KEY, KEY_BRIGHTNESSUP, 1},
110 "video/brightnessup BRTUP 00000086 00000000"},
111 {{{0,0}, EV_KEY, KEY_KBDILLUMTOGGLE, 1},
112 "button/kbdillumtoggle KBILLUM 00000080 00000000"},
113 {{{0,0}, EV_KEY, KEY_VOLUMEDOWN, 1},
114 "button/volumedown VOLDN 00000080 00000000"},
115 {{{0,0}, EV_KEY, KEY_VOLUMEUP, 1},
116 "button/volumeup VOLUP 00000080 00000000"},
117 {{{0,0}, EV_KEY, KEY_MUTE, 1},
118 "button/mute MUTE 00000080 00000000"},
119 /* cd play/pause buttons */
120 {{{0,0}, EV_KEY, KEY_NEXTSONG, 1},
121 "cd/next CDNEXT 00000080 00000000"},
122 {{{0,0}, EV_KEY, KEY_PREVIOUSSONG, 1},
123 "cd/prev CDPREV 00000080 00000000"},
124 {{{0,0}, EV_KEY, KEY_PLAYPAUSE, 1},
125 "cd/play CDPLAY 00000080 00000000"},
126 {{{0,0}, EV_KEY, KEY_STOPCD, 1},
127 "cd/stop CDSTOP 00000080 00000000"},
128 /* additional events divined from the kernel's video.c */
129 {{{0,0}, EV_KEY, KEY_VIDEO_NEXT, 1},
130 "video/next NEXT 00000083 00000000"},
131 {{{0,0}, EV_KEY, KEY_VIDEO_PREV, 1},
132 "video/prev PREV 00000084 00000000"},
133 {{{0,0}, EV_KEY, KEY_BRIGHTNESS_CYCLE, 1},
134 "video/brightnesscycle BCYC 00000085 00000000"},
135 {{{0,0}, EV_KEY, KEY_BRIGHTNESS_ZERO, 1},
136 "video/brightnesszero BZRO 00000088 00000000"},
137 {{{0,0}, EV_KEY, KEY_DISPLAY_OFF, 1},
138 "video/displayoff DOFF 00000089 00000000"}
141 /*----------------------------------------------------------------------*/
142 /* Given an input event, returns the string corresponding to that event.
143 If there is no corresponding string, NULL is returned. */
145 event_string(struct input_event event)
149 /* for each entry in the event table */
150 /* ??? is there a faster way? */
151 for (i = 0; i < DIM(evtab); ++i)
153 /* if this is a matching event, return its string */
154 if (event.type == evtab[i].event.type &&
155 event.code == evtab[i].event.code &&
156 event.value == evtab[i].event.value) {
164 /*-----------------------------------------------------------------*/
165 /* returns non-zero if the event type/code is one we need */
167 need_event(int type, int code)
171 /* for each entry in the event table */
172 for (i = 0; i < DIM(evtab); ++i) {
173 /* if we found a matching event */
174 if (type == evtab[i].event.type &&
175 code == evtab[i].event.code) {
183 /*-----------------------------------------------------------------*/
184 /* called when an input layer event is received */
185 void process_input(int fd)
187 struct input_event event;
191 struct connection *c;
194 nbytes = read(fd, &event, sizeof(event));
197 acpid_log(LOG_WARNING, "input layer connection closed");
202 /* if it's a signal, bail */
205 if (errno == ENODEV) {
206 acpid_log(LOG_WARNING, "input device has been disconnected, fd %d",
208 delete_connection(fd);
211 acpid_log(LOG_ERR, "input layer read error: %s (%d)",
212 strerror(errno), errno);
213 if (++nerrs >= ACPID_MAX_ERRS) {
215 "too many errors reading "
216 "input layer - aborting");
222 /* ??? Is it possible for a partial message to come across? */
223 /* If so, we've got more code to write... */
225 if (nbytes != sizeof(event)) {
226 acpid_log(LOG_WARNING, "input layer unexpected length: "
227 "%d expected: %d", nbytes, sizeof(event));
231 c = find_connection(fd);
233 /* if we're getting scancodes, we probably have a keyboard */
234 if (event.type == EV_MSC && event.code == MSC_SCAN) {
236 c->kybd = 1; /* appears to be a keyboard device */
239 /* convert the event into a string */
240 str = event_string(event);
241 /* if this is not an event we care about, bail */
245 /* If we suspect this is a keyboard, and we have enough space, tack a
246 * "K" on to the end of the event string. */
247 if (c && c->kybd && strnlen(str, sizeof(str2)) <= sizeof(str2) - 3) {
253 /* if we're locked, don't process the event */
257 "lockfile present, not processing "
258 "input layer event \"%s\"", str);
265 "received input layer event \"%s\"", str);
267 /* send the event off to the handler */
268 acpid_handle_event(str);
272 "completed input layer event \"%s\"", str);
275 #define BITS_PER_LONG (sizeof(long) * 8)
276 #define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
277 #define OFF(x) ((x)%BITS_PER_LONG)
278 #define LONG(x) ((x)/BITS_PER_LONG)
279 #define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
281 /*--------------------------------------------------------------------*/
282 /* returns non-zero if the file descriptor supports one of the events */
283 /* supported by event_string(). */
288 unsigned long bit[EV_MAX][NBITS(KEY_MAX)];
290 memset(bit, 0, sizeof(bit));
291 /* get the event type bitmap */
292 ioctl(fd, EVIOCGBIT(0, sizeof(bit[0])), bit[0]);
294 /* for each event type */
295 for (type = 0; type < EV_MAX; type++) {
296 /* if this event type is supported */
297 if (test_bit(type, bit[0])) {
299 if (type == EV_SYN) continue;
300 /* get the event code mask */
301 ioctl(fd, EVIOCGBIT(type, sizeof(bit[type])), bit[type]);
302 /* for each event code */
303 for (code = 0; code < KEY_MAX; code++) {
304 /* if this event code is supported */
305 if (test_bit(code, bit[type])) {
306 /* if we need this event */
307 if (need_event(type, code) != 0)
316 /*-----------------------------------------------------------------*
317 * open a single input layer file for input */
318 int open_inputfile(const char *filename)
323 fd = open(filename, O_RDONLY | O_NONBLOCK);
325 /* Make sure scripts we exec() (in event.c) don't get our file
327 fcntl(fd, F_SETFD, FD_CLOEXEC);
332 /* if this file doesn't have events we need, indicate failure */
333 if (!has_event(fd)) {
338 /* get this event file's name for debugging */
339 strcpy(evname, "Unknown");
340 ioctl(fd, EVIOCGNAME(sizeof(evname)), evname);
342 acpid_log(LOG_DEBUG, "input layer %s (%s) "
343 "opened successfully, fd %d", filename, evname, fd);
345 /* add a connection to the list */
347 c.process = process_input;
348 /* delete_connection() will free */
349 c.pathname = malloc(strlen(filename) + 1);
351 strcpy(c.pathname, filename);
352 /* assume not a keyboard until we see a scancode */
356 return 0; /* success */
359 /* open unsuccessful */
363 /*-----------------------------------------------------------------*
364 * open each of the appropriate /dev/input/event* files for input */
365 void open_input(void)
367 char *filename = NULL;
372 /* get all the matching event filenames */
373 glob(ACPID_INPUTLAYERFILES, 0, NULL, &globbuf);
375 /* for each event file */
376 for (i = 0; i < globbuf.gl_pathc; ++i) {
377 filename = globbuf.gl_pathv[i];
379 /* open this input layer device file */
380 if (open_inputfile(filename) == 0)
385 acpid_log(LOG_ERR, "cannot open input layer");