mirror of
https://git.sr.ht/~thestr4ng3r/chiaki
synced 2025-08-19 21:13:12 -07:00
Begin libsetsu with udev scan
This commit is contained in:
parent
2f8d9d189d
commit
ec7b46ac67
7 changed files with 281 additions and 0 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -22,3 +22,5 @@ chiaki.rb
|
||||||
*.jks
|
*.jks
|
||||||
secret.tar
|
secret.tar
|
||||||
keystore-env.sh
|
keystore-env.sh
|
||||||
|
compile_commands.json
|
||||||
|
.ccls-cache
|
||||||
|
|
|
@ -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
24
setsu/CMakeLists.txt
Normal 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()
|
||||||
|
|
26
setsu/cmake/FindUDEV.cmake
Normal file
26
setsu/cmake/FindUDEV.cmake
Normal 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
26
setsu/include/setsu.h
Normal 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
177
setsu/src/setsu.c
Normal 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
25
setsu/test/main.c
Normal 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;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue