Add udev monitor to setsu

This commit is contained in:
Florian Märkl 2020-07-01 20:48:01 +02:00
commit 38123ea38f
No known key found for this signature in database
GPG key ID: 125BC8A5A6A1E857
3 changed files with 91 additions and 11 deletions

View file

@ -71,5 +71,6 @@ void setsu_free(Setsu *setsu);
void setsu_poll(Setsu *setsu, SetsuEventCb cb, void *user); 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);
void setsu_disconnect(Setsu *setsu, SetsuDevice *dev); void setsu_disconnect(Setsu *setsu, SetsuDevice *dev);
const char *setsu_device_get_path(SetsuDevice *dev);
#endif #endif

View file

@ -29,7 +29,13 @@
#include <stdio.h> #include <stdio.h>
#define ENABLE_LOG
#ifdef ENABLE_LOG
#define SETSU_LOG(...) fprintf(stderr, __VA_ARGS__) #define SETSU_LOG(...) fprintf(stderr, __VA_ARGS__)
#else
#define SETSU_LOG(...) do {} while(0)
#endif
typedef struct setsu_avail_device_t typedef struct setsu_avail_device_t
{ {
@ -68,12 +74,13 @@ typedef struct setsu_device_t
struct setsu_t struct setsu_t
{ {
struct udev *udev; struct udev *udev;
struct udev_monitor *udev_mon;
SetsuAvailDevice *avail_dev; SetsuAvailDevice *avail_dev;
SetsuDevice *dev; SetsuDevice *dev;
}; };
static void scan_udev(Setsu *setsu); 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 SetsuDevice *connect(Setsu *setsu, const char *path);
static void disconnect(Setsu *setsu, SetsuDevice *dev); static void disconnect(Setsu *setsu, SetsuDevice *dev);
static void poll_device(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, void *user); static void poll_device(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, void *user);
@ -93,7 +100,14 @@ Setsu *setsu_new()
return NULL; 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); scan_udev(setsu);
@ -104,6 +118,8 @@ void setsu_free(Setsu *setsu)
{ {
while(setsu->dev) while(setsu->dev)
setsu_disconnect(setsu, setsu->dev); setsu_disconnect(setsu, setsu->dev);
if(setsu->udev_mon)
udev_monitor_unref(setsu->udev_mon);
udev_unref(setsu->udev); udev_unref(setsu->udev);
free(setsu); free(setsu);
} }
@ -131,8 +147,7 @@ static void scan_udev(Setsu *setsu)
struct udev_device *dev = udev_device_new_from_syspath(setsu->udev, path); struct udev_device *dev = udev_device_new_from_syspath(setsu->udev, path);
if(!dev) if(!dev)
continue; continue;
SETSU_LOG("enum device: %s\n", path); update_udev_device(setsu, dev);
update_udev_device(setsu, dev, true);
udev_device_unref(dev); udev_device_unref(dev);
} }
@ -166,7 +181,7 @@ static bool is_device_interesting(struct udev_device *dev)
return false; 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)) if(!is_device_interesting(dev))
return; return;
@ -174,6 +189,15 @@ static void update_udev_device(Setsu *setsu, struct udev_device *dev, bool added
if(!path) if(!path)
return; 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) for(SetsuAvailDevice *adev = setsu->avail_dev; adev; adev=adev->next)
{ {
if(!strcmp(adev->path, path)) 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 return; // already added, do nothing
// disconnected // disconnected
adev->disconnect_dirty = true; adev->disconnect_dirty = true;
return;
} }
} }
// not yet added // not yet added
@ -199,6 +224,20 @@ static void update_udev_device(Setsu *setsu, struct udev_device *dev, bool added
adev->connect_dirty = true; 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 *setsu_connect(Setsu *setsu, const char *path)
{ {
SetsuDevice *dev = calloc(1, sizeof(SetsuDevice)); SetsuDevice *dev = calloc(1, sizeof(SetsuDevice));
@ -264,6 +303,11 @@ void setsu_disconnect(Setsu *setsu, SetsuDevice *dev)
free(dev); free(dev);
} }
const char *setsu_device_get_path(SetsuDevice *dev)
{
return dev->path;
}
void kill_avail_device(Setsu *setsu, SetsuAvailDevice *adev) void kill_avail_device(Setsu *setsu, SetsuAvailDevice *adev)
{ {
for(SetsuDevice *dev = setsu->dev; dev;) for(SetsuDevice *dev = setsu->dev; dev;)
@ -273,6 +317,7 @@ void kill_avail_device(Setsu *setsu, SetsuAvailDevice *adev)
SetsuDevice *next = dev->next; SetsuDevice *next = dev->next;
setsu_disconnect(setsu, dev); setsu_disconnect(setsu, dev);
dev = next; dev = next;
continue;
} }
dev = dev->next; dev = dev->next;
} }
@ -296,6 +341,8 @@ void kill_avail_device(Setsu *setsu, SetsuAvailDevice *adev)
void setsu_poll(Setsu *setsu, SetsuEventCb cb, void *user) void setsu_poll(Setsu *setsu, SetsuEventCb cb, void *user)
{ {
poll_udev_monitor(setsu);
for(SetsuAvailDevice *adev = setsu->avail_dev; adev;) for(SetsuAvailDevice *adev = setsu->avail_dev; adev;)
{ {
if(adev->connect_dirty) 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); device_event(setsu, dev, &ev, cb, user);
else if(r == LIBEVDEV_READ_STATUS_SYNC) else if(r == LIBEVDEV_READ_STATUS_SYNC)
sync = true; sync = true;
else if(r == -ENODEV) { break; } // device probably disconnected, udev remove event should follow soon
else 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; break;
} }
} }

