1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2012 Lennart Poettering
11 #include <sys/ioctl.h>
13 #include <linux/input.h>
15 #include "sd-messages.h"
17 #include "alloc-util.h"
19 #include "logind-button.h"
20 #include "string-util.h"
23 #define CONST_MAX4(a, b, c, d) CONST_MAX(CONST_MAX(a, b), CONST_MAX(c, d))
25 #define ULONG_BITS (sizeof(unsigned long)*8)
27 static bool bitset_get(const unsigned long *bits
, unsigned i
) {
28 return (bits
[i
/ ULONG_BITS
] >> (i
% ULONG_BITS
)) & 1UL;
31 static void bitset_put(unsigned long *bits
, unsigned i
) {
32 bits
[i
/ ULONG_BITS
] |= (unsigned long) 1 << (i
% ULONG_BITS
);
35 Button
* button_new(Manager
*m
, const char *name
) {
45 b
->name
= strdup(name
);
49 if (hashmap_put(m
->buttons
, b
->name
, b
) < 0) {
60 void button_free(Button
*b
) {
63 hashmap_remove(b
->manager
->buttons
, b
->name
);
65 sd_event_source_unref(b
->io_event_source
);
66 sd_event_source_unref(b
->check_event_source
);
69 /* If the device has been unplugged close() returns
70 * ENODEV, let's ignore this, hence we don't use
79 int button_set_seat(Button
*b
, const char *sn
) {
95 static void button_lid_switch_handle_action(Manager
*manager
, bool is_edge
) {
96 HandleAction handle_action
;
100 /* If we are docked or on external power, handle the lid switch
102 if (manager_is_docked_or_external_displays(manager
))
103 handle_action
= manager
->handle_lid_switch_docked
;
104 else if (manager
->handle_lid_switch_ep
!= _HANDLE_ACTION_INVALID
&&
105 manager_is_on_external_power())
106 handle_action
= manager
->handle_lid_switch_ep
;
108 handle_action
= manager
->handle_lid_switch
;
110 manager_handle_action(manager
, INHIBIT_HANDLE_LID_SWITCH
, handle_action
, manager
->lid_switch_ignore_inhibited
, is_edge
);
113 static int button_recheck(sd_event_source
*e
, void *userdata
) {
114 Button
*b
= userdata
;
117 assert(b
->lid_closed
);
119 button_lid_switch_handle_action(b
->manager
, false);
123 static int button_install_check_event_source(Button
*b
) {
127 /* Install a post handler, so that we keep rechecking as long as the lid is closed. */
129 if (b
->check_event_source
)
132 r
= sd_event_add_post(b
->manager
->event
, &b
->check_event_source
, button_recheck
, b
);
136 return sd_event_source_set_priority(b
->check_event_source
, SD_EVENT_PRIORITY_IDLE
+1);
139 static int button_dispatch(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
140 Button
*b
= userdata
;
141 struct input_event ev
;
148 l
= read(b
->fd
, &ev
, sizeof(ev
));
150 return errno
!= EAGAIN
? -errno
: 0;
151 if ((size_t) l
< sizeof(ev
))
154 if (ev
.type
== EV_KEY
&& ev
.value
> 0) {
161 LOG_MESSAGE("Power key pressed."),
162 "MESSAGE_ID=" SD_MESSAGE_POWER_KEY_STR
);
164 manager_handle_action(b
->manager
, INHIBIT_HANDLE_POWER_KEY
, b
->manager
->handle_power_key
, b
->manager
->power_key_ignore_inhibited
, true);
167 /* The kernel is a bit confused here:
169 KEY_SLEEP = suspend-to-ram, which everybody else calls "suspend"
170 KEY_SUSPEND = suspend-to-disk, which everybody else calls "hibernate"
175 LOG_MESSAGE("Suspend key pressed."),
176 "MESSAGE_ID=" SD_MESSAGE_SUSPEND_KEY_STR
);
178 manager_handle_action(b
->manager
, INHIBIT_HANDLE_SUSPEND_KEY
, b
->manager
->handle_suspend_key
, b
->manager
->suspend_key_ignore_inhibited
, true);
183 LOG_MESSAGE("Hibernate key pressed."),
184 "MESSAGE_ID=" SD_MESSAGE_HIBERNATE_KEY_STR
);
186 manager_handle_action(b
->manager
, INHIBIT_HANDLE_HIBERNATE_KEY
, b
->manager
->handle_hibernate_key
, b
->manager
->hibernate_key_ignore_inhibited
, true);
190 } else if (ev
.type
== EV_SW
&& ev
.value
> 0) {
192 if (ev
.code
== SW_LID
) {
194 LOG_MESSAGE("Lid closed."),
195 "MESSAGE_ID=" SD_MESSAGE_LID_CLOSED_STR
);
197 b
->lid_closed
= true;
198 button_lid_switch_handle_action(b
->manager
, true);
199 button_install_check_event_source(b
);
201 } else if (ev
.code
== SW_DOCK
) {
203 LOG_MESSAGE("System docked."),
204 "MESSAGE_ID=" SD_MESSAGE_SYSTEM_DOCKED_STR
);
209 } else if (ev
.type
== EV_SW
&& ev
.value
== 0) {
211 if (ev
.code
== SW_LID
) {
213 LOG_MESSAGE("Lid opened."),
214 "MESSAGE_ID=" SD_MESSAGE_LID_OPENED_STR
);
216 b
->lid_closed
= false;
217 b
->check_event_source
= sd_event_source_unref(b
->check_event_source
);
219 } else if (ev
.code
== SW_DOCK
) {
221 LOG_MESSAGE("System undocked."),
222 "MESSAGE_ID=" SD_MESSAGE_SYSTEM_UNDOCKED_STR
);
231 static int button_suitable(Button
*b
) {
232 unsigned long types
[CONST_MAX(EV_KEY
, EV_SW
)/ULONG_BITS
+1];
237 if (ioctl(b
->fd
, EVIOCGBIT(EV_SYN
, sizeof(types
)), types
) < 0)
240 if (bitset_get(types
, EV_KEY
)) {
241 unsigned long keys
[CONST_MAX4(KEY_POWER
, KEY_POWER2
, KEY_SLEEP
, KEY_SUSPEND
)/ULONG_BITS
+1];
243 if (ioctl(b
->fd
, EVIOCGBIT(EV_KEY
, sizeof(keys
)), keys
) < 0)
246 if (bitset_get(keys
, KEY_POWER
) ||
247 bitset_get(keys
, KEY_POWER2
) ||
248 bitset_get(keys
, KEY_SLEEP
) ||
249 bitset_get(keys
, KEY_SUSPEND
))
253 if (bitset_get(types
, EV_SW
)) {
254 unsigned long switches
[CONST_MAX(SW_LID
, SW_DOCK
)/ULONG_BITS
+1];
256 if (ioctl(b
->fd
, EVIOCGBIT(EV_SW
, sizeof(switches
)), switches
) < 0)
259 if (bitset_get(switches
, SW_LID
) ||
260 bitset_get(switches
, SW_DOCK
))
267 static int button_set_mask(Button
*b
) {
269 types
[CONST_MAX(EV_KEY
, EV_SW
)/ULONG_BITS
+1] = {},
270 keys
[CONST_MAX4(KEY_POWER
, KEY_POWER2
, KEY_SLEEP
, KEY_SUSPEND
)/ULONG_BITS
+1] = {},
271 switches
[CONST_MAX(SW_LID
, SW_DOCK
)/ULONG_BITS
+1] = {};
272 struct input_mask mask
;
277 bitset_put(types
, EV_KEY
);
278 bitset_put(types
, EV_SW
);
280 mask
= (struct input_mask
) {
282 .codes_size
= sizeof(types
),
283 .codes_ptr
= PTR_TO_UINT64(types
),
286 if (ioctl(b
->fd
, EVIOCSMASK
, &mask
) < 0)
287 /* Log only at debug level if the kernel doesn't do EVIOCSMASK yet */
288 return log_full_errno(IN_SET(errno
, ENOTTY
, EOPNOTSUPP
, EINVAL
) ? LOG_DEBUG
: LOG_WARNING
,
289 errno
, "Failed to set EV_SYN event mask on /dev/input/%s: %m", b
->name
);
291 bitset_put(keys
, KEY_POWER
);
292 bitset_put(keys
, KEY_POWER2
);
293 bitset_put(keys
, KEY_SLEEP
);
294 bitset_put(keys
, KEY_SUSPEND
);
296 mask
= (struct input_mask
) {
298 .codes_size
= sizeof(keys
),
299 .codes_ptr
= PTR_TO_UINT64(keys
),
302 if (ioctl(b
->fd
, EVIOCSMASK
, &mask
) < 0)
303 return log_warning_errno(errno
, "Failed to set EV_KEY event mask on /dev/input/%s: %m", b
->name
);
305 bitset_put(switches
, SW_LID
);
306 bitset_put(switches
, SW_DOCK
);
308 mask
= (struct input_mask
) {
310 .codes_size
= sizeof(switches
),
311 .codes_ptr
= PTR_TO_UINT64(switches
),
314 if (ioctl(b
->fd
, EVIOCSMASK
, &mask
) < 0)
315 return log_warning_errno(errno
, "Failed to set EV_SW event mask on /dev/input/%s: %m", b
->name
);
320 int button_open(Button
*b
) {
326 b
->fd
= safe_close(b
->fd
);
328 p
= strjoina("/dev/input/", b
->name
);
330 b
->fd
= open(p
, O_RDWR
|O_CLOEXEC
|O_NOCTTY
|O_NONBLOCK
);
332 return log_warning_errno(errno
, "Failed to open %s: %m", p
);
334 r
= button_suitable(b
);
336 return log_warning_errno(r
, "Failed to determine whether input device is relevant to us: %m");
338 log_debug("Device %s does not expose keys or switches relevant to us, ignoring.", p
);
339 return -EADDRNOTAVAIL
;
342 if (ioctl(b
->fd
, EVIOCGNAME(sizeof(name
)), name
) < 0) {
343 r
= log_error_errno(errno
, "Failed to get input name: %m");
347 (void) button_set_mask(b
);
349 r
= sd_event_add_io(b
->manager
->event
, &b
->io_event_source
, b
->fd
, EPOLLIN
, button_dispatch
, b
);
351 log_error_errno(r
, "Failed to add button event: %m");
355 log_info("Watching system buttons on /dev/input/%s (%s)", b
->name
, name
);
360 b
->fd
= safe_close(b
->fd
);
364 int button_check_switches(Button
*b
) {
365 unsigned long switches
[CONST_MAX(SW_LID
, SW_DOCK
)/ULONG_BITS
+1] = {};
371 if (ioctl(b
->fd
, EVIOCGSW(sizeof(switches
)), switches
) < 0)
374 b
->lid_closed
= bitset_get(switches
, SW_LID
);
375 b
->docked
= bitset_get(switches
, SW_DOCK
);
378 button_install_check_event_source(b
);