From 4a1ad05b5dde9b607fa09dd1c128030596f38a3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Wed, 1 Jul 2020 18:44:54 +0200 Subject: [PATCH] Device Events in Setsu --- setsu/include/setsu.h | 37 +++++++++-- setsu/src/setsu.c | 151 ++++++++++++++++++++++++++++++++---------- setsu/test/main.c | 5 ++ 3 files changed, 155 insertions(+), 38 deletions(-) diff --git a/setsu/include/setsu.h b/setsu/include/setsu.h index de64970..eaf32a6 100644 --- a/setsu/include/setsu.h +++ b/setsu/include/setsu.h @@ -25,16 +25,43 @@ typedef struct setsu_device_t SetsuDevice; typedef int SetsuTrackingId; typedef enum { + /* New device available to connect. + * Event will have path set to the new device. */ + SETSU_EVENT_DEVICE_ADDED, + + /* Previously available device removed. + * Event will have path set to the new 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. */ + SETSU_EVENT_DEVICE_REMOVED, + + /* Touch down. + * Event will have dev and tracking_id set. */ SETSU_EVENT_DOWN, + + /* Touch down. + * Event will have dev and tracking_id set. */ SETSU_EVENT_UP, + + /* Touch position update. + * Event will have dev, tracking_id, x and y set. */ SETSU_EVENT_POSITION } SetsuEventType; -typedef struct setsu_event_t { - SetsuDevice *dev; - SetsuTrackingId tracking_id; +typedef struct setsu_event_t +{ SetsuEventType type; - uint32_t x, y; + union + { + const char *path; + struct + { + SetsuDevice *dev; + SetsuTrackingId tracking_id; + uint32_t x, y; + }; + }; } SetsuEvent; typedef void (*SetsuEventCb)(SetsuEvent *event, void *user); @@ -42,5 +69,7 @@ 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); +void setsu_disconnect(Setsu *setsu, SetsuDevice *dev); #endif diff --git a/setsu/src/setsu.c b/setsu/src/setsu.c index f43a3cc..56682fb 100644 --- a/setsu/src/setsu.c +++ b/setsu/src/setsu.c @@ -27,12 +27,18 @@ #include #include - #include - #define SETSU_LOG(...) fprintf(stderr, __VA_ARGS__) +typedef struct setsu_avail_device_t +{ + struct setsu_avail_device_t *next; + 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 +} SetsuAvailDevice; + #define SLOTS_COUNT 16 typedef struct setsu_device_t @@ -41,6 +47,7 @@ typedef struct setsu_device_t char *path; 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. @@ -60,13 +67,13 @@ typedef struct setsu_device_t struct setsu_t { - struct udev *udev_setsu; + struct udev *udev; + SetsuAvailDevice *avail_dev; SetsuDevice *dev; }; - -static void scan(Setsu *setsu); -static void update_device(Setsu *setsu, struct udev_device *dev, bool added); +static void scan_udev(Setsu *setsu); +static void update_udev_device(Setsu *setsu, struct udev_device *dev, bool added); static SetsuDevice *connect(Setsu *setsu, const char *path); static void disconnect(Setsu *setsu, SetsuDevice *dev); static void poll_device(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, void *user); @@ -75,14 +82,12 @@ static void device_drain(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, void * Setsu *setsu_new() { - Setsu *setsu = malloc(sizeof(Setsu)); + Setsu *setsu = calloc(1, sizeof(Setsu)); if(!setsu) return NULL; - setsu->dev = NULL; - - setsu->udev_setsu = udev_new(); - if(!setsu->udev_setsu) + setsu->udev = udev_new(); + if(!setsu->udev) { free(setsu); return NULL; @@ -90,7 +95,7 @@ Setsu *setsu_new() // TODO: monitor - scan(setsu); + scan_udev(setsu); return setsu; } @@ -98,14 +103,14 @@ Setsu *setsu_new() void setsu_free(Setsu *setsu) { while(setsu->dev) - disconnect(setsu, setsu->dev); - udev_unref(setsu->udev_setsu); + setsu_disconnect(setsu, setsu->dev); + udev_unref(setsu->udev); free(setsu); } -static void scan(Setsu *setsu) +static void scan_udev(Setsu *setsu) { - struct udev_enumerate *udev_enum = udev_enumerate_new(setsu->udev_setsu); + struct udev_enumerate *udev_enum = udev_enumerate_new(setsu->udev); if(!udev_enum) return; @@ -123,11 +128,11 @@ static void scan(Setsu *setsu) const char *path = udev_list_entry_get_name(entry); if(!path) continue; - struct udev_device *dev = udev_device_new_from_syspath(setsu->udev_setsu, path); + struct udev_device *dev = udev_device_new_from_syspath(setsu->udev, path); if(!dev) continue; SETSU_LOG("enum device: %s\n", path); - update_device(setsu, dev, true); + update_udev_device(setsu, dev, true); udev_device_unref(dev); } @@ -161,7 +166,7 @@ static bool is_device_interesting(struct udev_device *dev) return false; } -static void update_device(Setsu *setsu, struct udev_device *dev, bool added) +static void update_udev_device(Setsu *setsu, struct udev_device *dev, bool added) { if(!is_device_interesting(dev)) return; @@ -169,19 +174,32 @@ static void update_device(Setsu *setsu, struct udev_device *dev, bool added) if(!path) return; - for(SetsuDevice *dev = setsu->dev; dev; dev=dev->next) + for(SetsuAvailDevice *adev = setsu->avail_dev; adev; adev=adev->next) { - if(!strcmp(dev->path, path)) + if(!strcmp(adev->path, path)) { if(added) return; // already added, do nothing - disconnect(setsu, dev); + // disconnected + adev->disconnect_dirty = true; } } - connect(setsu, path); + // not yet added + SetsuAvailDevice *adev = calloc(1, sizeof(SetsuAvailDevice)); + if(!adev) + return; + adev->path = strdup(path); + if(!adev->path) + { + free(adev); + return; + } + adev->next = setsu->avail_dev; + setsu->avail_dev = adev; + adev->connect_dirty = true; } -static SetsuDevice *connect(Setsu *setsu, const char *path) +SetsuDevice *setsu_connect(Setsu *setsu, const char *path) { SetsuDevice *dev = calloc(1, sizeof(SetsuDevice)); if(!dev) @@ -196,14 +214,21 @@ static SetsuDevice *connect(Setsu *setsu, const char *path) goto error; if(libevdev_new_from_fd(dev->fd, &dev->evdev) < 0) + { + dev->evdev = NULL; goto error; + } - // TODO: expose these values: - int min_x = libevdev_get_abs_minimum(dev->evdev, ABS_X); - int min_y = libevdev_get_abs_minimum(dev->evdev, ABS_Y); - int max_x = libevdev_get_abs_maximum(dev->evdev, ABS_X); - int max_y = libevdev_get_abs_maximum(dev->evdev, ABS_Y); - SETSU_LOG("connected to %s: %d %d -> %d %d\n", libevdev_get_name(dev->evdev), min_x, min_y, max_x, max_y); + 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; + } dev->next = setsu->dev; setsu->dev = dev; @@ -218,13 +243,13 @@ error: return NULL; } -static void disconnect(Setsu *setsu, SetsuDevice *dev) +void setsu_disconnect(Setsu *setsu, SetsuDevice *dev) { if(setsu->dev == dev) setsu->dev = dev->next; else { - for(SetsuDevice *pdev = setsu->dev; pdev; pdev=pdev->next) + for(SetsuDevice *pdev = setsu->dev; pdev; pdev = pdev->next) { if(pdev->next == dev) { @@ -233,13 +258,69 @@ static void disconnect(Setsu *setsu, SetsuDevice *dev) } } } - + libevdev_free(dev->evdev); + close(dev->fd); free(dev->path); free(dev); } +void kill_avail_device(Setsu *setsu, SetsuAvailDevice *adev) +{ + for(SetsuDevice *dev = setsu->dev; dev;) + { + if(!strcmp(dev->path, adev->path)) + { + SetsuDevice *next = dev->next; + setsu_disconnect(setsu, dev); + dev = next; + } + dev = dev->next; + } + + if(setsu->avail_dev == adev) + setsu->avail_dev = adev->next; + else + { + for(SetsuAvailDevice *padev = setsu->avail_dev; padev; padev = padev->next) + { + if(padev->next == adev) + { + padev->next = adev->next; + break; + } + } + } + free(adev->path); + free(adev); +} + void setsu_poll(Setsu *setsu, SetsuEventCb cb, void *user) { + for(SetsuAvailDevice *adev = setsu->avail_dev; adev;) + { + if(adev->connect_dirty) + { + SetsuEvent event = { 0 }; + event.type = SETSU_EVENT_DEVICE_ADDED; + event.path = adev->path; + cb(&event, user); + adev->connect_dirty = false; + } + if(adev->disconnect_dirty) + { + SetsuEvent event = { 0 }; + event.type = SETSU_EVENT_DEVICE_REMOVED; + event.path = adev->path; + cb(&event, user); + // kill the device only after sending the event + SetsuAvailDevice *next = adev->next; + kill_avail_device(setsu, adev); + adev = next; + continue; + } + adev = adev->next; + } + for(SetsuDevice *dev = setsu->dev; dev; dev = dev->next) poll_device(setsu, dev, cb, user); } @@ -303,7 +384,8 @@ static void device_event(Setsu *setsu, SetsuDevice *dev, struct input_event *ev, S.pos_dirty = false; } S.tracking_id = ev->value; - S.downed = true; + if(ev->value != -1) + S.downed = true; break; case ABS_MT_POSITION_X: S.x = ev->value; @@ -317,6 +399,7 @@ static void device_event(Setsu *setsu, SetsuDevice *dev, struct input_event *ev, } else if(ev->type == EV_SYN && ev->code == SYN_REPORT) device_drain(setsu, dev, cb, user); +#undef S } static void device_drain(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, void *user) diff --git a/setsu/test/main.c b/setsu/test/main.c index 6bc5882..f9bdbab 100644 --- a/setsu/test/main.c +++ b/setsu/test/main.c @@ -86,6 +86,11 @@ void event(SetsuEvent *event, void *user) dirty = true; switch(event->type) { + case SETSU_EVENT_DEVICE_ADDED: + setsu_connect(setsu, event->path); + break; + case SETSU_EVENT_DEVICE_REMOVED: + break; case SETSU_EVENT_DOWN: for(size_t i=0; i