mirror of
https://git.sr.ht/~thestr4ng3r/chiaki
synced 2025-08-20 21:43:12 -07:00
Device Events in Setsu
This commit is contained in:
parent
43dd40e466
commit
4a1ad05b5d
3 changed files with 155 additions and 38 deletions
|
@ -25,16 +25,43 @@ typedef struct setsu_device_t SetsuDevice;
|
||||||
typedef int SetsuTrackingId;
|
typedef int SetsuTrackingId;
|
||||||
|
|
||||||
typedef enum {
|
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,
|
SETSU_EVENT_DOWN,
|
||||||
|
|
||||||
|
/* Touch down.
|
||||||
|
* Event will have dev and tracking_id set. */
|
||||||
SETSU_EVENT_UP,
|
SETSU_EVENT_UP,
|
||||||
|
|
||||||
|
/* Touch position update.
|
||||||
|
* Event will have dev, tracking_id, x and y set. */
|
||||||
SETSU_EVENT_POSITION
|
SETSU_EVENT_POSITION
|
||||||
} SetsuEventType;
|
} SetsuEventType;
|
||||||
|
|
||||||
typedef struct setsu_event_t {
|
typedef struct setsu_event_t
|
||||||
|
{
|
||||||
|
SetsuEventType type;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
const char *path;
|
||||||
|
struct
|
||||||
|
{
|
||||||
SetsuDevice *dev;
|
SetsuDevice *dev;
|
||||||
SetsuTrackingId tracking_id;
|
SetsuTrackingId tracking_id;
|
||||||
SetsuEventType type;
|
|
||||||
uint32_t x, y;
|
uint32_t x, y;
|
||||||
|
};
|
||||||
|
};
|
||||||
} SetsuEvent;
|
} SetsuEvent;
|
||||||
|
|
||||||
typedef void (*SetsuEventCb)(SetsuEvent *event, void *user);
|
typedef void (*SetsuEventCb)(SetsuEvent *event, void *user);
|
||||||
|
@ -42,5 +69,7 @@ typedef void (*SetsuEventCb)(SetsuEvent *event, void *user);
|
||||||
Setsu *setsu_new();
|
Setsu *setsu_new();
|
||||||
void setsu_free(Setsu *setsu);
|
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);
|
||||||
|
void setsu_disconnect(Setsu *setsu, SetsuDevice *dev);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -27,12 +27,18 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
#define SETSU_LOG(...) fprintf(stderr, __VA_ARGS__)
|
#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
|
#define SLOTS_COUNT 16
|
||||||
|
|
||||||
typedef struct setsu_device_t
|
typedef struct setsu_device_t
|
||||||
|
@ -41,6 +47,7 @@ typedef struct setsu_device_t
|
||||||
char *path;
|
char *path;
|
||||||
int fd;
|
int fd;
|
||||||
struct libevdev *evdev;
|
struct libevdev *evdev;
|
||||||
|
int min_x, min_y, max_x, max_y;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
/* Saves the old tracking id that was just up-ed.
|
/* Saves the old tracking id that was just up-ed.
|
||||||
|
@ -60,13 +67,13 @@ typedef struct setsu_device_t
|
||||||
|
|
||||||
struct setsu_t
|
struct setsu_t
|
||||||
{
|
{
|
||||||
struct udev *udev_setsu;
|
struct udev *udev;
|
||||||
|
SetsuAvailDevice *avail_dev;
|
||||||
SetsuDevice *dev;
|
SetsuDevice *dev;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void scan_udev(Setsu *setsu);
|
||||||
static void scan(Setsu *setsu);
|
static void update_udev_device(Setsu *setsu, struct udev_device *dev, bool added);
|
||||||
static void update_device(Setsu *setsu, struct udev_device *dev, bool added);
|
|
||||||
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);
|
||||||
|
@ -75,14 +82,12 @@ static void device_drain(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, void *
|
||||||
|
|
||||||
Setsu *setsu_new()
|
Setsu *setsu_new()
|
||||||
{
|
{
|
||||||
Setsu *setsu = malloc(sizeof(Setsu));
|
Setsu *setsu = calloc(1, sizeof(Setsu));
|
||||||
if(!setsu)
|
if(!setsu)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
setsu->dev = NULL;
|
setsu->udev = udev_new();
|
||||||
|
if(!setsu->udev)
|
||||||
setsu->udev_setsu = udev_new();
|
|
||||||
if(!setsu->udev_setsu)
|
|
||||||
{
|
{
|
||||||
free(setsu);
|
free(setsu);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -90,7 +95,7 @@ Setsu *setsu_new()
|
||||||
|
|
||||||
// TODO: monitor
|
// TODO: monitor
|
||||||
|
|
||||||
scan(setsu);
|
scan_udev(setsu);
|
||||||
|
|
||||||
return setsu;
|
return setsu;
|
||||||
}
|
}
|
||||||
|
@ -98,14 +103,14 @@ Setsu *setsu_new()
|
||||||
void setsu_free(Setsu *setsu)
|
void setsu_free(Setsu *setsu)
|
||||||
{
|
{
|
||||||
while(setsu->dev)
|
while(setsu->dev)
|
||||||
disconnect(setsu, setsu->dev);
|
setsu_disconnect(setsu, setsu->dev);
|
||||||
udev_unref(setsu->udev_setsu);
|
udev_unref(setsu->udev);
|
||||||
free(setsu);
|
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)
|
if(!udev_enum)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -123,11 +128,11 @@ static void scan(Setsu *setsu)
|
||||||
const char *path = udev_list_entry_get_name(entry);
|
const char *path = udev_list_entry_get_name(entry);
|
||||||
if(!path)
|
if(!path)
|
||||||
continue;
|
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)
|
if(!dev)
|
||||||
continue;
|
continue;
|
||||||
SETSU_LOG("enum device: %s\n", path);
|
SETSU_LOG("enum device: %s\n", path);
|
||||||
update_device(setsu, dev, true);
|
update_udev_device(setsu, dev, true);
|
||||||
udev_device_unref(dev);
|
udev_device_unref(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +166,7 @@ static bool is_device_interesting(struct udev_device *dev)
|
||||||
return false;
|
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))
|
if(!is_device_interesting(dev))
|
||||||
return;
|
return;
|
||||||
|
@ -169,19 +174,32 @@ static void update_device(Setsu *setsu, struct udev_device *dev, bool added)
|
||||||
if(!path)
|
if(!path)
|
||||||
return;
|
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)
|
if(added)
|
||||||
return; // already added, do nothing
|
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));
|
SetsuDevice *dev = calloc(1, sizeof(SetsuDevice));
|
||||||
if(!dev)
|
if(!dev)
|
||||||
|
@ -196,14 +214,21 @@ static SetsuDevice *connect(Setsu *setsu, const char *path)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if(libevdev_new_from_fd(dev->fd, &dev->evdev) < 0)
|
if(libevdev_new_from_fd(dev->fd, &dev->evdev) < 0)
|
||||||
|
{
|
||||||
|
dev->evdev = NULL;
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: expose these values:
|
dev->min_x = libevdev_get_abs_minimum(dev->evdev, ABS_X);
|
||||||
int min_x = libevdev_get_abs_minimum(dev->evdev, ABS_X);
|
dev->min_y = libevdev_get_abs_minimum(dev->evdev, ABS_Y);
|
||||||
int min_y = libevdev_get_abs_minimum(dev->evdev, ABS_Y);
|
dev->max_x = libevdev_get_abs_maximum(dev->evdev, ABS_X);
|
||||||
int max_x = libevdev_get_abs_maximum(dev->evdev, ABS_X);
|
dev->max_y = libevdev_get_abs_maximum(dev->evdev, ABS_Y);
|
||||||
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);
|
for(size_t i=0; i<SLOTS_COUNT; i++)
|
||||||
|
{
|
||||||
|
dev->slots[i].tracking_id_prev = -1;
|
||||||
|
dev->slots[i].tracking_id = -1;
|
||||||
|
}
|
||||||
|
|
||||||
dev->next = setsu->dev;
|
dev->next = setsu->dev;
|
||||||
setsu->dev = dev;
|
setsu->dev = dev;
|
||||||
|
@ -218,7 +243,7 @@ error:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void disconnect(Setsu *setsu, SetsuDevice *dev)
|
void setsu_disconnect(Setsu *setsu, SetsuDevice *dev)
|
||||||
{
|
{
|
||||||
if(setsu->dev == dev)
|
if(setsu->dev == dev)
|
||||||
setsu->dev = dev->next;
|
setsu->dev = dev->next;
|
||||||
|
@ -233,13 +258,69 @@ static void disconnect(Setsu *setsu, SetsuDevice *dev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
libevdev_free(dev->evdev);
|
||||||
|
close(dev->fd);
|
||||||
free(dev->path);
|
free(dev->path);
|
||||||
free(dev);
|
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)
|
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)
|
for(SetsuDevice *dev = setsu->dev; dev; dev = dev->next)
|
||||||
poll_device(setsu, dev, cb, user);
|
poll_device(setsu, dev, cb, user);
|
||||||
}
|
}
|
||||||
|
@ -303,6 +384,7 @@ static void device_event(Setsu *setsu, SetsuDevice *dev, struct input_event *ev,
|
||||||
S.pos_dirty = false;
|
S.pos_dirty = false;
|
||||||
}
|
}
|
||||||
S.tracking_id = ev->value;
|
S.tracking_id = ev->value;
|
||||||
|
if(ev->value != -1)
|
||||||
S.downed = true;
|
S.downed = true;
|
||||||
break;
|
break;
|
||||||
case ABS_MT_POSITION_X:
|
case ABS_MT_POSITION_X:
|
||||||
|
@ -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)
|
else if(ev->type == EV_SYN && ev->code == SYN_REPORT)
|
||||||
device_drain(setsu, dev, cb, user);
|
device_drain(setsu, dev, cb, user);
|
||||||
|
#undef S
|
||||||
}
|
}
|
||||||
|
|
||||||
static void device_drain(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, void *user)
|
static void device_drain(Setsu *setsu, SetsuDevice *dev, SetsuEventCb cb, void *user)
|
||||||
|
|
|
@ -86,6 +86,11 @@ void event(SetsuEvent *event, void *user)
|
||||||
dirty = true;
|
dirty = true;
|
||||||
switch(event->type)
|
switch(event->type)
|
||||||
{
|
{
|
||||||
|
case SETSU_EVENT_DEVICE_ADDED:
|
||||||
|
setsu_connect(setsu, event->path);
|
||||||
|
break;
|
||||||
|
case SETSU_EVENT_DEVICE_REMOVED:
|
||||||
|
break;
|
||||||
case SETSU_EVENT_DOWN:
|
case SETSU_EVENT_DOWN:
|
||||||
for(size_t i=0; i<TOUCHES_MAX; i++)
|
for(size_t i=0; i<TOUCHES_MAX; i++)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue