Begin libsetsu with udev scan

This commit is contained in:
Florian Märkl 2020-06-21 14:19:30 +02:00
commit ec7b46ac67
No known key found for this signature in database
GPG key ID: 125BC8A5A6A1E857
7 changed files with 281 additions and 0 deletions

2
.gitignore vendored
View file

@ -22,3 +22,5 @@ chiaki.rb
*.jks *.jks
secret.tar secret.tar
keystore-env.sh keystore-env.sh
compile_commands.json
.ccls-cache

View file

@ -65,6 +65,7 @@ if(CHIAKI_ENABLE_CLI)
endif() endif()
if(CHIAKI_ENABLE_GUI) if(CHIAKI_ENABLE_GUI)
add_subdirectory(setsu)
add_subdirectory(gui) add_subdirectory(gui)
endif() endif()

24
setsu/CMakeLists.txt Normal file
View file

@ -0,0 +1,24 @@
cmake_minimum_required(VERSION 3.2)
project(libsetsu)
option(SETSU_BUILD_TEST "Build testing executable for libsetsu" OFF)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
add_library(setsu
include/setsu.h
src/setsu.c)
target_include_directories(setsu PUBLIC include)
find_package(UDEV REQUIRED)
target_link_libraries(setsu UDEV::libudev)
if(SETSU_BUILD_TEST)
add_executable(setsutest
test/main.c)
target_link_libraries(setsutest setsu)
endif()

View file

@ -0,0 +1,26 @@
# Provides: UDEV::libudev
set(_prefix UDEV)
set(_target "${_prefix}::libudev")
find_package(PkgConfig REQUIRED)
pkg_check_modules("${_prefix}" libudev)
function(resolve_location)
endfunction()
if(${_prefix}_FOUND)
add_library("${_target}" INTERFACE IMPORTED)
target_link_libraries("${_target}" INTERFACE ${${_prefix}_LIBRARIES})
target_include_directories("${_target}" INTERFACE ${${_prefix}_INCLUDE_DIRS})
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args("${_prefix}"
REQUIRED_VARS "${_prefix}_LIBRARIES"
VERSION_VAR "${_prefix}_VERSION")
unset(_prefix)
unset(_target)

26
setsu/include/setsu.h Normal file
View file

@ -0,0 +1,26 @@
/*
* This file is part of Chiaki.
*
* Chiaki is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Chiaki is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Chiaki. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _SETSU_H
#define _SETSU_H
typedef struct setsu_ctx_t SetsuCtx;
SetsuCtx *setsu_ctx_new();
void setsu_ctx_free(SetsuCtx *ctx);
#endif

177
setsu/src/setsu.c Normal file
View file

@ -0,0 +1,177 @@
#include <setsu.h>
#include <libudev.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
typedef struct setsu_device_t
{
struct setsu_device_t *next;
char *path;
int fd;
} SetsuDevice;
struct setsu_ctx_t
{
struct udev *udev_ctx;
SetsuDevice *dev;
};
static void scan(SetsuCtx *ctx);
static void update_device(SetsuCtx *ctx, struct udev_device *dev, bool added);
static SetsuDevice *connect(SetsuCtx *ctx, const char *path);
static void disconnect(SetsuCtx *ctx, SetsuDevice *dev);
SetsuCtx *setsu_ctx_new()
{
SetsuCtx *ctx = malloc(sizeof(SetsuCtx));
if(!ctx)
return NULL;
ctx->dev = NULL;
ctx->udev_ctx = udev_new();
if(!ctx->udev_ctx)
{
free(ctx);
return NULL;
}
// TODO: monitor
scan(ctx);
return ctx;
}
void setsu_ctx_free(SetsuCtx *ctx)
{
while(ctx->dev)
disconnect(ctx, ctx->dev);
udev_unref(ctx->udev_ctx);
free(ctx);
}
static void scan(SetsuCtx *ctx)
{
struct udev_enumerate *udev_enum = udev_enumerate_new(ctx->udev_ctx);
if(!udev_enum)
return;
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_scan_devices(udev_enum) < 0)
goto beach;
for(struct udev_list_entry *entry = udev_enumerate_get_list_entry(udev_enum); entry; entry = udev_list_entry_get_next(entry))
{
const char *path = udev_list_entry_get_name(entry);
if(!path)
continue;
struct udev_device *dev = udev_device_new_from_syspath(ctx->udev_ctx, path);
if(!dev)
continue;
update_device(ctx, dev, true);
udev_device_unref(dev);
}
beach:
udev_enumerate_unref(udev_enum);
}
static bool is_device_interesting(struct udev_device *dev)
{
static const char *device_ids[] = {
// vendor id, model id
"054c", "05c4", // DualShock 4 USB
NULL
};
// 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;
const char *vendor = udev_device_get_property_value(dev, "ID_VENDOR_ID");
const char *model = udev_device_get_property_value(dev, "ID_MODEL_ID");
if(!vendor || !model)
return false;
for(const char **dev_id = device_ids; *dev_id; dev_id += 2)
{
if(!strcmp(vendor, dev_id[0]) && !strcmp(model, dev_id[1]))
return true;
}
return false;
}
static void update_device(SetsuCtx *ctx, struct udev_device *dev, bool added)
{
if(!is_device_interesting(dev))
return;
const char *path = udev_device_get_devnode(dev);
if(!path)
return;
for(SetsuDevice *dev = ctx->dev; dev; dev=dev->next)
{
if(!strcmp(dev->path, path))
{
if(added)
return; // already added, do nothing
disconnect(ctx, dev);
}
}
connect(ctx, path);
}
static SetsuDevice *connect(SetsuCtx *ctx, const char *path)
{
SetsuDevice *dev = malloc(sizeof(SetsuDevice));
if(!dev)
return NULL;
dev->path = strdup(path);
if(!dev->path)
{
free(dev);
return NULL;
}
printf("connect %s\n", dev->path);
//dev->fd = open(dev->path, O_RDONLY | O_NONBLOCK);
dev->next = ctx->dev;
ctx->dev = dev;
return dev;
}
static void disconnect(SetsuCtx *ctx, SetsuDevice *dev)
{
if(ctx->dev == dev)
ctx->dev = dev->next;
else
{
for(SetsuDevice *pdev = ctx->dev; pdev; pdev=pdev->next)
{
if(pdev->next == dev)
{
pdev->next = dev->next;
break;
}
}
}
free(dev->path);
free(dev);
}

25
setsu/test/main.c Normal file
View file

@ -0,0 +1,25 @@
#include <setsu.h>
#include <stdlib.h>
#include <stdio.h>
SetsuCtx *ctx;
void quit()
{
setsu_ctx_free(ctx);
}
int main()
{
ctx = setsu_ctx_new();
if(!ctx)
{
printf("Failed to init setsu\n");
return 1;
}
atexit(quit);
return 0;
}