input: add features mechanism
[platform/upstream/kmscon.git] / src / input.c
1 /*
2  * kmscon - udev input hotplug and evdev handling
3  *
4  * Copyright (c) 2011 Ran Benita <ran234@gmail.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files
8  * (the "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25
26 /*
27  * The main object kmscon_input discovers and monitors input devices, and
28  * adds/removes them accordingly from the devices linked list.
29  *
30  * The udev monitor keeps running even while the object is in INPUT_ASLEEP.
31  * We do this because we'll either lose track of the devices, or otherwise
32  * have to re-scan the devices at every wakeup.
33  *
34  * The kmscon_input_device objects hold the file descriptors for their device
35  * nodes. All events go through the input-object callback; there is currently
36  * no "routing" or any differentiation between them. When the input is put to
37  * sleep, all fd's are closed. When woken up, they are opened. There should be
38  * not spurious events delivered. The initial state depends on the
39  * kmscon_input's state.
40  */
41
42 #include <errno.h>
43 #include <fcntl.h>
44 #include <libudev.h>
45 #include <linux/input.h>
46 #include <stdbool.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <unistd.h>
50
51 #include "eloop.h"
52 #include "input.h"
53 #include "kbd.h"
54 #include "log.h"
55
56 /* How many longs are needed to hold \n bits. */
57 #define NLONGS(n) (((n) + LONG_BIT - 1) / LONG_BIT)
58
59 enum input_state {
60         INPUT_ASLEEP,
61         INPUT_AWAKE,
62 };
63
64 /* See probe_device_features(). */
65 enum device_feature {
66         FEATURE_HAS_KEYS = 0x01,
67 };
68
69 struct kmscon_input_device {
70         size_t ref;
71         struct kmscon_input_device *next;
72         struct kmscon_input *input;
73
74         unsigned int features;
75
76         int rfd;
77         char *devnode;
78         struct kmscon_fd *fd;
79
80         struct kmscon_kbd *kbd;
81 };
82
83 struct kmscon_input {
84         size_t ref;
85         enum input_state state;
86         struct kmscon_input_device *devices;
87
88         struct kmscon_eloop *eloop;
89         kmscon_input_cb cb;
90         void *data;
91
92         struct udev *udev;
93         struct udev_monitor *monitor;
94         struct kmscon_fd *monitor_fd;
95
96         struct kmscon_kbd_desc *desc;
97 };
98
99 static void remove_device(struct kmscon_input *input, const char *node);
100
101 static void notify_key(struct kmscon_input_device *device,
102                                 uint16_t type, uint16_t code, int32_t value)
103 {
104         int ret;
105         struct kmscon_input_event ev;
106         struct kmscon_input *input;
107
108         if (type != EV_KEY)
109                 return;
110
111         input = device->input;
112         ret = kmscon_kbd_process_key(device->kbd, value, code, &ev);
113
114         if (ret && ret != -ENOKEY)
115                 return;
116
117         if (ret != -ENOKEY && input->cb)
118                 input->cb(input, &ev, input->data);
119 }
120
121 static void device_data_arrived(struct kmscon_fd *fd, int mask, void *data)
122 {
123         int i;
124         ssize_t len, n;
125         struct kmscon_input_device *device = data;
126         struct kmscon_input *input = device->input;
127         struct input_event ev[16];
128
129         len = sizeof(ev);
130         while (len == sizeof(ev)) {
131                 len = read(device->rfd, &ev, sizeof(ev));
132                 if (len < 0) {
133                         if (errno == EWOULDBLOCK)
134                                 break;
135
136                         log_warn("input: reading device %s failed %d\n",
137                                                 device->devnode, errno);
138                         remove_device(input, device->devnode);
139                 } else if (len == 0) {
140                         log_debug("input: EOF device %s\n", device->devnode);
141                         remove_device(input, device->devnode);
142                 } else if (len % sizeof(*ev)) {
143                         log_warn("input: read invalid input_event\n");
144                 } else {
145                         n = len / sizeof(*ev);
146                         for (i = 0; i < n; i++)
147                                 notify_key(device, ev[i].type, ev[i].code,
148                                                                 ev[i].value);
149                 }
150         }
151 }
152
153 int kmscon_input_device_wake_up(struct kmscon_input_device *device)
154 {
155         int ret;
156
157         if (!device || !device->input || !device->input->eloop)
158                 return -EINVAL;
159
160         if (device->fd)
161                 return 0;
162
163         device->rfd = open(device->devnode, O_CLOEXEC | O_NONBLOCK | O_RDONLY);
164         if (device->rfd < 0) {
165                 log_warn("input: cannot open input device %s: %d\n",
166                                                 device->devnode, errno);
167                 return -errno;
168         }
169
170         if (device->features & FEATURE_HAS_KEYS) {
171                 /* rediscover the keyboard state if sth changed during sleep */
172                 kmscon_kbd_reset(device->kbd, device->rfd);
173
174                 ret = kmscon_eloop_new_fd(device->input->eloop, &device->fd,
175                                                 device->rfd, KMSCON_READABLE,
176                                                 device_data_arrived, device);
177                 if (ret) {
178                         close(device->rfd);
179                         device->rfd = -1;
180                         return ret;
181                 }
182         }
183
184         return 0;
185 }
186
187 void kmscon_input_device_sleep(struct kmscon_input_device *device)
188 {
189         if (!device)
190                 return;
191
192         if (device->rfd < 0)
193                 return;
194
195         if (device->features & FEATURE_HAS_KEYS)
196                 kmscon_eloop_rm_fd(device->fd);
197
198         device->fd = NULL;
199         close(device->rfd);
200         device->rfd = -1;
201 }
202
203 static int kmscon_input_device_new(struct kmscon_input_device **out,
204                         struct kmscon_input *input, const char *devnode,
205                                                 unsigned int features)
206 {
207         int ret;
208         struct kmscon_input_device *device;
209
210         if (!out || !input)
211                 return -EINVAL;
212
213         log_debug("input: new input device %s\n", devnode);
214
215         device = malloc(sizeof(*device));
216         if (!device)
217                 return -ENOMEM;
218
219         memset(device, 0, sizeof(*device));
220         device->ref = 1;
221
222         device->devnode = strdup(devnode);
223         if (!device->devnode) {
224                 free(device);
225                 return -ENOMEM;
226         }
227
228         ret = kmscon_kbd_new(&device->kbd, input->desc);
229         if (ret) {
230                 free(device->devnode);
231                 free(device);
232                 return ret;
233         }
234
235         device->input = input;
236         device->features = features;
237         device->rfd = -1;
238
239         *out = device;
240         return 0;
241 }
242
243 /* static void kmscon_input_device_ref(struct kmscon_input_device *device) */
244 /* { */
245 /*      if (!device) */
246 /*              return; */
247
248 /*      ++device->ref; */
249 /* } */
250
251 static void kmscon_input_device_unref(struct kmscon_input_device *device)
252 {
253         if (!device || !device->ref)
254                 return;
255
256         if (--device->ref)
257                 return;
258
259         kmscon_input_device_sleep(device);
260         kmscon_kbd_unref(device->kbd);
261         log_debug("input: destroying input device %s\n", device->devnode);
262         free(device->devnode);
263         free(device);
264 }
265
266 int kmscon_input_new(struct kmscon_input **out)
267 {
268         int ret;
269         struct kmscon_input *input;
270         static const char *layout, *variant, *options;
271
272         if (!out)
273                 return -EINVAL;
274
275         input = malloc(sizeof(*input));
276         if (!input)
277                 return -ENOMEM;
278
279         log_debug("input: creating input object\n");
280
281         memset(input, 0, sizeof(*input));
282         input->ref = 1;
283         input->state = INPUT_ASLEEP;
284
285         /* TODO: Make properly configurable */
286         layout = getenv("KMSCON_XKB_LAYOUT") ?: "us";
287         variant = getenv("KMSCON_XKB_VARIANT") ?: "";
288         options = getenv("KMSCON_XKB_OPTIONS") ?: "";
289
290         ret = kmscon_kbd_desc_new(&input->desc, layout, variant, options);
291         if (ret) {
292                 log_warn("input: cannot create xkb description\n");
293                 goto err_free;
294         }
295
296         input->udev = udev_new();
297         if (!input->udev) {
298                 log_warn("input: cannot create udev object\n");
299                 ret = -EFAULT;
300                 goto err_xkb;
301         }
302
303         input->monitor = udev_monitor_new_from_netlink(input->udev, "udev");
304         if (!input->monitor) {
305                 log_warn("input: cannot create udev monitor\n");
306                 ret = -EFAULT;
307                 goto err_udev;
308         }
309
310         ret = udev_monitor_filter_add_match_subsystem_devtype(input->monitor,
311                                                                 "input", NULL);
312         if (ret) {
313                 log_warn("input: cannot add udev filter\n");
314                 ret = -EFAULT;
315                 goto err_monitor;
316         }
317
318         ret = udev_monitor_enable_receiving(input->monitor);
319         if (ret) {
320                 log_warn("input: cannot start udev monitor\n");
321                 ret = -EFAULT;
322                 goto err_monitor;
323         }
324
325         *out = input;
326         return 0;
327
328 err_monitor:
329         udev_monitor_unref(input->monitor);
330 err_udev:
331         udev_unref(input->udev);
332 err_xkb:
333         kmscon_kbd_desc_unref(input->desc);
334 err_free:
335         free(input);
336         return ret;
337 }
338
339 void kmscon_input_ref(struct kmscon_input *input)
340 {
341         if (!input)
342                 return;
343
344         ++input->ref;
345 }
346
347 void kmscon_input_unref(struct kmscon_input *input)
348 {
349         if (!input || !input->ref)
350                 return;
351
352         if (--input->ref)
353                 return;
354
355         kmscon_input_disconnect_eloop(input);
356         udev_monitor_unref(input->monitor);
357         udev_unref(input->udev);
358         kmscon_kbd_desc_unref(input->desc);
359         free(input);
360         log_debug("input: destroying input object\n");
361 }
362
363 /*
364  * See if the device has anything useful to offer.
365  * We go over the desired features and return a mask of enum device_feature's.
366  * */
367 static unsigned int probe_device_features(const char *node)
368 {
369         int i, fd;
370         unsigned int features = 0;
371         unsigned long evbits[NLONGS(EV_CNT)] = { 0 };
372         unsigned long keybits[NLONGS(KEY_CNT)] = { 0 };
373
374         fd = open(node, O_NONBLOCK | O_CLOEXEC);
375         if (fd < 0)
376                 return 0;
377
378         /* Which types of input events the device supports. */
379         errno = 0;
380         ioctl(fd, EVIOCGBIT(0, sizeof(evbits)), evbits);
381         if (errno)
382                 goto err_ioctl;
383
384         /* Device supports keys/buttons. */
385         if (kmscon_evdev_bit_is_set(evbits, EV_KEY)) {
386                 errno = 0;
387                 ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits);
388                 if (errno)
389                         goto err_ioctl;
390
391                 /*
392                  * If the device support any of the normal keyboard keys, we
393                  * take it. Even if the keys are not ordinary they can be
394                  * mapped to anything by the keyboard backend.
395                  */
396                 for (i = KEY_RESERVED; i <= KEY_MIN_INTERESTING; i++) {
397                         if (kmscon_evdev_bit_is_set(keybits, i)) {
398                                 features |= FEATURE_HAS_KEYS;
399                                 break;
400                         }
401                 }
402         }
403
404         close(fd);
405         return features;
406
407 err_ioctl:
408         if (errno != ENOTTY)
409                 log_warn("input: cannot probe features of device (%s): %m\n",
410                                                                         node);
411         close(fd);
412         return 0;
413 }
414
415 static void add_device(struct kmscon_input *input,
416                                         struct udev_device *udev_device)
417 {
418         int ret;
419         struct kmscon_input_device *device;
420         const char *node;
421         unsigned int features;
422
423         if (!input || !udev_device)
424                 return;
425
426         node = udev_device_get_devnode(udev_device);
427         if (!node)
428                 return;
429
430         features = probe_device_features(node);
431         if (!(features & FEATURE_HAS_KEYS)) {
432                 log_debug("input: ignoring non-useful device %s\n", node);
433                 return;
434         }
435
436         ret = kmscon_input_device_new(&device, input, node, features);
437         if (ret) {
438                 log_warn("input: cannot create input device for %s\n",
439                                                                         node);
440                 return;
441         }
442
443         if (input->state == INPUT_AWAKE) {
444                 ret = kmscon_input_device_wake_up(device);
445                 if (ret) {
446                         log_warn("input: cannot wake up new device %s\n",
447                                                                         node);
448                         kmscon_input_device_unref(device);
449                         return;
450                 }
451         }
452
453         device->next = input->devices;
454         input->devices = device;
455         log_debug("input: added device %s (features: %#x)\n", node, features);
456 }
457
458 static void remove_device(struct kmscon_input *input, const char *node)
459 {
460         struct kmscon_input_device *iter, *prev;
461
462         if (!input || !node || !input->devices)
463                 return;
464
465         iter = input->devices;
466         prev = NULL;
467
468         while (iter) {
469                 if (!strcmp(iter->devnode, node)) {
470                         if (prev == NULL)
471                                 input->devices = iter->next;
472                         else
473                                 prev->next = iter->next;
474
475                         kmscon_input_device_unref(iter);
476                         log_debug("input: removed device %s\n", node);
477                         break;
478                 }
479
480                 prev = iter;
481                 iter = iter->next;
482         }
483 }
484
485 static void remove_device_udev(struct kmscon_input *input,
486                                         struct udev_device *udev_device)
487 {
488         const char *node;
489
490         if (!udev_device)
491                 return;
492
493         node = udev_device_get_devnode(udev_device);
494         if (!node)
495                 return;
496
497         remove_device(input, node);
498 }
499
500 static void device_changed(struct kmscon_fd *fd, int mask, void *data)
501 {
502         struct kmscon_input *input = data;
503         struct udev_device *udev_device;
504         const char *action;
505
506         udev_device = udev_monitor_receive_device(input->monitor);
507         if (!udev_device)
508                 return;
509
510         action = udev_device_get_action(udev_device);
511         if (!action) {
512                 log_warn("input: cannot get action field of new device\n");
513                 goto err_device;
514         }
515
516         if (!strcmp(action, "add"))
517                 add_device(input, udev_device);
518         else if (!strcmp(action, "remove"))
519                 remove_device_udev(input, udev_device);
520
521 err_device:
522         udev_device_unref(udev_device);
523 }
524
525 static void add_initial_devices(struct kmscon_input *input)
526 {
527         int ret;
528         struct udev_enumerate *e;
529         struct udev_list_entry *first;
530         struct udev_list_entry *item;
531         struct udev_device *udev_device;
532         const char *syspath;
533
534         e = udev_enumerate_new(input->udev);
535         if (!e) {
536                 log_warn("input: cannot create udev enumeration\n");
537                 return;
538         }
539
540         ret = udev_enumerate_add_match_subsystem(e, "input");
541         if (ret) {
542                 log_warn("input: cannot add match to udev enumeration\n");
543                 goto err_enum;
544         }
545
546         ret = udev_enumerate_scan_devices(e);
547         if (ret) {
548                 log_warn("input: cannot scan udev enumeration\n");
549                 goto err_enum;
550         }
551
552         first = udev_enumerate_get_list_entry(e);
553         udev_list_entry_foreach(item, first) {
554                 syspath = udev_list_entry_get_name(item);
555                 if (!syspath)
556                         continue;
557
558                 udev_device = udev_device_new_from_syspath(input->udev, syspath);
559                 if (!udev_device) {
560                         log_warn("input: cannot create device "
561                                                         "from udev path\n");
562                         continue;
563                 }
564
565                 add_device(input, udev_device);
566                 udev_device_unref(udev_device);
567         }
568
569 err_enum:
570         udev_enumerate_unref(e);
571 }
572
573 int kmscon_input_connect_eloop(struct kmscon_input *input,
574                 struct kmscon_eloop *eloop, kmscon_input_cb cb, void *data)
575 {
576         int ret;
577         int fd;
578
579         if (!input || !eloop || !cb)
580                 return -EINVAL;
581
582         if (input->eloop)
583                 return -EALREADY;
584
585         fd = udev_monitor_get_fd(input->monitor);
586         ret = kmscon_eloop_new_fd(eloop, &input->monitor_fd, fd,
587                                 KMSCON_READABLE, device_changed, input);
588         if (ret)
589                 return ret;
590
591         kmscon_eloop_ref(eloop);
592         input->eloop = eloop;
593         input->cb = cb;
594         input->data = data;
595
596         add_initial_devices(input);
597
598         return 0;
599 }
600
601 void kmscon_input_disconnect_eloop(struct kmscon_input *input)
602 {
603         struct kmscon_input_device *tmp;
604
605         if (!input || !input->eloop)
606                 return;
607
608         while (input->devices) {
609                 tmp = input->devices;
610                 input->devices = tmp->next;
611                 kmscon_input_device_unref(tmp);
612         }
613
614         kmscon_eloop_rm_fd(input->monitor_fd);
615         input->monitor_fd = NULL;
616         kmscon_eloop_unref(input->eloop);
617         input->eloop = NULL;
618         input->cb = NULL;
619         input->data = NULL;
620 }
621
622 void kmscon_input_sleep(struct kmscon_input *input)
623 {
624         struct kmscon_input_device *iter;
625
626         if (!input)
627                 return;
628
629         for (iter = input->devices; iter; iter = iter->next)
630                 kmscon_input_device_sleep(iter);
631
632         input->state = INPUT_ASLEEP;
633 }
634
635 void kmscon_input_wake_up(struct kmscon_input *input)
636 {
637         struct kmscon_input_device *iter, *prev, *tmp;
638         int ret;
639
640         if (!input)
641                 return;
642
643         prev = NULL;
644         iter = input->devices;
645
646         while (iter) {
647                 ret = kmscon_input_device_wake_up(iter);
648                 if (ret) {
649                         if (!prev)
650                                 input->devices = iter->next;
651                         else
652                                 prev->next = iter->next;
653
654                         tmp = iter;
655                         iter = iter->next;
656
657                         log_warn("input: device %s does not wake up, "
658                                         "removing device\n", tmp->devnode);
659                         kmscon_input_device_unref(tmp);
660                 } else {
661                         prev = iter;
662                         iter = iter->next;
663                 }
664         }
665
666         input->state = INPUT_AWAKE;
667 }
668
669 bool kmscon_input_is_asleep(struct kmscon_input *input)
670 {
671         if (!input)
672                 return false;
673
674         return input->state == INPUT_ASLEEP;
675 }