blob: 3e5ef68258985c9e52a313ab4f66d1b9e1800b5a [file] [log] [blame]
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -07001/*
2 * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
David Sodmanbf3f2842014-11-12 08:26:58 -08007#include <ctype.h>
David Sodman8ef20062015-01-06 09:23:40 -08008#include <errno.h>
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -07009#include <fcntl.h>
David Sodman8ef20062015-01-06 09:23:40 -080010#include <libudev.h>
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -070011#include <stdint.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
Dominik Behr93899452014-08-18 22:16:21 -070015#include <sys/select.h>
David Sodman8ef20062015-01-06 09:23:40 -080016#include <unistd.h>
17
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -070018#include "input.h"
David Sodman8ef20062015-01-06 09:23:40 -080019
David Sodmanbbcb0522014-09-19 10:34:07 -070020#include "dbus_interface.h"
21#include "dbus.h"
David Sodmanbf3f2842014-11-12 08:26:58 -080022#include "keysym.h"
David Sodmanbbcb0522014-09-19 10:34:07 -070023#include "util.h"
David Sodman8ef20062015-01-06 09:23:40 -080024
David Sodmanf0a925a2015-05-04 11:19:19 -070025#define MAX_STD_TERMINALS (3)
26#define NUM_SPLASH_TERMINAL (1)
27#define MAX_TERMINALS (MAX_STD_TERMINALS + NUM_SPLASH_TERMINAL)
28#define SPLASH_TERMINAL (MAX_TERMINALS - 1)
David Sodmanbf3f2842014-11-12 08:26:58 -080029
Dominik Behr93899452014-08-18 22:16:21 -070030struct input_dev {
31 int fd;
32 char *path;
33};
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -070034
David Sodmanbf3f2842014-11-12 08:26:58 -080035struct keyboard_state {
36 int shift_state;
37 int control_state;
38 int alt_state;
David Sodmane0cc8312014-11-18 11:16:36 -080039 int search_state;
David Sodmanbf3f2842014-11-12 08:26:58 -080040};
41
Dominik Behr93899452014-08-18 22:16:21 -070042struct {
43 struct udev *udev;
44 struct udev_monitor *udev_monitor;
45 int udev_fd;
46 unsigned int ndevs;
47 struct input_dev *devs;
David Sodmanbf3f2842014-11-12 08:26:58 -080048 struct keyboard_state kbd_state;
David Sodmanbbcb0522014-09-19 10:34:07 -070049 dbus_t *dbus;
David Sodmanbf3f2842014-11-12 08:26:58 -080050 uint32_t current_terminal;
51 terminal_t *terminals[MAX_TERMINALS];
Dominik Behr93899452014-08-18 22:16:21 -070052} input = {
53 .udev = NULL,
54 .udev_monitor = NULL,
55 .udev_fd = -1,
56 .ndevs = 0,
57 .devs = NULL,
David Sodmanbf3f2842014-11-12 08:26:58 -080058 .dbus = NULL,
59 .current_terminal = 0
Dominik Behr93899452014-08-18 22:16:21 -070060};
61
David Sodmane0cc8312014-11-18 11:16:36 -080062static void report_user_activity(int activity_type)
63{
David Sodman19e4f9d2015-03-10 11:11:09 -070064 dbus_bool_t allow_off = false;
David Sodman8ef20062015-01-06 09:23:40 -080065 if (!input.dbus)
66 return;
67
David Sodmane0cc8312014-11-18 11:16:36 -080068 dbus_method_call1(input.dbus, kPowerManagerServiceName,
69 kPowerManagerServicePath,
70 kPowerManagerInterface,
71 kHandleUserActivityMethod,
David Sodman19e4f9d2015-03-10 11:11:09 -070072 DBUS_TYPE_INT32, &activity_type);
David Sodmane0cc8312014-11-18 11:16:36 -080073
74 switch (activity_type) {
75 case USER_ACTIVITY_BRIGHTNESS_UP_KEY_PRESS:
76 (void)dbus_method_call0(input.dbus,
77 kPowerManagerServiceName,
78 kPowerManagerServicePath,
79 kPowerManagerInterface,
80 kIncreaseScreenBrightnessMethod);
81 break;
82 case USER_ACTIVITY_BRIGHTNESS_DOWN_KEY_PRESS:
David Sodman19e4f9d2015-03-10 11:11:09 -070083 /*
84 * Shouldn't allow the screen to go
85 * completely off while frecon is active
86 * so passing false to allow_off
87 */
88 (void)dbus_method_call1(input.dbus,
David Sodmane0cc8312014-11-18 11:16:36 -080089 kPowerManagerServiceName,
90 kPowerManagerServicePath,
91 kPowerManagerInterface,
David Sodman19e4f9d2015-03-10 11:11:09 -070092 kDecreaseScreenBrightnessMethod,
93 DBUS_TYPE_BOOLEAN, &allow_off);
David Sodmane0cc8312014-11-18 11:16:36 -080094 break;
95 }
96}
97
David Sodmanbf3f2842014-11-12 08:26:58 -080098static int input_special_key(struct input_key_event *ev)
99{
100 unsigned int i;
David Sodmanb0697c22014-12-12 10:29:25 -0800101 terminal_t *terminal;
David Sodmanbf3f2842014-11-12 08:26:58 -0800102
103 uint32_t ignore_keys[] = {
104 BTN_TOUCH, // touchpad events
105 BTN_TOOL_FINGER,
106 BTN_TOOL_DOUBLETAP,
107 BTN_TOOL_TRIPLETAP,
108 BTN_TOOL_QUADTAP,
109 BTN_TOOL_QUINTTAP,
110 BTN_LEFT, // mouse buttons
111 BTN_RIGHT,
112 BTN_MIDDLE,
113 BTN_SIDE,
114 BTN_EXTRA,
115 BTN_FORWARD,
116 BTN_BACK,
117 BTN_TASK
118 };
119
David Sodmanafba0d92015-01-27 19:07:46 -0800120 terminal = input.terminals[input.current_terminal];
121
David Sodmanbf3f2842014-11-12 08:26:58 -0800122 for (i = 0; i < ARRAY_SIZE(ignore_keys); i++)
123 if (ev->code == ignore_keys[i])
124 return 1;
125
126 switch (ev->code) {
127 case KEY_LEFTSHIFT:
128 case KEY_RIGHTSHIFT:
129 input.kbd_state.shift_state = ! !ev->value;
130 return 1;
131 case KEY_LEFTCTRL:
132 case KEY_RIGHTCTRL:
133 input.kbd_state.control_state = ! !ev->value;
134 return 1;
135 case KEY_LEFTALT:
136 case KEY_RIGHTALT:
137 input.kbd_state.alt_state = ! !ev->value;
138 return 1;
David Sodmane0cc8312014-11-18 11:16:36 -0800139 case KEY_LEFTMETA: // search key
140 input.kbd_state.search_state = ! !ev->value;
141 return 1;
David Sodmanbf3f2842014-11-12 08:26:58 -0800142 }
143
David Sodmanafba0d92015-01-27 19:07:46 -0800144 if (term_is_active(terminal)) {
145 if (input.kbd_state.shift_state && ev->value) {
146 switch (ev->code) {
147 case KEY_PAGEUP:
David Sodmane0cc8312014-11-18 11:16:36 -0800148 term_page_up(input.terminals[input.current_terminal]);
149 return 1;
David Sodmanafba0d92015-01-27 19:07:46 -0800150 case KEY_PAGEDOWN:
David Sodmane0cc8312014-11-18 11:16:36 -0800151 term_page_down(input.terminals[input.current_terminal]);
152 return 1;
David Sodmanafba0d92015-01-27 19:07:46 -0800153 case KEY_UP:
154 term_line_up(input.terminals[input.current_terminal]);
155 return 1;
156 case KEY_DOWN:
157 term_line_down(input.terminals[input.current_terminal]);
158 return 1;
159 }
160 }
161
162 if (input.kbd_state.search_state && ev->value) {
163 switch (ev->code) {
164 case KEY_UP:
165 term_page_up(input.terminals[input.current_terminal]);
166 return 1;
167 case KEY_DOWN:
168 term_page_down(input.terminals[input.current_terminal]);
169 return 1;
170 }
171 }
172
173 if (!(input.kbd_state.search_state || input.kbd_state.alt_state ||
174 input.kbd_state.control_state) &&
175 ev->value && (ev->code >= KEY_F1) && (ev->code <= KEY_F10)) {
176 switch (ev->code) {
177 case KEY_F1:
178 case KEY_F2:
179 case KEY_F3:
180 case KEY_F4:
181 case KEY_F5:
182 break;
183 case KEY_F6:
184 case KEY_F7:
185 report_user_activity(USER_ACTIVITY_BRIGHTNESS_DOWN_KEY_PRESS -
186 (ev->code - KEY_F6));
187 break;
188 case KEY_F8:
189 case KEY_F9:
190 case KEY_F10:
191 break;
192 }
193 return 1;
David Sodmane0cc8312014-11-18 11:16:36 -0800194 }
195 }
196
David Sodmanbf3f2842014-11-12 08:26:58 -0800197 if (input.kbd_state.alt_state && input.kbd_state.control_state && ev->value) {
David Sodman1d1c67f2015-03-12 11:01:08 -0700198 /*
199 * Special case for key sequence that is used by external program. Just
200 * explicitly ignore here and do nothing.
201 */
202 if (input.kbd_state.shift_state)
203 return 1;
204
David Sodmanb0697c22014-12-12 10:29:25 -0800205 if (ev->code == KEY_F1) {
David Sodmanb0697c22014-12-12 10:29:25 -0800206 if (term_is_active(terminal)) {
David Sodmanf0a925a2015-05-04 11:19:19 -0700207 term_deactivate(terminal);
208 if (input.terminals[SPLASH_TERMINAL] != NULL) {
209 term_activate(input.terminals[SPLASH_TERMINAL]);
210 } else {
211 if (input.dbus != NULL)
212 (void)dbus_method_call0(input.dbus,
213 kLibCrosServiceName,
214 kLibCrosServicePath,
215 kLibCrosServiceInterface,
216 kTakeDisplayOwnership);
217 }
David Sodman8ef20062015-01-06 09:23:40 -0800218 }
David Sodmanf0a925a2015-05-04 11:19:19 -0700219 } else if ((ev->code >= KEY_F2) && (ev->code < KEY_F2 + MAX_STD_TERMINALS)) {
David Sodman8ef20062015-01-06 09:23:40 -0800220 if (input.dbus != NULL)
David Sodmanbf3f2842014-11-12 08:26:58 -0800221 (void)dbus_method_call0(input.dbus,
222 kLibCrosServiceName,
223 kLibCrosServicePath,
224 kLibCrosServiceInterface,
David Sodman8ef20062015-01-06 09:23:40 -0800225 kReleaseDisplayOwnership);
David Sodmanbf3f2842014-11-12 08:26:58 -0800226 if (term_is_active(terminal))
David Sodmanf0a925a2015-05-04 11:19:19 -0700227 term_deactivate(terminal);
David Sodmanbf3f2842014-11-12 08:26:58 -0800228 input.current_terminal = ev->code - KEY_F2;
229 terminal = input.terminals[input.current_terminal];
230 if (terminal == NULL) {
231 input.terminals[input.current_terminal] =
David Sodmanf0a925a2015-05-04 11:19:19 -0700232 term_init(true, NULL);
David Sodmanbf3f2842014-11-12 08:26:58 -0800233 terminal =
234 input.terminals[input.current_terminal];
David Sodman8ef20062015-01-06 09:23:40 -0800235 term_activate(terminal);
David Sodmanbf3f2842014-11-12 08:26:58 -0800236 if (!term_is_valid(terminal)) {
237 LOG(ERROR, "Term init failed");
238 return 1;
239 }
240 }
David Sodmanf0a925a2015-05-04 11:19:19 -0700241 term_activate(input.terminals[input.current_terminal]);
David Sodmanbf3f2842014-11-12 08:26:58 -0800242 }
243
244 return 1;
245
246 }
247
248 return 0;
249}
250
251static void input_get_keysym_and_unicode(struct input_key_event *event,
252 uint32_t *keysym, uint32_t *unicode)
253{
254 struct {
255 uint32_t code;
256 uint32_t keysym;
257 } non_ascii_keys[] = {
258 { KEY_ESC, KEYSYM_ESC},
259 { KEY_HOME, KEYSYM_HOME},
260 { KEY_LEFT, KEYSYM_LEFT},
261 { KEY_UP, KEYSYM_UP},
262 { KEY_RIGHT, KEYSYM_RIGHT},
263 { KEY_DOWN, KEYSYM_DOWN},
264 { KEY_PAGEUP, KEYSYM_PAGEUP},
265 { KEY_PAGEDOWN, KEYSYM_PAGEDOWN},
266 { KEY_END, KEYSYM_END},
267 { KEY_INSERT, KEYSYM_INSERT},
268 { KEY_DELETE, KEYSYM_DELETE},
269 };
270
271 for (unsigned i = 0; i < ARRAY_SIZE(non_ascii_keys); i++) {
272 if (non_ascii_keys[i].code == event->code) {
273 *keysym = non_ascii_keys[i].keysym;
274 *unicode = -1;
275 return;
276 }
277 }
278
279 if (event->code >= ARRAY_SIZE(keysym_table) / 2) {
280 *keysym = '?';
281 } else {
282 *keysym = keysym_table[event->code * 2 + input.kbd_state.shift_state];
283 if ((input.kbd_state.control_state) && isascii(*keysym))
284 *keysym = tolower(*keysym) - 'a' + 1;
285 }
286
287 *unicode = *keysym;
288}
289
Dominik Behr93899452014-08-18 22:16:21 -0700290static int input_add(const char *devname)
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700291{
Dominik Behr93899452014-08-18 22:16:21 -0700292 int ret = 0, fd = -1;
293 /* for some reason every device has a null enumerations and notifications
294 of every device come with NULL string first */
295 if (!devname) {
296 ret = -EINVAL;
297 goto errorret;
298 }
299 ret = fd = open(devname, O_RDONLY);
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700300 if (fd < 0)
Dominik Behr93899452014-08-18 22:16:21 -0700301 goto errorret;
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700302
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700303 ret = ioctl(fd, EVIOCGRAB, (void *) 1);
304
305 if (!ret) {
306 ioctl(fd, EVIOCGRAB, (void *) 0);
307 } else {
David Sodmanbbcb0522014-09-19 10:34:07 -0700308 LOG(ERROR, "Evdev device %s grabbed by another process",
Dominik Behr93899452014-08-18 22:16:21 -0700309 devname);
310 ret = -EBUSY;
311 goto closefd;
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700312 }
313
Dominik Behr93899452014-08-18 22:16:21 -0700314 struct input_dev *newdevs =
315 realloc(input.devs, (input.ndevs + 1) * sizeof (struct input_dev));
316 if (!newdevs) {
317 ret = -ENOMEM;
318 goto closefd;
319 }
320 input.devs = newdevs;
321 input.devs[input.ndevs].fd = fd;
322 input.devs[input.ndevs].path = strdup(devname);
323 if (!input.devs[input.ndevs].path) {
324 ret = -ENOMEM;
325 goto closefd;
326 }
327 input.ndevs++;
328
329 return fd;
330
331closefd:
332 close(fd);
333errorret:
334 return ret;
335}
336
337static void input_remove(const char *devname)
338{
339 if (!devname) {
340 return;
341 }
342 unsigned int u;
343 for (u = 0; u < input.ndevs; u++) {
344 if (!strcmp(devname, input.devs[u].path)) {
345 free(input.devs[u].path);
346 close(input.devs[u].fd);
347 input.ndevs--;
348 if (u != input.ndevs) {
349 input.devs[u] = input.devs[input.ndevs];
350 }
351 return;
352 }
353 }
354}
355
Dominik Behr93899452014-08-18 22:16:21 -0700356
357int input_init()
358{
359 input.udev = udev_new();
360 if (!input.udev)
361 return -ENOENT;
362 input.udev_monitor = udev_monitor_new_from_netlink(input.udev, "udev");
363 if (!input.udev_monitor) {
364 udev_unref(input.udev);
365 return -ENOENT;
366 }
367 udev_monitor_filter_add_match_subsystem_devtype(input.udev_monitor, "input",
368 NULL);
369 udev_monitor_enable_receiving(input.udev_monitor);
370 input.udev_fd = udev_monitor_get_fd(input.udev_monitor);
371
372 struct udev_enumerate *udev_enum;
373 struct udev_list_entry *devices, *deventry;
374 udev_enum = udev_enumerate_new(input.udev);
375 udev_enumerate_add_match_subsystem(udev_enum, "input");
376 udev_enumerate_scan_devices(udev_enum);
377 devices = udev_enumerate_get_list_entry(udev_enum);
378 udev_list_entry_foreach(deventry, devices) {
379 const char *syspath;
380 struct udev_device *dev;
381 syspath = udev_list_entry_get_name(deventry);
382 dev = udev_device_new_from_syspath(input.udev, syspath);
383 input_add(udev_device_get_devnode(dev));
384 udev_device_unref(dev);
385 }
386 udev_enumerate_unref(udev_enum);
387
388 if (!isatty(fileno(stdout)))
389 setbuf(stdout, NULL);
390
David Sodmanbbcb0522014-09-19 10:34:07 -0700391 if (input.ndevs == 0) {
392 LOG(ERROR, "No valid inputs for terminal");
393 exit(EXIT_SUCCESS);
394 }
395
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700396 return 0;
397}
398
399void input_close()
400{
Dominik Behr93899452014-08-18 22:16:21 -0700401 unsigned int u;
402 for (u = 0; u < input.ndevs; u++) {
403 free(input.devs[u].path);
404 close(input.devs[u].fd);
405 }
406 free(input.devs);
407 input.devs = NULL;
408 input.ndevs = 0;
409
410 udev_monitor_unref(input.udev_monitor);
411 input.udev_monitor = NULL;
412 udev_unref(input.udev);
413 input.udev = NULL;
414 input.udev_fd = -1;
415
David Sodmanbbcb0522014-09-19 10:34:07 -0700416 dbus_destroy(input.dbus);
417
418}
419
420void input_set_dbus(dbus_t* dbus)
421{
422 input.dbus = dbus;
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700423}
424
Dominik Behr93899452014-08-18 22:16:21 -0700425int input_setfds(fd_set * read_set, fd_set * exception_set)
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700426{
Dominik Behr93899452014-08-18 22:16:21 -0700427 unsigned int u;
428 int max = -1;
429 for (u = 0; u < input.ndevs; u++) {
430 FD_SET(input.devs[u].fd, read_set);
431 FD_SET(input.devs[u].fd, exception_set);
432 if (input.devs[u].fd > max)
433 max = input.devs[u].fd;
434 }
435
436 FD_SET(input.udev_fd, read_set);
437 FD_SET(input.udev_fd, exception_set);
438 if (input.udev_fd > max)
439 max = input.udev_fd;
440 return max;
441}
442
Dominik Behr93899452014-08-18 22:16:21 -0700443struct input_key_event *input_get_event(fd_set * read_set,
444 fd_set * exception_set)
445{
446 unsigned int u;
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700447 struct input_event ev;
448 int ret;
449
Dominik Behr93899452014-08-18 22:16:21 -0700450 if (FD_ISSET(input.udev_fd, exception_set)) {
451 /* udev died on us? */
David Sodmanbbcb0522014-09-19 10:34:07 -0700452 LOG(ERROR, "Exception on udev fd");
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700453 }
454
Dominik Behr93899452014-08-18 22:16:21 -0700455 if (FD_ISSET(input.udev_fd, read_set)
456 && !FD_ISSET(input.udev_fd, exception_set)) {
457 /* we got an udev notification */
458 struct udev_device *dev =
459 udev_monitor_receive_device(input.udev_monitor);
460 if (dev) {
461 if (!strcmp("add", udev_device_get_action(dev))) {
462 input_add(udev_device_get_devnode(dev));
463 } else
464 if (!strcmp("remove", udev_device_get_action(dev)))
465 {
466 input_remove(udev_device_get_devnode(dev));
467 }
468 udev_device_unref(dev);
469 }
470 }
471
472 for (u = 0; u < input.ndevs; u++) {
473 if (FD_ISSET(input.devs[u].fd, read_set)
474 && !FD_ISSET(input.devs[u].fd, exception_set)) {
475 ret =
476 read(input.devs[u].fd, &ev, sizeof (struct input_event));
Michael Spang24d20122015-04-22 13:58:16 -0400477 if (ret < 0) {
478 if (errno == EINTR || errno == EAGAIN)
479 continue;
480 if (errno != ENODEV) {
481 LOG(ERROR, "read: %s: %s", input.devs[u].path,
482 strerror(errno));
483 }
484 input_remove(input.devs[u].path);
485 return NULL;
486 } else if (ret < (int) sizeof (struct input_event)) {
David Sodmanbbcb0522014-09-19 10:34:07 -0700487 LOG(ERROR, "expected %d bytes, got %d",
Dominik Behr93899452014-08-18 22:16:21 -0700488 (int) sizeof (struct input_event), ret);
489 return NULL;
490 }
491
492 if (ev.type == EV_KEY) {
493 struct input_key_event *event =
494 malloc(sizeof (*event));
495 event->code = ev.code;
496 event->value = ev.value;
Dominik Behr93899452014-08-18 22:16:21 -0700497 return event;
498 }
499 }
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700500 }
501
502 return NULL;
503}
504
David Sodmanf0a925a2015-05-04 11:19:19 -0700505int input_process(terminal_t* splash_term, uint32_t usec)
506{
507 terminal_t *terminal;
508 terminal_t *new_terminal;
509 fd_set read_set, exception_set;
510 int maxfd;
511 int sstat;
512 struct timeval tm;
513 struct timeval *ptm;
514
515 terminal = input.terminals[input.current_terminal];
516
517 FD_ZERO(&read_set);
518 FD_ZERO(&exception_set);
519
520 if (input.dbus) {
521 dbus_add_fd(input.dbus, &read_set, &exception_set);
522 maxfd = dbus_get_fd(input.dbus) + 1;
523 } else {
524 maxfd = 0;
525 }
526
527 maxfd = MAX(maxfd, input_setfds(&read_set, &exception_set)) + 1;
528
529 for (int i = 0; i < MAX_TERMINALS; i++) {
530 if (term_is_valid(input.terminals[i])) {
531 term_add_fd(input.terminals[i], &read_set, &exception_set);
532 maxfd = MAX(maxfd, term_fd(input.terminals[i])) + 1;
533 term_dispatch_io(input.terminals[i], &read_set);
534 }
535 }
536
537 if (usec) {
538 ptm = &tm;
539 tm.tv_sec = 0;
540 tm.tv_usec = usec;
541 } else
542 ptm = NULL;
543
544 sstat = select(maxfd, &read_set, NULL, &exception_set, ptm);
545 if (sstat == 0)
546 return 0;
547
548
549 if (input.dbus)
550 dbus_dispatch_io(input.dbus);
551
552 if (term_exception(terminal, &exception_set))
553 return -1;
554
555 struct input_key_event *event;
556 event = input_get_event(&read_set, &exception_set);
557 if (event) {
558 if (!input_special_key(event) && event->value) {
559 uint32_t keysym, unicode;
560 // current_terminal can possibly change during
561 // execution of input_special_key
562 terminal = input.terminals[input.current_terminal];
563 if (term_is_active(terminal)) {
564 // Only report user activity when the terminal is active
565 report_user_activity(USER_ACTIVITY_OTHER);
566 input_get_keysym_and_unicode(
567 event, &keysym, &unicode);
568 term_key_event(terminal,
569 keysym, unicode);
570 }
571 }
572 input_put_event(event);
573 }
574
575 for (int i = 0; i < MAX_TERMINALS; i++) {
576 if (term_is_valid(input.terminals[i])) {
577 term_add_fd(input.terminals[i], &read_set, &exception_set);
578 term_dispatch_io(input.terminals[i], &read_set);
579 }
580 }
581
582 if (term_is_valid(terminal)) {
583 if (term_is_child_done(terminal)) {
584 if (terminal == input.terminals[SPLASH_TERMINAL]) {
585 /*
586 * Note: reference is not lost because it is still referenced
587 * by the splash_t structure which will ultimately destroy
588 * it, once it's safe to do so
589 */
590 input.terminals[SPLASH_TERMINAL] = NULL;
591 return -1;
592 }
593 input.terminals[input.current_terminal] = term_init(true, NULL);
594 new_terminal = input.terminals[input.current_terminal];
595 if (!term_is_valid(new_terminal)) {
596 return -1;
597 }
598 term_activate(new_terminal);
599 term_close(terminal);
600 }
601 }
602
603 return 0;
604}
605
David Sodmanbf3f2842014-11-12 08:26:58 -0800606int input_run(bool standalone)
607{
David Sodmanbf3f2842014-11-12 08:26:58 -0800608 terminal_t* terminal;
David Sodmanf0a925a2015-05-04 11:19:19 -0700609 int status;
David Sodmanbf3f2842014-11-12 08:26:58 -0800610
611 if (standalone) {
David Sodman8ef20062015-01-06 09:23:40 -0800612 if (input.dbus) {
613 (void)dbus_method_call0(input.dbus,
614 kLibCrosServiceName,
615 kLibCrosServicePath,
616 kLibCrosServiceInterface,
617 kReleaseDisplayOwnership);
618 }
David Sodmanbf3f2842014-11-12 08:26:58 -0800619
David Sodmanf0a925a2015-05-04 11:19:19 -0700620 input.terminals[input.current_terminal] = term_init(true, NULL);
David Sodmanbf3f2842014-11-12 08:26:58 -0800621 terminal = input.terminals[input.current_terminal];
David Sodman8ef20062015-01-06 09:23:40 -0800622 term_activate(terminal);
David Sodmanbf3f2842014-11-12 08:26:58 -0800623 if (term_is_valid(terminal)) {
624 input_grab();
625 }
626 }
627
628 while (1) {
David Sodmanf0a925a2015-05-04 11:19:19 -0700629 status = input_process(NULL, 0);
630 if (status != 0) {
631 LOG(ERROR, "input process returned %d", status);
632 break;
David Sodmanbf3f2842014-11-12 08:26:58 -0800633 }
634 }
635
636 return 0;
637}
638
Stéphane Marchesinae37e6c2014-08-08 18:19:40 -0700639void input_put_event(struct input_key_event *event)
640{
641 free(event);
642}
David Sodmanbbcb0522014-09-19 10:34:07 -0700643
644void input_grab()
645{
646 unsigned int i;
647 for (i = 0; i < input.ndevs; i++) {
648 (void)ioctl(input.devs[i].fd, EVIOCGRAB, (void *) 1);
649 }
650}
651
652void input_ungrab()
653{
654 unsigned int i;
655 for (i = 0; i < input.ndevs; i++) {
656 (void)ioctl(input.devs[i].fd, EVIOCGRAB, (void*) 0);
657 }
658}
David Sodman8ef20062015-01-06 09:23:40 -0800659
660terminal_t* input_create_term(int vt)
661{
662 terminal_t* terminal;
663
664 if (vt == 0)
665 return input.terminals[input.current_terminal];
666
667 terminal = input.terminals[vt-1];
668 if (term_is_active(terminal))
669 return terminal;
670
671 if (terminal == NULL) {
David Sodmanf0a925a2015-05-04 11:19:19 -0700672 input.terminals[vt-1] = term_init(false, NULL);
David Sodman8ef20062015-01-06 09:23:40 -0800673 terminal = input.terminals[vt-1];
674 if (!term_is_valid(terminal)) {
675 LOG(ERROR, "create_term: Term init failed");
676 }
677 }
678
679 return terminal;
680}
681
David Sodmanf0a925a2015-05-04 11:19:19 -0700682terminal_t* input_create_splash_term(video_t* video)
683{
684 input.terminals[SPLASH_TERMINAL] = term_init(false, video);
685 return input.terminals[SPLASH_TERMINAL];
686}
687
688void input_destroy_splash_term()
689{
690 input.terminals[SPLASH_TERMINAL] = NULL;
691}
692
David Sodman8ef20062015-01-06 09:23:40 -0800693void input_set_current(terminal_t* terminal)
694{
695 int i;
696
David Sodmanf0a925a2015-05-04 11:19:19 -0700697 if (!terminal) {
698 input.terminals[input.current_terminal] = NULL;
699 input.current_terminal = 0;
David Sodman8ef20062015-01-06 09:23:40 -0800700 return;
David Sodmanf0a925a2015-05-04 11:19:19 -0700701 }
David Sodman8ef20062015-01-06 09:23:40 -0800702
703 for (i = 0; i < MAX_TERMINALS; i++) {
704 if (terminal == input.terminals[i]) {
705 input.current_terminal = i;
706 return;
707 }
708 }
709}
710
711unsigned int input_get_maxterminals()
712{
David Sodmanf0a925a2015-05-04 11:19:19 -0700713 return MAX_STD_TERMINALS;
David Sodman8ef20062015-01-06 09:23:40 -0800714}