uterm: input: allow passing "model" for keyboard descs
[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 *model,
45                    const char *layout,
46                    const char *variant,
47                    const char *options)
48 {
49         int ret;
50         struct xkb_rule_names rmlvo = {
51                 .rules = "evdev",
52                 .model = model,
53                 .layout = layout,
54                 .variant = variant,
55                 .options = options,
56         };
57
58         input->ctx = xkb_context_new(0);
59         if (!input->ctx) {
60                 log_error("cannot create XKB context");
61                 return -ENOMEM;
62         }
63
64         input->keymap = xkb_keymap_new_from_names(input->ctx, &rmlvo, 0);
65         if (!input->keymap) {
66                 log_warn("failed to create keymap (%s, %s, %s, %s), "
67                          "reverting to default system keymap",
68                          model, layout, variant, options);
69
70                 rmlvo.model = "";
71                 rmlvo.layout = "";
72                 rmlvo.variant = "";
73                 rmlvo.options = "";
74
75                 input->keymap = xkb_keymap_new_from_names(input->ctx,
76                                                           &rmlvo, 0);
77                 if (!input->keymap) {
78                         log_warn("failed to create XKB keymap");
79                         ret = -EFAULT;
80                         goto err_ctx;
81                 }
82         }
83
84         log_debug("new keyboard description (%s, %s, %s, %s)",
85                   model, layout, variant, options);
86         return 0;
87
88 err_ctx:
89         xkb_context_unref(input->ctx);
90         return ret;
91 }
92
93 void uxkb_desc_destroy(struct uterm_input *input)
94 {
95         xkb_keymap_unref(input->keymap);
96         xkb_context_unref(input->ctx);
97 }
98
99 static void timer_event(struct ev_timer *timer, uint64_t num, void *data)
100 {
101         struct uterm_input_dev *dev = data;
102
103         dev->repeat_event.handled = false;
104         shl_hook_call(dev->input->hook, dev->input, &dev->repeat_event);
105 }
106
107 int uxkb_dev_init(struct uterm_input_dev *dev)
108 {
109         int ret;
110
111         ret = ev_eloop_new_timer(dev->input->eloop, &dev->repeat_timer, NULL,
112                                  timer_event, dev);
113         if (ret)
114                 return ret;
115
116         dev->state = xkb_state_new(dev->input->keymap);
117         if (!dev->state) {
118                 log_error("cannot create XKB state");
119                 ret = -ENOMEM;
120                 goto err_timer;
121         }
122
123         return 0;
124
125 err_timer:
126         ev_eloop_rm_timer(dev->repeat_timer);
127         return ret;
128 }
129
130 void uxkb_dev_destroy(struct uterm_input_dev *dev)
131 {
132         xkb_state_unref(dev->state);
133         ev_eloop_rm_timer(dev->repeat_timer);
134 }
135
136 #define EVDEV_KEYCODE_OFFSET 8
137 enum {
138         KEY_RELEASED = 0,
139         KEY_PRESSED = 1,
140         KEY_REPEATED = 2,
141 };
142
143 static void uxkb_dev_update_keyboard_leds(struct uterm_input_dev *dev)
144 {
145         static const struct {
146                 int evdev_led;
147                 const char *xkb_led;
148         } leds[] = {
149                 { LED_NUML, XKB_LED_NAME_NUM },
150                 { LED_CAPSL, XKB_LED_NAME_CAPS },
151                 { LED_SCROLLL, XKB_LED_NAME_SCROLL },
152         };
153         struct input_event events[sizeof(leds) / sizeof(*leds)];
154         int i;
155
156         if (!(dev->capabilities & UTERM_DEVICE_HAS_LEDS))
157                 return;
158
159         memset(events, 0, sizeof(events));
160
161         for (i = 0; i < sizeof(leds) / sizeof(*leds); i++) {
162                 events[i].type = EV_LED;
163                 events[i].code = leds[i].evdev_led;
164                 if (xkb_state_led_name_is_active(dev->state,
165                                                 leds[i].xkb_led) > 0)
166                         events[i].value = 1;
167         }
168
169         write(dev->rfd, events, sizeof(events));
170 }
171
172 static inline int uxkb_dev_resize_event(struct uterm_input_dev *dev, size_t s)
173 {
174         uint32_t *tmp;
175
176         if (s > dev->num_syms) {
177                 tmp = realloc(dev->event.keysyms,
178                               sizeof(uint32_t) * s);
179                 if (!tmp) {
180                         log_warning("cannot reallocate keysym buffer");
181                         return -ENOKEY;
182                 }
183                 dev->event.keysyms = tmp;
184
185                 tmp = realloc(dev->event.codepoints,
186                               sizeof(uint32_t) * s);
187                 if (!tmp) {
188                         log_warning("cannot reallocate codepoints buffer");
189                         return -ENOKEY;
190                 }
191                 dev->event.codepoints = tmp;
192
193                 tmp = realloc(dev->repeat_event.keysyms,
194                               sizeof(uint32_t) * s);
195                 if (!tmp) {
196                         log_warning("cannot reallocate keysym buffer");
197                         return -ENOKEY;
198                 }
199                 dev->repeat_event.keysyms = tmp;
200
201                 tmp = realloc(dev->repeat_event.codepoints,
202                               sizeof(uint32_t) * s);
203                 if (!tmp) {
204                         log_warning("cannot reallocate codepoints buffer");
205                         return -ENOKEY;
206                 }
207                 dev->repeat_event.codepoints = tmp;
208
209                 dev->num_syms = s;
210         }
211
212         return 0;
213 }
214
215 static int uxkb_dev_fill_event(struct uterm_input_dev *dev,
216                                struct uterm_input_event *ev,
217                                xkb_keycode_t code,
218                                int num_syms,
219                                const xkb_keysym_t *syms)
220 {
221         int ret, i;
222
223         ret = uxkb_dev_resize_event(dev, num_syms);
224         if (ret)
225                 return ret;
226
227         ev->keycode = code;
228         ev->ascii = shl_get_ascii(dev->state, code, syms, num_syms);
229         ev->mods = shl_get_xkb_mods(dev->state);
230         ev->num_syms = num_syms;
231         memcpy(ev->keysyms, syms, sizeof(uint32_t) * num_syms);
232
233         for (i = 0; i < num_syms; ++i) {
234                 ev->codepoints[i] = xkb_keysym_to_utf32(syms[i]);
235                 if (!ev->codepoints[i])
236                         ev->codepoints[i] = UTERM_INPUT_INVALID;
237         }
238
239         return 0;
240 }
241
242 static void uxkb_dev_repeat(struct uterm_input_dev *dev, unsigned int state)
243 {
244         struct xkb_keymap *keymap = xkb_state_get_keymap(dev->state);
245         unsigned int i;
246         int num_keysyms, ret;
247         const uint32_t *keysyms;
248         struct itimerspec spec;
249
250         if (dev->repeating && dev->repeat_event.keycode == dev->event.keycode) {
251                 if (state == KEY_RELEASED) {
252                         dev->repeating = false;
253                         ev_timer_update(dev->repeat_timer, NULL);
254                 }
255                 return;
256         }
257
258         if (state == KEY_PRESSED &&
259             xkb_keymap_key_repeats(keymap, dev->event.keycode)) {
260                 dev->repeat_event.keycode = dev->event.keycode;
261                 dev->repeat_event.ascii = dev->event.ascii;
262                 dev->repeat_event.mods = dev->event.mods;
263                 dev->repeat_event.num_syms = dev->event.num_syms;
264
265                 for (i = 0; i < dev->event.num_syms; ++i) {
266                         dev->repeat_event.keysyms[i] = dev->event.keysyms[i];
267                         dev->repeat_event.codepoints[i] =
268                                                 dev->event.codepoints[i];
269                 }
270         } else if (dev->repeating &&
271                    !xkb_keymap_key_repeats(keymap, dev->event.keycode)) {
272                 num_keysyms = xkb_state_key_get_syms(dev->state,
273                                                      dev->repeat_event.keycode,
274                                                      &keysyms);
275                 if (num_keysyms <= 0)
276                         return;
277
278                 ret = uxkb_dev_fill_event(dev, &dev->repeat_event,
279                                           dev->repeat_event.keycode,
280                                           num_keysyms, keysyms);
281                 if (ret)
282                         return;
283
284                 return;
285         } else {
286                 return;
287         }
288
289         dev->repeating = true;
290         spec.it_interval.tv_sec = 0;
291         spec.it_interval.tv_nsec = dev->input->repeat_rate * 1000000;
292         spec.it_value.tv_sec = 0;
293         spec.it_value.tv_nsec = dev->input->repeat_delay * 1000000;
294         ev_timer_update(dev->repeat_timer, &spec);
295 }
296
297 int uxkb_dev_process(struct uterm_input_dev *dev,
298                      uint16_t key_state, uint16_t code)
299 {
300         struct xkb_state *state;
301         xkb_keycode_t keycode;
302         const xkb_keysym_t *keysyms;
303         int num_keysyms, ret;
304         enum xkb_state_component changed;
305
306         if (key_state == KEY_REPEATED)
307                 return -ENOKEY;
308
309         state = dev->state;
310         keycode = code + EVDEV_KEYCODE_OFFSET;
311
312         num_keysyms = xkb_state_key_get_syms(state, keycode, &keysyms);
313
314         changed = 0;
315         if (key_state == KEY_PRESSED)
316                 changed = xkb_state_update_key(state, keycode, XKB_KEY_DOWN);
317         else if (key_state == KEY_RELEASED)
318                 changed = xkb_state_update_key(state, keycode, XKB_KEY_UP);
319
320         if (changed & XKB_STATE_LEDS)
321                 uxkb_dev_update_keyboard_leds(dev);
322
323         if (num_keysyms <= 0)
324                 return -ENOKEY;
325
326         ret = uxkb_dev_fill_event(dev, &dev->event, keycode, num_keysyms,
327                                   keysyms);
328         if (ret)
329                 return -ENOKEY;
330
331         uxkb_dev_repeat(dev, key_state);
332
333         if (key_state == KEY_RELEASED)
334                 return -ENOKEY;
335
336         dev->event.handled = false;
337         shl_hook_call(dev->input->hook, dev->input, &dev->event);
338
339         return 0;
340 }
341
342 /*
343  * Call this when we regain control of the keyboard after losing it.
344  * We don't reset the locked group, this should survive a VT switch, etc.
345  */
346 void uxkb_dev_reset(struct uterm_input_dev *dev)
347 {
348         struct xkb_state *state;
349
350         /* TODO: Urghs, while the input device was closed we might have missed
351          * some events that affect internal state. As xkbcommon does not provide
352          * a way to reset the internal state, we simply recreate the state. This
353          * should have the same effect.
354          * It also has a bug that if the CTRL-Release event is skipped, then
355          * every further release will never perform a _real_ release. Kind of
356          * buggy so we should fix it upstream. */
357         state = xkb_state_new(dev->input->keymap);
358         if (!state) {
359                 log_warning("cannot recreate xkb-state");
360                 return;
361         }
362         xkb_state_unref(dev->state);
363         dev->state = state;
364
365         uxkb_dev_update_keyboard_leds(dev);
366 }