View file

@ -36,6 +36,9 @@ struct {
} touches[TOUCHES_MAX]; } touches[TOUCHES_MAX];
bool dirty = false; bool dirty = false;
bool log_mode;
#define LOG(...) do { if(log_mode) fprintf(stderr, __VA_ARGS__); } while(0)
void quit() void quit()
{ {
@ -86,12 +89,16 @@ void event(SetsuEvent *event, void *user)
dirty = true; dirty = true;
switch(event->type) switch(event->type)
{ {
case SETSU_EVENT_DEVICE_ADDED: case SETSU_EVENT_DEVICE_ADDED: {
setsu_connect(setsu, event->path); SetsuDevice *dev = setsu_connect(setsu, event->path);
LOG("Device added: %s, connect %s\n", event->path, dev ? "succeeded" : "FAILED!");
break; break;
}
case SETSU_EVENT_DEVICE_REMOVED: case SETSU_EVENT_DEVICE_REMOVED:
LOG("Device removed: %s\n", event->path);
break; break;
case SETSU_EVENT_DOWN: 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; i<TOUCHES_MAX; i++) for(size_t i=0; i<TOUCHES_MAX; i++)
{ {
if(!touches[i].down) if(!touches[i].down)
@ -104,6 +111,11 @@ void event(SetsuEvent *event, void *user)
break; break;
case SETSU_EVENT_POSITION: case SETSU_EVENT_POSITION:
case SETSU_EVENT_UP: case SETSU_EVENT_UP:
if(event->type == 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; i<TOUCHES_MAX; i++) for(size_t i=0; i<TOUCHES_MAX; i++)
{ {
if(touches[i].down && touches[i].tracking_id == event->tracking_id) if(touches[i].down && touches[i].tracking_id == event->tracking_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)); memset(touches, 0, sizeof(touches));
setsu = setsu_new(); setsu = setsu_new();
if(!setsu) if(!setsu)
@ -138,7 +167,7 @@ int main()
dirty = true; dirty = true;
while(1) while(1)
{ {
if(dirty) if(dirty && !log_mode)
print_state(); print_state();
dirty = false; dirty = false;
setsu_poll(setsu, event, NULL); setsu_poll(setsu, event, NULL);