X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flogin%2Flogind-button.c;fp=src%2Flogin%2Flogind-button.c;h=e53dd63c29756e79088cf83c70f9dd361ffd2bbf;hp=c47c415e6076fa8f17c068c2dbcc9e642957c9b0;hb=88bbc24cd275253fd495d7bc896adda644316bb5;hpb=964a6d9fb555cc86528eb1cc1f6d044f85584842 diff --git a/src/login/logind-button.c b/src/login/logind-button.c index c47c415e6..e53dd63c2 100644 --- a/src/login/logind-button.c +++ b/src/login/logind-button.c @@ -243,6 +243,42 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u return 0; } +static int button_suitable(Button *b) { + unsigned long types[CONST_MAX(EV_KEY, EV_SW)/ULONG_BITS+1]; + + assert(b); + assert(b->fd); + + if (ioctl(b->fd, EVIOCGBIT(EV_SYN, sizeof(types)), types) < 0) + return -errno; + + if (bitset_get(types, EV_KEY)) { + unsigned long keys[CONST_MAX4(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND)/ULONG_BITS+1]; + + if (ioctl(b->fd, EVIOCGBIT(EV_KEY, sizeof(keys)), keys) < 0) + return -errno; + + if (bitset_get(keys, KEY_POWER) || + bitset_get(keys, KEY_POWER2) || + bitset_get(keys, KEY_SLEEP) || + bitset_get(keys, KEY_SUSPEND)) + return true; + } + + if (bitset_get(types, EV_SW)) { + unsigned long switches[CONST_MAX(SW_LID, SW_DOCK)/ULONG_BITS+1]; + + if (ioctl(b->fd, EVIOCGBIT(EV_SW, sizeof(switches)), switches) < 0) + return -errno; + + if (bitset_get(switches, SW_LID) || + bitset_get(switches, SW_DOCK)) + return true; + } + + return false; +} + static int button_set_mask(Button *b) { unsigned long types[CONST_MAX(EV_KEY, EV_SW)/ULONG_BITS+1] = {}, @@ -308,7 +344,15 @@ int button_open(Button *b) { b->fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); if (b->fd < 0) - return log_warning_errno(errno, "Failed to open %s: %m", b->name); + return log_warning_errno(errno, "Failed to open %s: %m", p); + + r = button_suitable(b); + if (r < 0) + return log_warning_errno(r, "Failed to determine whether input device is relevant to us: %m"); + if (r == 0) { + log_debug("Device %s does not expose keys or switches relevant to us, ignoring.", p); + return -EADDRNOTAVAIL; + } if (ioctl(b->fd, EVIOCGNAME(sizeof(name)), name) < 0) { r = log_error_errno(errno, "Failed to get input name: %m");