logind-button.c revision e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cd
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering This file is part of systemd.
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering Copyright 2012 Lennart Poettering
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering systemd is free software; you can redistribute it and/or modify it
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering under the terms of the GNU Lesser General Public License as published by
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering (at your option) any later version.
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering systemd is distributed in the hope that it will be useful, but
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering Lesser General Public License for more details.
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering You should have received a copy of the GNU Lesser General Public License
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart PoetteringButton* button_new(Manager *m, const char *name) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering if (hashmap_put(m->buttons, b->name, b) < 0) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering hashmap_remove(b->manager->buttons, b->name);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering if (b->fd >= 0) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering hashmap_remove(b->manager->button_fds, INT_TO_PTR(b->fd + 1));
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering assert_se(epoll_ctl(b->manager->epoll_fd, EPOLL_CTL_DEL, b->fd, NULL) == 0);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poetteringint button_set_seat(Button *b, const char *sn) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering if (b->fd >= 0) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering b->fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering if (b->fd < 0) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering log_warning("Failed to open %s: %m", b->name);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering if (ioctl(b->fd, EVIOCGNAME(sizeof(name)), name) < 0) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering log_error("Failed to get input name: %m");
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering if (epoll_ctl(b->manager->epoll_fd, EPOLL_CTL_ADD, b->fd, &ev) < 0) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering r = hashmap_put(b->manager->button_fds, INT_TO_PTR(b->fd + 1), b);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering log_error("Failed to add to hash map: %s", strerror(-r));
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering assert_se(epoll_ctl(b->manager->epoll_fd, EPOLL_CTL_DEL, b->fd, NULL) == 0);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering log_info("Watching system buttons on /dev/input/%s (%s)", b->name, name);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poetteringstatic bool has_graphical_session(Manager *m, const char *seat) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poetteringstatic int button_power_off(Button *b, HandleButton handle) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering if (hashmap_size(b->manager->sessions) > 0) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering log_error("Refusing power-off, user is logged in.");
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering if (manager_is_inhibited(b->manager, INHIBIT_SHUTDOWN, INHIBIT_BLOCK, NULL)) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering log_error("Refusing power-off, shutdown is inhibited.");
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering r = bus_manager_shutdown_or_sleep_now_or_later(b->manager, SPECIAL_POWEROFF_TARGET, INHIBIT_SHUTDOWN, &error);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering log_error("Failed to power off: %s", bus_error_message(&error));
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poetteringstatic int button_suspend(Button *b, HandleButton handle) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering if (hashmap_size(b->manager->sessions) > 0) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering log_error("Refusing suspend, user is logged in.");
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering if (manager_is_inhibited(b->manager, INHIBIT_SLEEP, INHIBIT_BLOCK, NULL)) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering log_error("Refusing suspend, sleeping is inhibited.");
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering r = bus_manager_shutdown_or_sleep_now_or_later(b->manager, SPECIAL_SUSPEND_TARGET, INHIBIT_SLEEP, &error);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering log_error("Failed to suspend: %s", bus_error_message(&error));
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering /* If there's a graphical session on the seat this device
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * belongs to we ignore events, it is job of the graphical
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering * session to handle the event. */
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering if (has_graphical_session(b->manager, b->seat))
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering return button_power_off(b, b->manager->handle_power_key);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering return button_suspend(b, b->manager->handle_sleep_key);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering } else if (ev.type == EV_SW && ev.value > 0) {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poettering return button_suspend(b, b->manager->handle_lid_switch);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart Poetteringstatic const char* const handle_button_table[_HANDLE_BUTTON_MAX] = {
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart PoetteringDEFINE_STRING_TABLE_LOOKUP(handle_button, HandleButton);
e9d21f240704f87c6bb5f7fca1c5e6d0f31c84cdLennart PoetteringDEFINE_CONFIG_PARSE_ENUM(config_parse_handle_button, handle_button, HandleButton, "Failed to parse handle button setting");