Tizen 2.1 base
[external/acpid.git] / kacpimon / 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, 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 <stdio.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <linux/input.h>
34 #include <string.h>
35 #include <errno.h>
36 #include <malloc.h>
37 #include <glob.h>
38
39 /* local */
40 #include "connection_list.h"
41 #include "kacpimon.h"
42
43 #define DIM(a)  (sizeof(a) / sizeof(a[0]))
44
45 #define INPUT_LAYER_FS "/dev/input/event*"
46
47 /*-----------------------------------------------------------------*/
48 /* called when an input layer event is received */
49 void process_input(int fd)
50 {
51         struct input_event event;
52         ssize_t nbytes;
53
54         nbytes = read(fd, &event, sizeof(event));
55
56         if (nbytes == 0) {
57                 printf("Input layer connection closed.\n");
58                 return;
59         }
60         
61         if (nbytes < 0) {
62                 /* if it's a signal, bail */
63                 if (errno == EINTR)
64                         return;
65                 
66                 printf("Input layer read error: %s (%d)\n",
67                         strerror(errno), errno);
68                 return;
69         }
70
71         /* ??? Is it possible for a partial message to come across? */
72         /*   If so, we've got more code to write... */
73         
74         if (nbytes != sizeof(event)) {
75                 printf("Input Layer unexpected Length\n");
76                 printf("  Expected: %lu   Got: %zd\n",
77                         (unsigned long) sizeof(event), nbytes);
78                 return;
79         }
80
81         /* If the Escape key was pressed, set the exitflag to exit. */
82         if (event.type == EV_KEY  &&
83             event.code == KEY_ESC  &&
84             event.value == 1) {
85                 printf("Escape key pressed\n");
86                 exitflag = 1;
87         }
88
89         if (event.type == EV_SYN)
90                 printf("Input Layer:  Sync\n");
91         else
92                 /* format and display the event struct in decimal */
93                 printf("Input Layer:  "
94                         "Type: %hu  Code: %hu  Value: %d\n",
95                         event.type, event.code, event.value);
96 }
97
98 #define BITS_PER_LONG (sizeof(long) * 8)
99 #define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
100 #define OFF(x)  ((x)%BITS_PER_LONG)
101 #define LONG(x) ((x)/BITS_PER_LONG)
102 #define test_bit(bit, array)    ((array[LONG(bit)] >> OFF(bit)) & 1)
103
104 /*-----------------------------------------------------------------*
105  * open each of the appropriate /dev/input/event* files for input  */
106 void open_input(void)
107 {
108         char *filename = NULL;
109         glob_t globbuf;
110         unsigned i;
111         int fd;
112         struct connection c;
113         int had_some_success = 0;
114         char evname[256];
115
116         /* get all the matching event filenames */
117         glob(INPUT_LAYER_FS, 0, NULL, &globbuf);
118
119         /* for each event file */
120         for (i = 0; i < globbuf.gl_pathc; ++i)
121         {
122                 filename = globbuf.gl_pathv[i];
123
124                 fd = open(filename, O_RDONLY | O_NONBLOCK);
125                 if (fd >= 0) {
126                         /* get this event file's name */
127                         strcpy(evname, "Unknown");
128                         ioctl(fd, EVIOCGNAME(sizeof(evname)), evname);
129
130                         printf("%s (%s) opened successfully\n", filename, evname);
131                         had_some_success = 1;
132
133                         /* add a connection to the list */
134                         c.fd = fd;
135                         c.process = process_input;
136                         add_connection(&c);
137                 }
138                 else
139                 {
140                         if (had_some_success == 1)
141                                 continue;
142                         int errno2 = errno;
143                         printf("open for %s failed: %s (%d)\n", 
144                                 filename, strerror(errno2), errno2);
145                         if (errno2 == EACCES)
146                                 printf("  (try running as root)\n");
147                         if (errno2 == ENOENT)
148                                 printf("  (input layer driver may not be present)\n");
149                 }
150         }
151
152         globfree(&globbuf);
153 }
154