Line data Source code
1 : /* SPDX-License-Identifier: LGPL-2.1+ */
2 :
3 : #include <errno.h>
4 : #include <fcntl.h>
5 : #include <string.h>
6 : #include <sys/ioctl.h>
7 : #include <unistd.h>
8 : #include <linux/input.h>
9 :
10 : #include "sd-messages.h"
11 :
12 : #include "alloc-util.h"
13 : #include "fd-util.h"
14 : #include "logind-button.h"
15 : #include "missing_input.h"
16 : #include "string-util.h"
17 : #include "util.h"
18 :
19 : #define CONST_MAX4(a, b, c, d) CONST_MAX(CONST_MAX(a, b), CONST_MAX(c, d))
20 :
21 : #define ULONG_BITS (sizeof(unsigned long)*8)
22 :
23 0 : static bool bitset_get(const unsigned long *bits, unsigned i) {
24 0 : return (bits[i / ULONG_BITS] >> (i % ULONG_BITS)) & 1UL;
25 : }
26 :
27 0 : static void bitset_put(unsigned long *bits, unsigned i) {
28 0 : bits[i / ULONG_BITS] |= (unsigned long) 1 << (i % ULONG_BITS);
29 0 : }
30 :
31 0 : Button* button_new(Manager *m, const char *name) {
32 : Button *b;
33 :
34 0 : assert(m);
35 0 : assert(name);
36 :
37 0 : b = new0(Button, 1);
38 0 : if (!b)
39 0 : return NULL;
40 :
41 0 : b->name = strdup(name);
42 0 : if (!b->name)
43 0 : return mfree(b);
44 :
45 0 : if (hashmap_put(m->buttons, b->name, b) < 0) {
46 0 : free(b->name);
47 0 : return mfree(b);
48 : }
49 :
50 0 : b->manager = m;
51 0 : b->fd = -1;
52 :
53 0 : return b;
54 : }
55 :
56 0 : void button_free(Button *b) {
57 0 : assert(b);
58 :
59 0 : hashmap_remove(b->manager->buttons, b->name);
60 :
61 0 : sd_event_source_unref(b->io_event_source);
62 0 : sd_event_source_unref(b->check_event_source);
63 :
64 0 : if (b->fd >= 0)
65 : /* If the device has been unplugged close() returns
66 : * ENODEV, let's ignore this, hence we don't use
67 : * safe_close() */
68 0 : (void) close(b->fd);
69 :
70 0 : free(b->name);
71 0 : free(b->seat);
72 0 : free(b);
73 0 : }
74 :
75 0 : int button_set_seat(Button *b, const char *sn) {
76 : char *s;
77 :
78 0 : assert(b);
79 0 : assert(sn);
80 :
81 0 : s = strdup(sn);
82 0 : if (!s)
83 0 : return -ENOMEM;
84 :
85 0 : free(b->seat);
86 0 : b->seat = s;
87 :
88 0 : return 0;
89 : }
90 :
91 0 : static void button_lid_switch_handle_action(Manager *manager, bool is_edge) {
92 : HandleAction handle_action;
93 :
94 0 : assert(manager);
95 :
96 : /* If we are docked or on external power, handle the lid switch
97 : * differently */
98 0 : if (manager_is_docked_or_external_displays(manager))
99 0 : handle_action = manager->handle_lid_switch_docked;
100 0 : else if (manager->handle_lid_switch_ep != _HANDLE_ACTION_INVALID &&
101 0 : manager_is_on_external_power())
102 0 : handle_action = manager->handle_lid_switch_ep;
103 : else
104 0 : handle_action = manager->handle_lid_switch;
105 :
106 0 : manager_handle_action(manager, INHIBIT_HANDLE_LID_SWITCH, handle_action, manager->lid_switch_ignore_inhibited, is_edge);
107 0 : }
108 :
109 0 : static int button_recheck(sd_event_source *e, void *userdata) {
110 0 : Button *b = userdata;
111 :
112 0 : assert(b);
113 0 : assert(b->lid_closed);
114 :
115 0 : button_lid_switch_handle_action(b->manager, false);
116 0 : return 1;
117 : }
118 :
119 0 : static int button_install_check_event_source(Button *b) {
120 : int r;
121 0 : assert(b);
122 :
123 : /* Install a post handler, so that we keep rechecking as long as the lid is closed. */
124 :
125 0 : if (b->check_event_source)
126 0 : return 0;
127 :
128 0 : r = sd_event_add_post(b->manager->event, &b->check_event_source, button_recheck, b);
129 0 : if (r < 0)
130 0 : return r;
131 :
132 0 : return sd_event_source_set_priority(b->check_event_source, SD_EVENT_PRIORITY_IDLE+1);
133 : }
134 :
135 0 : static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
136 0 : Button *b = userdata;
137 : struct input_event ev;
138 : ssize_t l;
139 :
140 0 : assert(s);
141 0 : assert(fd == b->fd);
142 0 : assert(b);
143 :
144 0 : l = read(b->fd, &ev, sizeof(ev));
145 0 : if (l < 0)
146 0 : return errno != EAGAIN ? -errno : 0;
147 0 : if ((size_t) l < sizeof(ev))
148 0 : return -EIO;
149 :
150 0 : if (ev.type == EV_KEY && ev.value > 0) {
151 :
152 0 : switch (ev.code) {
153 :
154 0 : case KEY_POWER:
155 : case KEY_POWER2:
156 0 : log_struct(LOG_INFO,
157 : LOG_MESSAGE("Power key pressed."),
158 : "MESSAGE_ID=" SD_MESSAGE_POWER_KEY_STR);
159 :
160 0 : manager_handle_action(b->manager, INHIBIT_HANDLE_POWER_KEY, b->manager->handle_power_key, b->manager->power_key_ignore_inhibited, true);
161 0 : break;
162 :
163 : /* The kernel is a bit confused here:
164 :
165 : KEY_SLEEP = suspend-to-ram, which everybody else calls "suspend"
166 : KEY_SUSPEND = suspend-to-disk, which everybody else calls "hibernate"
167 : */
168 :
169 0 : case KEY_SLEEP:
170 0 : log_struct(LOG_INFO,
171 : LOG_MESSAGE("Suspend key pressed."),
172 : "MESSAGE_ID=" SD_MESSAGE_SUSPEND_KEY_STR);
173 :
174 0 : manager_handle_action(b->manager, INHIBIT_HANDLE_SUSPEND_KEY, b->manager->handle_suspend_key, b->manager->suspend_key_ignore_inhibited, true);
175 0 : break;
176 :
177 0 : case KEY_SUSPEND:
178 0 : log_struct(LOG_INFO,
179 : LOG_MESSAGE("Hibernate key pressed."),
180 : "MESSAGE_ID=" SD_MESSAGE_HIBERNATE_KEY_STR);
181 :
182 0 : manager_handle_action(b->manager, INHIBIT_HANDLE_HIBERNATE_KEY, b->manager->handle_hibernate_key, b->manager->hibernate_key_ignore_inhibited, true);
183 0 : break;
184 : }
185 :
186 0 : } else if (ev.type == EV_SW && ev.value > 0) {
187 :
188 0 : if (ev.code == SW_LID) {
189 0 : log_struct(LOG_INFO,
190 : LOG_MESSAGE("Lid closed."),
191 : "MESSAGE_ID=" SD_MESSAGE_LID_CLOSED_STR);
192 :
193 0 : b->lid_closed = true;
194 0 : button_lid_switch_handle_action(b->manager, true);
195 0 : button_install_check_event_source(b);
196 :
197 0 : } else if (ev.code == SW_DOCK) {
198 0 : log_struct(LOG_INFO,
199 : LOG_MESSAGE("System docked."),
200 : "MESSAGE_ID=" SD_MESSAGE_SYSTEM_DOCKED_STR);
201 :
202 0 : b->docked = true;
203 : }
204 :
205 0 : } else if (ev.type == EV_SW && ev.value == 0) {
206 :
207 0 : if (ev.code == SW_LID) {
208 0 : log_struct(LOG_INFO,
209 : LOG_MESSAGE("Lid opened."),
210 : "MESSAGE_ID=" SD_MESSAGE_LID_OPENED_STR);
211 :
212 0 : b->lid_closed = false;
213 0 : b->check_event_source = sd_event_source_unref(b->check_event_source);
214 :
215 0 : } else if (ev.code == SW_DOCK) {
216 0 : log_struct(LOG_INFO,
217 : LOG_MESSAGE("System undocked."),
218 : "MESSAGE_ID=" SD_MESSAGE_SYSTEM_UNDOCKED_STR);
219 :
220 0 : b->docked = false;
221 : }
222 : }
223 :
224 0 : return 0;
225 : }
226 :
227 0 : static int button_suitable(int fd) {
228 : unsigned long types[CONST_MAX(EV_KEY, EV_SW)/ULONG_BITS+1];
229 :
230 0 : assert(fd >= 0);
231 :
232 0 : if (ioctl(fd, EVIOCGBIT(EV_SYN, sizeof types), types) < 0)
233 0 : return -errno;
234 :
235 0 : if (bitset_get(types, EV_KEY)) {
236 : unsigned long keys[CONST_MAX4(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND)/ULONG_BITS+1];
237 :
238 0 : if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof keys), keys) < 0)
239 0 : return -errno;
240 :
241 0 : if (bitset_get(keys, KEY_POWER) ||
242 0 : bitset_get(keys, KEY_POWER2) ||
243 0 : bitset_get(keys, KEY_SLEEP) ||
244 0 : bitset_get(keys, KEY_SUSPEND))
245 0 : return true;
246 : }
247 :
248 0 : if (bitset_get(types, EV_SW)) {
249 : unsigned long switches[CONST_MAX(SW_LID, SW_DOCK)/ULONG_BITS+1];
250 :
251 0 : if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof switches), switches) < 0)
252 0 : return -errno;
253 :
254 0 : if (bitset_get(switches, SW_LID) ||
255 0 : bitset_get(switches, SW_DOCK))
256 0 : return true;
257 : }
258 :
259 0 : return false;
260 : }
261 :
262 0 : static int button_set_mask(const char *name, int fd) {
263 : unsigned long
264 0 : types[CONST_MAX(EV_KEY, EV_SW)/ULONG_BITS+1] = {},
265 0 : keys[CONST_MAX4(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND)/ULONG_BITS+1] = {},
266 0 : switches[CONST_MAX(SW_LID, SW_DOCK)/ULONG_BITS+1] = {};
267 : struct input_mask mask;
268 :
269 0 : assert(name);
270 0 : assert(fd >= 0);
271 :
272 0 : bitset_put(types, EV_KEY);
273 0 : bitset_put(types, EV_SW);
274 :
275 0 : mask = (struct input_mask) {
276 : .type = EV_SYN,
277 : .codes_size = sizeof(types),
278 0 : .codes_ptr = PTR_TO_UINT64(types),
279 : };
280 :
281 0 : if (ioctl(fd, EVIOCSMASK, &mask) < 0)
282 : /* Log only at debug level if the kernel doesn't do EVIOCSMASK yet */
283 0 : return log_full_errno(IN_SET(errno, ENOTTY, EOPNOTSUPP, EINVAL) ? LOG_DEBUG : LOG_WARNING,
284 : errno, "Failed to set EV_SYN event mask on /dev/input/%s: %m", name);
285 :
286 0 : bitset_put(keys, KEY_POWER);
287 0 : bitset_put(keys, KEY_POWER2);
288 0 : bitset_put(keys, KEY_SLEEP);
289 0 : bitset_put(keys, KEY_SUSPEND);
290 :
291 0 : mask = (struct input_mask) {
292 : .type = EV_KEY,
293 : .codes_size = sizeof(keys),
294 0 : .codes_ptr = PTR_TO_UINT64(keys),
295 : };
296 :
297 0 : if (ioctl(fd, EVIOCSMASK, &mask) < 0)
298 0 : return log_warning_errno(errno, "Failed to set EV_KEY event mask on /dev/input/%s: %m", name);
299 :
300 0 : bitset_put(switches, SW_LID);
301 0 : bitset_put(switches, SW_DOCK);
302 :
303 0 : mask = (struct input_mask) {
304 : .type = EV_SW,
305 : .codes_size = sizeof(switches),
306 0 : .codes_ptr = PTR_TO_UINT64(switches),
307 : };
308 :
309 0 : if (ioctl(fd, EVIOCSMASK, &mask) < 0)
310 0 : return log_warning_errno(errno, "Failed to set EV_SW event mask on /dev/input/%s: %m", name);
311 :
312 0 : return 0;
313 : }
314 :
315 0 : int button_open(Button *b) {
316 0 : _cleanup_close_ int fd = -1;
317 : const char *p;
318 : char name[256];
319 : int r;
320 :
321 0 : assert(b);
322 :
323 0 : b->fd = safe_close(b->fd);
324 :
325 0 : p = strjoina("/dev/input/", b->name);
326 :
327 0 : fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
328 0 : if (fd < 0)
329 0 : return log_warning_errno(errno, "Failed to open %s: %m", p);
330 :
331 0 : r = button_suitable(fd);
332 0 : if (r < 0)
333 0 : return log_warning_errno(r, "Failed to determine whether input device %s is relevant to us: %m", p);
334 0 : if (r == 0)
335 0 : return log_debug_errno(SYNTHETIC_ERRNO(EADDRNOTAVAIL),
336 : "Device %s does not expose keys or switches relevant to us, ignoring.", p);
337 :
338 0 : if (ioctl(fd, EVIOCGNAME(sizeof name), name) < 0)
339 0 : return log_error_errno(errno, "Failed to get input name for %s: %m", p);
340 :
341 0 : (void) button_set_mask(b->name, fd);
342 :
343 0 : b->io_event_source = sd_event_source_unref(b->io_event_source);
344 0 : r = sd_event_add_io(b->manager->event, &b->io_event_source, fd, EPOLLIN, button_dispatch, b);
345 0 : if (r < 0)
346 0 : return log_error_errno(r, "Failed to add button event for %s: %m", p);
347 :
348 0 : b->fd = TAKE_FD(fd);
349 0 : log_info("Watching system buttons on %s (%s)", p, name);
350 0 : return 0;
351 : }
352 :
353 0 : int button_check_switches(Button *b) {
354 0 : unsigned long switches[CONST_MAX(SW_LID, SW_DOCK)/ULONG_BITS+1] = {};
355 0 : assert(b);
356 :
357 0 : if (b->fd < 0)
358 0 : return -EINVAL;
359 :
360 0 : if (ioctl(b->fd, EVIOCGSW(sizeof(switches)), switches) < 0)
361 0 : return -errno;
362 :
363 0 : b->lid_closed = bitset_get(switches, SW_LID);
364 0 : b->docked = bitset_get(switches, SW_DOCK);
365 :
366 0 : if (b->lid_closed)
367 0 : button_install_check_event_source(b);
368 :
369 0 : return 0;
370 : }
|