chiark / gitweb /
logind: filter out input devices that have none of the keys/switche we care about
[elogind.git] / src / login / logind-button.c
index c47c415e6076fa8f17c068c2dbcc9e642957c9b0..e53dd63c29756e79088cf83c70f9dd361ffd2bbf 100644 (file)
@@ -243,6 +243,42 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
         return 0;
 }
 
         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] = {},
 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)
 
         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");
 
         if (ioctl(b->fd, EVIOCGNAME(sizeof(name)), name) < 0) {
                 r = log_error_errno(errno, "Failed to get input name: %m");