From abc9a27208592e34fce2fe850a35222f9f2efd1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Wed, 6 Jan 2021 11:31:13 +0100 Subject: [PATCH] Add Motion Stub to Setsu --- gui/src/streamsession.cpp | 2 +- setsu/CMakeLists.txt | 9 +- setsu/demo/{main.c => touchpad.c} | 6 +- setsu/include/setsu.h | 21 ++- setsu/src/setsu.c | 288 ++++++++++++++++++------------ 5 files changed, 196 insertions(+), 130 deletions(-) rename setsu/demo/{main.c => touchpad.c} (94%) diff --git a/gui/src/streamsession.cpp b/gui/src/streamsession.cpp index 01008a8..52915f0 100644 --- a/gui/src/streamsession.cpp +++ b/gui/src/streamsession.cpp @@ -409,7 +409,7 @@ void StreamSession::HandleSetsuEvent(SetsuEvent *event) switch(event->type) { case SETSU_EVENT_DEVICE_ADDED: - setsu_connect(setsu, event->path); + setsu_connect(setsu, event->path, event->dev_type); break; case SETSU_EVENT_DEVICE_REMOVED: for(auto it=setsu_ids.begin(); it!=setsu_ids.end();) diff --git a/setsu/CMakeLists.txt b/setsu/CMakeLists.txt index 90c1465..186f9c0 100644 --- a/setsu/CMakeLists.txt +++ b/setsu/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.2) project(libsetsu) -option(SETSU_BUILD_DEMO "Build testing executable for libsetsu" OFF) +option(SETSU_BUILD_DEMOS "Build testing executables for libsetsu" OFF) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") @@ -17,9 +17,8 @@ find_package(Udev REQUIRED) find_package(Evdev REQUIRED) target_link_libraries(setsu Udev::libudev Evdev::libevdev) -if(SETSU_BUILD_DEMO) - add_executable(setsu-demo - demo/main.c) - target_link_libraries(setsu-demo setsu) +if(SETSU_BUILD_DEMOS) + add_executable(setsu-demo-touchpad demo/touchpad.c) + target_link_libraries(setsu-demo-touchpad setsu) endif() diff --git a/setsu/demo/main.c b/setsu/demo/touchpad.c similarity index 94% rename from setsu/demo/main.c rename to setsu/demo/touchpad.c index 4219638..5f7deff 100644 --- a/setsu/demo/main.c +++ b/setsu/demo/touchpad.c @@ -68,11 +68,15 @@ void event(SetsuEvent *event, void *user) switch(event->type) { case SETSU_EVENT_DEVICE_ADDED: { - SetsuDevice *dev = setsu_connect(setsu, event->path); + if(event->dev_type != SETSU_DEVICE_TYPE_TOUCHPAD) + break; + SetsuDevice *dev = setsu_connect(setsu, event->path, SETSU_DEVICE_TYPE_TOUCHPAD); LOG("Device added: %s, connect %s\n", event->path, dev ? "succeeded" : "FAILED!"); break; } case SETSU_EVENT_DEVICE_REMOVED: + if(event->dev_type != SETSU_DEVICE_TYPE_TOUCHPAD) + break; LOG("Device removed: %s\n", event->path); break; case SETSU_EVENT_TOUCH_DOWN: diff --git a/setsu/include/setsu.h b/setsu/include/setsu.h index 5e546bc..a2ca4ed 100644 --- a/setsu/include/setsu.h +++ b/setsu/include/setsu.h @@ -13,13 +13,18 @@ typedef struct setsu_t Setsu; typedef struct setsu_device_t SetsuDevice; typedef int SetsuTrackingId; +typedef enum { + SETSU_DEVICE_TYPE_TOUCHPAD, + SETSU_DEVICE_TYPE_MOTION +} SetsuDeviceType; + typedef enum { /* New device available to connect. - * Event will have path set to the new device. */ + * Event will have path and type set to the new device. */ SETSU_EVENT_DEVICE_ADDED, /* Previously available device removed. - * Event will have path set to the new device. + * Event will have path and type set to the removed device. * Any SetsuDevice connected to this path will automatically * be disconnected and their pointers will be invalid immediately * after the callback for this event returns. */ @@ -53,7 +58,11 @@ typedef struct setsu_event_t SetsuEventType type; union { - const char *path; + struct + { + const char *path; + SetsuDeviceType dev_type; + }; struct { SetsuDevice *dev; @@ -75,11 +84,11 @@ typedef void (*SetsuEventCb)(SetsuEvent *event, void *user); Setsu *setsu_new(); void setsu_free(Setsu *setsu); void setsu_poll(Setsu *setsu, SetsuEventCb cb, void *user); -SetsuDevice *setsu_connect(Setsu *setsu, const char *path); +SetsuDevice *setsu_connect(Setsu *setsu, const char *path, SetsuDeviceType type); void setsu_disconnect(Setsu *setsu, SetsuDevice *dev); const char *setsu_device_get_path(SetsuDevice *dev); -uint32_t setsu_device_get_width(SetsuDevice *dev); -uint32_t setsu_device_get_height(SetsuDevice *dev); +uint32_t setsu_device_touchpad_get_width(SetsuDevice *dev); +uint32_t setsu_device_touchpad_get_height(SetsuDevice *dev); #ifdef __cplusplus } diff --git a/setsu/src/setsu.c b/setsu/src/setsu.c index 819b174..b93ef2c 100644 --- a/setsu/src/setsu.c +++ b/setsu/src/setsu.c @@ -25,6 +25,7 @@ typedef struct setsu_avail_device_t { struct setsu_avail_device_t *next; + SetsuDeviceType type; char *path; bool connect_dirty; // whether the connect has not been sent as an event yet bool disconnect_dirty; // whether the disconnect has not been sent as an event yet @@ -36,27 +37,38 @@ typedef struct setsu_device_t { struct setsu_device_t *next; char *path; + SetsuDeviceType type; int fd; struct libevdev *evdev; - int min_x, min_y, max_x, max_y; - struct { - /* Saves the old tracking id that was just up-ed. - * also for handling "atomic" up->down - * i.e. when there is an up, then down with a different tracking id - * in a single frame (before SYN_REPORT), this saves the old - * tracking id that must be reported as up. */ - int tracking_id_prev; + union + { + struct + { + int min_x, min_y, max_x, max_y; - int tracking_id; - int x, y; - bool downed; - bool pos_dirty; - } slots[SLOTS_COUNT]; - unsigned int slot_cur; + struct + { + /* Saves the old tracking id that was just up-ed. + * also for handling "atomic" up->down + * i.e. when there is an up, then down with a different tracking id + * in a single frame (before SYN_REPORT), this saves the old + * tracking id that must be reported as up. */ + int tracking_id_prev; - uint64_t buttons_prev; - uint64_t buttons_cur; + int tracking_id; + int x, y; + bool downed; + bool pos_dirty; + } slots[SLOTS_COUNT]; + unsigned int slot_cur; + uint64_t buttons_prev; + uint64_t buttons_cur; + } touchpad; + struct + { + } motion; + }; } SetsuDevice; struct setsu_t @@ -131,8 +143,8 @@ static void scan_udev(Setsu *setsu) if(udev_enumerate_add_match_subsystem(udev_enum, "input") < 0) goto beach; - if(udev_enumerate_add_match_property(udev_enum, "ID_INPUT_TOUCHPAD", "1") < 0) - goto beach; + //if(udev_enumerate_add_match_property(udev_enum, "ID_INPUT_TOUCHPAD", "1") < 0) + // goto beach; if(udev_enumerate_scan_devices(udev_enum) < 0) goto beach; @@ -153,7 +165,7 @@ beach: udev_enumerate_unref(udev_enum); } -static bool is_device_interesting(struct udev_device *dev) +static bool is_device_interesting(struct udev_device *dev, SetsuDeviceType *type) { static const uint32_t device_ids[] = { // vendor id, model id @@ -162,8 +174,18 @@ static bool is_device_interesting(struct udev_device *dev) 0x54c, 0x0ce6 // DualSense }; - // Filter mouse-device (/dev/input/mouse*) away and only keep the evdev (/dev/input/event*) one: - if(!udev_device_get_property_value(dev, "ID_INPUT_TOUCHPAD_INTEGRATION")) + const char *touchpad_str = udev_device_get_property_value(dev, "ID_INPUT_TOUCHPAD"); + const char *accel_str = udev_device_get_property_value(dev, "ID_INPUT_ACCELEROMETER"); + if(touchpad_str && !strcmp(touchpad_str, "1")) + { + // Filter mouse-device (/dev/input/mouse*) away and only keep the evdev (/dev/input/event*) one: + if(!udev_device_get_property_value(dev, "ID_INPUT_TOUCHPAD_INTEGRATION")) + return false; + *type = SETSU_DEVICE_TYPE_TOUCHPAD; + } + else if(touchpad_str && !strcmp(touchpad_str, "1")) + *type = SETSU_DEVICE_TYPE_MOTION; + else return false; uint32_t vendor; @@ -221,12 +243,14 @@ static void update_udev_device(Setsu *setsu, struct udev_device *dev) } // not yet added - if(!is_device_interesting(dev)) + SetsuDeviceType type; + if(!is_device_interesting(dev, &type)) return; SetsuAvailDevice *adev = calloc(1, sizeof(SetsuAvailDevice)); if(!adev) return; + adev->type = type; adev->path = strdup(path); if(!adev->path) { @@ -272,7 +296,7 @@ bool get_dev_ids(const char *path, uint32_t *vendor_id, uint32_t *model_id) return true; } -SetsuDevice *setsu_connect(Setsu *setsu, const char *path) +SetsuDevice *setsu_connect(Setsu *setsu, const char *path, SetsuDeviceType type) { SetsuDevice *dev = calloc(1, sizeof(SetsuDevice)); if(!dev) @@ -281,6 +305,7 @@ SetsuDevice *setsu_connect(Setsu *setsu, const char *path) dev->path = strdup(path); if(!dev->path) goto error; + dev->type = type; dev->fd = open(dev->path, O_RDONLY | O_NONBLOCK); if(dev->fd == -1) @@ -292,15 +317,23 @@ SetsuDevice *setsu_connect(Setsu *setsu, const char *path) goto error; } - dev->min_x = libevdev_get_abs_minimum(dev->evdev, ABS_X); - dev->min_y = libevdev_get_abs_minimum(dev->evdev, ABS_Y); - dev->max_x = libevdev_get_abs_maximum(dev->evdev, ABS_X); - dev->max_y = libevdev_get_abs_maximum(dev->evdev, ABS_Y); - - for(size_t i=0; islots[i].tracking_id_prev = -1; - dev->slots[i].tracking_id = -1; + case SETSU_DEVICE_TYPE_TOUCHPAD: + dev->touchpad.min_x = libevdev_get_abs_minimum(dev->evdev, ABS_X); + dev->touchpad.min_y = libevdev_get_abs_minimum(dev->evdev, ABS_Y); + dev->touchpad.max_x = libevdev_get_abs_maximum(dev->evdev, ABS_X); + dev->touchpad.max_y = libevdev_get_abs_maximum(dev->evdev, ABS_Y); + + for(size_t i=0; itouchpad.slots[i].tracking_id_prev = -1; + dev->touchpad.slots[i].tracking_id = -1; + } + break; + case SETSU_DEVICE_TYPE_MOTION: + // TODO: init to defaults + break; } dev->next = setsu->dev; @@ -342,14 +375,18 @@ const char *setsu_device_get_path(SetsuDevice *dev) return dev->path; } -uint32_t setsu_device_get_width(SetsuDevice *dev) +uint32_t setsu_device_touchpad_get_width(SetsuDevice *dev) { - return dev->max_x - dev->min_x; + if(dev->type != SETSU_DEVICE_TYPE_TOUCHPAD) + return 0; + return dev->touchpad.max_x - dev->touchpad.min_x; } -uint32_t setsu_device_get_height(SetsuDevice *dev) +uint32_t setsu_device_touchpad_get_height(SetsuDevice *dev) { - return dev->max_y - dev->min_y; + if(dev->type != SETSU_DEVICE_TYPE_TOUCHPAD) + return 0; + return dev->touchpad.max_y - dev->touchpad.min_y; } void kill_avail_device(Setsu *setsu, SetsuAvailDevice *adev) @@ -466,59 +503,68 @@ static void device_event(Setsu *setsu, SetsuDevice *dev, struct input_event *ev, libevdev_event_code_get_name(ev->type, ev->code), ev->value); #endif -#define S dev->slots[dev->slot_cur] - switch(ev->type) + if(ev->type == EV_SYN && ev->code == SYN_REPORT) { - case EV_ABS: - switch(ev->code) + device_drain(setsu, dev, cb, user); + return; + } + switch(dev->type) + { + case SETSU_DEVICE_TYPE_TOUCHPAD: + switch(ev->type) { - case ABS_MT_SLOT: - if((unsigned int)ev->value >= SLOTS_COUNT) + case EV_ABS: +#define S dev->touchpad.slots[dev->touchpad.slot_cur] + switch(ev->code) { - SETSU_LOG("slot too high\n"); + case ABS_MT_SLOT: + if((unsigned int)ev->value >= SLOTS_COUNT) + { + SETSU_LOG("slot too high\n"); + break; + } + dev->touchpad.slot_cur = ev->value; + break; + case ABS_MT_TRACKING_ID: + if(S.tracking_id != -1 && S.tracking_id_prev == -1) + { + // up the tracking id + S.tracking_id_prev = S.tracking_id; + // reset the rest + S.x = S.y = 0; + S.pos_dirty = false; + } + S.tracking_id = ev->value; + if(ev->value != -1) + S.downed = true; + break; + case ABS_MT_POSITION_X: + S.x = ev->value; + S.pos_dirty = true; + break; + case ABS_MT_POSITION_Y: + S.y = ev->value; + S.pos_dirty = true; + break; + } + break; +#undef S + case EV_KEY: { + uint64_t button = button_from_evdev(ev->code); + if(!button) break; - } - dev->slot_cur = ev->value; - break; - case ABS_MT_TRACKING_ID: - if(S.tracking_id != -1 && S.tracking_id_prev == -1) - { - // up the tracking id - S.tracking_id_prev = S.tracking_id; - // reset the rest - S.x = S.y = 0; - S.pos_dirty = false; - } - S.tracking_id = ev->value; - if(ev->value != -1) - S.downed = true; - break; - case ABS_MT_POSITION_X: - S.x = ev->value; - S.pos_dirty = true; - break; - case ABS_MT_POSITION_Y: - S.y = ev->value; - S.pos_dirty = true; + if(ev->value) + dev->touchpad.buttons_cur |= button; + else + dev->touchpad.buttons_cur &= ~button; break; + } } break; - case EV_KEY: { - uint64_t button = button_from_evdev(ev->code); - if(!button) - break; - if(ev->value) - dev->buttons_cur |= button; - else - dev->buttons_cur &= ~button; - break; - } - case EV_SYN: - if(ev->code == SYN_REPORT) - device_drain(setsu, dev, cb, user); + case SETSU_DEVICE_TYPE_MOTION: + // TODO: handle the events break; } -#undef S } static void device_drain(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, void *user) @@ -526,48 +572,56 @@ static void device_drain(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, void * SetsuEvent event; #define BEGIN_EVENT(tp) do { memset(&event, 0, sizeof(event)); event.dev = dev; event.type = tp; } while(0) #define SEND_EVENT() do { cb(&event, user); } while (0) - for(size_t i=0; itype) { - if(dev->slots[i].tracking_id_prev != -1) - { - BEGIN_EVENT(SETSU_EVENT_TOUCH_UP); - event.tracking_id = dev->slots[i].tracking_id_prev; - SEND_EVENT(); - dev->slots[i].tracking_id_prev = -1; - } - if(dev->slots[i].downed) - { - BEGIN_EVENT(SETSU_EVENT_TOUCH_DOWN); - event.tracking_id = dev->slots[i].tracking_id; - SEND_EVENT(); - dev->slots[i].downed = false; - } - if(dev->slots[i].pos_dirty) - { - BEGIN_EVENT(SETSU_EVENT_TOUCH_POSITION); - event.tracking_id = dev->slots[i].tracking_id; - event.x = (uint32_t)(dev->slots[i].x - dev->min_x); - event.y = (uint32_t)(dev->slots[i].y - dev->min_y); - SEND_EVENT(); - dev->slots[i].pos_dirty = false; - } - } + case SETSU_DEVICE_TYPE_TOUCHPAD: + for(size_t i=0; itouchpad.slots[i].tracking_id_prev != -1) + { + BEGIN_EVENT(SETSU_EVENT_TOUCH_UP); + event.tracking_id = dev->touchpad.slots[i].tracking_id_prev; + SEND_EVENT(); + dev->touchpad.slots[i].tracking_id_prev = -1; + } + if(dev->touchpad.slots[i].downed) + { + BEGIN_EVENT(SETSU_EVENT_TOUCH_DOWN); + event.tracking_id = dev->touchpad.slots[i].tracking_id; + SEND_EVENT(); + dev->touchpad.slots[i].downed = false; + } + if(dev->touchpad.slots[i].pos_dirty) + { + BEGIN_EVENT(SETSU_EVENT_TOUCH_POSITION); + event.tracking_id = dev->touchpad.slots[i].tracking_id; + event.x = (uint32_t)(dev->touchpad.slots[i].x - dev->touchpad.min_x); + event.y = (uint32_t)(dev->touchpad.slots[i].y - dev->touchpad.min_y); + SEND_EVENT(); + dev->touchpad.slots[i].pos_dirty = false; + } + } - uint64_t buttons_diff = dev->buttons_prev ^ dev->buttons_cur; - for(uint64_t i=0; i<64; i++) - { - if(buttons_diff & 1) - { - uint64_t button = 1 << i; - BEGIN_EVENT((dev->buttons_cur & button) ? SETSU_EVENT_BUTTON_DOWN : SETSU_EVENT_BUTTON_UP); - event.button = button; - SEND_EVENT(); - } - buttons_diff >>= 1; - if(!buttons_diff) + uint64_t buttons_diff = dev->touchpad.buttons_prev ^ dev->touchpad.buttons_cur; + for(uint64_t i=0; i<64; i++) + { + if(buttons_diff & 1) + { + uint64_t button = 1 << i; + BEGIN_EVENT((dev->touchpad.buttons_cur & button) ? SETSU_EVENT_BUTTON_DOWN : SETSU_EVENT_BUTTON_UP); + event.button = button; + SEND_EVENT(); + } + buttons_diff >>= 1; + if(!buttons_diff) + break; + } + dev->touchpad.buttons_prev = dev->touchpad.buttons_cur; + break; + case SETSU_DEVICE_TYPE_MOTION: + // TODO break; } - dev->buttons_prev = dev->buttons_cur; #undef BEGIN_EVENT #undef SEND_EVENT }