From 38123ea38f9103d27cf36c4501a85b4ea75aac75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Wed, 1 Jul 2020 20:48:01 +0200 Subject: [PATCH] Add udev monitor to setsu --- setsu/include/setsu.h | 1 + setsu/src/setsu.c | 64 ++++++++++++++++++++++++++++++++++++++----- setsu/test/main.c | 37 ++++++++++++++++++++++--- 3 files changed, 91 insertions(+), 11 deletions(-) diff --git a/setsu/include/setsu.h b/setsu/include/setsu.h index eaf32a6..3e8b51e 100644 --- a/setsu/include/setsu.h +++ b/setsu/include/setsu.h @@ -71,5 +71,6 @@ 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); +const char *setsu_device_get_path(SetsuDevice *dev); #endif diff --git a/setsu/src/setsu.c b/setsu/src/setsu.c index 56682fb..6a4eb38 100644 --- a/setsu/src/setsu.c +++ b/setsu/src/setsu.c @@ -29,7 +29,13 @@ #include +#define ENABLE_LOG + +#ifdef ENABLE_LOG #define SETSU_LOG(...) fprintf(stderr, __VA_ARGS__) +#else +#define SETSU_LOG(...) do {} while(0) +#endif typedef struct setsu_avail_device_t { @@ -68,12 +74,13 @@ typedef struct setsu_device_t struct setsu_t { struct udev *udev; + struct udev_monitor *udev_mon; SetsuAvailDevice *avail_dev; SetsuDevice *dev; }; static void scan_udev(Setsu *setsu); -static void update_udev_device(Setsu *setsu, struct udev_device *dev, bool added); +static void update_udev_device(Setsu *setsu, struct udev_device *dev); 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); @@ -93,7 +100,14 @@ Setsu *setsu_new() return NULL; } - // TODO: monitor + setsu->udev_mon = udev_monitor_new_from_netlink(setsu->udev, "udev"); + if(setsu->udev_mon) + { + udev_monitor_filter_add_match_subsystem_devtype(setsu->udev_mon, "input", NULL); + udev_monitor_enable_receiving(setsu->udev_mon); + } + else + SETSU_LOG("Failed to create udev monitor\n"); scan_udev(setsu); @@ -104,6 +118,8 @@ void setsu_free(Setsu *setsu) { while(setsu->dev) setsu_disconnect(setsu, setsu->dev); + if(setsu->udev_mon) + udev_monitor_unref(setsu->udev_mon); udev_unref(setsu->udev); free(setsu); } @@ -131,8 +147,7 @@ static void scan_udev(Setsu *setsu) struct udev_device *dev = udev_device_new_from_syspath(setsu->udev, path); if(!dev) continue; - SETSU_LOG("enum device: %s\n", path); - update_udev_device(setsu, dev, true); + update_udev_device(setsu, dev); udev_device_unref(dev); } @@ -166,14 +181,23 @@ static bool is_device_interesting(struct udev_device *dev) return false; } -static void update_udev_device(Setsu *setsu, struct udev_device *dev, bool added) +static void update_udev_device(Setsu *setsu, struct udev_device *dev) { if(!is_device_interesting(dev)) return; const char *path = udev_device_get_devnode(dev); if(!path) return; - + + const char *action = udev_device_get_action(dev); + bool added; + if(!action || !strcmp(action, "add")) + added = true; + else if(!strcmp(action, "remove")) + added = false; + else + return; + for(SetsuAvailDevice *adev = setsu->avail_dev; adev; adev=adev->next) { if(!strcmp(adev->path, path)) @@ -182,6 +206,7 @@ static void update_udev_device(Setsu *setsu, struct udev_device *dev, bool added return; // already added, do nothing // disconnected adev->disconnect_dirty = true; + return; } } // not yet added @@ -199,6 +224,20 @@ static void update_udev_device(Setsu *setsu, struct udev_device *dev, bool added adev->connect_dirty = true; } +static void poll_udev_monitor(Setsu *setsu) +{ + if(!setsu->udev_mon) + return; + while(1) + { + struct udev_device *dev = udev_monitor_receive_device(setsu->udev_mon); + if(!dev) + break; + update_udev_device(setsu, dev); + udev_device_unref(dev); + } +} + SetsuDevice *setsu_connect(Setsu *setsu, const char *path) { SetsuDevice *dev = calloc(1, sizeof(SetsuDevice)); @@ -264,6 +303,11 @@ void setsu_disconnect(Setsu *setsu, SetsuDevice *dev) free(dev); } +const char *setsu_device_get_path(SetsuDevice *dev) +{ + return dev->path; +} + void kill_avail_device(Setsu *setsu, SetsuAvailDevice *adev) { for(SetsuDevice *dev = setsu->dev; dev;) @@ -273,6 +317,7 @@ void kill_avail_device(Setsu *setsu, SetsuAvailDevice *adev) SetsuDevice *next = dev->next; setsu_disconnect(setsu, dev); dev = next; + continue; } dev = dev->next; } @@ -296,6 +341,8 @@ void kill_avail_device(Setsu *setsu, SetsuAvailDevice *adev) void setsu_poll(Setsu *setsu, SetsuEventCb cb, void *user) { + poll_udev_monitor(setsu); + for(SetsuAvailDevice *adev = setsu->avail_dev; adev;) { if(adev->connect_dirty) @@ -345,9 +392,12 @@ static void poll_device(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, void *u device_event(setsu, dev, &ev, cb, user); else if(r == LIBEVDEV_READ_STATUS_SYNC) sync = true; + else if(r == -ENODEV) { break; } // device probably disconnected, udev remove event should follow soon else { - SETSU_LOG("evdev poll failed\n"); + char buf[256]; + strerror_r(-r, buf, sizeof(buf)); + SETSU_LOG("evdev poll failed: %s\n", buf); break; } } diff --git a/setsu/test/main.c b/setsu/test/main.c index f9bdbab..0244cad 100644 --- a/setsu/test/main.c +++ b/setsu/test/main.c @@ -36,6 +36,9 @@ struct { } touches[TOUCHES_MAX]; bool dirty = false; +bool log_mode; + +#define LOG(...) do { if(log_mode) fprintf(stderr, __VA_ARGS__); } while(0) void quit() { @@ -86,12 +89,16 @@ void event(SetsuEvent *event, void *user) dirty = true; switch(event->type) { - case SETSU_EVENT_DEVICE_ADDED: - setsu_connect(setsu, event->path); + case SETSU_EVENT_DEVICE_ADDED: { + SetsuDevice *dev = setsu_connect(setsu, event->path); + LOG("Device added: %s, connect %s\n", event->path, dev ? "succeeded" : "FAILED!"); break; + } case SETSU_EVENT_DEVICE_REMOVED: + LOG("Device removed: %s\n", event->path); break; case SETSU_EVENT_DOWN: + LOG("Down for %s, tracking id %d\n", setsu_device_get_path(event->dev), event->tracking_id); for(size_t i=0; itype == SETSU_EVENT_UP) + LOG("Up for %s, tracking id %d\n", setsu_device_get_path(event->dev), event->tracking_id); + else + LOG("Position for %s, tracking id %d: %u, %u\n", setsu_device_get_path(event->dev), + event->tracking_id, (unsigned int)event->x, (unsigned int)event->y); for(size_t i=0; itracking_id) @@ -126,8 +138,25 @@ void event(SetsuEvent *event, void *user) } } -int main() +void usage(const char *prog) { + printf("usage: %s [-l]\n -l log mode\n", prog); + exit(1); +} + +int main(int argc, const char *argv[]) +{ + log_mode = false; + if(argc == 2) + { + if(!strcmp(argv[1], "-l")) + log_mode = true; + else + usage(argv[0]); + } + else if(argc != 1) + usage(argv[0]); + memset(touches, 0, sizeof(touches)); setsu = setsu_new(); if(!setsu) @@ -138,7 +167,7 @@ int main() dirty = true; while(1) { - if(dirty) + if(dirty && !log_mode) print_state(); dirty = false; setsu_poll(setsu, event, NULL);