Added lirc.
[irreco.git] / lirc-0.8.4a / daemons / hw_devinput.c
blob42dcf71287cb7978e9babebb2463293ebc2638fb
1 /****************************************************************************
2 ** hw_devinput.c ***********************************************************
3 ****************************************************************************
5 * receive keycodes input via /dev/input/...
6 *
7 * Copyright (C) 2002 Oliver Endriss <o.endriss@gmx.de>
9 * Distribute under GPL version 2 or later.
14 TODO:
16 - use more than 32 bits (?)
22 #ifdef HAVE_CONFIG_H
23 # include <config.h>
24 #endif
26 #include <stdio.h>
27 #include <errno.h>
28 #include <signal.h>
29 #include <unistd.h>
30 #include <sys/fcntl.h>
31 #include <sys/types.h>
32 #include <dirent.h>
33 #include <fnmatch.h>
35 #include <linux/input.h>
37 #ifndef EV_SYN
38 /* previous name */
39 #define EV_SYN EV_RST
40 #endif
42 #include "hardware.h"
43 #include "ir_remote.h"
44 #include "lircd.h"
45 #include "receive.h"
48 static int devinput_init();
49 static int devinput_deinit(void);
50 static int devinput_decode(struct ir_remote *remote,
51 ir_code *prep, ir_code *codep, ir_code *postp,
52 int *repeat_flagp,
53 lirc_t *min_remaining_gapp,
54 lirc_t *max_remaining_gapp);
55 static char *devinput_rec(struct ir_remote *remotes);
57 enum locate_type {
58 locate_by_name,
59 locate_by_phys,
62 struct hardware hw_devinput=
64 "/dev/input/event0", /* "device" */
65 -1, /* fd (device) */
66 LIRC_CAN_REC_LIRCCODE, /* features */
67 0, /* send_mode */
68 LIRC_MODE_LIRCCODE, /* rec_mode */
69 32, /* code_length */
70 devinput_init, /* init_func */
71 NULL, /* config_func */
72 devinput_deinit, /* deinit_func */
73 NULL, /* send_func */
74 devinput_rec, /* rec_func */
75 devinput_decode, /* decode_func */
76 NULL, /* ioctl_func */
77 NULL, /* readdata */
78 "devinput"
81 static ir_code code;
82 static int repeat_flag=0;
84 #if 0
85 /* using fnmatch */
86 static int do_match (const char *text, const char *wild)
88 while (*wild)
90 if (*wild == '*')
92 const char *next = text;
93 wild++;
94 while(*next)
96 if(do_match (next, wild))
98 return 1;
100 next++;
102 return *wild ? 0:1;
104 else if (*wild == '?')
106 wild++;
107 if (!*text++) return 0;
109 else if (*wild == '\\')
111 if (!wild[1])
113 return 0;
115 if (wild[1] != *text++)
117 return 0;
119 wild += 2;
121 else if (*wild++ != *text++)
123 return 0;
126 return *text ? 0:1;
128 #endif
130 static int locate_dev (const char *pattern, enum locate_type type)
132 static char devname[FILENAME_MAX];
133 char ioname[255];
134 DIR *dir;
135 struct dirent *obj;
136 int request;
138 dir = opendir ("/dev/input");
139 if (!dir)
141 return 1;
144 devname[0] = 0;
145 switch (type)
147 case locate_by_name:
148 request = EVIOCGNAME (sizeof (ioname));
149 break;
150 #ifdef EVIOCGPHYS
151 case locate_by_phys:
152 request = EVIOCGPHYS (sizeof (ioname));
153 break;
154 #endif
155 default:
156 closedir (dir);
157 return 1;
160 while ((obj = readdir (dir)))
162 int fd;
163 if (obj->d_name[0] == '.' &&
164 (obj->d_name[1] == 0 ||
165 (obj->d_name[1] == '.' && obj->d_name[2] == 0)))
167 continue; /* skip "." and ".." */
169 sprintf (devname, "/dev/input/%s", obj->d_name);
170 fd = open (devname, O_RDONLY);
171 if (!fd)
173 continue;
175 if (ioctl (fd, request, ioname) >= 0)
177 int ret;
178 close (fd);
180 ioname[sizeof(ioname)-1] = 0;
181 //ret = !do_match (ioname, pattern);
182 ret = fnmatch(pattern, ioname, 0);
183 if (ret == 0)
185 hw.device = devname;
186 closedir (dir);
187 return 0;
190 close (fd);
193 closedir (dir);
194 return 1;
197 int devinput_init()
199 logprintf(LOG_INFO, "initializing '%s'", hw.device);
201 if (!strncmp (hw.device, "name=", 5)) {
202 if (locate_dev (hw.device + 5, locate_by_name)) {
203 logprintf(LOG_ERR, "unable to find '%s'", hw.device);
204 return 0;
207 else if (!strncmp (hw.device, "phys=", 5)) {
208 if (locate_dev (hw.device + 5, locate_by_phys)) {
209 logprintf(LOG_ERR, "unable to find '%s'", hw.device);
210 return 0;
214 if ((hw.fd = open(hw.device, O_RDONLY)) < 0) {
215 logprintf(LOG_ERR, "unable to open '%s'", hw.device);
216 return 0;
219 #ifdef EVIOCGRAB
220 if (ioctl(hw.fd, EVIOCGRAB, 1) == -1)
222 logprintf(LOG_WARNING, "can't get exclusive access to events "
223 "comming from `%s' interface",
224 hw.device);
226 #endif
228 return 1;
232 int devinput_deinit(void)
234 logprintf(LOG_INFO, "closing '%s'", hw.device);
235 close(hw.fd);
236 hw.fd=-1;
237 return 1;
241 int devinput_decode(struct ir_remote *remote,
242 ir_code *prep, ir_code *codep, ir_code *postp,
243 int *repeat_flagp,
244 lirc_t *min_remaining_gapp,
245 lirc_t *max_remaining_gapp)
247 LOGPRINTF(1, "devinput_decode");
249 if(!map_code(remote,prep,codep,postp,
250 0,0,hw_devinput.code_length,code,0,0))
252 return(0);
255 *repeat_flagp = repeat_flag;
256 *min_remaining_gapp = 0;
257 *max_remaining_gapp = 0;
259 return 1;
263 char *devinput_rec(struct ir_remote *remotes)
265 struct input_event event;
266 int rd;
269 LOGPRINTF(1, "devinput_rec");
271 rd = read(hw.fd, &event, sizeof event);
272 if (rd != sizeof event) {
273 logprintf(LOG_ERR, "error reading '%s'", hw.device);
274 if(rd <= 0 && errno != EINTR) raise(SIGTERM);
275 return 0;
278 LOGPRINTF(1, "time %ld.%06ld type %d code %d value %d",
279 event.time.tv_sec, event.time.tv_usec,
280 event.type, event.code, event.value);
282 code = (event.type == EV_KEY && event.value != 0) ? 0x80000000 : 0;
283 code |= ((event.type & 0x7fff) << 16);
284 code |= event.code;
286 repeat_flag = (event.type == EV_KEY && event.value == 2) ? 1:0;
288 LOGPRINTF(1, "code %.8llx", code);
290 /* ignore EV_SYN */
291 if(event.type == EV_SYN) return NULL;
293 return decode_all(remotes);