]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/login/logind-button.c
tree-wide: use LOG_MESSAGE() where possible
[thirdparty/systemd.git] / src / login / logind-button.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <sys/ioctl.h>
6 #include <unistd.h>
7
8 #include "sd-messages.h"
9
10 #include "alloc-util.h"
11 #include "async.h"
12 #include "fd-util.h"
13 #include "logind-button.h"
14 #include "missing_input.h"
15 #include "string-util.h"
16 #include "util.h"
17
18 #define CONST_MAX5(a, b, c, d, e) CONST_MAX(CONST_MAX(a, b), CONST_MAX(CONST_MAX(c, d), e))
19
20 #define ULONG_BITS (sizeof(unsigned long)*8)
21
22 #define LONG_PRESS_DURATION (5 * USEC_PER_SEC)
23
24 static bool bitset_get(const unsigned long *bits, unsigned i) {
25 return (bits[i / ULONG_BITS] >> (i % ULONG_BITS)) & 1UL;
26 }
27
28 static void bitset_put(unsigned long *bits, unsigned i) {
29 bits[i / ULONG_BITS] |= (unsigned long) 1 << (i % ULONG_BITS);
30 }
31
32 Button* button_new(Manager *m, const char *name) {
33 Button *b;
34
35 assert(m);
36 assert(name);
37
38 b = new0(Button, 1);
39 if (!b)
40 return NULL;
41
42 b->name = strdup(name);
43 if (!b->name)
44 return mfree(b);
45
46 if (hashmap_put(m->buttons, b->name, b) < 0) {
47 free(b->name);
48 return mfree(b);
49 }
50
51 b->manager = m;
52 b->fd = -1;
53
54 return b;
55 }
56
57 void button_free(Button *b) {
58 assert(b);
59
60 hashmap_remove(b->manager->buttons, b->name);
61
62 sd_event_source_unref(b->io_event_source);
63 sd_event_source_unref(b->check_event_source);
64
65 asynchronous_close(b->fd);
66
67 free(b->name);
68 free(b->seat);
69 free(b);
70 }
71
72 int button_set_seat(Button *b, const char *sn) {
73 assert(b);
74
75 return free_and_strdup(&b->seat, sn);
76 }
77
78 static void button_lid_switch_handle_action(Manager *manager, bool is_edge) {
79 HandleAction handle_action;
80
81 assert(manager);
82
83 /* If we are docked or on external power, handle the lid switch
84 * differently */
85 if (manager_is_docked_or_external_displays(manager))
86 handle_action = manager->handle_lid_switch_docked;
87 else if (handle_action_valid(manager->handle_lid_switch_ep) && manager_is_on_external_power())
88 handle_action = manager->handle_lid_switch_ep;
89 else
90 handle_action = manager->handle_lid_switch;
91
92 manager_handle_action(manager, INHIBIT_HANDLE_LID_SWITCH, handle_action, manager->lid_switch_ignore_inhibited, is_edge);
93 }
94
95 static int button_recheck(sd_event_source *e, void *userdata) {
96 Button *b = userdata;
97
98 assert(b);
99 assert(b->lid_closed);
100
101 button_lid_switch_handle_action(b->manager, false);
102 return 1;
103 }
104
105 static int button_install_check_event_source(Button *b) {
106 int r;
107 assert(b);
108
109 /* Install a post handler, so that we keep rechecking as long as the lid is closed. */
110
111 if (b->check_event_source)
112 return 0;
113
114 r = sd_event_add_post(b->manager->event, &b->check_event_source, button_recheck, b);
115 if (r < 0)
116 return r;
117
118 return sd_event_source_set_priority(b->check_event_source, SD_EVENT_PRIORITY_IDLE+1);
119 }
120
121 static int long_press_of_power_key_handler(sd_event_source *e, uint64_t usec, void *userdata) {
122 Manager *m = userdata;
123
124 assert(e);
125 assert(m);
126
127 m->power_key_long_press_event_source = sd_event_source_unref(m->power_key_long_press_event_source);
128
129 log_struct(LOG_INFO,
130 LOG_MESSAGE("Power key pressed long."),
131 "MESSAGE_ID=" SD_MESSAGE_POWER_KEY_LONG_PRESS_STR);
132
133 manager_handle_action(m, INHIBIT_HANDLE_POWER_KEY, m->handle_power_key_long_press, m->power_key_ignore_inhibited, true);
134 return 0;
135 }
136
137 static int long_press_of_reboot_key_handler(sd_event_source *e, uint64_t usec, void *userdata) {
138 Manager *m = userdata;
139
140 assert(e);
141 assert(m);
142
143 m->reboot_key_long_press_event_source = sd_event_source_unref(m->reboot_key_long_press_event_source);
144
145 log_struct(LOG_INFO,
146 LOG_MESSAGE("Reboot key pressed long."),
147 "MESSAGE_ID=" SD_MESSAGE_REBOOT_KEY_LONG_PRESS_STR);
148
149 manager_handle_action(m, INHIBIT_HANDLE_REBOOT_KEY, m->handle_reboot_key_long_press, m->reboot_key_ignore_inhibited, true);
150 return 0;
151 }
152
153 static int long_press_of_suspend_key_handler(sd_event_source *e, uint64_t usec, void *userdata) {
154 Manager *m = userdata;
155
156 assert(e);
157 assert(m);
158
159 m->suspend_key_long_press_event_source = sd_event_source_unref(m->suspend_key_long_press_event_source);
160
161 log_struct(LOG_INFO,
162 LOG_MESSAGE("Suspend key pressed long."),
163 "MESSAGE_ID=" SD_MESSAGE_SUSPEND_KEY_LONG_PRESS_STR);
164
165 manager_handle_action(m, INHIBIT_HANDLE_SUSPEND_KEY, m->handle_suspend_key_long_press, m->suspend_key_ignore_inhibited, true);
166 return 0;
167 }
168
169 static int long_press_of_hibernate_key_handler(sd_event_source *e, uint64_t usec, void *userdata) {
170 Manager *m = userdata;
171
172 assert(e);
173 assert(m);
174
175 m->hibernate_key_long_press_event_source = sd_event_source_unref(m->hibernate_key_long_press_event_source);
176
177 log_struct(LOG_INFO,
178 LOG_MESSAGE("Hibernate key pressed long."),
179 "MESSAGE_ID=" SD_MESSAGE_HIBERNATE_KEY_LONG_PRESS_STR);
180
181 manager_handle_action(m, INHIBIT_HANDLE_HIBERNATE_KEY, m->handle_hibernate_key_long_press, m->hibernate_key_ignore_inhibited, true);
182 return 0;
183 }
184
185 static void start_long_press(Manager *m, sd_event_source **e, sd_event_time_handler_t callback) {
186 int r;
187
188 assert(m);
189 assert(e);
190
191 if (*e)
192 return;
193
194 r = sd_event_add_time_relative(
195 m->event,
196 e,
197 CLOCK_MONOTONIC,
198 LONG_PRESS_DURATION, 0,
199 callback, m);
200 if (r < 0)
201 log_warning_errno(r, "Failed to add long press timer event, ignoring: %m");
202 }
203
204 static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
205 Button *b = userdata;
206 struct input_event ev;
207 ssize_t l;
208
209 assert(s);
210 assert(fd == b->fd);
211 assert(b);
212
213 l = read(b->fd, &ev, sizeof(ev));
214 if (l < 0)
215 return errno != EAGAIN ? -errno : 0;
216 if ((size_t) l < sizeof(ev))
217 return -EIO;
218
219 if (ev.type == EV_KEY && ev.value > 0) {
220
221 switch (ev.code) {
222
223 case KEY_POWER:
224 case KEY_POWER2:
225 if (b->manager->handle_power_key_long_press != HANDLE_IGNORE && b->manager->handle_power_key_long_press != b->manager->handle_power_key) {
226 log_debug("Power key pressed. Further action depends on the key press duration.");
227 start_long_press(b->manager, &b->manager->power_key_long_press_event_source, long_press_of_power_key_handler);
228 } else {
229 log_struct(LOG_INFO,
230 LOG_MESSAGE("Power key pressed short."),
231 "MESSAGE_ID=" SD_MESSAGE_POWER_KEY_STR);
232 manager_handle_action(b->manager, INHIBIT_HANDLE_POWER_KEY, b->manager->handle_power_key, b->manager->power_key_ignore_inhibited, true);
233 }
234 break;
235
236 /* The kernel naming is a bit confusing here:
237 KEY_RESTART was probably introduced for media playback purposes, but
238 is now being predominantly used to indicate device reboot.
239 */
240
241 case KEY_RESTART:
242 if (b->manager->handle_reboot_key_long_press != HANDLE_IGNORE && b->manager->handle_reboot_key_long_press != b->manager->handle_reboot_key) {
243 log_debug("Reboot key pressed. Further action depends on the key press duration.");
244 start_long_press(b->manager, &b->manager->reboot_key_long_press_event_source, long_press_of_reboot_key_handler);
245 } else {
246 log_struct(LOG_INFO,
247 LOG_MESSAGE("Reboot key pressed short."),
248 "MESSAGE_ID=" SD_MESSAGE_REBOOT_KEY_STR);
249 manager_handle_action(b->manager, INHIBIT_HANDLE_REBOOT_KEY, b->manager->handle_reboot_key, b->manager->reboot_key_ignore_inhibited, true);
250 }
251 break;
252
253 /* The kernel naming is a bit confusing here:
254
255 KEY_SLEEP = suspend-to-ram, which everybody else calls "suspend"
256 KEY_SUSPEND = suspend-to-disk, which everybody else calls "hibernate"
257 */
258
259 case KEY_SLEEP:
260 if (b->manager->handle_suspend_key_long_press != HANDLE_IGNORE && b->manager->handle_suspend_key_long_press != b->manager->handle_suspend_key) {
261 log_debug("Suspend key pressed. Further action depends on the key press duration.");
262 start_long_press(b->manager, &b->manager->suspend_key_long_press_event_source, long_press_of_suspend_key_handler);
263 } else {
264 log_struct(LOG_INFO,
265 LOG_MESSAGE("Suspend key pressed short."),
266 "MESSAGE_ID=" SD_MESSAGE_SUSPEND_KEY_STR);
267 manager_handle_action(b->manager, INHIBIT_HANDLE_SUSPEND_KEY, b->manager->handle_suspend_key, b->manager->suspend_key_ignore_inhibited, true);
268 }
269 break;
270
271 case KEY_SUSPEND:
272 if (b->manager->handle_hibernate_key_long_press != HANDLE_IGNORE && b->manager->handle_hibernate_key_long_press != b->manager->handle_hibernate_key) {
273 log_debug("Hibernate key pressed. Further action depends on the key press duration.");
274 start_long_press(b->manager, &b->manager->hibernate_key_long_press_event_source, long_press_of_hibernate_key_handler);
275 } else {
276 log_struct(LOG_INFO,
277 LOG_MESSAGE("Hibernate key pressed short."),
278 "MESSAGE_ID=" SD_MESSAGE_HIBERNATE_KEY_STR);
279 manager_handle_action(b->manager, INHIBIT_HANDLE_HIBERNATE_KEY, b->manager->handle_hibernate_key, b->manager->hibernate_key_ignore_inhibited, true);
280 }
281 break;
282 }
283
284 } else if (ev.type == EV_KEY && ev.value == 0) {
285
286 switch (ev.code) {
287
288 case KEY_POWER:
289 case KEY_POWER2:
290 if (b->manager->power_key_long_press_event_source) {
291 /* Long press event timer is still pending and key release
292 event happened. This means that key press duration was
293 insufficient to trigger a long press event
294 */
295 log_struct(LOG_INFO,
296 LOG_MESSAGE("Power key pressed short."),
297 "MESSAGE_ID=" SD_MESSAGE_POWER_KEY_STR);
298
299 b->manager->power_key_long_press_event_source = sd_event_source_unref(b->manager->power_key_long_press_event_source);
300
301 manager_handle_action(b->manager, INHIBIT_HANDLE_POWER_KEY, b->manager->handle_power_key, b->manager->power_key_ignore_inhibited, true);
302 }
303 break;
304
305 case KEY_RESTART:
306 if (b->manager->reboot_key_long_press_event_source) {
307 log_struct(LOG_INFO,
308 LOG_MESSAGE("Reboot key pressed short."),
309 "MESSAGE_ID=" SD_MESSAGE_REBOOT_KEY_STR);
310
311 b->manager->reboot_key_long_press_event_source = sd_event_source_unref(b->manager->reboot_key_long_press_event_source);
312
313 manager_handle_action(b->manager, INHIBIT_HANDLE_REBOOT_KEY, b->manager->handle_reboot_key, b->manager->reboot_key_ignore_inhibited, true);
314 }
315 break;
316
317 case KEY_SLEEP:
318 if (b->manager->suspend_key_long_press_event_source) {
319 log_struct(LOG_INFO,
320 LOG_MESSAGE("Suspend key pressed short."),
321 "MESSAGE_ID=" SD_MESSAGE_SUSPEND_KEY_STR);
322
323 b->manager->suspend_key_long_press_event_source = sd_event_source_unref(b->manager->suspend_key_long_press_event_source);
324
325 manager_handle_action(b->manager, INHIBIT_HANDLE_SUSPEND_KEY, b->manager->handle_suspend_key, b->manager->suspend_key_ignore_inhibited, true);
326 }
327 break;
328 case KEY_SUSPEND:
329 if (b->manager->hibernate_key_long_press_event_source) {
330 log_struct(LOG_INFO,
331 LOG_MESSAGE("Hibernate key pressed short."),
332 "MESSAGE_ID=" SD_MESSAGE_HIBERNATE_KEY_STR);
333
334 b->manager->hibernate_key_long_press_event_source = sd_event_source_unref(b->manager->hibernate_key_long_press_event_source);
335
336 manager_handle_action(b->manager, INHIBIT_HANDLE_HIBERNATE_KEY, b->manager->handle_hibernate_key, b->manager->hibernate_key_ignore_inhibited, true);
337 }
338 break;
339 }
340
341 } else if (ev.type == EV_SW && ev.value > 0) {
342
343 if (ev.code == SW_LID) {
344 log_struct(LOG_INFO,
345 LOG_MESSAGE("Lid closed."),
346 "MESSAGE_ID=" SD_MESSAGE_LID_CLOSED_STR);
347
348 b->lid_closed = true;
349 button_lid_switch_handle_action(b->manager, true);
350 button_install_check_event_source(b);
351
352 } else if (ev.code == SW_DOCK) {
353 log_struct(LOG_INFO,
354 LOG_MESSAGE("System docked."),
355 "MESSAGE_ID=" SD_MESSAGE_SYSTEM_DOCKED_STR);
356
357 b->docked = true;
358 }
359
360 } else if (ev.type == EV_SW && ev.value == 0) {
361
362 if (ev.code == SW_LID) {
363 log_struct(LOG_INFO,
364 LOG_MESSAGE("Lid opened."),
365 "MESSAGE_ID=" SD_MESSAGE_LID_OPENED_STR);
366
367 b->lid_closed = false;
368 b->check_event_source = sd_event_source_unref(b->check_event_source);
369
370 } else if (ev.code == SW_DOCK) {
371 log_struct(LOG_INFO,
372 LOG_MESSAGE("System undocked."),
373 "MESSAGE_ID=" SD_MESSAGE_SYSTEM_UNDOCKED_STR);
374
375 b->docked = false;
376 }
377 }
378
379 return 0;
380 }
381
382 static int button_suitable(int fd) {
383 unsigned long types[CONST_MAX(EV_KEY, EV_SW)/ULONG_BITS+1];
384
385 assert(fd >= 0);
386
387 if (ioctl(fd, EVIOCGBIT(EV_SYN, sizeof types), types) < 0)
388 return -errno;
389
390 if (bitset_get(types, EV_KEY)) {
391 unsigned long keys[CONST_MAX5(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND, KEY_RESTART)/ULONG_BITS+1];
392
393 if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof keys), keys) < 0)
394 return -errno;
395
396 if (bitset_get(keys, KEY_POWER) ||
397 bitset_get(keys, KEY_POWER2) ||
398 bitset_get(keys, KEY_SLEEP) ||
399 bitset_get(keys, KEY_SUSPEND) ||
400 bitset_get(keys, KEY_RESTART))
401 return true;
402 }
403
404 if (bitset_get(types, EV_SW)) {
405 unsigned long switches[CONST_MAX(SW_LID, SW_DOCK)/ULONG_BITS+1];
406
407 if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof switches), switches) < 0)
408 return -errno;
409
410 if (bitset_get(switches, SW_LID) ||
411 bitset_get(switches, SW_DOCK))
412 return true;
413 }
414
415 return false;
416 }
417
418 static int button_set_mask(const char *name, int fd) {
419 unsigned long
420 types[CONST_MAX(EV_KEY, EV_SW)/ULONG_BITS+1] = {},
421 keys[CONST_MAX5(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND, KEY_RESTART)/ULONG_BITS+1] = {},
422 switches[CONST_MAX(SW_LID, SW_DOCK)/ULONG_BITS+1] = {};
423 struct input_mask mask;
424
425 assert(name);
426 assert(fd >= 0);
427
428 bitset_put(types, EV_KEY);
429 bitset_put(types, EV_SW);
430
431 mask = (struct input_mask) {
432 .type = EV_SYN,
433 .codes_size = sizeof(types),
434 .codes_ptr = PTR_TO_UINT64(types),
435 };
436
437 if (ioctl(fd, EVIOCSMASK, &mask) < 0)
438 /* Log only at debug level if the kernel doesn't do EVIOCSMASK yet */
439 return log_full_errno(IN_SET(errno, ENOTTY, EOPNOTSUPP, EINVAL) ? LOG_DEBUG : LOG_WARNING,
440 errno, "Failed to set EV_SYN event mask on /dev/input/%s: %m", name);
441
442 bitset_put(keys, KEY_POWER);
443 bitset_put(keys, KEY_POWER2);
444 bitset_put(keys, KEY_SLEEP);
445 bitset_put(keys, KEY_SUSPEND);
446 bitset_put(keys, KEY_RESTART);
447
448 mask = (struct input_mask) {
449 .type = EV_KEY,
450 .codes_size = sizeof(keys),
451 .codes_ptr = PTR_TO_UINT64(keys),
452 };
453
454 if (ioctl(fd, EVIOCSMASK, &mask) < 0)
455 return log_warning_errno(errno, "Failed to set EV_KEY event mask on /dev/input/%s: %m", name);
456
457 bitset_put(switches, SW_LID);
458 bitset_put(switches, SW_DOCK);
459
460 mask = (struct input_mask) {
461 .type = EV_SW,
462 .codes_size = sizeof(switches),
463 .codes_ptr = PTR_TO_UINT64(switches),
464 };
465
466 if (ioctl(fd, EVIOCSMASK, &mask) < 0)
467 return log_warning_errno(errno, "Failed to set EV_SW event mask on /dev/input/%s: %m", name);
468
469 return 0;
470 }
471
472 int button_open(Button *b) {
473 _cleanup_(asynchronous_closep) int fd = -1;
474 const char *p;
475 char name[256];
476 int r;
477
478 assert(b);
479
480 b->fd = asynchronous_close(b->fd);
481
482 p = strjoina("/dev/input/", b->name);
483
484 fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
485 if (fd < 0)
486 return log_warning_errno(errno, "Failed to open %s: %m", p);
487
488 r = button_suitable(fd);
489 if (r < 0)
490 return log_warning_errno(r, "Failed to determine whether input device %s is relevant to us: %m", p);
491 if (r == 0)
492 return log_debug_errno(SYNTHETIC_ERRNO(EADDRNOTAVAIL),
493 "Device %s does not expose keys or switches relevant to us, ignoring.", p);
494
495 if (ioctl(fd, EVIOCGNAME(sizeof name), name) < 0)
496 return log_error_errno(errno, "Failed to get input name for %s: %m", p);
497
498 (void) button_set_mask(b->name, fd);
499
500 b->io_event_source = sd_event_source_unref(b->io_event_source);
501 r = sd_event_add_io(b->manager->event, &b->io_event_source, fd, EPOLLIN, button_dispatch, b);
502 if (r < 0)
503 return log_error_errno(r, "Failed to add button event for %s: %m", p);
504
505 b->fd = TAKE_FD(fd);
506 log_info("Watching system buttons on %s (%s)", p, name);
507 return 0;
508 }
509
510 int button_check_switches(Button *b) {
511 unsigned long switches[CONST_MAX(SW_LID, SW_DOCK)/ULONG_BITS+1] = {};
512 assert(b);
513
514 if (b->fd < 0)
515 return -EINVAL;
516
517 if (ioctl(b->fd, EVIOCGSW(sizeof(switches)), switches) < 0)
518 return -errno;
519
520 b->lid_closed = bitset_get(switches, SW_LID);
521 b->docked = bitset_get(switches, SW_DOCK);
522
523 if (b->lid_closed)
524 button_install_check_event_source(b);
525
526 return 0;
527 }