fix systemd unit install path
[external/acpid.git] / input_layer.c
1 /*
2  *  input_layer - Kernel ACPI Event Input Layer Interface
3  *
4  *  Handles the details of getting kernel ACPI events from the input
5  *  layer (/dev/input/event*).
6  *
7  *  Inspired by (and in some cases blatantly lifted from) Vojtech Pavlik's
8  *  evtest.c.
9  *
10  *  Copyright (C) 2008-2009, Ted Felix (www.tedfelix.com)
11  *
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.
16  *
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.
21  *
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
25  *
26  *  (tabs at 4)
27  */
28
29 /* system */
30 #include <unistd.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <fcntl.h>
34 #include <linux/input.h>
35 #include <string.h>
36 #include <errno.h>
37 #include <malloc.h>
38 #include <glob.h>
39
40 /* local */
41 #include "acpid.h"
42 #include "log.h"
43 #include "connection_list.h"
44 #include "event.h"
45
46 #define DIM(a)  (sizeof(a) / sizeof(a[0]))
47
48 struct evtab_entry {
49         struct input_event event;
50         const char *str;
51 };
52
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
55    table. */
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"},
85
86 #if 0
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.  */
90
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"},
93
94         /* EV_MSC, MSC_SCAN, KEY_EQUAL  Triggered by the equals key. */
95         {{{0,0}, EV_MSC, 4, 13}, "button/fnins FNINS 00000080 00000000"},
96
97         /* EV_MSC, MSC_SCAN, KEY_BACKSPACE   Triggered by the backspace key. */
98         {{{0,0}, EV_MSC, 4, 14}, "button/fndel FNDEL 00000080 00000000"},
99
100         /* EV_MSC, MSC_SCAN, KEY_E   Triggered by the 'E' key. */
101         {{{0,0}, EV_MSC, 4, 18}, "button/fnpgdown FNPGDOWN 00000080 00000000"},
102 #endif
103
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"}
139 };
140
141 /*----------------------------------------------------------------------*/
142 /* Given an input event, returns the string corresponding to that event.
143    If there is no corresponding string, NULL is returned.  */
144 static const char *
145 event_string(struct input_event event)
146 {
147         unsigned i;
148         
149         /* for each entry in the event table */
150         /* ??? is there a faster way? */
151         for (i = 0; i < DIM(evtab); ++i)
152         {
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) {
157                         return evtab[i].str;
158                 }
159         }
160         
161         return NULL;
162 }
163
164 /*-----------------------------------------------------------------*/
165 /* returns non-zero if the event type/code is one we need */
166 static int 
167 need_event(int type, int code)
168 {
169         unsigned i;
170
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) {
176                         return 1;
177                 }
178         }
179
180         return 0;
181 }
182
183 /*-----------------------------------------------------------------*/
184 /* called when an input layer event is received */
185 void process_input(int fd)
186 {
187         struct input_event event;
188         ssize_t nbytes;
189         const char *str;
190         static int nerrs;
191         struct connection *c;
192         char str2[100];
193
194         nbytes = read(fd, &event, sizeof(event));
195
196         if (nbytes == 0) {
197                 acpid_log(LOG_WARNING, "input layer connection closed");
198                 exit(EXIT_FAILURE);
199         }
200         
201         if (nbytes < 0) {
202                 /* if it's a signal, bail */
203                 if (errno == EINTR)
204                         return;
205                 if (errno == ENODEV) {
206                         acpid_log(LOG_WARNING, "input device has been disconnected, fd %d",
207                                   fd);
208                         delete_connection(fd);
209                         return;
210                 }
211                 acpid_log(LOG_ERR, "input layer read error: %s (%d)",
212                         strerror(errno), errno);
213                 if (++nerrs >= ACPID_MAX_ERRS) {
214                         acpid_log(LOG_ERR,
215                                 "too many errors reading "
216                                 "input layer - aborting");
217                         exit(EXIT_FAILURE);
218                 }
219                 return;
220         }
221
222         /* ??? Is it possible for a partial message to come across? */
223         /*   If so, we've got more code to write... */
224         
225         if (nbytes != sizeof(event)) {
226                 acpid_log(LOG_WARNING, "input layer unexpected length: "
227                         "%d   expected: %d", nbytes, sizeof(event));
228                 return;
229         }
230
231         c = find_connection(fd);
232         
233         /* if we're getting scancodes, we probably have a keyboard */
234         if (event.type == EV_MSC  &&  event.code == MSC_SCAN) {
235                 if (c)
236                         c->kybd = 1;  /* appears to be a keyboard device */
237         }
238         
239         /* convert the event into a string */
240         str = event_string(event);
241         /* if this is not an event we care about, bail */
242         if (str == NULL)
243                 return;
244
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) {
248                 strcpy(str2, str);
249                 strcat(str2, " K");
250                 str = str2;
251         }
252         
253         /* if we're locked, don't process the event */
254         if (locked()) {
255                 if (logevents) {
256                         acpid_log(LOG_INFO,
257                                 "lockfile present, not processing "
258                                 "input layer event \"%s\"", str);
259                 }
260                 return;
261         }
262
263         if (logevents)
264                 acpid_log(LOG_INFO,
265                         "received input layer event \"%s\"", str);
266         
267         /* send the event off to the handler */
268         acpid_handle_event(str);
269
270         if (logevents)
271                 acpid_log(LOG_INFO,
272                         "completed input layer event \"%s\"", str);
273 }
274
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)
280
281 /*--------------------------------------------------------------------*/
282 /* returns non-zero if the file descriptor supports one of the events */
283 /* supported by event_string().  */
284 static int 
285 has_event(int fd)
286 {
287         int type, code;
288         unsigned long bit[EV_MAX][NBITS(KEY_MAX)];
289
290         memset(bit, 0, sizeof(bit));
291         /* get the event type bitmap */
292         ioctl(fd, EVIOCGBIT(0, sizeof(bit[0])), bit[0]);
293
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])) {
298                         /* skip sync */
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)
308                                                 return 1;
309                                 }
310                         }
311                 }
312         }
313         return 0;
314 }
315
316 /*-----------------------------------------------------------------*
317  * open a single input layer file for input  */
318 int open_inputfile(const char *filename)
319 {
320         int fd;
321         struct connection c;
322
323         fd = open(filename, O_RDONLY | O_NONBLOCK);
324
325     /* Make sure scripts we exec() (in event.c) don't get our file 
326        descriptors. */
327     fcntl(fd, F_SETFD, FD_CLOEXEC);
328
329         if (fd >= 0) {
330                 char evname[256];
331                 
332                 /* if this file doesn't have events we need, indicate failure */
333                 if (!has_event(fd)) {
334                         close(fd);
335                         return -1;
336                 }
337
338                 /* get this event file's name for debugging */
339                 strcpy(evname, "Unknown");
340                 ioctl(fd, EVIOCGNAME(sizeof(evname)), evname);
341
342                 acpid_log(LOG_DEBUG, "input layer %s (%s) "
343                         "opened successfully, fd %d", filename, evname, fd);
344
345                 /* add a connection to the list */
346                 c.fd = fd;
347                 c.process = process_input;
348                 /* delete_connection() will free */
349                 c.pathname = malloc(strlen(filename) + 1);
350                 if (c.pathname)
351                         strcpy(c.pathname, filename);
352                 /* assume not a keyboard until we see a scancode */
353                 c.kybd = 0;
354                 add_connection(&c);
355
356                 return 0;  /* success */
357         }
358         
359         /* open unsuccessful */
360         return -1;
361 }
362
363 /*-----------------------------------------------------------------*
364  * open each of the appropriate /dev/input/event* files for input  */
365 void open_input(void)
366 {
367         char *filename = NULL;
368         glob_t globbuf;
369         unsigned i;
370         int success = 0;
371
372         /* get all the matching event filenames */
373         glob(ACPID_INPUTLAYERFILES, 0, NULL, &globbuf);
374
375         /* for each event file */
376         for (i = 0; i < globbuf.gl_pathc; ++i) {
377                 filename = globbuf.gl_pathv[i];
378
379                 /* open this input layer device file */
380                 if (open_inputfile(filename) == 0)
381                         success = 1;
382         }
383
384         if (!success)
385                 acpid_log(LOG_ERR, "cannot open input layer");
386
387         globfree(&globbuf);
388 }
389