This commit is contained in:
Nitload
2025-08-25 09:50:30 +08:00
parent bd0e31e922
commit 1359ff4ecc
1630 changed files with 738486 additions and 2399 deletions
@@ -0,0 +1,107 @@
cmake_minimum_required(VERSION 3.6.3...3.25 FATAL_ERROR)
list(APPEND HIDAPI_PUBLIC_HEADERS "hidapi_libusb.h")
add_library(hidapi_libusb
${HIDAPI_PUBLIC_HEADERS}
hid.c
)
target_link_libraries(hidapi_libusb PUBLIC hidapi_include)
if(TARGET usb-1.0)
target_link_libraries(hidapi_libusb PRIVATE usb-1.0)
else()
include(FindPkgConfig)
pkg_check_modules(libusb REQUIRED IMPORTED_TARGET libusb-1.0>=1.0.9)
target_link_libraries(hidapi_libusb PRIVATE PkgConfig::libusb)
endif()
find_package(Threads REQUIRED)
target_link_libraries(hidapi_libusb PRIVATE Threads::Threads)
if(HIDAPI_NO_ICONV)
target_compile_definitions(hidapi_libusb PRIVATE NO_ICONV)
else()
if(NOT ANDROID)
include(CheckCSourceCompiles)
if(NOT CMAKE_VERSION VERSION_LESS 3.11)
message(STATUS "Check for Iconv")
find_package(Iconv)
if(Iconv_FOUND)
if(NOT Iconv_IS_BUILT_IN)
target_link_libraries(hidapi_libusb PRIVATE Iconv::Iconv)
set(CMAKE_REQUIRED_LIBRARIES "Iconv::Iconv")
if(NOT BUILD_SHARED_LIBS)
set(HIDAPI_NEED_EXPORT_ICONV TRUE PARENT_SCOPE)
endif()
endif()
else()
message(STATUS "Iconv Explicitly check '-liconv'")
# Sometime the build environment is not setup
# in a way CMake can find Iconv on its own by default.
# But if we simply link against iconv (-liconv), the build may succeed
# due to other compiler/link flags.
set(CMAKE_REQUIRED_LIBRARIES "iconv")
check_c_source_compiles("
#include <stddef.h>
#include <iconv.h>
int main() {
char *a, *b;
size_t i, j;
iconv_t ic;
ic = iconv_open(\"to\", \"from\");
iconv(ic, &a, &i, &b, &j);
iconv_close(ic);
}
"
Iconv_EXPLICITLY_AT_ENV)
if(Iconv_EXPLICITLY_AT_ENV)
message(STATUS "Iconv Explicitly check '-liconv' - Available")
target_link_libraries(hidapi_libusb PRIVATE iconv)
else()
message(FATAL_ERROR "Iconv is not found, make sure to provide it in the build environment")
endif()
endif()
else()
# otherwise there is 2 options:
# 1) iconv is provided by Standard C library and the build will be just fine
# 2) The _user_ has to provide additional compilation options for this project/target
endif()
# check for error: "conflicting types for 'iconv'"
check_c_source_compiles("#include<iconv.h>
extern size_t iconv (iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
int main() {}"
HIDAPI_ICONV_CONST)
if(HIDAPI_ICONV_CONST)
target_compile_definitions(hidapi_libusb PRIVATE "ICONV_CONST=const")
endif()
else()
# On Android Iconv is disabled on the code level anyway, so no issue;
endif()
endif()
set_target_properties(hidapi_libusb
PROPERTIES
EXPORT_NAME "libusb"
OUTPUT_NAME "hidapi-libusb"
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
PUBLIC_HEADER "${HIDAPI_PUBLIC_HEADERS}"
)
# compatibility with find_package()
add_library(hidapi::libusb ALIAS hidapi_libusb)
# compatibility with raw library link
add_library(hidapi-libusb ALIAS hidapi_libusb)
if(HIDAPI_INSTALL_TARGETS)
install(TARGETS hidapi_libusb EXPORT hidapi
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/hidapi"
)
endif()
hidapi_configure_pc("${PROJECT_ROOT}/pc/hidapi-libusb.pc.in")
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,56 @@
/*******************************************************
HIDAPI - Multi-Platform library for
communication with HID devices.
libusb/hidapi Team
Copyright 2021, All Rights Reserved.
At the discretion of the user of this library,
this software may be licensed under the terms of the
GNU General Public License v3, a BSD-Style license, or the
original HIDAPI license as outlined in the LICENSE.txt,
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
files located at the root of the source distribution.
These files may also be found in the public source
code repository located at:
https://github.com/libusb/hidapi .
********************************************************/
/** @file
* @defgroup API hidapi API
* Since version 0.11.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 11, 0).
*/
#ifndef HIDAPI_LIBUSB_H__
#define HIDAPI_LIBUSB_H__
#include <stdint.h>
#include "../hidapi/hidapi.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Open a HID device using libusb_wrap_sys_device.
See https://libusb.sourceforge.io/api-1.0/group__libusb__dev.html#ga98f783e115ceff4eaf88a60e6439563c,
for details on libusb_wrap_sys_device.
@ingroup API
@param sys_dev Platform-specific file descriptor that can be recognised by libusb.
@param interface_num USB interface number of the device to be used as HID interface.
Pass -1 to select first HID interface of the device.
@returns
This function returns a pointer to a #hid_device object on
success or NULL on failure.
*/
HID_API_EXPORT hid_device * HID_API_CALL hid_libusb_wrap_sys_device(intptr_t sys_dev, int interface_num);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,174 @@
/*******************************************************
HIDAPI - Multi-Platform library for
communication with HID devices.
Alan Ott
Signal 11 Software
libusb/hidapi Team
Sam Lantinga
Copyright 2023, All Rights Reserved.
At the discretion of the user of this library,
this software may be licensed under the terms of the
GNU General Public License v3, a BSD-Style license, or the
original HIDAPI license as outlined in the LICENSE.txt,
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
files located at the root of the source distribution.
These files may also be found in the public source
code repository located at:
https://github.com/libusb/hidapi .
********************************************************/
#include <pthread.h>
#if defined(__ANDROID__) && __ANDROID_API__ < __ANDROID_API_N__
/* Barrier implementation because Android/Bionic don't have pthread_barrier.
This implementation came from Brent Priddy and was posted on
StackOverflow. It is used with his permission. */
typedef int pthread_barrierattr_t;
typedef struct pthread_barrier {
pthread_mutex_t mutex;
pthread_cond_t cond;
int count;
int trip_count;
} pthread_barrier_t;
static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count)
{
if(count == 0) {
errno = EINVAL;
return -1;
}
if(pthread_mutex_init(&barrier->mutex, 0) < 0) {
return -1;
}
if(pthread_cond_init(&barrier->cond, 0) < 0) {
pthread_mutex_destroy(&barrier->mutex);
return -1;
}
barrier->trip_count = count;
barrier->count = 0;
return 0;
}
static int pthread_barrier_destroy(pthread_barrier_t *barrier)
{
pthread_cond_destroy(&barrier->cond);
pthread_mutex_destroy(&barrier->mutex);
return 0;
}
static int pthread_barrier_wait(pthread_barrier_t *barrier)
{
pthread_mutex_lock(&barrier->mutex);
++(barrier->count);
if(barrier->count >= barrier->trip_count) {
barrier->count = 0;
pthread_cond_broadcast(&barrier->cond);
pthread_mutex_unlock(&barrier->mutex);
return 1;
}
else {
pthread_cond_wait(&barrier->cond, &(barrier->mutex));
pthread_mutex_unlock(&barrier->mutex);
return 0;
}
}
#endif
#define HIDAPI_THREAD_TIMED_OUT ETIMEDOUT
typedef struct timespec hidapi_timespec;
typedef struct
{
pthread_t thread;
pthread_mutex_t mutex; /* Protects input_reports */
pthread_cond_t condition;
pthread_barrier_t barrier; /* Ensures correct startup sequence */
} hidapi_thread_state;
static void hidapi_thread_state_init(hidapi_thread_state *state)
{
pthread_mutex_init(&state->mutex, NULL);
pthread_cond_init(&state->condition, NULL);
pthread_barrier_init(&state->barrier, NULL, 2);
}
static void hidapi_thread_state_destroy(hidapi_thread_state *state)
{
pthread_barrier_destroy(&state->barrier);
pthread_cond_destroy(&state->condition);
pthread_mutex_destroy(&state->mutex);
}
#define hidapi_thread_cleanup_push pthread_cleanup_push
#define hidapi_thread_cleanup_pop pthread_cleanup_pop
static void hidapi_thread_mutex_lock(hidapi_thread_state *state)
{
pthread_mutex_lock(&state->mutex);
}
static void hidapi_thread_mutex_unlock(hidapi_thread_state *state)
{
pthread_mutex_unlock(&state->mutex);
}
static void hidapi_thread_cond_wait(hidapi_thread_state *state)
{
pthread_cond_wait(&state->condition, &state->mutex);
}
static int hidapi_thread_cond_timedwait(hidapi_thread_state *state, hidapi_timespec *ts)
{
return pthread_cond_timedwait(&state->condition, &state->mutex, ts);
}
static void hidapi_thread_cond_signal(hidapi_thread_state *state)
{
pthread_cond_signal(&state->condition);
}
static void hidapi_thread_cond_broadcast(hidapi_thread_state *state)
{
pthread_cond_broadcast(&state->condition);
}
static void hidapi_thread_barrier_wait(hidapi_thread_state *state)
{
pthread_barrier_wait(&state->barrier);
}
static void hidapi_thread_create(hidapi_thread_state *state, void *(*func)(void*), void *func_arg)
{
pthread_create(&state->thread, NULL, func, func_arg);
}
static void hidapi_thread_join(hidapi_thread_state *state)
{
pthread_join(state->thread, NULL);
}
static void hidapi_thread_gettime(hidapi_timespec *ts)
{
clock_gettime(CLOCK_REALTIME, ts);
}
static void hidapi_thread_addtime(hidapi_timespec *ts, int milliseconds)
{
ts->tv_sec += milliseconds / 1000;
ts->tv_nsec += (milliseconds % 1000) * 1000000;
if (ts->tv_nsec >= 1000000000L) {
ts->tv_sec++;
ts->tv_nsec -= 1000000000L;
}
}
@@ -0,0 +1,202 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/* Barrier implementation because Android/Bionic don't have pthread_barrier.
This implementation came from Brent Priddy and was posted on
StackOverflow. It is used with his permission. */
typedef struct _SDL_ThreadBarrier
{
SDL_Mutex *mutex;
SDL_Condition *cond;
Uint32 count;
Uint32 trip_count;
} SDL_ThreadBarrier;
static int SDL_CreateThreadBarrier(SDL_ThreadBarrier *barrier, Uint32 count)
{
SDL_assert(barrier != NULL);
SDL_assert(count != 0);
barrier->mutex = SDL_CreateMutex();
if (barrier->mutex == NULL) {
return -1; /* Error set by CreateMutex */
}
barrier->cond = SDL_CreateCondition();
if (barrier->cond == NULL) {
return -1; /* Error set by CreateCond */
}
barrier->trip_count = count;
barrier->count = 0;
return 0;
}
static void SDL_DestroyThreadBarrier(SDL_ThreadBarrier *barrier)
{
SDL_DestroyCondition(barrier->cond);
SDL_DestroyMutex(barrier->mutex);
}
static int SDL_WaitThreadBarrier(SDL_ThreadBarrier *barrier)
{
SDL_LockMutex(barrier->mutex);
barrier->count += 1;
if (barrier->count >= barrier->trip_count) {
barrier->count = 0;
SDL_BroadcastCondition(barrier->cond);
SDL_UnlockMutex(barrier->mutex);
return 1;
}
SDL_WaitCondition(barrier->cond, barrier->mutex);
SDL_UnlockMutex(barrier->mutex);
return 0;
}
#include "../../thread/SDL_systhread.h"
#define HIDAPI_THREAD_TIMED_OUT 1
typedef Uint64 hidapi_timespec;
typedef struct
{
SDL_Thread *thread;
SDL_Mutex *mutex; /* Protects input_reports */
SDL_Condition *condition;
SDL_ThreadBarrier barrier; /* Ensures correct startup sequence */
} hidapi_thread_state;
static void hidapi_thread_state_init(hidapi_thread_state *state)
{
state->mutex = SDL_CreateMutex();
state->condition = SDL_CreateCondition();
SDL_CreateThreadBarrier(&state->barrier, 2);
}
static void hidapi_thread_state_destroy(hidapi_thread_state *state)
{
SDL_DestroyThreadBarrier(&state->barrier);
SDL_DestroyCondition(state->condition);
SDL_DestroyMutex(state->mutex);
}
static void hidapi_thread_cleanup_push(void (*routine)(void *), void *arg)
{
/* There isn't an equivalent in SDL, and it's only useful for threads calling hid_read_timeout() */
}
static void hidapi_thread_cleanup_pop(int execute)
{
}
static void hidapi_thread_mutex_lock(hidapi_thread_state *state)
{
SDL_LockMutex(state->mutex);
}
static void hidapi_thread_mutex_unlock(hidapi_thread_state *state)
{
SDL_UnlockMutex(state->mutex);
}
static void hidapi_thread_cond_wait(hidapi_thread_state *state)
{
SDL_WaitCondition(state->condition, state->mutex);
}
static int hidapi_thread_cond_timedwait(hidapi_thread_state *state, hidapi_timespec *ts)
{
Sint64 timeout_ns;
Sint32 timeout_ms;
timeout_ns = (Sint64)(*ts - SDL_GetTicksNS());
if (timeout_ns <= 0) {
timeout_ms = 0;
} else {
timeout_ms = (Sint32)SDL_NS_TO_MS(timeout_ns);
}
if (SDL_WaitConditionTimeout(state->condition, state->mutex, timeout_ms)) {
return 0;
} else {
return HIDAPI_THREAD_TIMED_OUT;
}
}
static void hidapi_thread_cond_signal(hidapi_thread_state *state)
{
SDL_SignalCondition(state->condition);
}
static void hidapi_thread_cond_broadcast(hidapi_thread_state *state)
{
SDL_BroadcastCondition(state->condition);
}
static void hidapi_thread_barrier_wait(hidapi_thread_state *state)
{
SDL_WaitThreadBarrier(&state->barrier);
}
typedef struct
{
void *(*func)(void*);
void *func_arg;
} RunInputThreadParam;
static int RunInputThread(void *param)
{
RunInputThreadParam *data = (RunInputThreadParam *)param;
void *(*func)(void*) = data->func;
void *func_arg = data->func_arg;
SDL_free(data);
func(func_arg);
return 0;
}
static void hidapi_thread_create(hidapi_thread_state *state, void *(*func)(void*), void *func_arg)
{
RunInputThreadParam *param = (RunInputThreadParam *)malloc(sizeof(*param));
/* Note that the hidapi code didn't check for thread creation failure.
* We'll crash if malloc() fails
*/
param->func = func;
param->func_arg = func_arg;
state->thread = SDL_CreateThread(RunInputThread, "libusb", param);
}
static void hidapi_thread_join(hidapi_thread_state *state)
{
SDL_WaitThread(state->thread, NULL);
}
static void hidapi_thread_gettime(hidapi_timespec *ts)
{
*ts = SDL_GetTicksNS();
}
static void hidapi_thread_addtime(hidapi_timespec *ts, int milliseconds)
{
*ts += SDL_MS_TO_NS(milliseconds);
}