Create a lid_switch_interface to handle lid switch events, so the touchpad can
be disabled when lid is closed.

Signed-off-by: James Ye <[email protected]>
---
Changes since v1:
 - style and text fixes

 src/evdev.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 src/evdev.h |  8 ++++++
 2 files changed, 100 insertions(+), 2 deletions(-)

diff --git a/src/evdev.c b/src/evdev.c
index c06daa6..56586af 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -68,6 +68,7 @@ enum evdev_device_udev_tags {
         EVDEV_UDEV_TAG_TABLET_PAD = (1 << 8),
         EVDEV_UDEV_TAG_POINTINGSTICK = (1 << 9),
         EVDEV_UDEV_TAG_TRACKBALL = (1 << 10),
+        EVDEV_UDEV_TAG_SWITCH = (1 << 11),
 };
 
 struct evdev_udev_tag_match {
@@ -88,6 +89,7 @@ static const struct evdev_udev_tag_match 
evdev_udev_tag_matches[] = {
        {"ID_INPUT_ACCELEROMETER",      EVDEV_UDEV_TAG_ACCELEROMETER},
        {"ID_INPUT_POINTINGSTICK",      EVDEV_UDEV_TAG_POINTINGSTICK},
        {"ID_INPUT_TRACKBALL",          EVDEV_UDEV_TAG_TRACKBALL},
+       {"ID_INPUT_SWITCH",             EVDEV_UDEV_TAG_SWITCH},
 
        /* sentinel value */
        { 0 },
@@ -1072,6 +1074,13 @@ evdev_tag_keyboard(struct evdev_device *device,
 }
 
 static void
+evdev_tag_lid_switch(struct evdev_device *device,
+                    struct udev_device *udev_device)
+{
+       device->tags |= EVDEV_TAG_LID_SWITCH;
+}
+
+static void
 fallback_process(struct evdev_dispatch *evdev_dispatch,
                 struct evdev_device *device,
                 struct input_event *event,
@@ -1113,6 +1122,32 @@ fallback_process(struct evdev_dispatch *evdev_dispatch,
 }
 
 static void
+lid_switch_process(struct evdev_dispatch *evdev_dispatch,
+                  struct evdev_device *device,
+                  struct input_event *event,
+                  uint64_t time)
+{
+       struct lid_switch_dispatch *dispatch =
+               (struct lid_switch_dispatch*)evdev_dispatch;
+
+       switch (event->type) {
+       case EV_SW:
+               dispatch->lid_is_closed = !!event->value;
+
+               switch_notify_toggle(&device->base,
+                                    time,
+                                    LIBINPUT_SWITCH_LID,
+                                    dispatch->lid_is_closed);
+               break;
+       case EV_SYN:
+               break;
+       default:
+               assert(0 && "Unknown event type");
+               break;
+       }
+}
+
+static void
 release_touches(struct fallback_dispatch *dispatch,
                struct evdev_device *device,
                uint64_t time)
@@ -1237,6 +1272,15 @@ fallback_destroy(struct evdev_dispatch *evdev_dispatch)
        free(dispatch);
 }
 
+static void
+lid_switch_destroy(struct evdev_dispatch *evdev_dispatch)
+{
+       struct lid_switch_dispatch *dispatch =
+               (struct lid_switch_dispatch*)evdev_dispatch;
+
+       free(dispatch);
+}
+
 static int
 evdev_calibration_has_matrix(struct libinput_device *libinput_device)
 {
@@ -1291,6 +1335,19 @@ struct evdev_dispatch_interface fallback_interface = {
        fallback_toggle_touch, /* toggle_touch */
 };
 
+struct evdev_dispatch_interface lid_switch_interface = {
+       lid_switch_process,
+       NULL, /* suspend */
+       NULL, /* remove */
+       lid_switch_destroy,
+       NULL, /* device_added */
+       NULL, /* device_removed */
+       NULL, /* device_suspended */
+       NULL, /* device_resumed */
+       NULL, /* post_added */
+       NULL, /* toggle_touch */
+};
+
 static uint32_t
 evdev_sendevents_get_modes(struct libinput_device *device)
 {
@@ -1800,6 +1857,25 @@ fallback_dispatch_create(struct libinput_device *device)
        return &dispatch->base;
 }
 
+static struct evdev_dispatch *
+lid_switch_dispatch_create(struct libinput_device *device)
+{
+       struct lid_switch_dispatch *dispatch = zalloc(sizeof *dispatch);
+       struct evdev_device *lid_device = (struct evdev_device *)device;
+
+       if (dispatch == NULL)
+               return NULL;
+
+       dispatch->base.interface = &lid_switch_interface;
+
+       evdev_init_sendevents(lid_device, &dispatch->base);
+
+       dispatch->lid_is_closed = false;
+
+       return &dispatch->base;
+}
+
+
 static inline void
 evdev_process_event(struct evdev_device *device, struct input_event *e)
 {
@@ -2508,7 +2584,7 @@ evdev_configure_device(struct evdev_device *device)
        }
 
        log_info(libinput,
-                "input device '%s', %s is tagged by udev 
as:%s%s%s%s%s%s%s%s%s%s\n",
+                "input device '%s', %s is tagged by udev 
as:%s%s%s%s%s%s%s%s%s%s%s\n",
                 device->devname, devnode,
                 udev_tags & EVDEV_UDEV_TAG_KEYBOARD ? " Keyboard" : "",
                 udev_tags & EVDEV_UDEV_TAG_MOUSE ? " Mouse" : "",
@@ -2519,7 +2595,8 @@ evdev_configure_device(struct evdev_device *device)
                 udev_tags & EVDEV_UDEV_TAG_JOYSTICK ? " Joystick" : "",
                 udev_tags & EVDEV_UDEV_TAG_ACCELEROMETER ? " Accelerometer" : 
"",
                 udev_tags & EVDEV_UDEV_TAG_TABLET_PAD ? " TabletPad" : "",
-                udev_tags & EVDEV_UDEV_TAG_TRACKBALL ? " Trackball" : "");
+                udev_tags & EVDEV_UDEV_TAG_TRACKBALL ? " Trackball" : "",
+                udev_tags & EVDEV_UDEV_TAG_SWITCH ? " Switch" : "");
 
        if (udev_tags & EVDEV_UDEV_TAG_ACCELEROMETER) {
                log_info(libinput,
@@ -2631,6 +2708,17 @@ evdev_configure_device(struct evdev_device *device)
                         device->devname, devnode);
        }
 
+       if (udev_tags & EVDEV_UDEV_TAG_SWITCH &&
+           libevdev_has_event_code(evdev, EV_SW, SW_LID)) {
+               dispatch = lid_switch_dispatch_create(&device->base);
+               device->seat_caps |= EVDEV_DEVICE_SWITCH;
+               evdev_tag_lid_switch(device, device->udev_device);
+               log_info(libinput,
+                        "input device '%s', %s is a switch device\n",
+                        device->devname, devnode);
+               return dispatch;
+       }
+
        if (device->seat_caps & EVDEV_DEVICE_POINTER &&
            libevdev_has_event_code(evdev, EV_REL, REL_X) &&
            libevdev_has_event_code(evdev, EV_REL, REL_Y) &&
@@ -3062,6 +3150,8 @@ evdev_device_has_capability(struct evdev_device *device,
                return !!(device->seat_caps & EVDEV_DEVICE_TABLET);
        case LIBINPUT_DEVICE_CAP_TABLET_PAD:
                return !!(device->seat_caps & EVDEV_DEVICE_TABLET_PAD);
+       case LIBINPUT_DEVICE_CAP_SWITCH:
+               return !!(device->seat_caps & EVDEV_DEVICE_SWITCH);
        default:
                return false;
        }
diff --git a/src/evdev.h b/src/evdev.h
index c07b09f..d65510c 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -63,6 +63,7 @@ enum evdev_device_seat_capability {
        EVDEV_DEVICE_TABLET = (1 << 3),
        EVDEV_DEVICE_TABLET_PAD = (1 << 4),
        EVDEV_DEVICE_GESTURE = (1 << 5),
+       EVDEV_DEVICE_SWITCH = (1 << 6),
 };
 
 enum evdev_device_tags {
@@ -71,6 +72,7 @@ enum evdev_device_tags {
        EVDEV_TAG_EXTERNAL_TOUCHPAD = (1 << 2),
        EVDEV_TAG_TRACKPOINT = (1 << 3),
        EVDEV_TAG_KEYBOARD = (1 << 4),
+       EVDEV_TAG_LID_SWITCH = (1 << 5),
 };
 
 enum evdev_middlebutton_state {
@@ -332,6 +334,12 @@ struct fallback_dispatch {
        bool ignore_events;
 };
 
+struct lid_switch_dispatch {
+       struct evdev_dispatch base;
+
+       bool lid_is_closed;
+};
+
 struct evdev_device *
 evdev_device_create(struct libinput_seat *seat,
                    struct udev_device *device);
-- 
2.9.3

_______________________________________________
wayland-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to