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