uterm_input_uxkb: update leds to match keyboard state
[platform/upstream/kmscon.git] / src / uterm_input_uxkb.c
1 /*
2  * uterm - Linux User-Space Terminal
3  *
4  * Copyright (c) 2011 Ran Benita <ran234@gmail.com>
5  * Copyright (c) 2012 David Herrmann <dh.herrmann@googlemail.com>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining
8  * a copy of this software and associated documentation files
9  * (the "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sublicense, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included
16  * in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  */
26
27 #include <errno.h>
28 #include <inttypes.h>
29 #include <linux/input.h>
30 #include <stdbool.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <xkbcommon/xkbcommon.h>
35 #include "log.h"
36 #include "shl_hook.h"
37 #include "shl_misc.h"
38 #include "uterm.h"
39 #include "uterm_input.h"
40
41 #define LOG_SUBSYSTEM "input_uxkb"
42
43 int uxkb_desc_init(struct uterm_input *input,
44                    const char *layout,
45                    const char *variant,
46                    const char *options)
47 {
48         int ret;
49         struct xkb_rule_names rmlvo = {
50                 .rules = "evdev",
51                 .model = "",
52                 .layout = layout,
53                 .variant = variant,
54                 .options = options,
55         };
56
57         input->ctx = xkb_context_new(0);
58         if (!input->ctx) {
59                 log_error("cannot create XKB context");
60                 return -ENOMEM;
61         }
62
63         input->keymap = xkb_keymap_new_from_names(input->ctx, &rmlvo, 0);
64         if (!input->keymap) {
65                 log_warn("failed to create keymap (%s, %s, %s), "
66                          "reverting to default system keymap",
67                          layout, variant, options);
68
69                 rmlvo.layout = "";
70                 rmlvo.variant = "";
71                 rmlvo.options = "";
72
73                 input->keymap = xkb_keymap_new_from_names(input->ctx,
74                                                           &rmlvo, 0);
75                 if (!input->keymap) {
76                         log_warn("failed to create XKB keymap");
77                         ret = -EFAULT;
78                         goto err_ctx;
79                 }
80         }
81
82         log_debug("new keyboard description (%s, %s, %s)",
83                   layout, variant, options);
84         return 0;
85
86 err_ctx:
87         xkb_context_unref(input->ctx);
88         return ret;
89 }
90
91 void uxkb_desc_destroy(struct uterm_input *input)
92 {
93         xkb_keymap_unref(input->keymap);
94         xkb_context_unref(input->ctx);
95 }
96
97 static void timer_event(struct ev_timer *timer, uint64_t num, void *data)
98 {
99         struct uterm_input_dev *dev = data;
100
101         dev->repeat_event.handled = false;
102         shl_hook_call(dev->input->hook, dev->input, &dev->repeat_event);
103 }
104
105 int uxkb_dev_init(struct uterm_input_dev *dev)
106 {
107         int ret;
108
109         ret = ev_eloop_new_timer(dev->input->eloop, &dev->repeat_timer, NULL,
110                                  timer_event, dev);
111         if (ret)
112                 return ret;
113
114         dev->state = xkb_state_new(dev->input->keymap);
115         if (!dev->state) {
116                 log_error("cannot create XKB state");
117                 ret = -ENOMEM;
118                 goto err_timer;
119         }
120
121         return 0;
122
123 err_timer:
124         ev_eloop_rm_timer(dev->repeat_timer);
125         return ret;
126 }
127
128 void uxkb_dev_destroy(struct uterm_input_dev *dev)
129 {
130         xkb_state_unref(dev->state);
131         ev_eloop_rm_timer(dev->repeat_timer);
132 }
133
134 #define EVDEV_KEYCODE_OFFSET 8
135 enum {
136         KEY_RELEASED = 0,
137         KEY_PRESSED = 1,
138         KEY_REPEATED = 2,
139 };
140
141 static void uxkb_dev_update_keyboard_leds(struct uterm_input_dev *dev)
142 {
143         static const struct {
144                 int evdev_led;
145                 const char *xkb_led;
146         } leds[] = {
147                 { LED_NUML, XKB_LED_NAME_NUM },
148                 { LED_CAPSL, XKB_LED_NAME_CAPS },
149                 { LED_SCROLLL, XKB_LED_NAME_SCROLL },
150         };
151         struct input_event events[sizeof(leds) / sizeof(*leds)];
152         int i;
153
154         if (!(dev->capabilities & UTERM_DEVICE_HAS_LEDS))
155                 return;
156
157         memset(events, 0, sizeof(events));
158
159         for (i = 0; i < sizeof(leds) / sizeof(*leds); i++) {
160                 events[i].type = EV_LED;
161                 events[i].code = leds[i].evdev_led;
162                 if (xkb_state_led_name_is_active(dev->state,
163                                                 leds[i].xkb_led) > 0)
164                         events[i].value = 1;
165         }
166
167         write(dev->rfd, events, sizeof(events));
168 }
169
170 static inline int uxkb_dev_resize_event(struct uterm_input_dev *dev, size_t s)
171 {
172         uint32_t *tmp;
173
174         if (s > dev->num_syms) {
175                 tmp = realloc(dev->event.keysyms,
176                               sizeof(uint32_t) * s);
177                 if (!tmp) {
178                         log_warning("cannot reallocate keysym buffer");
179                         return -ENOKEY;
180                 }
181                 dev->event.keysyms = tmp;
182
183                 tmp = realloc(dev->event.codepoints,
184                               sizeof(uint32_t) * s);
185                 if (!tmp) {
186                         log_warning("cannot reallocate codepoints buffer");
187                         return -ENOKEY;
188                 }
189                 dev->event.codepoints = tmp;
190
191                 tmp = realloc(dev->repeat_event.keysyms,
192                               sizeof(uint32_t) * s);
193                 if (!tmp) {
194                         log_warning("cannot reallocate keysym buffer");
195                         return -ENOKEY;
196                 }
197                 dev->repeat_event.keysyms = tmp;
198
199                 tmp = realloc(dev->repeat_event.codepoints,
200                               sizeof(uint32_t) * s);
201                 if (!tmp) {
202                         log_warning("cannot reallocate codepoints buffer");
203                         return -ENOKEY;
204                 }
205                 dev->repeat_event.codepoints = tmp;
206
207                 dev->num_syms = s;
208         }
209
210         return 0;
211 }
212
213 static int uxkb_dev_fill_event(struct uterm_input_dev *dev,
214                                struct uterm_input_event *ev,
215                                xkb_keycode_t code,
216                                int num_syms,
217                                const xkb_keysym_t *syms)
218 {
219         int ret, i;
220
221         ret = uxkb_dev_resize_event(dev, num_syms);
222         if (ret)
223                 return ret;
224
225         ev->keycode = code;
226         ev->ascii = shl_get_ascii(dev->state, code, syms, num_syms);
227         ev->mods = shl_get_xkb_mods(dev->state);
228         ev->num_syms = num_syms;
229         memcpy(ev->keysyms, syms, sizeof(uint32_t) * num_syms);
230
231         for (i = 0; i < num_syms; ++i) {
232                 ev->codepoints[i] = xkb_keysym_to_utf32(syms[i]);
233                 if (!ev->codepoints[i])
234                         ev->codepoints[i] = UTERM_INPUT_INVALID;
235         }
236
237         return 0;
238 }
239
240 static void uxkb_dev_repeat(struct uterm_input_dev *dev, unsigned int state)
241 {
242         struct xkb_keymap *keymap = xkb_state_get_keymap(dev->state);
243         unsigned int i;
244         int num_keysyms, ret;
245         const uint32_t *keysyms;
246         struct itimerspec spec;
247
248         if (dev->repeating && dev->repeat_event.keycode == dev->event.keycode) {
249                 if (state == KEY_RELEASED) {
250                         dev->repeating = false;
251                         ev_timer_update(dev->repeat_timer, NULL);
252                 }
253                 return;
254         }
255
256         if (state == KEY_PRESSED &&
257             xkb_keymap_key_repeats(keymap, dev->event.keycode)) {
258                 dev->repeat_event.keycode = dev->event.keycode;
259                 dev->repeat_event.ascii = dev->event.ascii;
260                 dev->repeat_event.mods = dev->event.mods;
261                 dev->repeat_event.num_syms = dev->event.num_syms;
262
263                 for (i = 0; i < dev->event.num_syms; ++i) {
264                         dev->repeat_event.keysyms[i] = dev->event.keysyms[i];
265                         dev->repeat_event.codepoints[i] =
266                                                 dev->event.codepoints[i];
267                 }
268         } else if (dev->repeating &&
269                    !xkb_keymap_key_repeats(keymap, dev->event.keycode)) {
270                 num_keysyms = xkb_state_key_get_syms(dev->state,
271                                                      dev->repeat_event.keycode,
272                                                      &keysyms);
273                 if (num_keysyms <= 0)
274                         return;
275
276                 ret = uxkb_dev_fill_event(dev, &dev->repeat_event,
277                                           dev->repeat_event.keycode,
278                                           num_keysyms, keysyms);
279                 if (ret)
280                         return;
281
282                 return;
283         } else {
284                 return;
285         }
286
287         dev->repeating = true;
288         spec.it_interval.tv_sec = 0;
289         spec.it_interval.tv_nsec = dev->input->repeat_rate * 1000000;
290         spec.it_value.tv_sec = 0;
291         spec.it_value.tv_nsec = dev->input->repeat_delay * 1000000;
292         ev_timer_update(dev->repeat_timer, &spec);
293 }
294
295 int uxkb_dev_process(struct uterm_input_dev *dev,
296                      uint16_t key_state, uint16_t code)
297 {
298         struct xkb_state *state;
299         xkb_keycode_t keycode;
300         const xkb_keysym_t *keysyms;
301         int num_keysyms, ret;
302         enum xkb_state_component changed;
303
304         if (key_state == KEY_REPEATED)
305                 return -ENOKEY;
306
307         state = dev->state;
308         keycode = code + EVDEV_KEYCODE_OFFSET;
309
310         num_keysyms = xkb_state_key_get_syms(state, keycode, &keysyms);
311
312         changed = 0;
313         if (key_state == KEY_PRESSED)
314                 changed = xkb_state_update_key(state, keycode, XKB_KEY_DOWN);
315         else if (key_state == KEY_RELEASED)
316                 changed = xkb_state_update_key(state, keycode, XKB_KEY_UP);
317
318         if (changed & XKB_STATE_LEDS)
319                 uxkb_dev_update_keyboard_leds(dev);
320
321         if (num_keysyms <= 0)
322                 return -ENOKEY;
323
324         ret = uxkb_dev_fill_event(dev, &dev->event, keycode, num_keysyms,
325                                   keysyms);
326         if (ret)
327                 return -ENOKEY;
328
329         uxkb_dev_repeat(dev, key_state);
330
331         if (key_state == KEY_RELEASED)
332                 return -ENOKEY;
333
334         dev->event.handled = false;
335         shl_hook_call(dev->input->hook, dev->input, &dev->event);
336
337         return 0;
338 }
339
340 /*
341  * Call this when we regain control of the keyboard after losing it.
342  * We don't reset the locked group, this should survive a VT switch, etc.
343  */
344 void uxkb_dev_reset(struct uterm_input_dev *dev)
345 {
346         struct xkb_state *state;
347
348         /* TODO: Urghs, while the input device was closed we might have missed
349          * some events that affect internal state. As xkbcommon does not provide
350          * a way to reset the internal state, we simply recreate the state. This
351          * should have the same effect.
352          * It also has a bug that if the CTRL-Release event is skipped, then
353          * every further release will never perform a _real_ release. Kind of
354          * buggy so we should fix it upstream. */
355         state = xkb_state_new(dev->input->keymap);
356         if (!state) {
357                 log_warning("cannot recreate xkb-state");
358                 return;
359         }
360         xkb_state_unref(dev->state);
361         dev->state = state;
362
363         uxkb_dev_update_keyboard_leds(dev);
364 }