mirror of
https://git.sr.ht/~thestr4ng3r/chiaki
synced 2025-08-19 04:59:19 -07:00
Add Motion Stub to Setsu
This commit is contained in:
parent
0e324a41a0
commit
abc9a27208
5 changed files with 196 additions and 130 deletions
|
@ -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();)
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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:
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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; i<SLOTS_COUNT; i++)
|
||||
switch(type)
|
||||
{
|
||||
dev->slots[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; i<SLOTS_COUNT; i++)
|
||||
{
|
||||
dev->touchpad.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; i<SLOTS_COUNT; i++)
|
||||
switch(dev->type)
|
||||
{
|
||||
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; i<SLOTS_COUNT; i++)
|
||||
{
|
||||
if(dev->touchpad.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
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue