Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .github/workflows/builds.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: CMake Build

on: [push, pull_request]

jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
build_type: [Release]

runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v6

- name: Install dependencies (Linux)
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y ninja-build

- name: Install dependencies (macOS)
if: runner.os == 'macOS'
run: brew install ninja

- name: Configure CMake
run: |
cmake -B build -G Ninja \
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \
-DENABLE_EXAMPLES=ON

- name: Build
run: cmake --build build --config ${{ matrix.build_type }}

- name: Test (lsusb example)
if: runner.os != 'Windows' # adjust as needed
working-directory: build
run: ./examples/lsusb || echo "lsusb example ran"
149 changes: 149 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
cmake_minimum_required(VERSION 3.16)

file(READ "${CMAKE_CURRENT_SOURCE_DIR}/configure.ac" CONFIGURE_AC_DATA)
string(REGEX MATCH "m4_define\\(\\[libusb_compat_version_suffix\\], \\[([0-9]+)\\]\\)" _ ${CONFIGURE_AC_DATA})
set(VERSION_SUB ${CMAKE_MATCH_1})
if(NOT VERSION_SUB)
set(VERSION_SUB 9)
endif()

project(libusb-compat
DESCRIPTION "A libusb-0.1 compatibility layer on top of libusb-1.0"
VERSION 0.1.${VERSION_SUB}
LANGUAGES C
)

message(STATUS "Building libusb-compat v${PROJECT_VERSION} for: ${CMAKE_SYSTEM_NAME}")

include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
include(FetchContent)

option(BUILD_SHARED_LIBS "Build shared libraries" ON)
option(ENABLE_EXAMPLES "Build example applications" ON)

# Fetch libusb via libusb-cmake
FetchContent_Declare(libusb_cmake
GIT_REPOSITORY https://github.com/libusb/libusb-cmake.git
GIT_TAG main
)

FetchContent_MakeAvailable(libusb_cmake)

# Sources
add_library(usb libusb/core.c)

# Link to the target provided by libusb-cmake (usually usb-1.0)
target_link_libraries(usb PRIVATE usb-1.0)

# API & platform defines
if(WIN32)
target_compile_definitions(usb PRIVATE
API_EXPORTED=__declspec(dllexport)
BUILDING_LIBUSB_COMPAT=1
_CRT_SECURE_NO_WARNINGS=1
_WIN32_WINNT=0x0600
)
if(MSVC)
set_target_properties(usb PROPERTIES PREFIX "lib")
endif()
target_link_libraries(usb PRIVATE kernel32 user32)
else()
target_compile_definitions(usb PRIVATE
API_EXPORTED=__attribute__((visibility("default")))
)
endif()

# Generated headers
set(GENERATED_CONFIG_DIR "${CMAKE_CURRENT_BINARY_DIR}/compat_config")
file(MAKE_DIRECTORY "${GENERATED_CONFIG_DIR}")

file(WRITE "${GENERATED_CONFIG_DIR}/config.h" "
#ifndef CONFIG_H
#define CONFIG_H
#define HAVE_STDINT_H 1
#define HAVE_INTTYPES_H 1
#define HAVE_SYS_TYPES_H 1
#define HAVE_STDLIB_H 1
#define HAVE_STRING_H 1
#if defined(_WIN32) || defined(__MINGW32__)
# define HAVE_WINDOWS_H 1
# define HAVE_UNISTD_H 0
#else
# define HAVE_UNISTD_H 1
#endif
#endif
")

if(WIN32)
file(WRITE "${GENERATED_CONFIG_DIR}/unistd.h" "
#ifndef UNISTD_H_SHIM
#define UNISTD_H_SHIM
#include <io.h>
#include <process.h>
#include <windows.h>
#define sleep(x) Sleep((x)*1000)
#endif
")
endif()

target_include_directories(usb
PRIVATE
${GENERATED_CONFIG_DIR}
${CMAKE_CURRENT_BINARY_DIR}
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/libusb>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)

if(MSVC)
target_compile_options(usb PRIVATE /W3 /wd4244)
elseif(CMAKE_C_COMPILER_ID MATCHES "Clang|GNU")
target_compile_options(usb PRIVATE -fvisibility=hidden -Wno-pointer-sign -Wall -Wextra)
endif()

set_target_properties(usb PROPERTIES
OUTPUT_NAME usb
VERSION 0.4.4
SOVERSION 4
)

if(ENABLE_EXAMPLES)
add_executable(lsusb examples/lsusb.c)
target_link_libraries(lsusb PRIVATE usb)
endif()

# Installation
install(TARGETS usb
EXPORT libusb-compat-targets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

install(FILES libusb/usb.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libusb)

# pkg-config
set(prefix ${CMAKE_INSTALL_PREFIX})
set(exec_prefix \${prefix})
set(libdir \${exec_prefix}/${CMAKE_INSTALL_LIBDIR})
set(includedir \${prefix}/${CMAKE_INSTALL_INCLUDEDIR})
set(VERSION ${PROJECT_VERSION})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libusb.pc.in
${CMAKE_CURRENT_BINARY_DIR}/libusb.pc @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libusb.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)

# CMake package
install(EXPORT libusb-compat-targets
FILE libusb-compat-config.cmake
NAMESPACE libusb::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libusb-compat
)
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/libusb-compat-config-version.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion
)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libusb-compat-config-version.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libusb-compat
)
42 changes: 31 additions & 11 deletions libusb/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <libusb.h>

Expand All @@ -44,6 +45,10 @@
#define ENODATA EIO
#endif

#ifndef EOVERFLOW
#define EOVERFLOW E2BIG
#endif

static libusb_context *ctx = NULL;
static int usb_debug = 0;

Expand All @@ -54,25 +59,27 @@ enum usbi_log_level {
LOG_LEVEL_ERROR,
};

/* Realigned to C99 __VA_ARGS__ standard for MSVC /Zc:preprocessor parser compatibility */
#ifdef ENABLE_LOGGING
#define _usbi_log(level, fmt...) usbi_log(level, __FUNCTION__, fmt)
#define _usbi_log(level, ...) usbi_log(level, __FUNCTION__, __VA_ARGS__)
#else
#define _usbi_log(level, fmt...)
#define _usbi_log(level, ...)
#endif

#ifdef ENABLE_DEBUG_LOGGING
#define usbi_dbg(fmt...) _usbi_log(LOG_LEVEL_DEBUG, fmt)
#define usbi_dbg(...) _usbi_log(LOG_LEVEL_DEBUG, __VA_ARGS__)
#else
#define usbi_dbg(fmt...)
#define usbi_dbg(...)
#endif

#define usbi_info(fmt...) _usbi_log(LOG_LEVEL_INFO, fmt)
#define usbi_warn(fmt...) _usbi_log(LOG_LEVEL_WARNING, fmt)
#define usbi_err(fmt...) _usbi_log(LOG_LEVEL_ERROR, fmt)
#define usbi_info(...) _usbi_log(LOG_LEVEL_INFO, __VA_ARGS__)
#define usbi_warn(...) _usbi_log(LOG_LEVEL_WARNING, __VA_ARGS__)
#define usbi_err(...) _usbi_log(LOG_LEVEL_ERROR, __VA_ARGS__)

API_EXPORTED struct usb_bus *usb_busses = NULL;

#define compat_err(e) -(errno=libusb_to_errno(e))
/* Safe evaluation comma expression across variant platform rvalues */
#define compat_err(e) ((errno = libusb_to_errno(e)), -errno)

#ifdef LIBUSB_1_0_SONAME
static void __attribute__ ((constructor)) _usb_init (void)
Expand All @@ -94,7 +101,7 @@ static void free_bus(struct usb_bus *bus)
free(bus);
}

static void __attribute__ ((destructor)) _usb_exit (void)
static void _usb_exit (void)
{
struct usb_bus *bus = usb_busses;
while (bus) {
Expand All @@ -113,6 +120,19 @@ static void __attribute__ ((destructor)) _usb_exit (void)
#endif
}

/* GNU destructor emulation block targeting native MSVC runtime execution layout */
#if defined(__GNUC__) || defined(__clang__)
static void __attribute__ ((destructor)) _usb_exit_gnu(void) {
_usb_exit();
}
#elif defined(_MSC_VER)
#pragma section(".CRT$XCU", read)
static void __cdecl _usb_exit_msvc(void) {
_usb_exit();
}
__declspec(allocate(".CRT$XCU")) void (__cdecl * _usb_exit_init)(void) = _usb_exit_msvc;
#endif

static int libusb_to_errno(int result)
{
switch (result) {
Expand Down Expand Up @@ -273,7 +293,7 @@ static int find_busses(struct usb_bus **ret)

memset(bus, 0, sizeof(*bus));
bus->location = bus_num;
sprintf(bus->dirname, "%03d", bus_num);
snprintf(bus->dirname, sizeof(bus->dirname), "%03d", bus_num);
LIST_ADD(busses, bus);
}

Expand Down Expand Up @@ -383,7 +403,7 @@ static int find_devices(libusb_device **dev_list, int dev_list_len,

dev->bus = bus;
dev->devnum = libusb_get_device_address(newlib_dev);
sprintf(dev->filename, "%03d", dev->devnum);
snprintf(dev->filename, sizeof(dev->filename), "%03d", dev->devnum);
LIST_ADD(devices, dev);
}

Expand Down
29 changes: 28 additions & 1 deletion libusb/usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,39 @@
#ifndef USB_H
#define USB_H

#ifndef _MSC_VER
#include <unistd.h>
#include <dirent.h>
#endif

#include <stdlib.h>
#include <stdint.h>
#include <limits.h>

#include <dirent.h>
/* Fix missing PATH_MAX definition on Windows/MSVC platforms */
#if !defined(PATH_MAX)
#if defined(_MAX_PATH)
#define PATH_MAX _MAX_PATH
#elif defined(MAX_PATH)
#define PATH_MAX MAX_PATH
#else
#define PATH_MAX 4096
#endif
#endif

#if defined(_WIN32) || defined(__CYGWIN__)
#if defined(BUILDING_LIBUSB_COMPAT)
#define API_EXPORTED __declspec(dllexport)
#else
#define API_EXPORTED __declspec(dllimport)
#endif
#else
#if defined(__GNUC__) && (__GNUC__ >= 4)
#define API_EXPORTED __attribute__((visibility("default")))
#else
#define API_EXPORTED
#endif
#endif

#ifdef interface
#undef interface
Expand Down
Loading