Updated hidapi to 0.14.0 release
Upstream: https://github.com/libusb/hidapi/releases/tag/hidapi-0.14.0main
parent
6b8b9af88a
commit
3b7b8f3c09
|
@ -0,0 +1,31 @@
|
|||
environment:
|
||||
matrix:
|
||||
- BUILD_ENV: msbuild
|
||||
arch: x64
|
||||
- BUILD_ENV: msbuild
|
||||
arch: Win32
|
||||
- BUILD_ENV: cygwin
|
||||
|
||||
for:
|
||||
-
|
||||
matrix:
|
||||
only:
|
||||
- BUILD_ENV: msbuild
|
||||
|
||||
os: Visual Studio 2015
|
||||
|
||||
build_script:
|
||||
- cmd: msbuild .\windows\hidapi.sln /p:Configuration=Release /p:Platform=%arch% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
|
||||
|
||||
-
|
||||
matrix:
|
||||
only:
|
||||
- BUILD_ENV: cygwin
|
||||
|
||||
os: Visual Studio 2022
|
||||
|
||||
install:
|
||||
- cmd: C:\cygwin64\setup-x86_64.exe --quiet-mode --no-shortcuts --upgrade-also --packages autoconf,automake
|
||||
|
||||
build_script:
|
||||
- cmd: C:\cygwin64\bin\bash -exlc "cd $APPVEYOR_BUILD_FOLDER; ./bootstrap; ./configure; make"
|
|
@ -0,0 +1,34 @@
|
|||
image: freebsd/latest
|
||||
packages:
|
||||
- autoconf
|
||||
- automake
|
||||
- gmake
|
||||
- libiconv
|
||||
- libtool
|
||||
- pkgconf
|
||||
- cmake
|
||||
- ninja
|
||||
sources:
|
||||
- https://github.com/libusb/hidapi
|
||||
tasks:
|
||||
- configure: |
|
||||
cd hidapi
|
||||
echo Configure Autotools build
|
||||
./bootstrap
|
||||
./configure
|
||||
echo Configure CMake build
|
||||
mkdir -p build install_cmake
|
||||
cmake -GNinja -B build -S . -DCMAKE_INSTALL_PREFIX=install_cmake
|
||||
- build-autotools: |
|
||||
cd hidapi
|
||||
make
|
||||
make DESTDIR=$PWD/root install
|
||||
make clean
|
||||
- build-cmake: |
|
||||
cd hidapi/build
|
||||
ninja
|
||||
ninja install
|
||||
ninja clean
|
||||
- build-manual: |
|
||||
cd hidapi/libusb
|
||||
gmake -f Makefile-manual
|
|
@ -0,0 +1,18 @@
|
|||
image: netbsd/latest
|
||||
packages:
|
||||
- cmake
|
||||
- pkgconf
|
||||
- libusb1
|
||||
- libiconv
|
||||
sources:
|
||||
- https://github.com/libusb/hidapi
|
||||
tasks:
|
||||
- configure: |
|
||||
cd hidapi
|
||||
mkdir -p build install
|
||||
cmake -B build -S . -DCMAKE_INSTALL_PREFIX=install
|
||||
- build: |
|
||||
cd hidapi/build
|
||||
make
|
||||
make install
|
||||
make clean
|
|
@ -0,0 +1,19 @@
|
|||
image: openbsd/latest
|
||||
packages:
|
||||
- cmake
|
||||
- pkgconf
|
||||
- libusb1--
|
||||
- libiconv
|
||||
- ninja
|
||||
sources:
|
||||
- https://github.com/libusb/hidapi
|
||||
tasks:
|
||||
- configure: |
|
||||
cd hidapi
|
||||
mkdir -p build install
|
||||
cmake -GNinja -B build -S . -DCMAKE_INSTALL_PREFIX=install
|
||||
- build: |
|
||||
cd hidapi/build
|
||||
ninja
|
||||
ninja install
|
||||
ninja clean
|
|
@ -0,0 +1,33 @@
|
|||
alpine_task:
|
||||
container:
|
||||
image: alpine:latest
|
||||
install_script: apk add autoconf automake g++ gcc libusb-dev libtool linux-headers eudev-dev make musl-dev
|
||||
script:
|
||||
- ./bootstrap
|
||||
- ./configure || { cat config.log; exit 1; }
|
||||
- make
|
||||
- make install
|
||||
|
||||
freebsd11_task:
|
||||
freebsd_instance:
|
||||
image: freebsd-11-2-release-amd64
|
||||
install_script:
|
||||
- pkg install -y
|
||||
autoconf automake libiconv libtool pkgconf
|
||||
script:
|
||||
- ./bootstrap
|
||||
- ./configure || { cat config.log; exit 1; }
|
||||
- make
|
||||
- make install
|
||||
|
||||
freebsd12_task:
|
||||
freebsd_instance:
|
||||
image: freebsd-12-1-release-amd64
|
||||
install_script:
|
||||
- pkg install -y
|
||||
autoconf automake libiconv libtool pkgconf
|
||||
script:
|
||||
- ./bootstrap
|
||||
- ./configure || { cat config.log; exit 1; }
|
||||
- make
|
||||
- make install
|
|
@ -0,0 +1,7 @@
|
|||
* text=auto
|
||||
|
||||
*.sln text eol=crlf
|
||||
*.vcproj text eol=crlf
|
||||
|
||||
bootstrap text eol=lf
|
||||
configure.ac text eol=lf
|
|
@ -0,0 +1,540 @@
|
|||
name: GitHub Builds
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
env:
|
||||
NIX_COMPILE_FLAGS: -Wall -Wextra -pedantic -Werror
|
||||
MSVC_COMPILE_FLAGS: /W4 /WX
|
||||
|
||||
jobs:
|
||||
macos-automake:
|
||||
|
||||
runs-on: macos-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install build tools
|
||||
run: brew install autoconf automake libtool
|
||||
- name: Configure Automake
|
||||
run: |
|
||||
./bootstrap
|
||||
./configure --prefix=$(pwd)/install
|
||||
- name: Build Automake
|
||||
run: |
|
||||
make
|
||||
make install
|
||||
- name: Clean build
|
||||
run: make clean
|
||||
- name: Build Manual makefile
|
||||
working-directory: mac
|
||||
run: make -f Makefile-manual
|
||||
|
||||
|
||||
macos-cmake:
|
||||
|
||||
runs-on: macos-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
path: hidapisrc
|
||||
- name: Install dependencies
|
||||
run: brew install meson ninja
|
||||
- name: Configure CMake
|
||||
run: |
|
||||
rm -rf build install
|
||||
cmake -B build/shared -S hidapisrc -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHIDAPI_ENABLE_ASAN=ON -DCMAKE_INSTALL_PREFIX=install/shared -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=${NIX_COMPILE_FLAGS}"
|
||||
cmake -B build/static -S hidapisrc -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHIDAPI_ENABLE_ASAN=ON -DCMAKE_INSTALL_PREFIX=install/static -DBUILD_SHARED_LIBS=FALSE -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=${NIX_COMPILE_FLAGS}"
|
||||
cmake -B build/framework -S hidapisrc -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHIDAPI_ENABLE_ASAN=ON -DCMAKE_INSTALL_PREFIX=install/framework -DCMAKE_FRAMEWORK=ON -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=${NIX_COMPILE_FLAGS}"
|
||||
- name: Build CMake Shared
|
||||
working-directory: build/shared
|
||||
run: make install
|
||||
- name: Build CMake Static
|
||||
working-directory: build/static
|
||||
run: make install
|
||||
- name: Build CMake Framework
|
||||
working-directory: build/framework
|
||||
run: make install
|
||||
- name: Check artifacts
|
||||
uses: andstor/file-existence-action@v2
|
||||
with:
|
||||
files: "install/shared/lib/libhidapi.dylib, \
|
||||
install/shared/include/hidapi/hidapi.h, \
|
||||
install/shared/include/hidapi/hidapi_darwin.h, \
|
||||
install/static/lib/libhidapi.a, \
|
||||
install/static/include/hidapi/hidapi.h, \
|
||||
install/static/include/hidapi/hidapi_darwin.h, \
|
||||
install/framework/lib/hidapi.framework/hidapi, \
|
||||
install/framework/lib/hidapi.framework/Headers/hidapi.h, \
|
||||
install/framework/lib/hidapi.framework/Headers/hidapi_darwin.h"
|
||||
fail: true
|
||||
- name: Check CMake Export Package Shared
|
||||
run: |
|
||||
cmake \
|
||||
-B build/shared_test \
|
||||
-S hidapisrc/hidtest \
|
||||
-Dhidapi_ROOT=install/shared \
|
||||
-DCMAKE_INSTALL_PREFIX=install/shared_test \
|
||||
"-DCMAKE_C_FLAGS=${NIX_COMPILE_FLAGS}"
|
||||
cd build/shared_test
|
||||
make install
|
||||
- name: Check CMake Export Package Static
|
||||
run: |
|
||||
cmake \
|
||||
-B build/static_test \
|
||||
-S hidapisrc/hidtest \
|
||||
-Dhidapi_ROOT=install/static \
|
||||
-DCMAKE_INSTALL_PREFIX=install/static_test \
|
||||
"-DCMAKE_C_FLAGS=${NIX_COMPILE_FLAGS}"
|
||||
cd build/static_test
|
||||
make install
|
||||
|
||||
- name: Check Meson build
|
||||
run: |
|
||||
meson setup build_meson hidapisrc
|
||||
cd build_meson
|
||||
ninja
|
||||
|
||||
|
||||
ubuntu-cmake:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
path: hidapisrc
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install libudev-dev libusb-1.0-0-dev python3-pip ninja-build
|
||||
sudo -H pip3 install meson
|
||||
- name: Configure CMake
|
||||
run: |
|
||||
rm -rf build install
|
||||
cmake -B build/shared -S hidapisrc -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHIDAPI_ENABLE_ASAN=ON -DCMAKE_INSTALL_PREFIX=install/shared -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=${NIX_COMPILE_FLAGS}"
|
||||
cmake -B build/static -S hidapisrc -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHIDAPI_ENABLE_ASAN=ON -DCMAKE_INSTALL_PREFIX=install/static -DBUILD_SHARED_LIBS=FALSE -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=${NIX_COMPILE_FLAGS}"
|
||||
- name: Build CMake Shared
|
||||
working-directory: build/shared
|
||||
run: make install
|
||||
- name: Build CMake Static
|
||||
working-directory: build/static
|
||||
run: make install
|
||||
- name: Check artifacts
|
||||
uses: andstor/file-existence-action@v2
|
||||
with:
|
||||
files: "install/shared/lib/libhidapi-libusb.so, \
|
||||
install/shared/lib/libhidapi-hidraw.so, \
|
||||
install/shared/include/hidapi/hidapi.h, \
|
||||
install/shared/include/hidapi/hidapi_libusb.h, \
|
||||
install/static/lib/libhidapi-libusb.a, \
|
||||
install/static/lib/libhidapi-hidraw.a, \
|
||||
install/static/include/hidapi/hidapi.h, \
|
||||
install/static/include/hidapi/hidapi_libusb.h"
|
||||
fail: true
|
||||
- name: Check CMake Export Package Shared
|
||||
run: |
|
||||
cmake \
|
||||
-B build/shared_test \
|
||||
-S hidapisrc/hidtest \
|
||||
-Dhidapi_ROOT=install/shared \
|
||||
-DCMAKE_INSTALL_PREFIX=install/shared_test \
|
||||
"-DCMAKE_C_FLAGS=${NIX_COMPILE_FLAGS}"
|
||||
cd build/shared_test
|
||||
make install
|
||||
- name: Check CMake Export Package Static
|
||||
run: |
|
||||
cmake \
|
||||
-B build/static_test \
|
||||
-S hidapisrc/hidtest \
|
||||
-Dhidapi_ROOT=install/static \
|
||||
-DCMAKE_INSTALL_PREFIX=install/static_test \
|
||||
"-DCMAKE_C_FLAGS=${NIX_COMPILE_FLAGS}"
|
||||
cd build/static_test
|
||||
make install
|
||||
|
||||
- name: Check Meson build
|
||||
run: |
|
||||
meson setup build_meson hidapisrc
|
||||
cd build_meson
|
||||
ninja
|
||||
|
||||
|
||||
windows-cmake:
|
||||
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
path: hidapisrc
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
choco install ninja
|
||||
pip3 install meson
|
||||
refreshenv
|
||||
- name: Configure CMake MSVC
|
||||
shell: cmd
|
||||
run: |
|
||||
cmake -B build\msvc -S hidapisrc -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHIDAPI_WITH_TESTS=ON -DHIDAPI_BUILD_PP_DATA_DUMP=ON -DHIDAPI_ENABLE_ASAN=ON -DCMAKE_INSTALL_PREFIX=install\msvc -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=%MSVC_COMPILE_FLAGS%"
|
||||
- name: Build CMake MSVC
|
||||
working-directory: build/msvc
|
||||
run: cmake --build . --config RelWithDebInfo --target install
|
||||
- name: Check artifacts MSVC
|
||||
uses: andstor/file-existence-action@v2
|
||||
with:
|
||||
files: "install/msvc/lib/hidapi.lib, \
|
||||
install/msvc/bin/hidapi.dll, \
|
||||
install/msvc/include/hidapi/hidapi.h, \
|
||||
install/msvc/include/hidapi/hidapi_winapi.h"
|
||||
fail: true
|
||||
- name: Check CMake Export Package
|
||||
shell: cmd
|
||||
run: |
|
||||
cmake ^
|
||||
-B build\msvc_test ^
|
||||
-S hidapisrc\hidtest ^
|
||||
-Dhidapi_ROOT=install\msvc ^
|
||||
-DCMAKE_INSTALL_PREFIX=install\msvc_test ^
|
||||
"-DCMAKE_C_FLAGS=%MSVC_COMPILE_FLAGS%"
|
||||
cd build\msvc_test
|
||||
cmake --build . --target install
|
||||
- name: Run CTest MSVC
|
||||
shell: cmd
|
||||
working-directory: build/msvc
|
||||
run: ctest -C RelWithDebInfo --rerun-failed --output-on-failure
|
||||
|
||||
- name: Configure CMake NMake
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
|
||||
cmake -G"NMake Makefiles" -B build\nmake -S hidapisrc -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHIDAPI_WITH_TESTS=ON -DHIDAPI_BUILD_PP_DATA_DUMP=ON -DHIDAPI_ENABLE_ASAN=ON -DCMAKE_INSTALL_PREFIX=install\nmake -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=%MSVC_COMPILE_FLAGS%"
|
||||
- name: Build CMake NMake
|
||||
working-directory: build\nmake
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
|
||||
nmake install
|
||||
- name: Check artifacts NMake
|
||||
uses: andstor/file-existence-action@v2
|
||||
with:
|
||||
files: "install/nmake/lib/hidapi.lib, \
|
||||
install/nmake/bin/hidapi.dll, \
|
||||
install/nmake/include/hidapi/hidapi.h, \
|
||||
install/nmake/include/hidapi/hidapi_winapi.h"
|
||||
fail: true
|
||||
- name: Check CMake Export Package NMake
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
|
||||
cmake ^
|
||||
-G"NMake Makefiles" ^
|
||||
-B build\nmake_test ^
|
||||
-S hidapisrc\hidtest ^
|
||||
-Dhidapi_ROOT=install\nmake ^
|
||||
-DCMAKE_INSTALL_PREFIX=install\nmake_test ^
|
||||
"-DCMAKE_C_FLAGS=%MSVC_COMPILE_FLAGS%"
|
||||
cd build\nmake_test
|
||||
nmake install
|
||||
- name: Run CTest NMake
|
||||
working-directory: build\nmake
|
||||
run: ctest --rerun-failed --output-on-failure
|
||||
|
||||
- name: Configure CMake MinGW
|
||||
shell: cmd
|
||||
run: |
|
||||
cmake -G"MinGW Makefiles" -B build\mingw -S hidapisrc -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHIDAPI_WITH_TESTS=ON -DHIDAPI_BUILD_PP_DATA_DUMP=ON -DCMAKE_INSTALL_PREFIX=install\mingw -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=%NIX_COMPILE_FLAGS%"
|
||||
- name: Build CMake MinGW
|
||||
working-directory: build\mingw
|
||||
run: cmake --build . --target install
|
||||
- name: Check artifacts MinGW
|
||||
uses: andstor/file-existence-action@v2
|
||||
with:
|
||||
files: "install/mingw/lib/libhidapi.dll.a, \
|
||||
install/mingw/bin/libhidapi.dll, \
|
||||
install/mingw/include/hidapi/hidapi.h, \
|
||||
install/mingw/include/hidapi/hidapi_winapi.h"
|
||||
fail: true
|
||||
- name: Check CMake Export Package MinGW
|
||||
shell: cmd
|
||||
run: |
|
||||
cmake ^
|
||||
-G"MinGW Makefiles" ^
|
||||
-B build\mingw_test ^
|
||||
-S hidapisrc\hidtest ^
|
||||
-Dhidapi_ROOT=install\mingw ^
|
||||
-DCMAKE_INSTALL_PREFIX=install\mingw_test ^
|
||||
"-DCMAKE_C_FLAGS=%NIX_COMPILE_FLAGS%"
|
||||
cd build\mingw_test
|
||||
cmake --build . --target install
|
||||
- name: Run CTest MinGW
|
||||
working-directory: build\mingw
|
||||
run: ctest --rerun-failed --output-on-failure
|
||||
|
||||
- name: Check Meson build
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
|
||||
meson setup build_meson hidapisrc
|
||||
cd build_meson
|
||||
ninja
|
||||
|
||||
|
||||
windows-msbuild:
|
||||
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: microsoft/setup-msbuild@v1.1
|
||||
- name: MSBuild x86
|
||||
run: msbuild windows\hidapi.sln /p:Configuration=Release /p:Platform=Win32
|
||||
- name: Check artifacts x86
|
||||
uses: andstor/file-existence-action@v2
|
||||
with:
|
||||
files: "windows/Release/hidapi.dll, windows/Release/hidapi.lib, windows/Release/hidapi.pdb"
|
||||
fail: true
|
||||
- name: MSBuild x64
|
||||
run: msbuild windows\hidapi.sln /p:Configuration=Release /p:Platform=x64
|
||||
- name: Check artifacts x64
|
||||
uses: andstor/file-existence-action@v2
|
||||
with:
|
||||
files: "windows/x64/Release/hidapi.dll, windows/x64/Release/hidapi.lib, windows/x64/Release/hidapi.pdb"
|
||||
fail: true
|
||||
- name: Gather artifacts
|
||||
run: |
|
||||
md artifacts
|
||||
md artifacts\x86
|
||||
md artifacts\x64
|
||||
md artifacts\include
|
||||
Copy-Item "windows\Release\hidapi.dll","windows\Release\hidapi.lib","windows\Release\hidapi.pdb" -Destination "artifacts\x86"
|
||||
Copy-Item "windows\x64\Release\hidapi.dll","windows\x64\Release\hidapi.lib","windows\x64\Release\hidapi.pdb" -Destination "artifacts\x64"
|
||||
Copy-Item "hidapi\hidapi.h","windows\hidapi_winapi.h" -Destination "artifacts\include"
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: hidapi-win
|
||||
path: artifacts/
|
||||
retention-days: ${{ (github.event_name == 'pull_request' || github.ref_name != 'master') && 7 || 90 }}
|
||||
|
||||
|
||||
fedora-mingw:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
container: fedora:latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
path: hidapisrc
|
||||
- name: Install dependencies
|
||||
run: sudo dnf install -y autoconf automake libtool mingw64-gcc cmake ninja-build make
|
||||
- name: Configure CMake
|
||||
run: |
|
||||
rm -rf build install
|
||||
mingw64-cmake -B build/shared-cmake -S hidapisrc -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=install/shared-cmake -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=${NIX_COMPILE_FLAGS}"
|
||||
mingw64-cmake -B build/static-cmake -S hidapisrc -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=install/static-cmake -DBUILD_SHARED_LIBS=FALSE -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=${NIX_COMPILE_FLAGS}"
|
||||
- name: Configure Automake
|
||||
working-directory: hidapisrc
|
||||
run: |
|
||||
./bootstrap
|
||||
mingw64-configure
|
||||
- name: Build CMake Shared
|
||||
working-directory: build/shared-cmake
|
||||
run: ninja install
|
||||
- name: Build CMake Static
|
||||
working-directory: build/static-cmake
|
||||
run: ninja install
|
||||
- name: Build Automake
|
||||
working-directory: hidapisrc
|
||||
run: |
|
||||
make
|
||||
make DESTDIR=$PWD/../install/automake install
|
||||
make clean
|
||||
- name: Build manual Makefile
|
||||
working-directory: hidapisrc/windows
|
||||
run: make -f Makefile-manual OS=MINGW CC=x86_64-w64-mingw32-gcc
|
||||
- name: Check artifacts
|
||||
uses: andstor/file-existence-action@v2
|
||||
with:
|
||||
files: "install/shared-cmake/bin/libhidapi.dll, \
|
||||
install/shared-cmake/lib/libhidapi.dll.a, \
|
||||
install/shared-cmake/include/hidapi/hidapi.h, \
|
||||
install/shared-cmake/include/hidapi/hidapi_winapi.h, \
|
||||
install/static-cmake/lib/libhidapi.a, \
|
||||
install/static-cmake/include/hidapi/hidapi.h, \
|
||||
install/static-cmake/include/hidapi/hidapi_winapi.h"
|
||||
fail: true
|
||||
- name: Check CMake Export Package Shared
|
||||
run: |
|
||||
mingw64-cmake \
|
||||
-GNinja \
|
||||
-B build/shared_test \
|
||||
-S hidapisrc/hidtest \
|
||||
-Dhidapi_DIR=$PWD/install/shared-cmake/lib/cmake/hidapi \
|
||||
-DCMAKE_INSTALL_PREFIX=install/shared_test \
|
||||
"-DCMAKE_C_FLAGS=${NIX_COMPILE_FLAGS}"
|
||||
cd build/shared_test
|
||||
ninja install
|
||||
- name: Check CMake Export Package Static
|
||||
run: |
|
||||
mingw64-cmake \
|
||||
-GNinja \
|
||||
-B build/static_test \
|
||||
-S hidapisrc/hidtest \
|
||||
-Dhidapi_DIR=$PWD/install/static-cmake/lib/cmake/hidapi \
|
||||
-DCMAKE_INSTALL_PREFIX=install/static_test \
|
||||
"-DCMAKE_C_FLAGS=${NIX_COMPILE_FLAGS}"
|
||||
cd build/static_test
|
||||
ninja install
|
||||
|
||||
|
||||
archlinux:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
container: archlinux:latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
path: hidapisrc
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pacman -Sy
|
||||
pacman -S --noconfirm gcc pkg-config autoconf automake libtool libusb libudev0 cmake make
|
||||
- name: Configure CMake
|
||||
run: |
|
||||
rm -rf build install
|
||||
cmake -B build/shared-cmake -S hidapisrc -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=install/shared-cmake -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=${NIX_COMPILE_FLAGS}"
|
||||
cmake -B build/static-cmake -S hidapisrc -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=install/static-cmake -DBUILD_SHARED_LIBS=FALSE -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=${NIX_COMPILE_FLAGS}"
|
||||
- name: Configure Automake
|
||||
working-directory: hidapisrc
|
||||
run: |
|
||||
./bootstrap
|
||||
./configure
|
||||
- name: Build CMake Shared
|
||||
working-directory: build/shared-cmake
|
||||
run: make install
|
||||
- name: Build CMake Static
|
||||
working-directory: build/static-cmake
|
||||
run: make install
|
||||
- name: Build Automake
|
||||
working-directory: hidapisrc
|
||||
run: |
|
||||
make
|
||||
make DESTDIR=$PWD/../install/automake install
|
||||
make clean
|
||||
- name: Build manual Makefile
|
||||
run: |
|
||||
cd hidapisrc/linux
|
||||
make -f Makefile-manual
|
||||
cd ../libusb
|
||||
make -f Makefile-manual
|
||||
- name: Check artifacts
|
||||
uses: andstor/file-existence-action@v2
|
||||
with:
|
||||
files: "install/shared-cmake/lib/libhidapi-libusb.so, \
|
||||
install/shared-cmake/lib/libhidapi-hidraw.so, \
|
||||
install/shared-cmake/include/hidapi/hidapi.h, \
|
||||
install/shared-cmake/include/hidapi/hidapi_libusb.h, \
|
||||
install/static-cmake/lib/libhidapi-libusb.a, \
|
||||
install/static-cmake/lib/libhidapi-hidraw.a, \
|
||||
install/static-cmake/include/hidapi/hidapi.h, \
|
||||
install/static-cmake/include/hidapi/hidapi_libusb.h"
|
||||
fail: true
|
||||
- name: Check CMake Export Package Shared
|
||||
run: |
|
||||
cmake \
|
||||
-B build/shared_test \
|
||||
-S hidapisrc/hidtest \
|
||||
-Dhidapi_ROOT=install/shared-cmake \
|
||||
-DCMAKE_INSTALL_PREFIX=install/shared_test \
|
||||
"-DCMAKE_C_FLAGS=${NIX_COMPILE_FLAGS}"
|
||||
cd build/shared_test
|
||||
make install
|
||||
- name: Check CMake Export Package Static
|
||||
run: |
|
||||
cmake \
|
||||
-B build/static_test \
|
||||
-S hidapisrc/hidtest \
|
||||
-Dhidapi_ROOT=install/static-cmake \
|
||||
-DCMAKE_INSTALL_PREFIX=install/static_test \
|
||||
"-DCMAKE_C_FLAGS=${NIX_COMPILE_FLAGS}"
|
||||
cd build/static_test
|
||||
make install
|
||||
|
||||
|
||||
alpine:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
container: alpine:edge
|
||||
env:
|
||||
# A bug in musl: https://www.openwall.com/lists/musl/2020/01/20/2
|
||||
ALPINE_COMPILE_FLAGS: ${NIX_COMPILE_FLAGS} -Wno-overflow
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
path: hidapisrc
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
apk add gcc musl-dev autoconf automake libtool eudev-dev libusb-dev linux-headers cmake ninja make
|
||||
- name: Configure CMake
|
||||
run: |
|
||||
rm -rf build install
|
||||
cmake -B build/shared-cmake -S hidapisrc -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=install/shared-cmake -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=${ALPINE_COMPILE_FLAGS}"
|
||||
cmake -B build/static-cmake -S hidapisrc -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=install/static-cmake -DBUILD_SHARED_LIBS=FALSE -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=${ALPINE_COMPILE_FLAGS}"
|
||||
- name: Configure Automake
|
||||
working-directory: hidapisrc
|
||||
run: |
|
||||
./bootstrap
|
||||
./configure
|
||||
- name: Build CMake Shared
|
||||
working-directory: build/shared-cmake
|
||||
run: ninja install
|
||||
- name: Build CMake Static
|
||||
working-directory: build/static-cmake
|
||||
run: ninja install
|
||||
- name: Build Automake
|
||||
working-directory: hidapisrc
|
||||
run: |
|
||||
make
|
||||
make DESTDIR=$PWD/../install/automake install
|
||||
make clean
|
||||
- name: Build manual Makefile
|
||||
run: |
|
||||
cd hidapisrc/linux
|
||||
make -f Makefile-manual
|
||||
cd ../libusb
|
||||
make -f Makefile-manual
|
||||
- name: Check artifacts
|
||||
uses: andstor/file-existence-action@v2
|
||||
with:
|
||||
files: "install/shared-cmake/lib/libhidapi-libusb.so, \
|
||||
install/shared-cmake/lib/libhidapi-hidraw.so, \
|
||||
install/shared-cmake/include/hidapi/hidapi.h, \
|
||||
install/shared-cmake/include/hidapi/hidapi_libusb.h, \
|
||||
install/static-cmake/lib/libhidapi-libusb.a, \
|
||||
install/static-cmake/lib/libhidapi-hidraw.a, \
|
||||
install/static-cmake/include/hidapi/hidapi.h, \
|
||||
install/static-cmake/include/hidapi/hidapi_libusb.h"
|
||||
fail: true
|
||||
- name: Check CMake Export Package Shared
|
||||
run: |
|
||||
cmake \
|
||||
-GNinja \
|
||||
-B build/shared_test \
|
||||
-S hidapisrc/hidtest \
|
||||
-Dhidapi_ROOT=install/shared-cmake \
|
||||
-DCMAKE_INSTALL_PREFIX=install/shared_test \
|
||||
"-DCMAKE_C_FLAGS=${ALPINE_COMPILE_FLAGS}"
|
||||
cd build/shared_test
|
||||
ninja install
|
||||
- name: Check CMake Export Package Static
|
||||
run: |
|
||||
cmake \
|
||||
-GNinja \
|
||||
-B build/static_test \
|
||||
-S hidapisrc/hidtest \
|
||||
-Dhidapi_ROOT=install/static-cmake \
|
||||
-DCMAKE_INSTALL_PREFIX=install/static_test \
|
||||
"-DCMAKE_C_FLAGS=${ALPINE_COMPILE_FLAGS}"
|
||||
cd build/static_test
|
||||
ninja install
|
|
@ -0,0 +1,196 @@
|
|||
name: Checks
|
||||
run-name: Code checks for '${{ github.ref_name }}'
|
||||
|
||||
# General comment:
|
||||
# Coverity doesn't support merging or including reports from multible machine/platforms (at least not officially).
|
||||
# But otherwise there is no good way to keep the issues from all platforms at Coverity Scans at once.
|
||||
# This script uses undocumented (but appears to be working) hack:
|
||||
# The build logs from one machine/platform gets moved to a next once,
|
||||
# and "fixed" so that cov-build can append logs from the next platform.
|
||||
# The "fix" is based on the fact, that Coverity perfectly allows appending logs from multiple builds
|
||||
# that are done *on the same host* machine.
|
||||
|
||||
on:
|
||||
# On-demand run
|
||||
workflow_dispatch:
|
||||
# Weekly run
|
||||
schedule:
|
||||
- cron: '30 5 * * 0'
|
||||
|
||||
jobs:
|
||||
coverity-windows:
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
path: src
|
||||
- name: Setup MSVC
|
||||
uses: TheMrMilchmann/setup-msvc-dev@v2.0.0
|
||||
with:
|
||||
arch: x64
|
||||
- name: Configure
|
||||
run: |
|
||||
cmake -B build -S src -G"NMake Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHIDAPI_WITH_TESTS=ON -DHIDAPI_BUILD_HIDTEST=ON
|
||||
- name: Lookup Coverity Build Tool hash
|
||||
id: coverity-cache-lookup
|
||||
run: |
|
||||
$coverity_hash=Invoke-RestMethod -Uri https://scan.coverity.com/download/cxx/win64 -Method Post -Body @{token='${{ secrets.COVERITY_SCAN_TOKEN }}';project='hidapi';md5=1}
|
||||
echo "coverity_hash=$coverity_hash" >> $Env:GITHUB_OUTPUT
|
||||
- name: Get cached Coverity Build Tool
|
||||
id: cov-build-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: cov-root
|
||||
key: cov-root-cxx-win64-${{ steps.coverity-cache-lookup.outputs.coverity_hash }}
|
||||
- name: Get and configure Coverity
|
||||
if: steps.cov-build-cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
Invoke-WebRequest -Uri https://scan.coverity.com/download/cxx/win64 -OutFile coverity.zip -Method Post -Body @{token='${{ secrets.COVERITY_SCAN_TOKEN }}';project='hidapi'}
|
||||
Remove-Item 'cov-root' -Recurse -Force -ErrorAction SilentlyContinue
|
||||
Expand-Archive coverity.zip -DestinationPath cov-root
|
||||
|
||||
$cov_root=Get-ChildItem -Path 'cov-root'
|
||||
$Env:PATH += ";$($cov_root.FullName)\bin"
|
||||
cov-configure -msvc
|
||||
- name: Make Coverity available in PATH
|
||||
run: |
|
||||
$cov_root=Get-ChildItem -Path 'cov-root'
|
||||
echo "$($cov_root.FullName)\bin" >> $Env:GITHUB_PATH
|
||||
- name: Build with Coverity
|
||||
working-directory: build
|
||||
run: |
|
||||
cov-build --dir cov-int nmake
|
||||
Rename-Item ".\cov-int\emit\$(hostname)" hostname
|
||||
- name: Backup Coverity logs
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: coverity-logs-windows
|
||||
path: build/cov-int
|
||||
retention-days: 7
|
||||
|
||||
|
||||
coverity-macos:
|
||||
runs-on: macos-latest
|
||||
needs: [coverity-windows]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
path: src
|
||||
- name: Install dependencies
|
||||
run: brew install ninja
|
||||
- name: Configure
|
||||
run: |
|
||||
cmake -B build -S src -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHIDAPI_WITH_TESTS=ON -DHIDAPI_BUILD_HIDTEST=ON -DCMAKE_C_COMPILER=clang
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: coverity-logs-windows
|
||||
path: build/cov-int
|
||||
- name: Fixup cov-int
|
||||
run: |
|
||||
rm -f build/cov-int/emit/hostname/emit-db.lock build/cov-int/emit/hostname/emit-db.write-lock
|
||||
mv build/cov-int/emit/hostname build/cov-int/emit/$(hostname)
|
||||
- name: Lookup Coverity Build Tool hash
|
||||
id: coverity-cache-lookup
|
||||
shell: bash
|
||||
run: |
|
||||
hash=$(curl https://scan.coverity.com/download/cxx/Darwin --data "token=${{ secrets.COVERITY_SCAN_TOKEN }}&project=hidapi&md5=1")
|
||||
echo "coverity_hash=${hash}" >> $GITHUB_OUTPUT
|
||||
- name: Get cached Coverity Build Tool
|
||||
id: cov-build-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: cov-root
|
||||
key: cov-root-cxx-Darwin-${{ steps.coverity-cache-lookup.outputs.coverity_hash }}
|
||||
- name: Get and configure Coverity
|
||||
if: steps.cov-build-cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
curl https://scan.coverity.com/download/cxx/Darwin --output coverity.dmg --data "token=${{ secrets.COVERITY_SCAN_TOKEN }}&project=hidapi"
|
||||
hdiutil attach coverity.dmg -mountroot coverity
|
||||
export COV_DIR_NAME=$(ls -1 --color=never coverity)
|
||||
rm -rf cov-root
|
||||
mkdir cov-root
|
||||
cp ./coverity/${COV_DIR_NAME}/${COV_DIR_NAME}.sh cov-root/
|
||||
cd cov-root/
|
||||
./${COV_DIR_NAME}.sh
|
||||
./bin/cov-configure --clang
|
||||
- name: Make Coverity available in PATH
|
||||
run: echo "$(pwd)/cov-root/bin" >> $GITHUB_PATH
|
||||
- name: Build with Coverity
|
||||
working-directory: build
|
||||
run: |
|
||||
cov-build --dir cov-int --append-log ninja
|
||||
mv cov-int/emit/$(hostname) cov-int/emit/hostname
|
||||
- name: Backup Coverity logs
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: coverity-logs-windows-macos
|
||||
path: build/cov-int
|
||||
retention-days: 7
|
||||
|
||||
|
||||
coverity-ubuntu:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [coverity-macos]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
path: src
|
||||
- name: Install dependencies
|
||||
run: sudo apt install libudev-dev libusb-1.0-0-dev ninja-build
|
||||
- name: Configure
|
||||
run: |
|
||||
cmake -B build -S src -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHIDAPI_WITH_TESTS=ON -DHIDAPI_BUILD_HIDTEST=ON -DCMAKE_C_COMPILER=gcc
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: coverity-logs-windows-macos
|
||||
path: build/cov-int
|
||||
- name: Fixup cov-int
|
||||
run: |
|
||||
rm -f build/cov-int/emit/hostname/emit-db.lock build/cov-int/emit/hostname/emit-db.write-lock
|
||||
mv build/cov-int/emit/hostname build/cov-int/emit/$(hostname)
|
||||
- name: Lookup Coverity Build Tool hash
|
||||
id: coverity-cache-lookup
|
||||
shell: bash
|
||||
run: |
|
||||
hash=$(curl https://scan.coverity.com/download/cxx/linux64 --data "token=${{ secrets.COVERITY_SCAN_TOKEN }}&project=hidapi&md5=1")
|
||||
echo "coverity_hash=${hash}" >> $GITHUB_OUTPUT
|
||||
- name: Get cached Coverity Build Tool
|
||||
id: cov-build-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: cov-root
|
||||
key: cov-root-cxx-linux64-${{ steps.coverity-cache-lookup.outputs.coverity_hash }}
|
||||
- name: Get and configure Coverity
|
||||
if: steps.cov-build-cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
curl https://scan.coverity.com/download/cxx/linux64 --output coverity.tar.gz --data "token=${{ secrets.COVERITY_SCAN_TOKEN }}&project=hidapi"
|
||||
rm -rf cov-root
|
||||
mkdir cov-root
|
||||
tar -xzf coverity.tar.gz --strip 1 -C cov-root
|
||||
./cov-root/bin/cov-configure --gcc
|
||||
- name: Make Coverity available in PATH
|
||||
run: echo "$(pwd)/cov-root/bin" >> $GITHUB_PATH
|
||||
- name: Build with Coverity
|
||||
working-directory: build
|
||||
run: |
|
||||
cov-build --dir cov-int --append-log ninja
|
||||
- name: Submit results to Coverity Scan
|
||||
working-directory: build
|
||||
run: |
|
||||
tar -czf cov-int.tar.gz cov-int
|
||||
curl --form token=${{ secrets.COVERITY_SCAN_TOKEN }} \
|
||||
--form email=${{ secrets.COVERITY_SCAN_EMAIL }} \
|
||||
--form file=@cov-int.tar.gz \
|
||||
--form version="$GITHUB_SHA" \
|
||||
--form description="Automatic HIDAPI build" \
|
||||
https://scan.coverity.com/builds?project=hidapi
|
||||
mv cov-int/emit/$(hostname) cov-int/emit/hostname
|
||||
- name: Backup Coverity logs
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: coverity-logs-windows-macos-linux
|
||||
path: build/cov-int
|
||||
retention-days: 7
|
|
@ -0,0 +1,58 @@
|
|||
name: Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- name: Install Doxygen static libclang deps
|
||||
run: sudo apt-get install libclang1-12 libclang-cpp12
|
||||
|
||||
- name: Install Doxygen from SF binary archives
|
||||
env:
|
||||
DOXYGEN_VERSION: '1.9.6'
|
||||
run: |
|
||||
mkdir .doxygen && cd .doxygen
|
||||
curl -L https://sourceforge.net/projects/doxygen/files/rel-$DOXYGEN_VERSION/doxygen-$DOXYGEN_VERSION.linux.bin.tar.gz > doxygen.tar.gz
|
||||
gunzip doxygen.tar.gz
|
||||
tar xf doxygen.tar
|
||||
cd doxygen-$DOXYGEN_VERSION
|
||||
sudo make install
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- run: doxygen
|
||||
working-directory: doxygen
|
||||
|
||||
- name: Save doxygen docs as artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: HIDAPI_doxygen_docs
|
||||
path: ${{ github.workspace }}/doxygen/html
|
||||
|
||||
deploy-docs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build]
|
||||
if: github.ref_type == 'branch' && github.ref_name == 'master'
|
||||
concurrency:
|
||||
group: "github-pages-deploy"
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- name: downlod artifact
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: HIDAPI_doxygen_docs
|
||||
path: docs
|
||||
|
||||
- name: upload to github pages
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./docs
|
||||
force_orphan: true
|
|
@ -0,0 +1,32 @@
|
|||
|
||||
# Autotools-added generated files
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
ar-lib
|
||||
autom4te.cache/
|
||||
config.*
|
||||
configure
|
||||
configure~
|
||||
compile
|
||||
depcomp
|
||||
install-sh
|
||||
libusb/Makefile.in
|
||||
linux/Makefile.in
|
||||
ltmain.sh
|
||||
mac/Makefile.in
|
||||
missing
|
||||
testgui/Makefile.in
|
||||
windows/Makefile.in
|
||||
|
||||
Makefile
|
||||
stamp-h1
|
||||
libtool
|
||||
|
||||
# macOS
|
||||
.DS_Store
|
||||
|
||||
# Qt Creator
|
||||
CMakeLists.txt.user
|
||||
|
||||
# doxgen output
|
||||
doxygen/html/
|
|
@ -10,7 +10,9 @@ Ludovic Rousseau <rousseau@debian.org>:
|
|||
Bug fixes
|
||||
Correctness fixes
|
||||
|
||||
libusb/hidapi Team:
|
||||
Development/maintainance since June 4th 2019
|
||||
|
||||
For a comprehensive list of contributions, see the commit list at github:
|
||||
https://github.com/libusb/hidapi/commits/master
|
||||
https://github.com/libusb/hidapi/graphs/contributors
|
||||
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
# Building HIDAPI using Autotools (deprecated)
|
||||
|
||||
---
|
||||
**NOTE**: for all intentions and purposes the Autotools build scripts for HIDAPI are _deprecated_ and going to be obsolete in the future.
|
||||
HIDAPI Team recommends using CMake build for HIDAPI.
|
||||
If you are already using Autotools build scripts provided by HIDAPI,
|
||||
consider switching to CMake build scripts as soon as possible.
|
||||
|
||||
---
|
||||
|
||||
To be able to use Autotools to build HIDAPI, it has to be [installed](#installing-autotools)/available in the system.
|
||||
|
||||
Make sure you've checked [prerequisites](BUILD.md#prerequisites) and installed all required dependencies.
|
||||
|
||||
## Installing Autotools
|
||||
|
||||
HIDAPI uses few specific tools/packages from Autotools: `autoconf`, `automake`, `libtool`.
|
||||
|
||||
On different platforms or package managers, those could be named a bit differently or packaged together.
|
||||
You'll have to check the documentation/package list for your specific package manager.
|
||||
|
||||
### Linux
|
||||
|
||||
On Ubuntu the tools are available via APT:
|
||||
|
||||
```sh
|
||||
sudo apt install autoconf automake libtool
|
||||
```
|
||||
|
||||
### FreeBSD
|
||||
|
||||
FreeBSD Autotools can be installed as:
|
||||
|
||||
```sh
|
||||
pkg_add -r autotools
|
||||
```
|
||||
|
||||
Additionally, on FreeBSD you will need to install GNU make:
|
||||
```sh
|
||||
pkg_add -r gmake
|
||||
```
|
||||
|
||||
## Building HIDAPI with Autotools
|
||||
|
||||
A simple command list, to build HIDAPI with Autotools as a _shared library_ and install in into your system:
|
||||
|
||||
```sh
|
||||
./bootstrap # this prepares the configure script
|
||||
./configure
|
||||
make # build the library
|
||||
make install # as root, or using sudo, this will install hidapi into your system
|
||||
```
|
||||
|
||||
`./configure` can take several arguments which control the build. A few commonly used options:
|
||||
```sh
|
||||
--enable-testgui
|
||||
# Enable the build of Foxit-based Test GUI. This requires Fox toolkit to
|
||||
# be installed/available. See README.md#test-gui for remarks.
|
||||
|
||||
--prefix=/usr
|
||||
# Specify where you want the output headers and libraries to
|
||||
# be installed. The example above will put the headers in
|
||||
# /usr/include and the binaries in /usr/lib. The default is to
|
||||
# install into /usr/local which is fine on most systems.
|
||||
|
||||
--disable-shared
|
||||
# By default, both shared and static libraries are going to be built/installed.
|
||||
# This option disables shared library build, if only static library is required.
|
||||
```
|
||||
|
||||
|
||||
## Cross Compiling
|
||||
|
||||
This section talks about cross compiling HIDAPI for Linux using Autotools.
|
||||
This is useful for using HIDAPI on embedded Linux targets. These
|
||||
instructions assume the most raw kind of embedded Linux build, where all
|
||||
prerequisites will need to be built first. This process will of course vary
|
||||
based on your embedded Linux build system if you are using one, such as
|
||||
OpenEmbedded or Buildroot.
|
||||
|
||||
For the purpose of this section, it will be assumed that the following
|
||||
environment variables are exported.
|
||||
```sh
|
||||
$ export STAGING=$HOME/out
|
||||
$ export HOST=arm-linux
|
||||
```
|
||||
|
||||
`STAGING` and `HOST` can be modified to suit your setup.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Depending on what backend you want to cross-compile, you also need to prepare the dependencies:
|
||||
`libusb` for libusb HIDAPI backend, or `libudev` for hidraw HIDAPI backend.
|
||||
|
||||
An example of cross-compiling `libusb`. From `libusb` source directory, run:
|
||||
```sh
|
||||
./configure --host=$HOST --prefix=$STAGING
|
||||
make
|
||||
make install
|
||||
```
|
||||
|
||||
An example of cross-comping `libudev` is not covered by this section.
|
||||
Check `libudev`'s documentation for details.
|
||||
|
||||
### Building HIDAPI
|
||||
|
||||
Build HIDAPI:
|
||||
```sh
|
||||
PKG_CONFIG_DIR= \
|
||||
PKG_CONFIG_LIBDIR=$STAGING/lib/pkgconfig:$STAGING/share/pkgconfig \
|
||||
PKG_CONFIG_SYSROOT_DIR=$STAGING \
|
||||
./configure --host=$HOST --prefix=$STAGING
|
||||
# make / make install - same as for a regular build
|
||||
```
|
|
@ -0,0 +1,280 @@
|
|||
# Building HIDAPI using CMake
|
||||
|
||||
To build HIDAPI with CMake, it has to be [installed](#installing-cmake)/available in the system.
|
||||
|
||||
Make sure you've checked [prerequisites](BUILD.md#prerequisites) and installed all required dependencies.
|
||||
|
||||
HIDAPI CMake build system allows you to build HIDAPI in two generally different ways:
|
||||
1) As a [standalone package/library](#standalone-package-build);
|
||||
2) As [part of a larger CMake project](#hidapi-as-a-subdirectory).
|
||||
|
||||
**TL;DR**: if you're experienced developer and have been working with CMake projects or have been written some of your own -
|
||||
most of this document may not be of interest for you; just check variables names, its default values and the target names.
|
||||
|
||||
## Installing CMake
|
||||
|
||||
CMake can be installed either using your system's package manager,
|
||||
or by downloading an installer/prebuilt version from the [official website](https://cmake.org/download/).
|
||||
|
||||
On most \*nix systems, the prefered way to install CMake is via package manager,
|
||||
e.g. `sudo apt install cmake`.
|
||||
|
||||
On Windows CMake could be provided by your development environment (e.g. by Visual Studio Installer or MinGW installer),
|
||||
or you may install it system-wise using the installer from the official website.
|
||||
|
||||
On macOS CMake may be installed by Homebrew/MacPorts or using the installer from the official website.
|
||||
|
||||
## Standalone package build
|
||||
|
||||
To build HIDAPI as a standalone package, you follow [general steps](https://cmake.org/runningcmake/) of building any CMake project.
|
||||
|
||||
An example of building HIDAPI with CMake:
|
||||
```sh
|
||||
# precondition: create a <build dir> somewhere on the filesystem (preferably outside of the HIDAPI source)
|
||||
# this is the place where all intermediate/build files are going to be located
|
||||
cd <build dir>
|
||||
# configure the build
|
||||
cmake <HIDAPI source dir>
|
||||
# build it!
|
||||
cmake --build .
|
||||
# install library; by default installs into /usr/local/
|
||||
cmake --build . --target install
|
||||
# NOTE: you need to run install command as root, to be able to install into /usr/local/
|
||||
```
|
||||
Such invocation will use the default (as per CMake magic) compiler/build environment available in your system.
|
||||
|
||||
You may pass some additional CMake variables to control the build configuration as `-D<CMake Variable>=value`.
|
||||
E.g.:
|
||||
```sh
|
||||
# install command now would install things into /usr
|
||||
cmake <HIDAPI source dir> -DCMAKE_INSTALL_PREFIX=/usr
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Using a specific CMake generator</summary>
|
||||
|
||||
An example of using `Ninja` as a CMake generator:
|
||||
|
||||
```sh
|
||||
cd <build dir>
|
||||
# configure the build
|
||||
cmake -GNinja <HIDAPI source dir>
|
||||
# we know, that CMake has generated build files for Ninja,
|
||||
# so we can use `ninja` directly, instead of `cmake --build .`
|
||||
ninja
|
||||
# install library
|
||||
ninja install
|
||||
```
|
||||
|
||||
`-G` here specifies a native build system CMake would generate build files for.
|
||||
Check [CMake Documentation](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html) for a list of available generators (system-specific).
|
||||
|
||||
</details><br>
|
||||
|
||||
Some of the [standard](https://cmake.org/cmake/help/latest/manual/cmake-variables.7.html) CMake variables you may want to use to configure a build:
|
||||
|
||||
- [`CMAKE_INSTALL_PREFIX`](https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html) - prefix where `install` target would install the library(ies);
|
||||
- [`CMAKE_BUILD_TYPE`](https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html) - standard possible values: `Debug`, `Release`, `RelWithDebInfo`, `MinSizeRel`; Defaults to `Release` for HIDAPI, if not specified;
|
||||
- [`BUILD_SHARED_LIBS`](https://cmake.org/cmake/help/latest/variable/BUILD_SHARED_LIBS.html) - when set to TRUE, HIDAPI is built as a shared library, otherwise build statically; Defaults to `TRUE` for HIDAPI, if not specified;
|
||||
|
||||
<details>
|
||||
<summary>macOS-specific variables</summary>
|
||||
|
||||
- [`CMAKE_FRAMEWORK`](https://cmake.org/cmake/help/latest/variable/CMAKE_FRAMEWORK.html) - (since CMake 3.15) when set to TRUE, HIDAPI is built as a framework library, otherwise build as a regular static/shared library; Defaults to `FALSE` for HIDAPI, if not specified;
|
||||
- [`CMAKE_OSX_DEPLOYMENT_TARGET`](https://cmake.org/cmake/help/latest/variable/CMAKE_OSX_DEPLOYMENT_TARGET.html) - minimum version of the target platform (e.g. macOS or iOS) on which the target binaries are to be deployed; defaults to a maximum supported target platform by currently used XCode/Toolchain;
|
||||
|
||||
</details><br>
|
||||
|
||||
HIDAPI-specific CMake variables:
|
||||
|
||||
- `HIDAPI_BUILD_HIDTEST` - when set to TRUE, build a small test application `hidtest`;
|
||||
- `HIDAPI_WITH_TESTS` - when set to TRUE, build all (unit-)tests;
|
||||
currently this option is only available on Windows, since only Windows backend has tests;
|
||||
|
||||
<details>
|
||||
<summary>Linux-specific variables</summary>
|
||||
|
||||
- `HIDAPI_WITH_HIDRAW` - when set to TRUE, build HIDRAW-based implementation of HIDAPI (`hidapi-hidraw`), otherwise don't build it; defaults to TRUE;
|
||||
- `HIDAPI_WITH_LIBUSB` - when set to TRUE, build LIBUSB-based implementation of HIDAPI (`hidapi-libusb`), otherwise don't build it; defaults to TRUE;
|
||||
|
||||
**NOTE**: at least one of `HIDAPI_WITH_HIDRAW` or `HIDAPI_WITH_LIBUSB` has to be set to TRUE.
|
||||
|
||||
</details><br>
|
||||
|
||||
To see all most-useful CMake variables available for HIDAPI, one of the most convenient ways is too use [`cmake-gui`](https://cmake.org/cmake/help/latest/manual/cmake-gui.1.html) tool ([example](https://cmake.org/runningcmake/)).
|
||||
|
||||
_NOTE_: HIDAPI packages built by CMake can be used with `pkg-config`, as if built with [Autotools](BUILD.autotools.md).
|
||||
|
||||
### MSVC and Ninja
|
||||
It is possible to build a CMake project (including HIDAPI) using MSVC compiler and Ninja (for medium and larger projects it is so much faster than msbuild).
|
||||
|
||||
For that:
|
||||
1) Open cmd.exe;
|
||||
2) Setup MSVC build environment variables, e.g.: `vcvarsall.bat x64`, where:
|
||||
- `vcvarsall.bat` is an environment setup script of your MSVC toolchain installation;<br>For MSVC 2019 Community edition it is located at: `C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\`;
|
||||
- `x64` -a target architecture to build;
|
||||
3) Follow general build steps, and use `Ninja` as a generator.
|
||||
|
||||
### Using HIDAPI in a CMake project
|
||||
|
||||
When HIDAPI is used as a standalone package (either installed into the system or built manually and installed elsewhere), the simplest way to use it is as showed in the example:
|
||||
|
||||
```cmake
|
||||
project(my_application)
|
||||
|
||||
add_executable(my_application main.c)
|
||||
|
||||
find_package(hidapi REQUIRED)
|
||||
target_link_libraries(my_application PRIVATE hidapi::hidapi)
|
||||
```
|
||||
|
||||
If HIDAPI isn't installed in your system, or `find_package` cannot find HIDAPI by default for any other reasons,
|
||||
the recommended way manually specify which HIDAPI package to use is via `hidapi_ROOT` CMake variable, e.g.:
|
||||
`-Dhidapi_ROOT=<path to HIDAPI installation prefix>`.
|
||||
|
||||
_NOTE_: usage of `hidapi_ROOT` is only possible (and recommended) with CMake 3.12 and higher. For older versions of CMake you'd need to specify [`CMAKE_PREFIX_PATH`](https://cmake.org/cmake/help/latest/variable/CMAKE_PREFIX_PATH.html#variable:CMAKE_PREFIX_PATH) instead.
|
||||
|
||||
Check with [`find_package`](https://cmake.org/cmake/help/latest/command/find_package.html) documentation if you need more details.
|
||||
|
||||
Available CMake targets after successful `find_package(hidapi)`:
|
||||
- `hidapi::hidapi` - indented to be used in most cases;
|
||||
- `hidapi::include` - if you need only to include `<hidapi.h>` but not link against the library;
|
||||
- `hidapi::winapi` - same as `hidapi::hidapi` on Windows; available only on Windows;
|
||||
- `hidapi::darwin` - same as `hidapi::hidapi` on macOS; available only on macOS;
|
||||
- `hidapi::libusb` - available when libusb backend is used/available;
|
||||
- `hidapi::hidraw` - available when hidraw backend is used/available on Linux;
|
||||
|
||||
**NOTE**: on Linux often both `hidapi::libusb` and `hidapi::hidraw` backends are available; in that case `hidapi::hidapi` is an alias for **`hidapi::hidraw`**. The motivation is that `hidraw` backend is a native Linux kernel implementation of HID protocol, and supports various HID devices (USB, Bluetooth, I2C, etc.). If `hidraw` backend isn't built at all (`hidapi::libusb` is the only target) - `hidapi::hidapi` is an alias for `hidapi::libusb`.
|
||||
If you're developing a cross-platform application and you are sure you need to use `libusb` backend on Linux, the simple way to achieve this is:
|
||||
```cmake
|
||||
if(TARGET hidapi::libusb)
|
||||
target_link_libraries(my_project PRIVATE hidapi::libusb)
|
||||
else()
|
||||
target_link_libraries(my_project PRIVATE hidapi::hidapi)
|
||||
endif()
|
||||
```
|
||||
|
||||
## HIDAPI as a subdirectory
|
||||
|
||||
HIDAPI can be easily used as a subdirectory of a larger CMake project:
|
||||
```cmake
|
||||
# root CMakeLists.txt
|
||||
cmake_minimum_required(VERSION 3.4.3 FATAL_ERROR)
|
||||
|
||||
add_subdirectory(hidapi)
|
||||
add_subdirectory(my_application)
|
||||
|
||||
# my_application/CMakeLists.txt
|
||||
project(my_application)
|
||||
|
||||
add_executable(my_application main.c)
|
||||
|
||||
# NOTE: no `find_package` is required, since HIDAPI targets are already a part of the project tree
|
||||
target_link_libraries(my_application PRIVATE hidapi::hidapi)
|
||||
```
|
||||
Lets call this "larger project" a "host project".
|
||||
|
||||
All of the variables described in [standalone build](#standalone-package-build) section can be used to control HIDAPI build in case of a subdirectory, e.g.:
|
||||
```cmake
|
||||
set(HIDAPI_WITH_LIBUSB FALSE) # surely will be used only on Linux
|
||||
set(BUILD_SHARED_LIBS FALSE) # HIDAPI as static library on all platforms
|
||||
add_subdirectory(hidapi)
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>NOTE</summary>
|
||||
|
||||
If you project happen to use `BUILD_SHARED_LIBS` as a `CACHE` variable globally for you project, setting it as simple variable, as showed above _will have not affect_ up until _CMake 3.13_. See [CMP0077](https://cmake.org/cmake/help/latest/policy/CMP0077.html) for details.
|
||||
</details><br>
|
||||
|
||||
There are several important differences in the behavior of HIDAPI CMake build system when CMake is built as standalone package vs subdirectory build:
|
||||
|
||||
1) In _standalone build_ a number of standard and HIDAPI-specific variables are marked as _cache variables_ or _options_.
|
||||
This is done for convenience: when you're building HIDAPI as a standalone package and using tools like `cmake-gui` - those are highlighted as variables that can be changed and has some short description/documentation. E.g.:
|
||||
![an example of highlighted variables in cmake-gui](documentation/cmake-gui-highlights.png "cmake-gui highlighted variables")<br>
|
||||
E.g.2:<br>
|
||||
![an example of drop-down menu in cmake-gui](documentation/cmake-gui-drop-down.png "cmake-gui drop-down menu")<br>
|
||||
When HIDAPI is built as a _subdirectory_ - **_none of the variables are marked for cache or as options_** by HIDAPI.
|
||||
This is done to let the host project's developer decide what is important (what needs to be highlighted) and what's not.
|
||||
|
||||
2) The default behavior/default value for some of the variables is a bit different:
|
||||
- by default, none of HIDAPI targets are [installed](https://cmake.org/cmake/help/latest/command/install.html); if required, HIDAPI targets can be installed by host project _after_ including HIDAPI subdirectory (requires CMake 3.13 or later); **or**, the default installation can be enabled by setting `HIDAPI_INSTALL_TARGETS` variable _before_ including HIDAPI subdirectory.
|
||||
HIDAPI uses [GNUInstallDirs](https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html) to specify install locations. Variables like `CMAKE_INSTALL_LIBDIR` can be used to control HIDAPI's installation locations. E.g.:
|
||||
```cmake
|
||||
# enable the installation if you need it
|
||||
set(HIDAPI_INSTALL_TARGETS ON)
|
||||
# (optionally) change default installation locations if it makes sense for your target platform, etc.
|
||||
set(CMAKE_INSTALL_LIBDIR "lib64")
|
||||
add_subdirectory(hidapi)
|
||||
```
|
||||
- HIDAPI prints its version during the configuration when built as a standalone package; to enable this for subdirectory builds - set `HIDAPI_PRINT_VERSION` to TRUE before including HIDAPI;
|
||||
|
||||
3) In a subdirectory build, HIDAPI _doesn't modify or set any of the CMake variables_ that may change the build behavior.
|
||||
For instance, in a _standalone build_, if CMAKE_BUILD_TYPE or BUILD_SHARED_LIBS variables are not set, those are defaulted to "Release" and "TRUE" explicitly.
|
||||
In a _subdirectory build_, even if not set, those variables remain unchanged, so a host project's developer has a full control over the HIDAPI build configuration.
|
||||
|
||||
Available CMake targets after `add_subdirectory(hidapi)` _are the same as in case of [standalone build](#standalone-package-build)_, and a few additional ones:
|
||||
- `hidapi_include` - the interface library; `hidapi::hidapi` is an alias of it;
|
||||
- `hidapi_winapi` - library target on Windows; `hidapi::winapi` is an alias of it;
|
||||
- `hidapi_darwin` - library target on macOS; `hidapi::darwin` is an alias of it;
|
||||
- `hidapi_libusb` - library target for libusb backend; `hidapi::libusb` is an alias of it;
|
||||
- `hidapi_hidraw` - library target for hidraw backend; `hidapi::hidraw` is an alias of it;
|
||||
- `hidapi-libusb` - an alias of `hidapi_libusb` for compatibility with raw library name;
|
||||
- `hidapi-hidraw` - an alias of `hidapi_hidraw` for compatibility with raw library name;
|
||||
- `hidapi` - an alias of `hidapi_winapi` or `hidapi_darwin` on Windows or macOS respectfully.
|
||||
|
||||
Advanced:
|
||||
- Why would I need additional targets described in this section above, if I already have alias targets compatible with `find_package`?
|
||||
- an example:
|
||||
```cmake
|
||||
add_subdirectory(hidapi)
|
||||
if(TARGET hidapi_libusb)
|
||||
# see libusb/hid.c for usage of `NO_ICONV`
|
||||
target_compile_definitions(hidapi_libusb PRIVATE NO_ICONV)
|
||||
endif()
|
||||
```
|
||||
|
||||
## Both Shared and Static build
|
||||
|
||||
If you're a former (or present) user of Autotools build scripts for HIDAPI, or you're a package manager maintainer and you're often working with those - you're likely asking how to build HIDAPI with CMake and get both Shared and Static libraries (as would be done by Autotools: `./configure --enable-static --enable-shared ...`).
|
||||
|
||||
CMake doesn't have such option of-the-box and it is decided not to introduce any manual CMake-level workarounds for HIDAPI on this matter.
|
||||
|
||||
If you want to mimic the Autotools behavior, it is possible by building/installing first the static version of the library and then shared version of the library. The installation folder (`CMAKE_INSTALL_PREFIX`) should point to the same directory for both variants, that way:
|
||||
- both static and shared library binaries will be available and usable;
|
||||
- a single header file(s) for both of them;
|
||||
- Autotools/pkg-config (`.pc`) files will be generated and usable _as if_ generated by Autotools natively and build configured with both `-enable-static --enable-shared` options;
|
||||
- CMake package scripts will be generated and fully usable, but _only the last build installed_, i.e. if the last was installed Shared version of the binary - CMake targets found by `find_package(hidapi)` would point to a Shared binaries.
|
||||
|
||||
There is a historical discussion, why such solution is simplest/preferable: https://github.com/libusb/hidapi/issues/424
|
||||
|
||||
#### TL;DR/Sample
|
||||
|
||||
```sh
|
||||
# First - configure/build
|
||||
|
||||
# Static libraries
|
||||
cmake -S <HIDAPI source dir> -B "<build dir>/static" -DCMAKE_INSTALL_PREFIX=<your installation prefix> -DBUILD_SHARED_LIBS=FALSE
|
||||
cmake --build "<build dir>/static"
|
||||
# Shared libraries
|
||||
cmake -S <HIDAPI source dir> -B "<build dir>/shared" -DCMAKE_INSTALL_PREFIX=<your installation prefix> -DBUILD_SHARED_LIBS=TRUE
|
||||
cmake --build "<build dir>/shared"
|
||||
|
||||
# (Optionally) change the installation destination.
|
||||
# NOTE1: this is supported by CMake only on UNIX platforms
|
||||
# See https://cmake.org/cmake/help/latest/envvar/DESTDIR.html
|
||||
# NOTE2: this is not the same as `CMAKE_INSTALL_PREFIX` set above
|
||||
# NOTE3: this is only required if you have a staging dir other than the final runtime dir,
|
||||
# e.g. during cross-compilation
|
||||
export DESTDIR="$STAGING_DIR"
|
||||
|
||||
#
|
||||
# Install the libraries
|
||||
# NOTE: order of installation matters - install Shared variant *the last*
|
||||
|
||||
# Static libraries
|
||||
cmake --install "<build dir>/static"
|
||||
# Shared libraries
|
||||
cmake --install "<build dir>/shared"
|
||||
|
||||
```
|
|
@ -0,0 +1,127 @@
|
|||
# Building HIDAPI from Source
|
||||
|
||||
## Table of content
|
||||
|
||||
* [Intro](#intro)
|
||||
* [Prerequisites](#prerequisites)
|
||||
* [Linux](#linux)
|
||||
* [FreeBSD](#freebsd)
|
||||
* [Mac](#mac)
|
||||
* [Windows](#windows)
|
||||
* [Embedding HIDAPI directly into your source tree](#embedding-hidapi-directly-into-your-source-tree)
|
||||
* [Building the manual way on Unix platforms](#building-the-manual-way-on-unix-platforms)
|
||||
* [Building on Windows](#building-on-windows)
|
||||
|
||||
## Intro
|
||||
|
||||
For various reasons, you may need to build HIDAPI on your own.
|
||||
|
||||
It can be done in several different ways:
|
||||
- using [CMake](BUILD.cmake.md);
|
||||
- using [Autotools](BUILD.autotools.md) (deprecated);
|
||||
- using [manual makefiles](#building-the-manual-way-on-unix-platforms);
|
||||
- using `Meson` (requires CMake);
|
||||
|
||||
**Autotools** build system is historically the first mature build system for
|
||||
HIDAPI. The most common usage of it is in its separate README: [BUILD.autotools.md](BUILD.autotools.md).<br/>
|
||||
NOTE: for all intentions and purposes the Autotools build scripts for HIDAPI are _deprecated_ and going to be obsolete in the future.
|
||||
HIDAPI Team recommends using CMake build for HIDAPI.
|
||||
|
||||
**CMake** build system is de facto an industry standard for many open-source and proprietary projects and solutions.
|
||||
HIDAPI is one of the projects which use the power of CMake to its advantage.
|
||||
More documentation is available in its separate README: [BUILD.cmake.md](BUILD.cmake.md).
|
||||
|
||||
**Meson** build system for HIDAPI is designed as a [wrapper](https://mesonbuild.com/CMake-module.html) over CMake build script.
|
||||
It is present for the convenience of Meson users who need to use HIDAPI and need to be sure HIDAPI is built in accordance with officially supported build scripts.<br>
|
||||
In the Meson script of your project you need a `hidapi = subproject('hidapi')` subproject, and `hidapi.get_variable('hidapi_dep')` as your dependency.
|
||||
There are also backend/platform-specific dependencies available: `hidapi_winapi`, `hidapi_darwin`, `hidapi_hidraw`, `hidapi_libusb`.
|
||||
|
||||
If you don't know where to start to build HIDAPI, we recommend starting with [CMake](BUILD.cmake.md) build.
|
||||
|
||||
## Prerequisites:
|
||||
|
||||
Regardless of what build system you choose to use, there are specific dependencies for each platform/backend.
|
||||
|
||||
### Linux:
|
||||
|
||||
Depending on which backend you're going to build, you'll need to install
|
||||
additional development packages. For `linux/hidraw` backend, you need a
|
||||
development package for `libudev`. For `libusb` backend, naturally, you need
|
||||
`libusb` development package.
|
||||
|
||||
On Debian/Ubuntu systems these can be installed by running:
|
||||
```sh
|
||||
# required only by hidraw backend
|
||||
sudo apt install libudev-dev
|
||||
# required only by libusb backend
|
||||
sudo apt install libusb-1.0-0-dev
|
||||
```
|
||||
|
||||
### FreeBSD:
|
||||
|
||||
On FreeBSD, you will need to install libiconv. This is done by running
|
||||
the following:
|
||||
```sh
|
||||
pkg_add -r libiconv
|
||||
```
|
||||
|
||||
### Mac:
|
||||
|
||||
Make sure you have XCode installed and its Command Line Tools.
|
||||
|
||||
### Windows:
|
||||
|
||||
You just need a compiler. You may use Visual Studio or Cygwin/MinGW,
|
||||
depending on which environment is best for your needs.
|
||||
|
||||
## Embedding HIDAPI directly into your source tree
|
||||
|
||||
Instead of using one of the provided standalone build systems,
|
||||
you may want to integrate HIDAPI directly into your source tree.
|
||||
|
||||
---
|
||||
If your project uses CMake as a build system, it is safe to add HIDAPI as a [subdirectory](BUILD.cmake.md#hidapi-as-a-subdirectory).
|
||||
|
||||
---
|
||||
If _the only option_ that works for you is adding HIDAPI sources directly
|
||||
to your project's build system, then you need:
|
||||
- include a _single source file_ into your project's build system,
|
||||
depending on your platform and the backend you want to use:
|
||||
- [`windows\hid.c`](windows/hid.c);
|
||||
- [`linux/hid.c`](linux/hid.c);
|
||||
- [`libusb/hid.c`](libusb/hid.c);
|
||||
- [`mac/hid.c`](mac/hid.c);
|
||||
- add a [`hidapi`](hidapi) folder to the include path when building `hid.c`;
|
||||
- make the platform/backend specific [dependencies](#prerequisites) available during the compilation/linking, when building `hid.c`;
|
||||
|
||||
NOTE: the above doesn't guarantee that having a copy of `<backend>/hid.c` and `hidapi/hidapi.h` is enough to build HIDAPI.
|
||||
The only guarantee that `<backend>/hid.c` includes all necessary sources to compile it as a single file.
|
||||
|
||||
Check the manual makefiles for a simple example/reference of what are the dependencies of each specific backend.
|
||||
|
||||
## Building the manual way on Unix platforms
|
||||
|
||||
Manual Makefiles are provided mostly to give the user an idea what it takes
|
||||
to build a program which embeds HIDAPI directly inside of it. These should
|
||||
really be used as examples only. If you want to build a system-wide shared
|
||||
library, use one of the build systems mentioned above.
|
||||
|
||||
To build HIDAPI using the manual Makefiles, change the directory
|
||||
of your platform and run make. For example, on Linux run:
|
||||
```sh
|
||||
cd linux/
|
||||
make -f Makefile-manual
|
||||
```
|
||||
|
||||
## Building on Windows
|
||||
|
||||
To build the HIDAPI DLL on Windows using Visual Studio, build the `.sln` file
|
||||
in the `windows/` directory.
|
||||
|
||||
To build HIDAPI using MinGW or Cygwin using Autotools, use general Autotools
|
||||
[instruction](BUILD.autotools.md).
|
||||
|
||||
Any windows builds (MSVC or MinGW/Cygwin) are also supported by [CMake](BUILD.cmake.md).
|
||||
|
||||
If you are looking for information regarding DDK build of HIDAPI:
|
||||
- the build has been broken for a while and now the support files are obsolete.
|
|
@ -0,0 +1,105 @@
|
|||
cmake_minimum_required(VERSION 3.1.3 FATAL_ERROR)
|
||||
|
||||
if(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||
add_subdirectory(src)
|
||||
# compatibility with find_package() vs add_subdirectory
|
||||
set(hidapi_VERSION "${hidapi_VERSION}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
# All of the below in this file is meant for a standalone build.
|
||||
# When building as a subdirectory of a larger project, most of the options may not make sense for it,
|
||||
# so it is up to developer to configure those, e.g.:
|
||||
#
|
||||
# # a subfolder of a master project, e.g.: 3rdparty/hidapi/CMakeLists.txt
|
||||
#
|
||||
# set(HIDAPI_WITH_HIDRAW OFF)
|
||||
# set(CMAKE_FRAMEWORK ON)
|
||||
# # and keep everything else to their defaults
|
||||
# add_subdirectory(hidapi)
|
||||
#
|
||||
|
||||
set(DEFAULT_CMAKE_BUILD_TYPES "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
|
||||
if(NOT DEFINED CMAKE_BUILD_TYPE OR NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "${DEFAULT_CMAKE_BUILD_TYPES}" FORCE)
|
||||
endif()
|
||||
# This part is for convenience, when used one of the standard build types with cmake-gui
|
||||
list(FIND DEFAULT_CMAKE_BUILD_TYPES "${CMAKE_BUILD_TYPE}" _build_type_index)
|
||||
if(${_build_type_index} GREATER -1)
|
||||
# set it optionally, so a custom CMAKE_BUILD_TYPE can be used as well, if needed
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${DEFAULT_CMAKE_BUILD_TYPES})
|
||||
endif()
|
||||
unset(_build_type_index)
|
||||
#
|
||||
|
||||
project(hidapi LANGUAGES C)
|
||||
|
||||
if(APPLE)
|
||||
if(NOT CMAKE_VERSION VERSION_LESS "3.15")
|
||||
option(CMAKE_FRAMEWORK "Build macOS/iOS Framework version of the library" OFF)
|
||||
endif()
|
||||
elseif(NOT WIN32)
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
option(HIDAPI_WITH_HIDRAW "Build HIDRAW-based implementation of HIDAPI" ON)
|
||||
option(HIDAPI_WITH_LIBUSB "Build LIBUSB-based implementation of HIDAPI" ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(BUILD_SHARED_LIBS "Build shared version of the libraries, otherwise build statically" ON)
|
||||
|
||||
set(HIDAPI_INSTALL_TARGETS ON)
|
||||
set(HIDAPI_PRINT_VERSION ON)
|
||||
|
||||
set(IS_DEBUG_BUILD OFF)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(IS_DEBUG_BUILD ON)
|
||||
endif()
|
||||
|
||||
option(HIDAPI_ENABLE_ASAN "Build HIDAPI with ASAN address sanitizer instrumentation" OFF)
|
||||
|
||||
if(HIDAPI_ENABLE_ASAN)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
|
||||
if(MSVC)
|
||||
# the default is to have "/INCREMENTAL" which causes a warning when "-fsanitize=address" is present
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /INCREMENTAL:NO")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /INCREMENTAL:NO")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /INCREMENTAL:NO")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO} /INCREMENTAL:NO")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
# so far only Windows has tests
|
||||
option(HIDAPI_WITH_TESTS "Build HIDAPI (unit-)tests" ${IS_DEBUG_BUILD})
|
||||
else()
|
||||
set(HIDAPI_WITH_TESTS OFF)
|
||||
endif()
|
||||
|
||||
if(HIDAPI_WITH_TESTS)
|
||||
enable_testing()
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
option(HIDAPI_BUILD_PP_DATA_DUMP "Build small Windows console application pp_data_dump.exe" ${IS_DEBUG_BUILD})
|
||||
endif()
|
||||
|
||||
add_subdirectory(src)
|
||||
|
||||
option(HIDAPI_BUILD_HIDTEST "Build small console test application hidtest" ${IS_DEBUG_BUILD})
|
||||
if(HIDAPI_BUILD_HIDTEST)
|
||||
add_subdirectory(hidtest)
|
||||
endif()
|
||||
|
||||
if(HIDAPI_ENABLE_ASAN)
|
||||
if(NOT MSVC)
|
||||
# MSVC doesn't recognize those options, other compilers - requiring it
|
||||
foreach(HIDAPI_TARGET hidapi_winapi hidapi_darwin hidapi_hidraw hidapi_libusb hidtest_hidraw hidtest_libusb hidtest)
|
||||
if(TARGET ${HIDAPI_TARGET})
|
||||
if(BUILD_SHARED_LIBS)
|
||||
target_link_options(${HIDAPI_TARGET} PRIVATE -fsanitize=address)
|
||||
else()
|
||||
target_link_options(${HIDAPI_TARGET} PUBLIC -fsanitize=address)
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
endif()
|
|
@ -1,15 +1,19 @@
|
|||
This file is mostly for the maintainer.
|
||||
|
||||
1. Build hidapi.dll
|
||||
2. Build hidtest.exe in DEBUG and RELEASE
|
||||
3. Commit all
|
||||
Updating a Version:
|
||||
1. Update VERSION file.
|
||||
2. HID_API_VERSION_MAJOR/HID_API_VERSION_MINOR/HID_API_VERSION_PATCH in hidapi.h.
|
||||
|
||||
4. Run the Following
|
||||
export VERSION=0.1.0
|
||||
export TAG_NAME=hidapi-$VERSION
|
||||
git tag $TAG_NAME
|
||||
git archive --format zip --prefix $TAG_NAME/ $TAG_NAME >../$TAG_NAME.zip
|
||||
5. Test the zip file.
|
||||
6. Run the following:
|
||||
git push origin $TAG_NAME
|
||||
Before firing a new release:
|
||||
1. Run the "Checks" Githtub Action
|
||||
2. Make sure no defects are found at: https://scan.coverity.com/projects/hidapi
|
||||
3. Fix if any
|
||||
|
||||
Firing a new release:
|
||||
1. Update the Version (if not yet updated).
|
||||
2. Prepare the Release Notes.
|
||||
3. Store the Release Notes into a file.
|
||||
4. Create locally an annotated git tag with release notes attached, e.g.: `git tag -aF ../hidapi_release_notes hidapi-<VERSION>`
|
||||
5. Push newly created tag: `git push origin hidapi-<VERSION>`
|
||||
6. Grab the hidapi-win.zip from Summary page of "GitHub Builds" Action for latest master build.
|
||||
7. Create a Github Release with hidapi-win.zip attached, for newly created tag.
|
||||
|
|
|
@ -23,10 +23,6 @@ if OS_DARWIN
|
|||
SUBDIRS += mac
|
||||
endif
|
||||
|
||||
if OS_IOS
|
||||
SUBDIRS += ios
|
||||
endif
|
||||
|
||||
if OS_FREEBSD
|
||||
SUBDIRS += libusb
|
||||
endif
|
||||
|
@ -35,6 +31,10 @@ if OS_KFREEBSD
|
|||
SUBDIRS += libusb
|
||||
endif
|
||||
|
||||
if OS_HAIKU
|
||||
SUBDIRS += libusb
|
||||
endif
|
||||
|
||||
if OS_WINDOWS
|
||||
SUBDIRS += windows
|
||||
endif
|
||||
|
@ -48,7 +48,7 @@ endif
|
|||
EXTRA_DIST = udev doxygen
|
||||
|
||||
dist_doc_DATA = \
|
||||
README.txt \
|
||||
README.md \
|
||||
AUTHORS.txt \
|
||||
LICENSE-bsd.txt \
|
||||
LICENSE-gpl3.txt \
|
||||
|
|
|
@ -0,0 +1,196 @@
|
|||
## HIDAPI library for Windows, Linux, FreeBSD and macOS
|
||||
|
||||
| CI instance | Status |
|
||||
|----------------------|--------|
|
||||
| `Linux/macOS/Windows (master)` | [![GitHub Builds](https://github.com/libusb/hidapi/workflows/GitHub%20Builds/badge.svg?branch=master)](https://github.com/libusb/hidapi/actions/workflows/builds.yml?query=branch%3Amaster) |
|
||||
| `Windows (master)` | [![Build status](https://ci.appveyor.com/api/projects/status/xfmr5fo8w0re8ded/branch/master?svg=true)](https://ci.appveyor.com/project/libusb/hidapi/branch/master) |
|
||||
| `BSD, last build (branch/PR)` | [![builds.sr.ht status](https://builds.sr.ht/~z3ntu/hidapi.svg)](https://builds.sr.ht/~z3ntu/hidapi) |
|
||||
| `Coverity Scan (last)` | ![Coverity Scan](https://scan.coverity.com/projects/583/badge.svg) |
|
||||
|
||||
HIDAPI is a multi-platform library which allows an application to interface
|
||||
with USB and Bluetooth HID-Class devices on Windows, Linux, FreeBSD, and macOS.
|
||||
HIDAPI can be either built as a shared library (`.so`, `.dll` or `.dylib`) or
|
||||
can be embedded directly into a target application by adding a _single source_
|
||||
file (per platform) and a single header.<br>
|
||||
See [remarks](BUILD.md#embedding-hidapi-directly-into-your-source-tree) on embedding _directly_ into your build system.
|
||||
|
||||
HIDAPI library was originally developed by Alan Ott ([signal11](https://github.com/signal11)).
|
||||
|
||||
It was moved to [libusb/hidapi](https://github.com/libusb/hidapi) on June 4th, 2019, in order to merge important bugfixes and continue development of the library.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [About](#about)
|
||||
* [Test GUI](#test-gui)
|
||||
* [Console Test App](#console-test-app)
|
||||
* [What Does the API Look Like?](#what-does-the-api-look-like)
|
||||
* [License](#license)
|
||||
* [Installing HIDAPI](#installing-hidapi)
|
||||
* [Build from Source](#build-from-source)
|
||||
|
||||
|
||||
## About
|
||||
|
||||
### HIDAPI has four back-ends:
|
||||
* Windows (using `hid.dll`)
|
||||
* Linux/hidraw (using the Kernel's hidraw driver)
|
||||
* libusb (using libusb-1.0 - Linux/BSD/other UNIX-like systems)
|
||||
* macOS (using IOHidManager)
|
||||
|
||||
On Linux, either the hidraw or the libusb back-end can be used. There are
|
||||
tradeoffs, and the functionality supported is slightly different. Both are
|
||||
built by default. It is up to the application linking to hidapi to choose
|
||||
the backend at link time by linking to either `libhidapi-libusb` or
|
||||
`libhidapi-hidraw`.
|
||||
|
||||
Note that you will need to install an udev rule file with your application
|
||||
for unprivileged users to be able to access HID devices with hidapi. Refer
|
||||
to the [69-hid.rules](udev/69-hid.rules) file in the `udev` directory
|
||||
for an example.
|
||||
|
||||
#### __Linux/hidraw__ (`linux/hid.c`):
|
||||
|
||||
This back-end uses the hidraw interface in the Linux kernel, and supports
|
||||
both USB and Bluetooth HID devices. It requires kernel version at least 2.6.39
|
||||
to build. In addition, it will only communicate with devices which have hidraw
|
||||
nodes associated with them.
|
||||
Keyboards, mice, and some other devices which are blacklisted from having
|
||||
hidraw nodes will not work. Fortunately, for nearly all the uses of hidraw,
|
||||
this is not a problem.
|
||||
|
||||
#### __Linux/FreeBSD/libusb__ (`libusb/hid.c`):
|
||||
|
||||
This back-end uses libusb-1.0 to communicate directly to a USB device. This
|
||||
back-end will of course not work with Bluetooth devices.
|
||||
|
||||
### Test GUI
|
||||
|
||||
HIDAPI also comes with a Test GUI. The Test GUI is cross-platform and uses
|
||||
Fox Toolkit <http://www.fox-toolkit.org>. It will build on every platform
|
||||
which HIDAPI supports. Since it relies on a 3rd party library, building it
|
||||
is optional but it is useful when debugging hardware.
|
||||
|
||||
NOTE: Test GUI based on Fox Toolkit is not actively developed nor supported
|
||||
by HIDAPI team. It is kept as a historical artifact. It may even work sometime
|
||||
or on some platforms, but it is not going to get any new features or bugfixes.
|
||||
|
||||
Instructions for installing Fox-Toolkit on each platform is not provided.
|
||||
Make sure to use Fox-Toolkit v1.6 if you choose to use it.
|
||||
|
||||
### Console Test App
|
||||
|
||||
If you want to play around with your HID device before starting
|
||||
any development with HIDAPI and using a GUI app is not an option for you, you may try [`hidapitester`](https://github.com/todbot/hidapitester).
|
||||
|
||||
This app has a console interface for most of the features supported
|
||||
by HIDAPI library.
|
||||
|
||||
## What Does the API Look Like?
|
||||
|
||||
The API provides the most commonly used HID functions including sending
|
||||
and receiving of input, output, and feature reports. The sample program,
|
||||
which communicates with a heavily hacked up version of the Microchip USB
|
||||
Generic HID sample looks like this (with error checking removed for
|
||||
simplicity):
|
||||
|
||||
**Warning: Only run the code you understand, and only when it conforms to the
|
||||
device spec. Writing data (`hid_write`) at random to your HID devices can break them.**
|
||||
|
||||
```c
|
||||
#include <stdio.h> // printf
|
||||
#include <wchar.h> // wchar_t
|
||||
|
||||
#include <hidapi.h>
|
||||
|
||||
#define MAX_STR 255
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int res;
|
||||
unsigned char buf[65];
|
||||
wchar_t wstr[MAX_STR];
|
||||
hid_device *handle;
|
||||
int i;
|
||||
|
||||
// Initialize the hidapi library
|
||||
res = hid_init();
|
||||
|
||||
// Open the device using the VID, PID,
|
||||
// and optionally the Serial number.
|
||||
handle = hid_open(0x4d8, 0x3f, NULL);
|
||||
if (!handle) {
|
||||
printf("Unable to open device\n");
|
||||
hid_exit();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Read the Manufacturer String
|
||||
res = hid_get_manufacturer_string(handle, wstr, MAX_STR);
|
||||
printf("Manufacturer String: %ls\n", wstr);
|
||||
|
||||
// Read the Product String
|
||||
res = hid_get_product_string(handle, wstr, MAX_STR);
|
||||
printf("Product String: %ls\n", wstr);
|
||||
|
||||
// Read the Serial Number String
|
||||
res = hid_get_serial_number_string(handle, wstr, MAX_STR);
|
||||
printf("Serial Number String: (%d) %ls\n", wstr[0], wstr);
|
||||
|
||||
// Read Indexed String 1
|
||||
res = hid_get_indexed_string(handle, 1, wstr, MAX_STR);
|
||||
printf("Indexed String 1: %ls\n", wstr);
|
||||
|
||||
// Toggle LED (cmd 0x80). The first byte is the report number (0x0).
|
||||
buf[0] = 0x0;
|
||||
buf[1] = 0x80;
|
||||
res = hid_write(handle, buf, 65);
|
||||
|
||||
// Request state (cmd 0x81). The first byte is the report number (0x0).
|
||||
buf[0] = 0x0;
|
||||
buf[1] = 0x81;
|
||||
res = hid_write(handle, buf, 65);
|
||||
|
||||
// Read requested state
|
||||
res = hid_read(handle, buf, 65);
|
||||
|
||||
// Print out the returned buffer.
|
||||
for (i = 0; i < 4; i++)
|
||||
printf("buf[%d]: %d\n", i, buf[i]);
|
||||
|
||||
// Close the device
|
||||
hid_close(handle);
|
||||
|
||||
// Finalize the hidapi library
|
||||
res = hid_exit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
You can also use [hidtest/test.c](hidtest/test.c)
|
||||
as a starting point for your applications.
|
||||
|
||||
|
||||
## License
|
||||
|
||||
HIDAPI may be used by one of three licenses as outlined in [LICENSE.txt](LICENSE.txt).
|
||||
|
||||
## Installing HIDAPI
|
||||
|
||||
If you want to build your own application that uses HID devices with HIDAPI,
|
||||
you need to get HIDAPI development package.
|
||||
|
||||
Depending on what your development environment is, HIDAPI likely to be provided
|
||||
by your package manager.
|
||||
|
||||
For instance on Ubuntu, HIDAPI is available via APT:
|
||||
```sh
|
||||
sudo apt install libhidapi-dev
|
||||
```
|
||||
|
||||
HIDAPI package name for other systems/package managers may differ.
|
||||
Check the documentation/package list of your package manager.
|
||||
|
||||
## Build from Source
|
||||
|
||||
Check [BUILD.md](BUILD.md) for details.
|
|
@ -1,339 +0,0 @@
|
|||
HIDAPI library for Windows, Linux, FreeBSD and Mac OS X
|
||||
=========================================================
|
||||
|
||||
About
|
||||
======
|
||||
|
||||
HIDAPI is a multi-platform library which allows an application to interface
|
||||
with USB and Bluetooth HID-Class devices on Windows, Linux, FreeBSD, and Mac
|
||||
OS X. HIDAPI can be either built as a shared library (.so or .dll) or
|
||||
can be embedded directly into a target application by adding a single source
|
||||
file (per platform) and a single header.
|
||||
|
||||
HIDAPI has four back-ends:
|
||||
* Windows (using hid.dll)
|
||||
* Linux/hidraw (using the Kernel's hidraw driver)
|
||||
* Linux/libusb (using libusb-1.0)
|
||||
* FreeBSD (using libusb-1.0)
|
||||
* Mac (using IOHidManager)
|
||||
|
||||
On Linux, either the hidraw or the libusb back-end can be used. There are
|
||||
tradeoffs, and the functionality supported is slightly different.
|
||||
|
||||
Linux/hidraw (linux/hid.c):
|
||||
This back-end uses the hidraw interface in the Linux kernel. While this
|
||||
back-end will support both USB and Bluetooth, it has some limitations on
|
||||
kernels prior to 2.6.39, including the inability to send or receive feature
|
||||
reports. In addition, it will only communicate with devices which have
|
||||
hidraw nodes associated with them. Keyboards, mice, and some other devices
|
||||
which are blacklisted from having hidraw nodes will not work. Fortunately,
|
||||
for nearly all the uses of hidraw, this is not a problem.
|
||||
|
||||
Linux/FreeBSD/libusb (libusb/hid.c):
|
||||
This back-end uses libusb-1.0 to communicate directly to a USB device. This
|
||||
back-end will of course not work with Bluetooth devices.
|
||||
|
||||
HIDAPI also comes with a Test GUI. The Test GUI is cross-platform and uses
|
||||
Fox Toolkit (http://www.fox-toolkit.org). It will build on every platform
|
||||
which HIDAPI supports. Since it relies on a 3rd party library, building it
|
||||
is optional but recommended because it is so useful when debugging hardware.
|
||||
|
||||
What Does the API Look Like?
|
||||
=============================
|
||||
The API provides the the most commonly used HID functions including sending
|
||||
and receiving of input, output, and feature reports. The sample program,
|
||||
which communicates with a heavily hacked up version of the Microchip USB
|
||||
Generic HID sample looks like this (with error checking removed for
|
||||
simplicity):
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "hidapi.h"
|
||||
|
||||
#define MAX_STR 255
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int res;
|
||||
unsigned char buf[65];
|
||||
wchar_t wstr[MAX_STR];
|
||||
hid_device *handle;
|
||||
int i;
|
||||
|
||||
// Initialize the hidapi library
|
||||
res = hid_init();
|
||||
|
||||
// Open the device using the VID, PID,
|
||||
// and optionally the Serial number.
|
||||
handle = hid_open(0x4d8, 0x3f, NULL);
|
||||
|
||||
// Read the Manufacturer String
|
||||
res = hid_get_manufacturer_string(handle, wstr, MAX_STR);
|
||||
wprintf(L"Manufacturer String: %s\n", wstr);
|
||||
|
||||
// Read the Product String
|
||||
res = hid_get_product_string(handle, wstr, MAX_STR);
|
||||
wprintf(L"Product String: %s\n", wstr);
|
||||
|
||||
// Read the Serial Number String
|
||||
res = hid_get_serial_number_string(handle, wstr, MAX_STR);
|
||||
wprintf(L"Serial Number String: (%d) %s\n", wstr[0], wstr);
|
||||
|
||||
// Read Indexed String 1
|
||||
res = hid_get_indexed_string(handle, 1, wstr, MAX_STR);
|
||||
wprintf(L"Indexed String 1: %s\n", wstr);
|
||||
|
||||
// Toggle LED (cmd 0x80). The first byte is the report number (0x0).
|
||||
buf[0] = 0x0;
|
||||
buf[1] = 0x80;
|
||||
res = hid_write(handle, buf, 65);
|
||||
|
||||
// Request state (cmd 0x81). The first byte is the report number (0x0).
|
||||
buf[0] = 0x0;
|
||||
buf[1] = 0x81;
|
||||
res = hid_write(handle, buf, 65);
|
||||
|
||||
// Read requested state
|
||||
res = hid_read(handle, buf, 65);
|
||||
|
||||
// Print out the returned buffer.
|
||||
for (i = 0; i < 4; i++)
|
||||
printf("buf[%d]: %d\n", i, buf[i]);
|
||||
|
||||
// Finalize the hidapi library
|
||||
res = hid_exit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
If you have your own simple test programs which communicate with standard
|
||||
hardware development boards (such as those from Microchip, TI, Atmel,
|
||||
FreeScale and others), please consider sending me something like the above
|
||||
for inclusion into the HIDAPI source. This will help others who have the
|
||||
same hardware as you do.
|
||||
|
||||
License
|
||||
========
|
||||
HIDAPI may be used by one of three licenses as outlined in LICENSE.txt.
|
||||
|
||||
Download
|
||||
=========
|
||||
HIDAPI can be downloaded from github
|
||||
git clone git://github.com/libusb/hidapi.git
|
||||
|
||||
Build Instructions
|
||||
===================
|
||||
|
||||
This section is long. Don't be put off by this. It's not long because it's
|
||||
complicated to build HIDAPI; it's quite the opposite. This section is long
|
||||
because of the flexibility of HIDAPI and the large number of ways in which
|
||||
it can be built and used. You will likely pick a single build method.
|
||||
|
||||
HIDAPI can be built in several different ways. If you elect to build a
|
||||
shared library, you will need to build it from the HIDAPI source
|
||||
distribution. If you choose instead to embed HIDAPI directly into your
|
||||
application, you can skip the building and look at the provided platform
|
||||
Makefiles for guidance. These platform Makefiles are located in linux/
|
||||
libusb/ mac/ and windows/ and are called Makefile-manual. In addition,
|
||||
Visual Studio projects are provided. Even if you're going to embed HIDAPI
|
||||
into your project, it is still beneficial to build the example programs.
|
||||
|
||||
|
||||
Prerequisites:
|
||||
---------------
|
||||
|
||||
Linux:
|
||||
-------
|
||||
On Linux, you will need to install development packages for libudev,
|
||||
libusb and optionally Fox-toolkit (for the test GUI). On
|
||||
Debian/Ubuntu systems these can be installed by running:
|
||||
sudo apt-get install libudev-dev libusb-1.0-0-dev libfox-1.6-dev
|
||||
|
||||
If you downloaded the source directly from the git repository (using
|
||||
git clone), you'll need Autotools:
|
||||
sudo apt-get install autotools-dev autoconf automake libtool
|
||||
|
||||
FreeBSD:
|
||||
---------
|
||||
On FreeBSD you will need to install GNU make, libiconv, and
|
||||
optionally Fox-Toolkit (for the test GUI). This is done by running
|
||||
the following:
|
||||
pkg_add -r gmake libiconv fox16
|
||||
|
||||
If you downloaded the source directly from the git repository (using
|
||||
git clone), you'll need Autotools:
|
||||
pkg_add -r autotools
|
||||
|
||||
Mac:
|
||||
-----
|
||||
On Mac, you will need to install Fox-Toolkit if you wish to build
|
||||
the Test GUI. There are two ways to do this, and each has a slight
|
||||
complication. Which method you use depends on your use case.
|
||||
|
||||
If you wish to build the Test GUI just for your own testing on your
|
||||
own computer, then the easiest method is to install Fox-Toolkit
|
||||
using ports:
|
||||
sudo port install fox
|
||||
|
||||
If you wish to build the TestGUI app bundle to redistribute to
|
||||
others, you will need to install Fox-toolkit from source. This is
|
||||
because the version of fox that gets installed using ports uses the
|
||||
ports X11 libraries which are not compatible with the Apple X11
|
||||
libraries. If you install Fox with ports and then try to distribute
|
||||
your built app bundle, it will simply fail to run on other systems.
|
||||
To install Fox-Toolkit manually, download the source package from
|
||||
http://www.fox-toolkit.org, extract it, and run the following from
|
||||
within the extracted source:
|
||||
./configure && make && make install
|
||||
|
||||
Windows:
|
||||
---------
|
||||
On Windows, if you want to build the test GUI, you will need to get
|
||||
the hidapi-externals.zip package from the download site. This
|
||||
contains pre-built binaries for Fox-toolkit. Extract
|
||||
hidapi-externals.zip just outside of hidapi, so that
|
||||
hidapi-externals and hidapi are on the same level, as shown:
|
||||
|
||||
Parent_Folder
|
||||
|
|
||||
+hidapi
|
||||
+hidapi-externals
|
||||
|
||||
Again, this step is not required if you do not wish to build the
|
||||
test GUI.
|
||||
|
||||
|
||||
Building HIDAPI into a shared library on Unix Platforms:
|
||||
---------------------------------------------------------
|
||||
|
||||
On Unix-like systems such as Linux, FreeBSD, Mac, and even Windows, using
|
||||
Mingw or Cygwin, the easiest way to build a standard system-installed shared
|
||||
library is to use the GNU Autotools build system. If you checked out the
|
||||
source from the git repository, run the following:
|
||||
|
||||
./bootstrap
|
||||
./configure
|
||||
make
|
||||
make install <----- as root, or using sudo
|
||||
|
||||
If you downloaded a source package (ie: if you did not run git clone), you
|
||||
can skip the ./bootstrap step.
|
||||
|
||||
./configure can take several arguments which control the build. The two most
|
||||
likely to be used are:
|
||||
--enable-testgui
|
||||
Enable build of the Test GUI. This requires Fox toolkit to
|
||||
be installed. Instructions for installing Fox-Toolkit on
|
||||
each platform are in the Prerequisites section above.
|
||||
|
||||
--prefix=/usr
|
||||
Specify where you want the output headers and libraries to
|
||||
be installed. The example above will put the headers in
|
||||
/usr/include and the binaries in /usr/lib. The default is to
|
||||
install into /usr/local which is fine on most systems.
|
||||
|
||||
Building the manual way on Unix platforms:
|
||||
-------------------------------------------
|
||||
|
||||
Manual Makefiles are provided mostly to give the user and idea what it takes
|
||||
to build a program which embeds HIDAPI directly inside of it. These should
|
||||
really be used as examples only. If you want to build a system-wide shared
|
||||
library, use the Autotools method described above.
|
||||
|
||||
To build HIDAPI using the manual makefiles, change to the directory
|
||||
of your platform and run make. For example, on Linux run:
|
||||
cd linux/
|
||||
make -f Makefile-manual
|
||||
|
||||
To build the Test GUI using the manual makefiles:
|
||||
cd testgui/
|
||||
make -f Makefile-manual
|
||||
|
||||
Building on Windows:
|
||||
---------------------
|
||||
|
||||
To build the HIDAPI DLL on Windows using Visual Studio, build the .sln file
|
||||
in the windows/ directory.
|
||||
|
||||
To build the Test GUI on windows using Visual Studio, build the .sln file in
|
||||
the testgui/ directory.
|
||||
|
||||
To build HIDAPI using MinGW or Cygwin using Autotools, use the instructions
|
||||
in the section titled "Building HIDAPI into a shared library on Unix
|
||||
Platforms" above. Note that building the Test GUI with MinGW or Cygwin will
|
||||
require the Windows procedure in the Prerequisites section above (ie:
|
||||
hidapi-externals.zip).
|
||||
|
||||
To build HIDAPI using MinGW using the Manual Makefiles, see the section
|
||||
"Building the manual way on Unix platforms" above.
|
||||
|
||||
HIDAPI can also be built using the Windows DDK (now also called the Windows
|
||||
Driver Kit or WDK). This method was originally required for the HIDAPI build
|
||||
but not anymore. However, some users still prefer this method. It is not as
|
||||
well supported anymore but should still work. Patches are welcome if it does
|
||||
not. To build using the DDK:
|
||||
|
||||
1. Install the Windows Driver Kit (WDK) from Microsoft.
|
||||
2. From the Start menu, in the Windows Driver Kits folder, select Build
|
||||
Environments, then your operating system, then the x86 Free Build
|
||||
Environment (or one that is appropriate for your system).
|
||||
3. From the console, change directory to the windows/ddk_build/ directory,
|
||||
which is part of the HIDAPI distribution.
|
||||
4. Type build.
|
||||
5. You can find the output files (DLL and LIB) in a subdirectory created
|
||||
by the build system which is appropriate for your environment. On
|
||||
Windows XP, this directory is objfre_wxp_x86/i386.
|
||||
|
||||
Cross Compiling
|
||||
================
|
||||
|
||||
This section talks about cross compiling HIDAPI for Linux using autotools.
|
||||
This is useful for using HIDAPI on embedded Linux targets. These
|
||||
instructions assume the most raw kind of embedded Linux build, where all
|
||||
prerequisites will need to be built first. This process will of course vary
|
||||
based on your embedded Linux build system if you are using one, such as
|
||||
OpenEmbedded or Buildroot.
|
||||
|
||||
For the purpose of this section, it will be assumed that the following
|
||||
environment variables are exported.
|
||||
|
||||
$ export STAGING=$HOME/out
|
||||
$ export HOST=arm-linux
|
||||
|
||||
STAGING and HOST can be modified to suit your setup.
|
||||
|
||||
Prerequisites
|
||||
--------------
|
||||
|
||||
Note that the build of libudev is the very basic configuration.
|
||||
|
||||
Build Libusb. From the libusb source directory, run:
|
||||
./configure --host=$HOST --prefix=$STAGING
|
||||
make
|
||||
make install
|
||||
|
||||
Build libudev. From the libudev source directory, run:
|
||||
./configure --disable-gudev --disable-introspection --disable-hwdb \
|
||||
--host=$HOST --prefix=$STAGING
|
||||
make
|
||||
make install
|
||||
|
||||
Building HIDAPI
|
||||
----------------
|
||||
|
||||
Build HIDAPI:
|
||||
|
||||
PKG_CONFIG_DIR= \
|
||||
PKG_CONFIG_LIBDIR=$STAGING/lib/pkgconfig:$STAGING/share/pkgconfig \
|
||||
PKG_CONFIG_SYSROOT_DIR=$STAGING \
|
||||
./configure --host=$HOST --prefix=$STAGING
|
||||
|
||||
|
||||
Signal 11 Software - 2010-04-11
|
||||
2010-07-28
|
||||
2011-09-10
|
||||
2012-05-01
|
||||
2012-07-03
|
|
@ -0,0 +1 @@
|
|||
0.14.0
|
File diff suppressed because it is too large
Load Diff
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 2022 Valve Corporation
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Purpose: Exporting table containing HIDDeviceManager native methods
|
||||
|
||||
#ifndef SDL_android_hid_h_
|
||||
#define SDL_android_hid_h_
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern JNINativeMethod HIDDeviceManager_tab[8];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,16 +0,0 @@
|
|||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
HIDAPI_ROOT_REL:= ../..
|
||||
HIDAPI_ROOT_ABS:= $(LOCAL_PATH)/../..
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_CPPFLAGS += -std=c++11
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
$(HIDAPI_ROOT_REL)/android/hid.cpp
|
||||
|
||||
LOCAL_MODULE := libhidapi
|
||||
LOCAL_LDLIBS := -llog
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
|
@ -1,2 +0,0 @@
|
|||
APP_STL := gnustl_static
|
||||
APP_ABI := armeabi-v7a
|
|
@ -1,14 +0,0 @@
|
|||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system edit
|
||||
# "ant.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
#
|
||||
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
|
||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||
|
||||
# Project target.
|
||||
target=android-21
|
|
@ -1,13 +1,9 @@
|
|||
AC_PREREQ(2.63)
|
||||
|
||||
# Version number. This is currently the only place.
|
||||
m4_define([HIDAPI_MAJOR], 0)
|
||||
m4_define([HIDAPI_MINOR], 8)
|
||||
m4_define([HIDAPI_RELEASE], 0)
|
||||
m4_define([HIDAPI_RC], -rc1)
|
||||
m4_define([VERSION_STRING], HIDAPI_MAJOR[.]HIDAPI_MINOR[.]HIDAPI_RELEASE[]HIDAPI_RC)
|
||||
AC_INIT([hidapi],[m4_normalize(m4_builtin([include], VERSION))],[https://github.com/libusb/hidapi/issues])
|
||||
|
||||
AC_INIT([hidapi],[VERSION_STRING],[alan@signal11.us])
|
||||
echo "This build script for HIDAPI is deprecated."
|
||||
echo "Consider using CMake instead."
|
||||
|
||||
# Library soname version
|
||||
# Follow the following rules (particularly the ones in the second link):
|
||||
|
@ -20,7 +16,6 @@ LTLDFLAGS="-version-info ${lt_current}:${lt_revision}:${lt_age}"
|
|||
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AM_INIT_AUTOMAKE([foreign -Wall -Werror])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
|
||||
LT_INIT
|
||||
|
@ -63,14 +58,14 @@ case $host in
|
|||
|
||||
# HIDAPI/hidraw libs
|
||||
PKG_CHECK_MODULES([libudev], [libudev], true, [hidapi_lib_error libudev])
|
||||
LIBS_HIDRAW_PR+=" $libudev_LIBS"
|
||||
CFLAGS_HIDRAW+=" $libudev_CFLAGS"
|
||||
LIBS_HIDRAW_PR="${LIBS_HIDRAW_PR} $libudev_LIBS"
|
||||
CFLAGS_HIDRAW="${CFLAGS_HIDRAW} $libudev_CFLAGS"
|
||||
|
||||
# HIDAPI/libusb libs
|
||||
AC_CHECK_LIB([rt], [clock_gettime], [LIBS_LIBUSB_PRIVATE+=" -lrt"], [hidapi_lib_error librt])
|
||||
AC_CHECK_LIB([rt], [clock_gettime], [LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} -lrt"], [hidapi_lib_error librt])
|
||||
PKG_CHECK_MODULES([libusb], [libusb-1.0 >= 1.0.9], true, [hidapi_lib_error libusb-1.0])
|
||||
LIBS_LIBUSB_PRIVATE+=" $libusb_LIBS"
|
||||
CFLAGS_LIBUSB+=" $libusb_CFLAGS"
|
||||
LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} $libusb_LIBS"
|
||||
CFLAGS_LIBUSB="${CFLAGS_LIBUSB} $libusb_CFLAGS"
|
||||
;;
|
||||
*-darwin*)
|
||||
AC_MSG_RESULT([ (Mac OS X back-end)])
|
||||
|
@ -79,7 +74,7 @@ case $host in
|
|||
backend="mac"
|
||||
os="darwin"
|
||||
threads="pthreads"
|
||||
LIBS="${LIBS} -framework IOKit -framework CoreFoundation"
|
||||
LIBS="${LIBS} -framework IOKit -framework CoreFoundation -framework AppKit"
|
||||
;;
|
||||
*-freebsd*)
|
||||
AC_MSG_RESULT([ (FreeBSD back-end)])
|
||||
|
@ -92,9 +87,10 @@ case $host in
|
|||
CFLAGS="$CFLAGS -I/usr/local/include"
|
||||
LDFLAGS="$LDFLAGS -L/usr/local/lib"
|
||||
LIBS="${LIBS}"
|
||||
AC_CHECK_LIB([usb], [libusb_init], [LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} -lusb"], [hidapi_lib_error libusb])
|
||||
PKG_CHECK_MODULES([libusb], [libusb-1.0 >= 1.0.9], true, [hidapi_lib_error libusb-1.0])
|
||||
LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} $libusb_LIBS"
|
||||
CFLAGS_LIBUSB="${CFLAGS_LIBUSB} $libusb_CFLAGS"
|
||||
AC_CHECK_LIB([iconv], [iconv_open], [LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} -liconv"], [hidapi_lib_error libiconv])
|
||||
echo libs_priv: $LIBS_LIBUSB_PRIVATE
|
||||
;;
|
||||
*-kfreebsd*)
|
||||
AC_MSG_RESULT([ (kFreeBSD back-end)])
|
||||
|
@ -104,8 +100,22 @@ case $host in
|
|||
os="kfreebsd"
|
||||
threads="pthreads"
|
||||
|
||||
AC_CHECK_LIB([usb], [libusb_init], [LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} -lusb"], [hidapi_lib_error libusb])
|
||||
echo libs_priv: $LIBS_LIBUSB_PRIVATE
|
||||
PKG_CHECK_MODULES([libusb], [libusb-1.0 >= 1.0.9], true, [hidapi_lib_error libusb-1.0])
|
||||
LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} $libusb_LIBS"
|
||||
CFLAGS_LIBUSB="${CFLAGS_LIBUSB} $libusb_CFLAGS"
|
||||
;;
|
||||
*-*-haiku)
|
||||
AC_MSG_RESULT([ (Haiku back-end)])
|
||||
AC_DEFINE(OS_HAIKU, 1, [Haiku implementation])
|
||||
AC_SUBST(OS_HAIKU)
|
||||
backend="libusb"
|
||||
os="haiku"
|
||||
threads="pthreads"
|
||||
|
||||
PKG_CHECK_MODULES([libusb], [libusb-1.0 >= 1.0.9], true, [hidapi_lib_error libusb-1.0])
|
||||
LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} $libusb_LIBS"
|
||||
CFLAGS_LIBUSB="${CFLAGS_LIBUSB} $libusb_CFLAGS"
|
||||
AC_CHECK_LIB([iconv], [libiconv_open], [LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} -liconv"], [hidapi_lib_error libiconv])
|
||||
;;
|
||||
*-mingw*)
|
||||
AC_MSG_RESULT([ (Windows back-end, using MinGW)])
|
||||
|
@ -113,6 +123,15 @@ case $host in
|
|||
os="windows"
|
||||
threads="windows"
|
||||
win_implementation="mingw"
|
||||
LDFLAGS="${LDFLAGS} -static-libgcc"
|
||||
;;
|
||||
*-msys*)
|
||||
AC_MSG_RESULT([ (Windows back-end, using MSYS2)])
|
||||
backend="windows"
|
||||
os="windows"
|
||||
threads="windows"
|
||||
win_implementation="mingw"
|
||||
LDFLAGS="${LDFLAGS} -static-libgcc"
|
||||
;;
|
||||
*-cygwin*)
|
||||
AC_MSG_RESULT([ (Windows back-end, using Cygwin)])
|
||||
|
@ -136,7 +155,7 @@ if test "x$os" = xwindows; then
|
|||
AC_DEFINE(OS_WINDOWS, 1, [Windows implementations])
|
||||
AC_SUBST(OS_WINDOWS)
|
||||
LDFLAGS="${LDFLAGS} -no-undefined"
|
||||
LIBS="${LIBS} -lsetupapi"
|
||||
LIBS="${LIBS}"
|
||||
fi
|
||||
|
||||
if test "x$threads" = xpthreads; then
|
||||
|
@ -175,15 +194,15 @@ mkdir testgui/TestGUI.app/Contents/MacOS/
|
|||
|
||||
if test "x$testgui_enabled" != "xno"; then
|
||||
if test "x$os" = xdarwin; then
|
||||
# On Mac OS, don't use pkg-config.
|
||||
# On Mac OS, do not use pkg-config.
|
||||
AC_CHECK_PROG([foxconfig], [fox-config], [fox-config], false)
|
||||
if test "x$foxconfig" = "xfalse"; then
|
||||
hidapi_prog_error fox-config "FOX Toolkit"
|
||||
fi
|
||||
LIBS_TESTGUI+=`$foxconfig --libs`
|
||||
LIBS_TESTGUI+=" -framework Cocoa -L/usr/X11R6/lib"
|
||||
CFLAGS_TESTGUI+=`$foxconfig --cflags`
|
||||
OBJCFLAGS+=" -x objective-c++"
|
||||
LIBS_TESTGUI="${LIBS_TESTGUI} `$foxconfig --libs`"
|
||||
LIBS_TESTGUI="${LIBS_TESTGUI} -framework Cocoa -L/usr/X11R6/lib"
|
||||
CFLAGS_TESTGUI="${CFLAGS_TESTGUI} `$foxconfig --cflags`"
|
||||
OBJCFLAGS="${OBJCFLAGS} -x objective-c++"
|
||||
elif test "x$os" = xwindows; then
|
||||
# On Windows, just set the paths for Fox toolkit
|
||||
if test "x$win_implementation" = xmingw; then
|
||||
|
@ -213,6 +232,7 @@ AM_CONDITIONAL(OS_LINUX, test "x$os" = xlinux)
|
|||
AM_CONDITIONAL(OS_DARWIN, test "x$os" = xdarwin)
|
||||
AM_CONDITIONAL(OS_FREEBSD, test "x$os" = xfreebsd)
|
||||
AM_CONDITIONAL(OS_KFREEBSD, test "x$os" = xkfreebsd)
|
||||
AM_CONDITIONAL(OS_HAIKU, test "x$os" = xhaiku)
|
||||
AM_CONDITIONAL(OS_WINDOWS, test "x$os" = xwindows)
|
||||
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
Pod::Spec.new do |spec|
|
||||
|
||||
spec.name = "hidapi"
|
||||
spec.version = File.read('../VERSION')
|
||||
spec.summary = "A Simple library for communicating with USB and Bluetooth HID devices on Linux, Mac and Windows."
|
||||
|
||||
spec.description = <<-DESC
|
||||
HIDAPI is a multi-platform library which allows an application to interface with USB and Bluetooth HID-Class devices on Windows, Linux, FreeBSD, and macOS. HIDAPI can be either built as a shared library (.so, .dll or .dylib) or can be embedded directly into a target application by adding a single source file (per platform) and a single header.
|
||||
DESC
|
||||
|
||||
spec.homepage = "https://github.com/libusb/hidapi"
|
||||
|
||||
spec.license = { :type=> "GNU GPLv3 or BSD or HIDAPI original", :file => "LICENSE.txt" }
|
||||
|
||||
spec.authors = { "Alan Ott" => "alan@signal11.us",
|
||||
"Ludovic Rousseau" => "rousseau@debian.org",
|
||||
"libusb/hidapi Team" => "https://github.com/libusb/hidapi/blob/master/AUTHORS.txt",
|
||||
}
|
||||
|
||||
spec.platform = :osx
|
||||
spec.osx.deployment_target = "10.7"
|
||||
|
||||
spec.source = { :git => "https://github.com/libusb/hidapi.git", :tag => "hidapi-#{spec.version}" }
|
||||
|
||||
spec.source_files = "mac/hid.c", "hidapi/hidapi.h", "mac/hidapi_darwin.h"
|
||||
|
||||
spec.public_header_files = "hidapi/hidapi.h", "mac/hidapi_darwin.h"
|
||||
|
||||
spec.frameworks = "IOKit", "CoreFoundation", "AppKit"
|
||||
|
||||
end
|
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
Binary file not shown.
After Width: | Height: | Size: 76 KiB |
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,13 @@
|
|||
# HIDAPI Doxygen output
|
||||
|
||||
This site is dedicated to hosting an [API reference for the HIDAPI library](#API).
|
||||
|
||||
For general information, see the [source repository](https://github.com/libusb/hidapi#readme).
|
||||
|
||||
There are also build instructions hosted on github:
|
||||
|
||||
- [Building from source](https://github.com/libusb/hidapi/blob/master/BUILD.md)
|
||||
- [Using CMake](https://github.com/libusb/hidapi/blob/master/BUILD.cmake.md)
|
||||
- [Using Autotools (deprecated)](https://github.com/libusb/hidapi/blob/master/BUILD.autotools.md)
|
||||
|
||||
\example test.c contains a basic example usage of the HIDAPI library.
|
|
@ -5,9 +5,9 @@
|
|||
Alan Ott
|
||||
Signal 11 Software
|
||||
|
||||
8/22/2009
|
||||
libusb/hidapi Team
|
||||
|
||||
Copyright 2009, All Rights Reserved.
|
||||
Copyright 2023, All Rights Reserved.
|
||||
|
||||
At the discretion of the user of this library,
|
||||
this software may be licensed under the terms of the
|
||||
|
@ -29,36 +29,123 @@
|
|||
|
||||
#include <wchar.h>
|
||||
|
||||
#ifdef SDL_hidapi_h_
|
||||
#define SDL_HIDAPI_IMPLEMENTATION
|
||||
#define hid_device_info SDL_hid_device_info
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(NAMESPACE) && !defined(SDL_HIDAPI_IMPLEMENTATION) /* SDL: don't export hidapi syms */
|
||||
/* #480: this is to be refactored properly for v1.0 */
|
||||
#ifdef _WIN32
|
||||
#ifndef HID_API_NO_EXPORT_DEFINE
|
||||
#define HID_API_EXPORT __declspec(dllexport)
|
||||
#define HID_API_CALL
|
||||
#else
|
||||
#endif
|
||||
#endif
|
||||
#ifndef HID_API_EXPORT
|
||||
#define HID_API_EXPORT /**< API export macro */
|
||||
#endif
|
||||
#ifndef HID_API_CALL
|
||||
#define HID_API_CALL /**< API call macro */
|
||||
#endif
|
||||
#define HID_API_EXPORT /**< API export macro */
|
||||
#endif
|
||||
/* To be removed in v1.0 */
|
||||
#define HID_API_CALL /**< API call macro */
|
||||
|
||||
#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/
|
||||
|
||||
#if defined(__cplusplus) && !defined(NAMESPACE)
|
||||
/** @brief Static/compile-time major version of the library.
|
||||
|
||||
@ingroup API
|
||||
*/
|
||||
#define HID_API_VERSION_MAJOR 0
|
||||
/** @brief Static/compile-time minor version of the library.
|
||||
|
||||
@ingroup API
|
||||
*/
|
||||
#define HID_API_VERSION_MINOR 14
|
||||
/** @brief Static/compile-time patch version of the library.
|
||||
|
||||
@ingroup API
|
||||
*/
|
||||
#define HID_API_VERSION_PATCH 0
|
||||
|
||||
/* Helper macros */
|
||||
#define HID_API_AS_STR_IMPL(x) #x
|
||||
#define HID_API_AS_STR(x) HID_API_AS_STR_IMPL(x)
|
||||
#define HID_API_TO_VERSION_STR(v1, v2, v3) HID_API_AS_STR(v1.v2.v3)
|
||||
|
||||
/** @brief Coverts a version as Major/Minor/Patch into a number:
|
||||
<8 bit major><16 bit minor><8 bit patch>.
|
||||
|
||||
This macro was added in version 0.12.0.
|
||||
|
||||
Convenient function to be used for compile-time checks, like:
|
||||
@code{.c}
|
||||
#if HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
|
||||
@endcode
|
||||
|
||||
@ingroup API
|
||||
*/
|
||||
#define HID_API_MAKE_VERSION(mj, mn, p) (((mj) << 24) | ((mn) << 8) | (p))
|
||||
|
||||
/** @brief Static/compile-time version of the library.
|
||||
|
||||
This macro was added in version 0.12.0.
|
||||
|
||||
@see @ref HID_API_MAKE_VERSION.
|
||||
|
||||
@ingroup API
|
||||
*/
|
||||
#define HID_API_VERSION HID_API_MAKE_VERSION(HID_API_VERSION_MAJOR, HID_API_VERSION_MINOR, HID_API_VERSION_PATCH)
|
||||
|
||||
/** @brief Static/compile-time string version of the library.
|
||||
|
||||
@ingroup API
|
||||
*/
|
||||
#define HID_API_VERSION_STR HID_API_TO_VERSION_STR(HID_API_VERSION_MAJOR, HID_API_VERSION_MINOR, HID_API_VERSION_PATCH)
|
||||
|
||||
/** @brief Maximum expected HID Report descriptor size in bytes.
|
||||
|
||||
Since version 0.13.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 13, 0)
|
||||
|
||||
@ingroup API
|
||||
*/
|
||||
#define HID_API_MAX_REPORT_DESCRIPTOR_SIZE 4096
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef NAMESPACE
|
||||
namespace NAMESPACE {
|
||||
#endif
|
||||
/** A structure to hold the version numbers. */
|
||||
struct hid_api_version {
|
||||
int major; /**< major version number */
|
||||
int minor; /**< minor version number */
|
||||
int patch; /**< patch version number */
|
||||
};
|
||||
|
||||
struct hid_device_;
|
||||
typedef struct hid_device_ hid_device; /**< opaque hidapi structure */
|
||||
|
||||
#ifndef SDL_HIDAPI_IMPLEMENTATION
|
||||
/** @brief HID underlying bus types.
|
||||
|
||||
@ingroup API
|
||||
*/
|
||||
typedef enum {
|
||||
/** Unknown bus type */
|
||||
HID_API_BUS_UNKNOWN = 0x00,
|
||||
|
||||
/** USB bus
|
||||
Specifications:
|
||||
https://usb.org/hid */
|
||||
HID_API_BUS_USB = 0x01,
|
||||
|
||||
/** Bluetooth or Bluetooth LE bus
|
||||
Specifications:
|
||||
https://www.bluetooth.com/specifications/specs/human-interface-device-profile-1-1-1/
|
||||
https://www.bluetooth.com/specifications/specs/hid-service-1-0/
|
||||
https://www.bluetooth.com/specifications/specs/hid-over-gatt-profile-1-0/ */
|
||||
HID_API_BUS_BLUETOOTH = 0x02,
|
||||
|
||||
/** I2C bus
|
||||
Specifications:
|
||||
https://docs.microsoft.com/previous-versions/windows/hardware/design/dn642101(v=vs.85) */
|
||||
HID_API_BUS_I2C = 0x03,
|
||||
|
||||
/** SPI bus
|
||||
Specifications:
|
||||
https://www.microsoft.com/download/details.aspx?id=103325 */
|
||||
HID_API_BUS_SPI = 0x04,
|
||||
} hid_bus_type;
|
||||
|
||||
/** hidapi info structure */
|
||||
struct hid_device_info {
|
||||
/** Platform-specific device path */
|
||||
|
@ -77,29 +164,27 @@ namespace NAMESPACE {
|
|||
/** Product string */
|
||||
wchar_t *product_string;
|
||||
/** Usage Page for this Device/Interface
|
||||
(Windows/Mac only). */
|
||||
(Windows/Mac/hidraw only) */
|
||||
unsigned short usage_page;
|
||||
/** Usage for this Device/Interface
|
||||
(Windows/Mac only).*/
|
||||
(Windows/Mac/hidraw only) */
|
||||
unsigned short usage;
|
||||
/** The USB interface which this logical device
|
||||
represents.
|
||||
|
||||
* Valid on both Linux implementations in all cases.
|
||||
* Valid on the Windows implementation only if the device
|
||||
contains more than one interface. */
|
||||
Valid only if the device is a USB HID device.
|
||||
Set to -1 in all other cases.
|
||||
*/
|
||||
int interface_number;
|
||||
|
||||
/** Additional information about the USB interface.
|
||||
Valid on libusb and Android implementations. */
|
||||
int interface_class;
|
||||
int interface_subclass;
|
||||
int interface_protocol;
|
||||
|
||||
/** Pointer to the next device */
|
||||
struct hid_device_info *next;
|
||||
|
||||
/** Underlying bus type
|
||||
Since version 0.13.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 13, 0)
|
||||
*/
|
||||
hid_bus_type bus_type;
|
||||
};
|
||||
#endif /* !SDL_HIDAPI_IMPLEMENTATION */
|
||||
|
||||
|
||||
/** @brief Initialize the HIDAPI library.
|
||||
|
@ -115,6 +200,7 @@ namespace NAMESPACE {
|
|||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
Call hid_error(NULL) to get the failure reason.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_init(void);
|
||||
|
||||
|
@ -126,7 +212,7 @@ namespace NAMESPACE {
|
|||
|
||||
@ingroup API
|
||||
|
||||
@returns
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_exit(void);
|
||||
|
@ -146,21 +232,25 @@ namespace NAMESPACE {
|
|||
@param product_id The Product ID (PID) of the types of
|
||||
device to open.
|
||||
|
||||
@returns
|
||||
This function returns a pointer to a linked list of type
|
||||
struct #hid_device_info, containing information about the HID devices
|
||||
attached to the system, or NULL in the case of failure. Free
|
||||
this linked list by calling hid_free_enumeration().
|
||||
@returns
|
||||
This function returns a pointer to a linked list of type
|
||||
struct #hid_device_info, containing information about the HID devices
|
||||
attached to the system,
|
||||
or NULL in the case of failure or if no HID devices present in the system.
|
||||
Call hid_error(NULL) to get the failure reason.
|
||||
|
||||
@note The returned value by this function must to be freed by calling hid_free_enumeration(),
|
||||
when not needed anymore.
|
||||
*/
|
||||
struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id);
|
||||
|
||||
/** @brief Free an enumeration Linked List
|
||||
|
||||
This function frees a linked list created by hid_enumerate().
|
||||
This function frees a linked list created by hid_enumerate().
|
||||
|
||||
@ingroup API
|
||||
@param devs Pointer to a list of struct_device returned from
|
||||
hid_enumerate().
|
||||
@param devs Pointer to a list of struct_device returned from
|
||||
hid_enumerate().
|
||||
*/
|
||||
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs);
|
||||
|
||||
|
@ -174,11 +264,15 @@ namespace NAMESPACE {
|
|||
@param vendor_id The Vendor ID (VID) of the device to open.
|
||||
@param product_id The Product ID (PID) of the device to open.
|
||||
@param serial_number The Serial Number of the device to open
|
||||
(Optionally NULL).
|
||||
(Optionally NULL).
|
||||
|
||||
@returns
|
||||
This function returns a pointer to a #hid_device object on
|
||||
success or NULL on failure.
|
||||
Call hid_error(NULL) to get the failure reason.
|
||||
|
||||
@note The returned object must be freed by calling hid_close(),
|
||||
when not needed anymore.
|
||||
*/
|
||||
HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number);
|
||||
|
||||
|
@ -189,13 +283,17 @@ namespace NAMESPACE {
|
|||
Linux).
|
||||
|
||||
@ingroup API
|
||||
@param path The path name of the device to open
|
||||
@param path The path name of the device to open
|
||||
|
||||
@returns
|
||||
This function returns a pointer to a #hid_device object on
|
||||
success or NULL on failure.
|
||||
Call hid_error(NULL) to get the failure reason.
|
||||
|
||||
@note The returned object must be freed by calling hid_close(),
|
||||
when not needed anymore.
|
||||
*/
|
||||
HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path, int bExclusive /* = false */);
|
||||
HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path);
|
||||
|
||||
/** @brief Write an Output report to a HID device.
|
||||
|
||||
|
@ -222,6 +320,7 @@ namespace NAMESPACE {
|
|||
@returns
|
||||
This function returns the actual number of bytes written and
|
||||
-1 on error.
|
||||
Call hid_error(dev) to get the failure reason.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length);
|
||||
|
||||
|
@ -241,7 +340,9 @@ namespace NAMESPACE {
|
|||
|
||||
@returns
|
||||
This function returns the actual number of bytes read and
|
||||
-1 on error. If no packet was available to be read within
|
||||
-1 on error.
|
||||
Call hid_error(dev) to get the failure reason.
|
||||
If no packet was available to be read within
|
||||
the timeout period, this function returns 0.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds);
|
||||
|
@ -249,7 +350,7 @@ namespace NAMESPACE {
|
|||
/** @brief Read an Input report from a HID device.
|
||||
|
||||
Input reports are returned
|
||||
to the host through the INTERRUPT IN endpoint. The first byte will
|
||||
to the host through the INTERRUPT IN endpoint. The first byte will
|
||||
contain the Report number if the device uses numbered reports.
|
||||
|
||||
@ingroup API
|
||||
|
@ -261,7 +362,9 @@ namespace NAMESPACE {
|
|||
|
||||
@returns
|
||||
This function returns the actual number of bytes read and
|
||||
-1 on error. If no packet was available to be read and
|
||||
-1 on error.
|
||||
Call hid_error(dev) to get the failure reason.
|
||||
If no packet was available to be read and
|
||||
the handle is in non-blocking mode, this function returns 0.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length);
|
||||
|
@ -283,6 +386,7 @@ namespace NAMESPACE {
|
|||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
Call hid_error(dev) to get the failure reason.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock);
|
||||
|
||||
|
@ -311,6 +415,7 @@ namespace NAMESPACE {
|
|||
@returns
|
||||
This function returns the actual number of bytes written and
|
||||
-1 on error.
|
||||
Call hid_error(dev) to get the failure reason.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length);
|
||||
|
||||
|
@ -336,9 +441,38 @@ namespace NAMESPACE {
|
|||
This function returns the number of bytes read plus
|
||||
one for the report ID (which is still in the first
|
||||
byte), or -1 on error.
|
||||
Call hid_error(dev) to get the failure reason.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length);
|
||||
|
||||
/** @brief Get a input report from a HID device.
|
||||
|
||||
Since version 0.10.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 10, 0)
|
||||
|
||||
Set the first byte of @p data[] to the Report ID of the
|
||||
report to be read. Make sure to allow space for this
|
||||
extra byte in @p data[]. Upon return, the first byte will
|
||||
still contain the Report ID, and the report data will
|
||||
start in data[1].
|
||||
|
||||
@ingroup API
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param data A buffer to put the read data into, including
|
||||
the Report ID. Set the first byte of @p data[] to the
|
||||
Report ID of the report to be read, or set it to zero
|
||||
if your device does not use numbered reports.
|
||||
@param length The number of bytes to read, including an
|
||||
extra byte for the report ID. The buffer can be longer
|
||||
than the actual report.
|
||||
|
||||
@returns
|
||||
This function returns the number of bytes read plus
|
||||
one for the report ID (which is still in the first
|
||||
byte), or -1 on error.
|
||||
Call hid_error(dev) to get the failure reason.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length);
|
||||
|
||||
/** @brief Close a HID device.
|
||||
|
||||
@ingroup API
|
||||
|
@ -355,6 +489,7 @@ namespace NAMESPACE {
|
|||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
Call hid_error(dev) to get the failure reason.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen);
|
||||
|
||||
|
@ -367,6 +502,7 @@ namespace NAMESPACE {
|
|||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
Call hid_error(dev) to get the failure reason.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen);
|
||||
|
||||
|
@ -379,9 +515,27 @@ namespace NAMESPACE {
|
|||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
Call hid_error(dev) to get the failure reason.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen);
|
||||
|
||||
/** @brief Get The struct #hid_device_info from a HID device.
|
||||
|
||||
Since version 0.13.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 13, 0)
|
||||
|
||||
@ingroup API
|
||||
@param dev A device handle returned from hid_open().
|
||||
|
||||
@returns
|
||||
This function returns a pointer to the struct #hid_device_info
|
||||
for this hid_device, or NULL in the case of failure.
|
||||
Call hid_error(dev) to get the failure reason.
|
||||
This struct is valid until the device is closed with hid_close().
|
||||
|
||||
@note The returned object is owned by the @p dev, and SHOULD NOT be freed by the user.
|
||||
*/
|
||||
struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_get_device_info(hid_device *dev);
|
||||
|
||||
/** @brief Get a string from a HID device, based on its string index.
|
||||
|
||||
@ingroup API
|
||||
|
@ -392,30 +546,79 @@ namespace NAMESPACE {
|
|||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
Call hid_error(dev) to get the failure reason.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen);
|
||||
|
||||
/** @brief Get a string describing the last error which occurred.
|
||||
/** @brief Get a report descriptor from a HID device.
|
||||
|
||||
Since version 0.14.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 14, 0)
|
||||
|
||||
User has to provide a preallocated buffer where descriptor will be copied to.
|
||||
The recommended size for preallocated buffer is @ref HID_API_MAX_REPORT_DESCRIPTOR_SIZE bytes.
|
||||
|
||||
@ingroup API
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param buf The buffer to copy descriptor into.
|
||||
@param buf_size The size of the buffer in bytes.
|
||||
|
||||
@returns
|
||||
This function returns a string containing the last error
|
||||
which occurred or NULL if none has occurred.
|
||||
This function returns non-negative number of bytes actually copied, or -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_get_report_descriptor(hid_device *dev, unsigned char *buf, size_t buf_size);
|
||||
|
||||
/** @brief Get a string describing the last error which occurred.
|
||||
|
||||
This function is intended for logging/debugging purposes.
|
||||
|
||||
This function guarantees to never return NULL.
|
||||
If there was no error in the last function call -
|
||||
the returned string clearly indicates that.
|
||||
|
||||
Any HIDAPI function that can explicitly indicate an execution failure
|
||||
(e.g. by an error code, or by returning NULL) - may set the error string,
|
||||
to be returned by this function.
|
||||
|
||||
Strings returned from hid_error() must not be freed by the user,
|
||||
i.e. owned by HIDAPI library.
|
||||
Device-specific error string may remain allocated at most until hid_close() is called.
|
||||
Global error string may remain allocated at most until hid_exit() is called.
|
||||
|
||||
@ingroup API
|
||||
@param dev A device handle returned from hid_open(),
|
||||
or NULL to get the last non-device-specific error
|
||||
(e.g. for errors in hid_open() or hid_enumerate()).
|
||||
|
||||
@returns
|
||||
A string describing the last error (if any).
|
||||
*/
|
||||
HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *dev);
|
||||
|
||||
#if defined(__IOS__) || defined(__TVOS__)
|
||||
HID_API_EXPORT void HID_API_CALL hid_ble_scan(int active);
|
||||
#endif
|
||||
/** @brief Get a runtime version of the library.
|
||||
|
||||
#if defined(__cplusplus) && !defined(NAMESPACE)
|
||||
}
|
||||
#endif
|
||||
#ifdef NAMESPACE
|
||||
This function is thread-safe.
|
||||
|
||||
@ingroup API
|
||||
|
||||
@returns
|
||||
Pointer to statically allocated struct, that contains version.
|
||||
*/
|
||||
HID_API_EXPORT const struct hid_api_version* HID_API_CALL hid_version(void);
|
||||
|
||||
|
||||
/** @brief Get a runtime version string of the library.
|
||||
|
||||
This function is thread-safe.
|
||||
|
||||
@ingroup API
|
||||
|
||||
@returns
|
||||
Pointer to statically allocated string, that contains version string.
|
||||
*/
|
||||
HID_API_EXPORT const char* HID_API_CALL hid_version_str(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
Debug
|
||||
Release
|
||||
*.exp
|
||||
*.ilk
|
||||
*.lib
|
||||
*.suo
|
||||
*.vcproj.*
|
||||
*.ncb
|
||||
*.suo
|
||||
*.dll
|
||||
*.pdb
|
||||
*.o
|
||||
.deps/
|
||||
.libs/
|
||||
hidtest-hidraw
|
||||
hidtest-libusb
|
||||
hidtest
|
|
@ -0,0 +1,40 @@
|
|||
cmake_minimum_required(VERSION 3.1.3 FATAL_ERROR)
|
||||
project(hidtest C)
|
||||
|
||||
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||
# hidtest is build as a standalone project
|
||||
|
||||
if(POLICY CMP0074)
|
||||
# allow using hidapi_ROOT if CMake supports it
|
||||
cmake_policy(SET CMP0074 NEW)
|
||||
endif()
|
||||
|
||||
find_package(hidapi 0.12 REQUIRED)
|
||||
message(STATUS "Using HIDAPI: ${hidapi_VERSION}")
|
||||
else()
|
||||
# hidtest is built as part of the main HIDAPI build
|
||||
message(STATUS "Building hidtest")
|
||||
endif()
|
||||
|
||||
set(HIDAPI_HIDTEST_TARGETS)
|
||||
if(NOT WIN32 AND NOT APPLE AND CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
if(TARGET hidapi::hidraw)
|
||||
add_executable(hidtest_hidraw test.c)
|
||||
target_link_libraries(hidtest_hidraw hidapi::hidraw)
|
||||
list(APPEND HIDAPI_HIDTEST_TARGETS hidtest_hidraw)
|
||||
endif()
|
||||
if(TARGET hidapi::libusb)
|
||||
add_executable(hidtest_libusb test.c)
|
||||
target_compile_definitions(hidtest_libusb PRIVATE USING_HIDAPI_LIBUSB)
|
||||
target_link_libraries(hidtest_libusb hidapi::libusb)
|
||||
list(APPEND HIDAPI_HIDTEST_TARGETS hidtest_libusb)
|
||||
endif()
|
||||
else()
|
||||
add_executable(hidtest test.c)
|
||||
target_link_libraries(hidtest hidapi::hidapi)
|
||||
list(APPEND HIDAPI_HIDTEST_TARGETS hidtest)
|
||||
endif()
|
||||
|
||||
install(TARGETS ${HIDAPI_HIDTEST_TARGETS}
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
||||
)
|
|
@ -4,17 +4,25 @@ AM_CPPFLAGS = -I$(top_srcdir)/hidapi/
|
|||
if OS_LINUX
|
||||
noinst_PROGRAMS = hidtest-libusb hidtest-hidraw
|
||||
|
||||
hidtest_hidraw_SOURCES = hidtest.cpp
|
||||
hidtest_hidraw_SOURCES = test.c
|
||||
hidtest_hidraw_LDADD = $(top_builddir)/linux/libhidapi-hidraw.la
|
||||
|
||||
hidtest_libusb_SOURCES = hidtest.cpp
|
||||
hidtest_libusb_SOURCES = test.c
|
||||
hidtest_libusb_LDADD = $(top_builddir)/libusb/libhidapi-libusb.la
|
||||
else
|
||||
|
||||
# Other OS's
|
||||
noinst_PROGRAMS = hidtest
|
||||
|
||||
hidtest_SOURCES = hidtest.cpp
|
||||
hidtest_SOURCES = test.c
|
||||
hidtest_LDADD = $(top_builddir)/$(backend)/libhidapi.la
|
||||
|
||||
endif
|
||||
|
||||
if OS_DARWIN
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/mac/
|
||||
endif
|
||||
|
||||
if OS_WINDOWS
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/windows/
|
||||
endif
|
||||
|
|
|
@ -1,194 +0,0 @@
|
|||
/*******************************************************
|
||||
Windows HID simplification
|
||||
|
||||
Alan Ott
|
||||
Signal 11 Software
|
||||
|
||||
8/22/2009
|
||||
|
||||
Copyright 2009
|
||||
|
||||
This contents of this file may be used by anyone
|
||||
for any reason without any conditions and may be
|
||||
used as a starting point for your own applications
|
||||
which use HIDAPI.
|
||||
********************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <wchar.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "hidapi.h"
|
||||
|
||||
// Headers needed for sleeping.
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int res;
|
||||
unsigned char buf[256];
|
||||
#define MAX_STR 255
|
||||
wchar_t wstr[MAX_STR];
|
||||
hid_device *handle;
|
||||
int i;
|
||||
|
||||
#ifdef WIN32
|
||||
UNREFERENCED_PARAMETER(argc);
|
||||
UNREFERENCED_PARAMETER(argv);
|
||||
#endif
|
||||
|
||||
struct hid_device_info *devs, *cur_dev;
|
||||
|
||||
if (hid_init())
|
||||
return -1;
|
||||
|
||||
devs = hid_enumerate(0x0, 0x0);
|
||||
cur_dev = devs;
|
||||
while (cur_dev) {
|
||||
printf("Device Found\n type: %04hx %04hx\n path: %s\n serial_number: %ls", cur_dev->vendor_id, cur_dev->product_id, cur_dev->path, cur_dev->serial_number);
|
||||
printf("\n");
|
||||
printf(" Manufacturer: %ls\n", cur_dev->manufacturer_string);
|
||||
printf(" Product: %ls\n", cur_dev->product_string);
|
||||
printf(" Release: %hx\n", cur_dev->release_number);
|
||||
printf(" Interface: %d\n", cur_dev->interface_number);
|
||||
printf("\n");
|
||||
cur_dev = cur_dev->next;
|
||||
}
|
||||
hid_free_enumeration(devs);
|
||||
|
||||
// Set up the command buffer.
|
||||
memset(buf,0x00,sizeof(buf));
|
||||
buf[0] = 0x01;
|
||||
buf[1] = 0x81;
|
||||
|
||||
|
||||
// Open the device using the VID, PID,
|
||||
// and optionally the Serial number.
|
||||
////handle = hid_open(0x4d8, 0x3f, L"12345");
|
||||
handle = hid_open(0x4d8, 0x3f, NULL);
|
||||
if (!handle) {
|
||||
printf("unable to open device\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Read the Manufacturer String
|
||||
wstr[0] = 0x0000;
|
||||
res = hid_get_manufacturer_string(handle, wstr, MAX_STR);
|
||||
if (res < 0)
|
||||
printf("Unable to read manufacturer string\n");
|
||||
printf("Manufacturer String: %ls\n", wstr);
|
||||
|
||||
// Read the Product String
|
||||
wstr[0] = 0x0000;
|
||||
res = hid_get_product_string(handle, wstr, MAX_STR);
|
||||
if (res < 0)
|
||||
printf("Unable to read product string\n");
|
||||
printf("Product String: %ls\n", wstr);
|
||||
|
||||
// Read the Serial Number String
|
||||
wstr[0] = 0x0000;
|
||||
res = hid_get_serial_number_string(handle, wstr, MAX_STR);
|
||||
if (res < 0)
|
||||
printf("Unable to read serial number string\n");
|
||||
printf("Serial Number String: (%d) %ls", wstr[0], wstr);
|
||||
printf("\n");
|
||||
|
||||
// Read Indexed String 1
|
||||
wstr[0] = 0x0000;
|
||||
res = hid_get_indexed_string(handle, 1, wstr, MAX_STR);
|
||||
if (res < 0)
|
||||
printf("Unable to read indexed string 1\n");
|
||||
printf("Indexed String 1: %ls\n", wstr);
|
||||
|
||||
// Set the hid_read() function to be non-blocking.
|
||||
hid_set_nonblocking(handle, 1);
|
||||
|
||||
// Try to read from the device. There shoud be no
|
||||
// data here, but execution should not block.
|
||||
res = hid_read(handle, buf, 17);
|
||||
|
||||
// Send a Feature Report to the device
|
||||
buf[0] = 0x2;
|
||||
buf[1] = 0xa0;
|
||||
buf[2] = 0x0a;
|
||||
buf[3] = 0x00;
|
||||
buf[4] = 0x00;
|
||||
res = hid_send_feature_report(handle, buf, 17);
|
||||
if (res < 0) {
|
||||
printf("Unable to send a feature report.\n");
|
||||
}
|
||||
|
||||
memset(buf,0,sizeof(buf));
|
||||
|
||||
// Read a Feature Report from the device
|
||||
buf[0] = 0x2;
|
||||
res = hid_get_feature_report(handle, buf, sizeof(buf));
|
||||
if (res < 0) {
|
||||
printf("Unable to get a feature report.\n");
|
||||
printf("%ls", hid_error(handle));
|
||||
}
|
||||
else {
|
||||
// Print out the returned buffer.
|
||||
printf("Feature Report\n ");
|
||||
for (i = 0; i < res; i++)
|
||||
printf("%02hhx ", buf[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
memset(buf,0,sizeof(buf));
|
||||
|
||||
// Toggle LED (cmd 0x80). The first byte is the report number (0x1).
|
||||
buf[0] = 0x1;
|
||||
buf[1] = 0x80;
|
||||
res = hid_write(handle, buf, 17);
|
||||
if (res < 0) {
|
||||
printf("Unable to write()\n");
|
||||
printf("Error: %ls\n", hid_error(handle));
|
||||
}
|
||||
|
||||
|
||||
// Request state (cmd 0x81). The first byte is the report number (0x1).
|
||||
buf[0] = 0x1;
|
||||
buf[1] = 0x81;
|
||||
hid_write(handle, buf, 17);
|
||||
if (res < 0)
|
||||
printf("Unable to write() (2)\n");
|
||||
|
||||
// Read requested state. hid_read() has been set to be
|
||||
// non-blocking by the call to hid_set_nonblocking() above.
|
||||
// This loop demonstrates the non-blocking nature of hid_read().
|
||||
res = 0;
|
||||
while (res == 0) {
|
||||
res = hid_read(handle, buf, sizeof(buf));
|
||||
if (res == 0)
|
||||
printf("waiting...\n");
|
||||
if (res < 0)
|
||||
printf("Unable to read()\n");
|
||||
#ifdef WIN32
|
||||
Sleep(500);
|
||||
#else
|
||||
usleep(500*1000);
|
||||
#endif
|
||||
}
|
||||
|
||||
printf("Data read:\n ");
|
||||
// Print out the returned buffer.
|
||||
for (i = 0; i < res; i++)
|
||||
printf("%02hhx ", buf[i]);
|
||||
printf("\n");
|
||||
|
||||
hid_close(handle);
|
||||
|
||||
/* Free static HIDAPI objects. */
|
||||
hid_exit();
|
||||
|
||||
#ifdef WIN32
|
||||
system("pause");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,316 @@
|
|||
/*******************************************************
|
||||
HIDAPI - Multi-Platform library for
|
||||
communication with HID devices.
|
||||
|
||||
Alan Ott
|
||||
Signal 11 Software
|
||||
|
||||
libusb/hidapi Team
|
||||
|
||||
Copyright 2022.
|
||||
|
||||
This contents of this file may be used by anyone
|
||||
for any reason without any conditions and may be
|
||||
used as a starting point for your own applications
|
||||
which use HIDAPI.
|
||||
********************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <wchar.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <hidapi.h>
|
||||
|
||||
// Headers needed for sleeping.
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
// Fallback/example
|
||||
#ifndef HID_API_MAKE_VERSION
|
||||
#define HID_API_MAKE_VERSION(mj, mn, p) (((mj) << 24) | ((mn) << 8) | (p))
|
||||
#endif
|
||||
#ifndef HID_API_VERSION
|
||||
#define HID_API_VERSION HID_API_MAKE_VERSION(HID_API_VERSION_MAJOR, HID_API_VERSION_MINOR, HID_API_VERSION_PATCH)
|
||||
#endif
|
||||
|
||||
//
|
||||
// Sample using platform-specific headers
|
||||
#if defined(__APPLE__) && HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
|
||||
#include <hidapi_darwin.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
|
||||
#include <hidapi_winapi.h>
|
||||
#endif
|
||||
|
||||
#if defined(USING_HIDAPI_LIBUSB) && HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
|
||||
#include <hidapi_libusb.h>
|
||||
#endif
|
||||
//
|
||||
|
||||
const char *hid_bus_name(hid_bus_type bus_type) {
|
||||
static const char *const HidBusTypeName[] = {
|
||||
"Unknown",
|
||||
"USB",
|
||||
"Bluetooth",
|
||||
"I2C",
|
||||
"SPI",
|
||||
};
|
||||
|
||||
if ((int)bus_type < 0)
|
||||
bus_type = HID_API_BUS_UNKNOWN;
|
||||
if ((int)bus_type >= (int)(sizeof(HidBusTypeName) / sizeof(HidBusTypeName[0])))
|
||||
bus_type = HID_API_BUS_UNKNOWN;
|
||||
|
||||
return HidBusTypeName[bus_type];
|
||||
}
|
||||
|
||||
void print_device(struct hid_device_info *cur_dev) {
|
||||
printf("Device Found\n type: %04hx %04hx\n path: %s\n serial_number: %ls", cur_dev->vendor_id, cur_dev->product_id, cur_dev->path, cur_dev->serial_number);
|
||||
printf("\n");
|
||||
printf(" Manufacturer: %ls\n", cur_dev->manufacturer_string);
|
||||
printf(" Product: %ls\n", cur_dev->product_string);
|
||||
printf(" Release: %hx\n", cur_dev->release_number);
|
||||
printf(" Interface: %d\n", cur_dev->interface_number);
|
||||
printf(" Usage (page): 0x%hx (0x%hx)\n", cur_dev->usage, cur_dev->usage_page);
|
||||
printf(" Bus type: %d (%s)\n", cur_dev->bus_type, hid_bus_name(cur_dev->bus_type));
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void print_hid_report_descriptor_from_device(hid_device *device) {
|
||||
unsigned char descriptor[HID_API_MAX_REPORT_DESCRIPTOR_SIZE];
|
||||
int res = 0;
|
||||
|
||||
printf(" Report Descriptor: ");
|
||||
res = hid_get_report_descriptor(device, descriptor, sizeof(descriptor));
|
||||
if (res < 0) {
|
||||
printf("error getting: %ls", hid_error(device));
|
||||
}
|
||||
else {
|
||||
printf("(%d bytes)", res);
|
||||
}
|
||||
for (int i = 0; i < res; i++) {
|
||||
if (i % 10 == 0) {
|
||||
printf("\n");
|
||||
}
|
||||
printf("0x%02x, ", descriptor[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void print_hid_report_descriptor_from_path(const char *path) {
|
||||
hid_device *device = hid_open_path(path);
|
||||
if (device) {
|
||||
print_hid_report_descriptor_from_device(device);
|
||||
hid_close(device);
|
||||
}
|
||||
else {
|
||||
printf(" Report Descriptor: Unable to open device by path\n");
|
||||
}
|
||||
}
|
||||
|
||||
void print_devices(struct hid_device_info *cur_dev) {
|
||||
for (; cur_dev; cur_dev = cur_dev->next) {
|
||||
print_device(cur_dev);
|
||||
}
|
||||
}
|
||||
|
||||
void print_devices_with_descriptor(struct hid_device_info *cur_dev) {
|
||||
for (; cur_dev; cur_dev = cur_dev->next) {
|
||||
print_device(cur_dev);
|
||||
print_hid_report_descriptor_from_path(cur_dev->path);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
int res;
|
||||
unsigned char buf[256];
|
||||
#define MAX_STR 255
|
||||
wchar_t wstr[MAX_STR];
|
||||
hid_device *handle;
|
||||
int i;
|
||||
|
||||
struct hid_device_info *devs;
|
||||
|
||||
printf("hidapi test/example tool. Compiled with hidapi version %s, runtime version %s.\n", HID_API_VERSION_STR, hid_version_str());
|
||||
if (HID_API_VERSION == HID_API_MAKE_VERSION(hid_version()->major, hid_version()->minor, hid_version()->patch)) {
|
||||
printf("Compile-time version matches runtime version of hidapi.\n\n");
|
||||
}
|
||||
else {
|
||||
printf("Compile-time version is different than runtime version of hidapi.\n]n");
|
||||
}
|
||||
|
||||
if (hid_init())
|
||||
return -1;
|
||||
|
||||
#if defined(__APPLE__) && HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
|
||||
// To work properly needs to be called before hid_open/hid_open_path after hid_init.
|
||||
// Best/recommended option - call it right after hid_init.
|
||||
hid_darwin_set_open_exclusive(0);
|
||||
#endif
|
||||
|
||||
devs = hid_enumerate(0x0, 0x0);
|
||||
print_devices_with_descriptor(devs);
|
||||
hid_free_enumeration(devs);
|
||||
|
||||
// Set up the command buffer.
|
||||
memset(buf,0x00,sizeof(buf));
|
||||
buf[0] = 0x01;
|
||||
buf[1] = 0x81;
|
||||
|
||||
|
||||
// Open the device using the VID, PID,
|
||||
// and optionally the Serial number.
|
||||
////handle = hid_open(0x4d8, 0x3f, L"12345");
|
||||
handle = hid_open(0x4d8, 0x3f, NULL);
|
||||
if (!handle) {
|
||||
printf("unable to open device\n");
|
||||
hid_exit();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Read the Manufacturer String
|
||||
wstr[0] = 0x0000;
|
||||
res = hid_get_manufacturer_string(handle, wstr, MAX_STR);
|
||||
if (res < 0)
|
||||
printf("Unable to read manufacturer string\n");
|
||||
printf("Manufacturer String: %ls\n", wstr);
|
||||
|
||||
// Read the Product String
|
||||
wstr[0] = 0x0000;
|
||||
res = hid_get_product_string(handle, wstr, MAX_STR);
|
||||
if (res < 0)
|
||||
printf("Unable to read product string\n");
|
||||
printf("Product String: %ls\n", wstr);
|
||||
|
||||
// Read the Serial Number String
|
||||
wstr[0] = 0x0000;
|
||||
res = hid_get_serial_number_string(handle, wstr, MAX_STR);
|
||||
if (res < 0)
|
||||
printf("Unable to read serial number string\n");
|
||||
printf("Serial Number String: (%d) %ls\n", wstr[0], wstr);
|
||||
|
||||
print_hid_report_descriptor_from_device(handle);
|
||||
|
||||
struct hid_device_info* info = hid_get_device_info(handle);
|
||||
if (info == NULL) {
|
||||
printf("Unable to get device info\n");
|
||||
} else {
|
||||
print_devices(info);
|
||||
}
|
||||
|
||||
// Read Indexed String 1
|
||||
wstr[0] = 0x0000;
|
||||
res = hid_get_indexed_string(handle, 1, wstr, MAX_STR);
|
||||
if (res < 0)
|
||||
printf("Unable to read indexed string 1\n");
|
||||
printf("Indexed String 1: %ls\n", wstr);
|
||||
|
||||
// Set the hid_read() function to be non-blocking.
|
||||
hid_set_nonblocking(handle, 1);
|
||||
|
||||
// Try to read from the device. There should be no
|
||||
// data here, but execution should not block.
|
||||
res = hid_read(handle, buf, 17);
|
||||
|
||||
// Send a Feature Report to the device
|
||||
buf[0] = 0x2;
|
||||
buf[1] = 0xa0;
|
||||
buf[2] = 0x0a;
|
||||
buf[3] = 0x00;
|
||||
buf[4] = 0x00;
|
||||
res = hid_send_feature_report(handle, buf, 17);
|
||||
if (res < 0) {
|
||||
printf("Unable to send a feature report.\n");
|
||||
}
|
||||
|
||||
memset(buf,0,sizeof(buf));
|
||||
|
||||
// Read a Feature Report from the device
|
||||
buf[0] = 0x2;
|
||||
res = hid_get_feature_report(handle, buf, sizeof(buf));
|
||||
if (res < 0) {
|
||||
printf("Unable to get a feature report: %ls\n", hid_error(handle));
|
||||
}
|
||||
else {
|
||||
// Print out the returned buffer.
|
||||
printf("Feature Report\n ");
|
||||
for (i = 0; i < res; i++)
|
||||
printf("%02x ", (unsigned int) buf[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
memset(buf,0,sizeof(buf));
|
||||
|
||||
// Toggle LED (cmd 0x80). The first byte is the report number (0x1).
|
||||
buf[0] = 0x1;
|
||||
buf[1] = 0x80;
|
||||
res = hid_write(handle, buf, 17);
|
||||
if (res < 0) {
|
||||
printf("Unable to write(): %ls\n", hid_error(handle));
|
||||
}
|
||||
|
||||
|
||||
// Request state (cmd 0x81). The first byte is the report number (0x1).
|
||||
buf[0] = 0x1;
|
||||
buf[1] = 0x81;
|
||||
hid_write(handle, buf, 17);
|
||||
if (res < 0) {
|
||||
printf("Unable to write()/2: %ls\n", hid_error(handle));
|
||||
}
|
||||
|
||||
// Read requested state. hid_read() has been set to be
|
||||
// non-blocking by the call to hid_set_nonblocking() above.
|
||||
// This loop demonstrates the non-blocking nature of hid_read().
|
||||
res = 0;
|
||||
i = 0;
|
||||
while (res == 0) {
|
||||
res = hid_read(handle, buf, sizeof(buf));
|
||||
if (res == 0) {
|
||||
printf("waiting...\n");
|
||||
}
|
||||
if (res < 0) {
|
||||
printf("Unable to read(): %ls\n", hid_error(handle));
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
if (i >= 10) { /* 10 tries by 500 ms - 5 seconds of waiting*/
|
||||
printf("read() timeout\n");
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
Sleep(500);
|
||||
#else
|
||||
usleep(500*1000);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (res > 0) {
|
||||
printf("Data read:\n ");
|
||||
// Print out the returned buffer.
|
||||
for (i = 0; i < res; i++)
|
||||
printf("%02x ", (unsigned int) buf[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
hid_close(handle);
|
||||
|
||||
/* Free static HIDAPI objects. */
|
||||
hid_exit();
|
||||
|
||||
#ifdef _WIN32
|
||||
system("pause");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
###########################################
|
||||
# Simple Makefile for HIDAPI test program
|
||||
#
|
||||
# Alan Ott
|
||||
# Signal 11 Software
|
||||
# 2010-07-03
|
||||
###########################################
|
||||
|
||||
all: hidtest
|
||||
|
||||
CC=gcc
|
||||
CXX=g++
|
||||
COBJS=hid.o
|
||||
CPPOBJS=../hidtest/hidtest.o
|
||||
OBJS=$(COBJS) $(CPPOBJS)
|
||||
CFLAGS+=-I../hidapi -Wall -g -c
|
||||
LIBS=-framework CoreBluetooth -framework CoreFoundation
|
||||
|
||||
|
||||
hidtest: $(OBJS)
|
||||
g++ -Wall -g $^ $(LIBS) -o hidtest
|
||||
|
||||
$(COBJS): %.o: %.c
|
||||
$(CC) $(CFLAGS) $< -o $@
|
||||
|
||||
$(CPPOBJS): %.o: %.cpp
|
||||
$(CXX) $(CFLAGS) $< -o $@
|
||||
|
||||
clean:
|
||||
rm -f *.o hidtest $(CPPOBJS)
|
||||
|
||||
.PHONY: clean
|
|
@ -1,9 +0,0 @@
|
|||
lib_LTLIBRARIES = libhidapi.la
|
||||
libhidapi_la_SOURCES = hid.m
|
||||
libhidapi_la_LDFLAGS = $(LTLDFLAGS)
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/hidapi/
|
||||
|
||||
hdrdir = $(includedir)/hidapi
|
||||
hdr_HEADERS = $(top_srcdir)/hidapi/hidapi.h
|
||||
|
||||
EXTRA_DIST = Makefile-manual
|
|
@ -1,996 +0,0 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 2021 Valve Corporation
|
||||
|
||||
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.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_HIDAPI_DISABLED
|
||||
|
||||
|
||||
#define hid_init PLATFORM_hid_init
|
||||
#define hid_exit PLATFORM_hid_exit
|
||||
#define hid_enumerate PLATFORM_hid_enumerate
|
||||
#define hid_free_enumeration PLATFORM_hid_free_enumeration
|
||||
#define hid_open PLATFORM_hid_open
|
||||
#define hid_open_path PLATFORM_hid_open_path
|
||||
#define hid_write PLATFORM_hid_write
|
||||
#define hid_read_timeout PLATFORM_hid_read_timeout
|
||||
#define hid_read PLATFORM_hid_read
|
||||
#define hid_set_nonblocking PLATFORM_hid_set_nonblocking
|
||||
#define hid_send_feature_report PLATFORM_hid_send_feature_report
|
||||
#define hid_get_feature_report PLATFORM_hid_get_feature_report
|
||||
#define hid_close PLATFORM_hid_close
|
||||
#define hid_get_manufacturer_string PLATFORM_hid_get_manufacturer_string
|
||||
#define hid_get_product_string PLATFORM_hid_get_product_string
|
||||
#define hid_get_serial_number_string PLATFORM_hid_get_serial_number_string
|
||||
#define hid_get_indexed_string PLATFORM_hid_get_indexed_string
|
||||
#define hid_error PLATFORM_hid_error
|
||||
|
||||
#include <CoreBluetooth/CoreBluetooth.h>
|
||||
#include <QuartzCore/QuartzCore.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <mach/mach_time.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include "../hidapi/hidapi.h"
|
||||
|
||||
#define VALVE_USB_VID 0x28DE
|
||||
#define D0G_BLE2_PID 0x1106
|
||||
|
||||
typedef uint32_t uint32;
|
||||
typedef uint64_t uint64;
|
||||
|
||||
// enables detailed NSLog logging of feature reports
|
||||
#define FEATURE_REPORT_LOGGING 0
|
||||
|
||||
#define REPORT_SEGMENT_DATA_FLAG 0x80
|
||||
#define REPORT_SEGMENT_LAST_FLAG 0x40
|
||||
|
||||
#define VALVE_SERVICE @"100F6C32-1735-4313-B402-38567131E5F3"
|
||||
|
||||
// (READ/NOTIFICATIONS)
|
||||
#define VALVE_INPUT_CHAR @"100F6C33-1735-4313-B402-38567131E5F3"
|
||||
|
||||
// (READ/WRITE)
|
||||
#define VALVE_REPORT_CHAR @"100F6C34-1735-4313-B402-38567131E5F3"
|
||||
|
||||
// TODO: create CBUUID's in __attribute__((constructor)) rather than doing [CBUUID UUIDWithString:...] everywhere
|
||||
|
||||
#pragma pack(push,1)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t segmentHeader;
|
||||
uint8_t featureReportMessageID;
|
||||
uint8_t length;
|
||||
uint8_t settingIdentifier;
|
||||
union {
|
||||
uint16_t usPayload;
|
||||
uint32_t uPayload;
|
||||
uint64_t ulPayload;
|
||||
uint8_t ucPayload[15];
|
||||
};
|
||||
} bluetoothSegment;
|
||||
|
||||
typedef struct {
|
||||
uint8_t id;
|
||||
union {
|
||||
bluetoothSegment segment;
|
||||
struct {
|
||||
uint8_t segmentHeader;
|
||||
uint8_t featureReportMessageID;
|
||||
uint8_t length;
|
||||
uint8_t settingIdentifier;
|
||||
union {
|
||||
uint16_t usPayload;
|
||||
uint32_t uPayload;
|
||||
uint64_t ulPayload;
|
||||
uint8_t ucPayload[15];
|
||||
};
|
||||
};
|
||||
};
|
||||
} hidFeatureReport;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
size_t GetBluetoothSegmentSize(bluetoothSegment *segment)
|
||||
{
|
||||
return segment->length + 3;
|
||||
}
|
||||
|
||||
#define RingBuffer_cbElem 19
|
||||
#define RingBuffer_nElem 4096
|
||||
|
||||
typedef struct {
|
||||
int _first, _last;
|
||||
uint8_t _data[ ( RingBuffer_nElem * RingBuffer_cbElem ) ];
|
||||
pthread_mutex_t accessLock;
|
||||
} RingBuffer;
|
||||
|
||||
static void RingBuffer_init( RingBuffer *this )
|
||||
{
|
||||
this->_first = -1;
|
||||
this->_last = 0;
|
||||
pthread_mutex_init( &this->accessLock, 0 );
|
||||
}
|
||||
|
||||
static bool RingBuffer_write( RingBuffer *this, const uint8_t *src )
|
||||
{
|
||||
pthread_mutex_lock( &this->accessLock );
|
||||
memcpy( &this->_data[ this->_last ], src, RingBuffer_cbElem );
|
||||
if ( this->_first == -1 )
|
||||
{
|
||||
this->_first = this->_last;
|
||||
}
|
||||
this->_last = ( this->_last + RingBuffer_cbElem ) % (RingBuffer_nElem * RingBuffer_cbElem);
|
||||
if ( this->_last == this->_first )
|
||||
{
|
||||
this->_first = ( this->_first + RingBuffer_cbElem ) % (RingBuffer_nElem * RingBuffer_cbElem);
|
||||
pthread_mutex_unlock( &this->accessLock );
|
||||
return false;
|
||||
}
|
||||
pthread_mutex_unlock( &this->accessLock );
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool RingBuffer_read( RingBuffer *this, uint8_t *dst )
|
||||
{
|
||||
pthread_mutex_lock( &this->accessLock );
|
||||
if ( this->_first == -1 )
|
||||
{
|
||||
pthread_mutex_unlock( &this->accessLock );
|
||||
return false;
|
||||
}
|
||||
memcpy( dst, &this->_data[ this->_first ], RingBuffer_cbElem );
|
||||
this->_first = ( this->_first + RingBuffer_cbElem ) % (RingBuffer_nElem * RingBuffer_cbElem);
|
||||
if ( this->_first == this->_last )
|
||||
{
|
||||
this->_first = -1;
|
||||
}
|
||||
pthread_mutex_unlock( &this->accessLock );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark HIDBLEDevice Definition
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BLEDeviceWaitState_None,
|
||||
BLEDeviceWaitState_Waiting,
|
||||
BLEDeviceWaitState_Complete,
|
||||
BLEDeviceWaitState_Error
|
||||
} BLEDeviceWaitState;
|
||||
|
||||
@interface HIDBLEDevice : NSObject <CBPeripheralDelegate>
|
||||
{
|
||||
RingBuffer _inputReports;
|
||||
uint8_t _featureReport[20];
|
||||
BLEDeviceWaitState _waitStateForReadFeatureReport;
|
||||
BLEDeviceWaitState _waitStateForWriteFeatureReport;
|
||||
}
|
||||
|
||||
@property (nonatomic, readwrite) bool connected;
|
||||
@property (nonatomic, readwrite) bool ready;
|
||||
|
||||
@property (nonatomic, strong) CBPeripheral *bleSteamController;
|
||||
@property (nonatomic, strong) CBCharacteristic *bleCharacteristicInput;
|
||||
@property (nonatomic, strong) CBCharacteristic *bleCharacteristicReport;
|
||||
|
||||
- (id)initWithPeripheral:(CBPeripheral *)peripheral;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface HIDBLEManager : NSObject <CBCentralManagerDelegate>
|
||||
|
||||
@property (nonatomic) int nPendingScans;
|
||||
@property (nonatomic) int nPendingPairs;
|
||||
@property (nonatomic, strong) CBCentralManager *centralManager;
|
||||
@property (nonatomic, strong) NSMapTable<CBPeripheral *, HIDBLEDevice *> *deviceMap;
|
||||
@property (nonatomic, retain) dispatch_queue_t bleSerialQueue;
|
||||
|
||||
+ (instancetype)sharedInstance;
|
||||
- (void)startScan:(int)duration;
|
||||
- (void)stopScan;
|
||||
- (int)updateConnectedSteamControllers:(BOOL) bForce;
|
||||
- (void)appWillResignActiveNotification:(NSNotification *)note;
|
||||
- (void)appDidBecomeActiveNotification:(NSNotification *)note;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// singleton class - access using HIDBLEManager.sharedInstance
|
||||
@implementation HIDBLEManager
|
||||
|
||||
+ (instancetype)sharedInstance
|
||||
{
|
||||
static HIDBLEManager *sharedInstance = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedInstance = [HIDBLEManager new];
|
||||
sharedInstance.nPendingScans = 0;
|
||||
sharedInstance.nPendingPairs = 0;
|
||||
|
||||
// Bluetooth is currently only used for Steam Controllers, so check that hint
|
||||
// before initializing Bluetooth, which will prompt the user for permission.
|
||||
if ( SDL_GetHintBoolean( SDL_HINT_JOYSTICK_HIDAPI_STEAM, SDL_FALSE ) )
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] addObserver:sharedInstance selector:@selector(appWillResignActiveNotification:) name: UIApplicationWillResignActiveNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:sharedInstance selector:@selector(appDidBecomeActiveNotification:) name:UIApplicationDidBecomeActiveNotification object:nil];
|
||||
|
||||
// receive reports on a high-priority serial-queue. optionally put writes on the serial queue to avoid logical
|
||||
// race conditions talking to the controller from multiple threads, although BLE fragmentation/assembly means
|
||||
// that we can still screw this up.
|
||||
// most importantly we need to consume reports at a high priority to avoid the OS thinking we aren't really
|
||||
// listening to the BLE device, as iOS on slower devices may stop delivery of packets to the app WITHOUT ACTUALLY
|
||||
// DISCONNECTING FROM THE DEVICE if we don't react quickly enough to their delivery.
|
||||
// see also the error-handling states in the peripheral delegate to re-open the device if it gets closed
|
||||
sharedInstance.bleSerialQueue = dispatch_queue_create( "com.valvesoftware.steamcontroller.ble", DISPATCH_QUEUE_SERIAL );
|
||||
dispatch_set_target_queue( sharedInstance.bleSerialQueue, dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_HIGH, 0 ) );
|
||||
|
||||
// creating a CBCentralManager will always trigger a future centralManagerDidUpdateState:
|
||||
// where any scanning gets started or connecting to existing peripherals happens, it's never already in a
|
||||
// powered-on state for a newly launched application.
|
||||
sharedInstance.centralManager = [[CBCentralManager alloc] initWithDelegate:sharedInstance queue:sharedInstance.bleSerialQueue];
|
||||
}
|
||||
sharedInstance.deviceMap = [[NSMapTable alloc] initWithKeyOptions:NSMapTableWeakMemory valueOptions:NSMapTableStrongMemory capacity:4];
|
||||
});
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
// called for NSNotification UIApplicationWillResignActiveNotification
|
||||
- (void)appWillResignActiveNotification:(NSNotification *)note
|
||||
{
|
||||
// we'll get resign-active notification if pairing is happening.
|
||||
if ( self.nPendingPairs > 0 )
|
||||
return;
|
||||
|
||||
for ( CBPeripheral *peripheral in self.deviceMap )
|
||||
{
|
||||
HIDBLEDevice *steamController = [self.deviceMap objectForKey:peripheral];
|
||||
if ( steamController )
|
||||
{
|
||||
steamController.connected = NO;
|
||||
steamController.ready = NO;
|
||||
[self.centralManager cancelPeripheralConnection:peripheral];
|
||||
}
|
||||
}
|
||||
[self.deviceMap removeAllObjects];
|
||||
}
|
||||
|
||||
// called for NSNotification UIApplicationDidBecomeActiveNotification
|
||||
// whenever the application comes back from being inactive, trigger a 20s pairing scan and reconnect
|
||||
// any devices that may have paired while we were inactive.
|
||||
- (void)appDidBecomeActiveNotification:(NSNotification *)note
|
||||
{
|
||||
[self updateConnectedSteamControllers:true];
|
||||
[self startScan:20];
|
||||
}
|
||||
|
||||
- (int)updateConnectedSteamControllers:(BOOL) bForce
|
||||
{
|
||||
static uint64_t s_unLastUpdateTick = 0;
|
||||
static mach_timebase_info_data_t s_timebase_info;
|
||||
|
||||
if ( self.centralManager == nil )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s_timebase_info.denom == 0)
|
||||
{
|
||||
mach_timebase_info( &s_timebase_info );
|
||||
}
|
||||
|
||||
uint64_t ticksNow = mach_approximate_time();
|
||||
if ( !bForce && ( ( (ticksNow - s_unLastUpdateTick) * s_timebase_info.numer ) / s_timebase_info.denom ) < (5ull * NSEC_PER_SEC) )
|
||||
return (int)self.deviceMap.count;
|
||||
|
||||
// we can see previously connected BLE peripherals but can't connect until the CBCentralManager
|
||||
// is fully powered up - only do work when we are in that state
|
||||
if ( self.centralManager.state != CBManagerStatePoweredOn )
|
||||
return (int)self.deviceMap.count;
|
||||
|
||||
// only update our last-check-time if we actually did work, otherwise there can be a long delay during initial power-up
|
||||
s_unLastUpdateTick = mach_approximate_time();
|
||||
|
||||
// if a pair is in-flight, the central manager may still give it back via retrieveConnected... and
|
||||
// cause the SDL layer to attempt to initialize it while some of its endpoints haven't yet been established
|
||||
if ( self.nPendingPairs > 0 )
|
||||
return (int)self.deviceMap.count;
|
||||
|
||||
NSArray<CBPeripheral *> *peripherals = [self.centralManager retrieveConnectedPeripheralsWithServices: @[ [CBUUID UUIDWithString:@"180A"]]];
|
||||
for ( CBPeripheral *peripheral in peripherals )
|
||||
{
|
||||
// we already know this peripheral
|
||||
if ( [self.deviceMap objectForKey: peripheral] != nil )
|
||||
continue;
|
||||
|
||||
NSLog( @"connected peripheral: %@", peripheral );
|
||||
if ( [peripheral.name isEqualToString:@"SteamController"] )
|
||||
{
|
||||
self.nPendingPairs += 1;
|
||||
HIDBLEDevice *steamController = [[HIDBLEDevice alloc] initWithPeripheral:peripheral];
|
||||
[self.deviceMap setObject:steamController forKey:peripheral];
|
||||
[self.centralManager connectPeripheral:peripheral options:nil];
|
||||
}
|
||||
}
|
||||
|
||||
return (int)self.deviceMap.count;
|
||||
}
|
||||
|
||||
// manual API for folks to start & stop scanning
|
||||
- (void)startScan:(int)duration
|
||||
{
|
||||
if ( self.centralManager == nil )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSLog( @"BLE: requesting scan for %d seconds", duration );
|
||||
@synchronized (self)
|
||||
{
|
||||
if ( _nPendingScans++ == 0 )
|
||||
{
|
||||
[self.centralManager scanForPeripheralsWithServices:nil options:nil];
|
||||
}
|
||||
}
|
||||
|
||||
if ( duration != 0 )
|
||||
{
|
||||
dispatch_after( dispatch_time( DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
[self stopScan];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
- (void)stopScan
|
||||
{
|
||||
if ( self.centralManager == nil )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSLog( @"BLE: stopping scan" );
|
||||
@synchronized (self)
|
||||
{
|
||||
if ( --_nPendingScans <= 0 )
|
||||
{
|
||||
_nPendingScans = 0;
|
||||
[self.centralManager stopScan];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma mark CBCentralManagerDelegate Implementation
|
||||
|
||||
// called whenever the BLE hardware state changes.
|
||||
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
|
||||
{
|
||||
switch ( central.state )
|
||||
{
|
||||
case CBCentralManagerStatePoweredOn:
|
||||
{
|
||||
NSLog( @"CoreBluetooth BLE hardware is powered on and ready" );
|
||||
|
||||
// at startup, if we have no already attached peripherals, do a 20s scan for new unpaired devices,
|
||||
// otherwise callers should occaisionally do additional scans. we don't want to continuously be
|
||||
// scanning because it drains battery, causes other nearby people to have a hard time pairing their
|
||||
// Steam Controllers, and may also trigger firmware weirdness when a device attempts to start
|
||||
// the pairing sequence multiple times concurrently
|
||||
if ( [self updateConnectedSteamControllers:false] == 0 )
|
||||
{
|
||||
// TODO: we could limit our scan to only peripherals supporting the SteamController service, but
|
||||
// that service doesn't currently fit in the base advertising packet, we'd need to put it into an
|
||||
// extended scan packet. Useful optimization downstream, but not currently necessary
|
||||
// NSArray *services = @[[CBUUID UUIDWithString:VALVE_SERVICE]];
|
||||
[self startScan:20];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CBCentralManagerStatePoweredOff:
|
||||
NSLog( @"CoreBluetooth BLE hardware is powered off" );
|
||||
break;
|
||||
|
||||
case CBCentralManagerStateUnauthorized:
|
||||
NSLog( @"CoreBluetooth BLE state is unauthorized" );
|
||||
break;
|
||||
|
||||
case CBCentralManagerStateUnknown:
|
||||
NSLog( @"CoreBluetooth BLE state is unknown" );
|
||||
break;
|
||||
|
||||
case CBCentralManagerStateUnsupported:
|
||||
NSLog( @"CoreBluetooth BLE hardware is unsupported on this platform" );
|
||||
break;
|
||||
|
||||
case CBCentralManagerStateResetting:
|
||||
NSLog( @"CoreBluetooth BLE manager is resetting" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
|
||||
{
|
||||
HIDBLEDevice *steamController = [_deviceMap objectForKey:peripheral];
|
||||
steamController.connected = YES;
|
||||
self.nPendingPairs -= 1;
|
||||
}
|
||||
|
||||
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
|
||||
{
|
||||
NSLog( @"Failed to connect: %@", error );
|
||||
[_deviceMap removeObjectForKey:peripheral];
|
||||
self.nPendingPairs -= 1;
|
||||
}
|
||||
|
||||
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
|
||||
{
|
||||
NSString *localName = [advertisementData objectForKey:CBAdvertisementDataLocalNameKey];
|
||||
NSString *log = [NSString stringWithFormat:@"Found '%@'", localName];
|
||||
|
||||
if ( [localName isEqualToString:@"SteamController"] )
|
||||
{
|
||||
NSLog( @"%@ : %@ - %@", log, peripheral, advertisementData );
|
||||
self.nPendingPairs += 1;
|
||||
HIDBLEDevice *steamController = [[HIDBLEDevice alloc] initWithPeripheral:peripheral];
|
||||
[self.deviceMap setObject:steamController forKey:peripheral];
|
||||
[self.centralManager connectPeripheral:peripheral options:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
|
||||
{
|
||||
HIDBLEDevice *steamController = [self.deviceMap objectForKey:peripheral];
|
||||
if ( steamController )
|
||||
{
|
||||
steamController.connected = NO;
|
||||
steamController.ready = NO;
|
||||
[self.deviceMap removeObjectForKey:peripheral];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// Core Bluetooth devices calling back on event boundaries of their run-loops. so annoying.
|
||||
static void process_pending_events()
|
||||
{
|
||||
CFRunLoopRunResult res;
|
||||
do
|
||||
{
|
||||
res = CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0.001, FALSE );
|
||||
}
|
||||
while( res != kCFRunLoopRunFinished && res != kCFRunLoopRunTimedOut );
|
||||
}
|
||||
|
||||
@implementation HIDBLEDevice
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if ( self = [super init] )
|
||||
{
|
||||
RingBuffer_init( &_inputReports );
|
||||
self.bleSteamController = nil;
|
||||
self.bleCharacteristicInput = nil;
|
||||
self.bleCharacteristicReport = nil;
|
||||
_connected = NO;
|
||||
_ready = NO;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithPeripheral:(CBPeripheral *)peripheral
|
||||
{
|
||||
if ( self = [super init] )
|
||||
{
|
||||
RingBuffer_init( &_inputReports );
|
||||
_connected = NO;
|
||||
_ready = NO;
|
||||
self.bleSteamController = peripheral;
|
||||
if ( peripheral )
|
||||
{
|
||||
peripheral.delegate = self;
|
||||
}
|
||||
self.bleCharacteristicInput = nil;
|
||||
self.bleCharacteristicReport = nil;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setConnected:(bool)connected
|
||||
{
|
||||
_connected = connected;
|
||||
if ( _connected )
|
||||
{
|
||||
[_bleSteamController discoverServices:nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog( @"Disconnected" );
|
||||
}
|
||||
}
|
||||
|
||||
- (size_t)read_input_report:(uint8_t *)dst
|
||||
{
|
||||
if ( RingBuffer_read( &_inputReports, dst+1 ) )
|
||||
{
|
||||
*dst = 0x03;
|
||||
return 20;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (int)send_report:(const uint8_t *)data length:(size_t)length
|
||||
{
|
||||
[_bleSteamController writeValue:[NSData dataWithBytes:data length:length] forCharacteristic:_bleCharacteristicReport type:CBCharacteristicWriteWithResponse];
|
||||
return (int)length;
|
||||
}
|
||||
|
||||
- (int)send_feature_report:(hidFeatureReport *)report
|
||||
{
|
||||
#if FEATURE_REPORT_LOGGING
|
||||
uint8_t *reportBytes = (uint8_t *)report;
|
||||
|
||||
NSLog( @"HIDBLE:send_feature_report (%02zu/19) [%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x]", GetBluetoothSegmentSize( report->segment ),
|
||||
reportBytes[1], reportBytes[2], reportBytes[3], reportBytes[4], reportBytes[5], reportBytes[6],
|
||||
reportBytes[7], reportBytes[8], reportBytes[9], reportBytes[10], reportBytes[11], reportBytes[12],
|
||||
reportBytes[13], reportBytes[14], reportBytes[15], reportBytes[16], reportBytes[17], reportBytes[18],
|
||||
reportBytes[19] );
|
||||
#endif
|
||||
|
||||
int sendSize = (int)GetBluetoothSegmentSize( &report->segment );
|
||||
if ( sendSize > 20 )
|
||||
sendSize = 20;
|
||||
|
||||
#if 1
|
||||
// fire-and-forget - we are going to not wait for the response here because all Steam Controller BLE send_feature_report's are ignored,
|
||||
// except errors.
|
||||
[_bleSteamController writeValue:[NSData dataWithBytes:&report->segment length:sendSize] forCharacteristic:_bleCharacteristicReport type:CBCharacteristicWriteWithResponse];
|
||||
|
||||
// pretend we received a result anybody cares about
|
||||
return 19;
|
||||
|
||||
#else
|
||||
// this is technically the correct send_feature_report logic if you want to make sure it gets through and is
|
||||
// acknowledged or errors out
|
||||
_waitStateForWriteFeatureReport = BLEDeviceWaitState_Waiting;
|
||||
[_bleSteamController writeValue:[NSData dataWithBytes:&report->segment length:sendSize
|
||||
] forCharacteristic:_bleCharacteristicReport type:CBCharacteristicWriteWithResponse];
|
||||
|
||||
while ( _waitStateForWriteFeatureReport == BLEDeviceWaitState_Waiting )
|
||||
{
|
||||
process_pending_events();
|
||||
}
|
||||
|
||||
if ( _waitStateForWriteFeatureReport == BLEDeviceWaitState_Error )
|
||||
{
|
||||
_waitStateForWriteFeatureReport = BLEDeviceWaitState_None;
|
||||
return -1;
|
||||
}
|
||||
|
||||
_waitStateForWriteFeatureReport = BLEDeviceWaitState_None;
|
||||
return 19;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (int)get_feature_report:(uint8_t)feature into:(uint8_t *)buffer
|
||||
{
|
||||
_waitStateForReadFeatureReport = BLEDeviceWaitState_Waiting;
|
||||
[_bleSteamController readValueForCharacteristic:_bleCharacteristicReport];
|
||||
|
||||
while ( _waitStateForReadFeatureReport == BLEDeviceWaitState_Waiting )
|
||||
process_pending_events();
|
||||
|
||||
if ( _waitStateForReadFeatureReport == BLEDeviceWaitState_Error )
|
||||
{
|
||||
_waitStateForReadFeatureReport = BLEDeviceWaitState_None;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy( buffer, _featureReport, sizeof(_featureReport) );
|
||||
|
||||
_waitStateForReadFeatureReport = BLEDeviceWaitState_None;
|
||||
|
||||
#if FEATURE_REPORT_LOGGING
|
||||
NSLog( @"HIDBLE:get_feature_report (19) [%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x]",
|
||||
buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6],
|
||||
buffer[7], buffer[8], buffer[9], buffer[10], buffer[11], buffer[12],
|
||||
buffer[13], buffer[14], buffer[15], buffer[16], buffer[17], buffer[18],
|
||||
buffer[19] );
|
||||
#endif
|
||||
|
||||
return 19;
|
||||
}
|
||||
|
||||
#pragma mark CBPeripheralDelegate Implementation
|
||||
|
||||
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
|
||||
{
|
||||
for (CBService *service in peripheral.services)
|
||||
{
|
||||
NSLog( @"Found Service: %@", service );
|
||||
if ( [service.UUID isEqual:[CBUUID UUIDWithString:VALVE_SERVICE]] )
|
||||
{
|
||||
[peripheral discoverCharacteristics:nil forService:service];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
|
||||
{
|
||||
// nothing yet needed here, enable for logging
|
||||
if ( /* DISABLES CODE */ (0) )
|
||||
{
|
||||
for ( CBDescriptor *descriptor in characteristic.descriptors )
|
||||
{
|
||||
NSLog( @" - Descriptor '%@'", descriptor );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
|
||||
{
|
||||
if ([service.UUID isEqual:[CBUUID UUIDWithString:VALVE_SERVICE]])
|
||||
{
|
||||
for (CBCharacteristic *aChar in service.characteristics)
|
||||
{
|
||||
NSLog( @"Found Characteristic %@", aChar );
|
||||
|
||||
if ( [aChar.UUID isEqual:[CBUUID UUIDWithString:VALVE_INPUT_CHAR]] )
|
||||
{
|
||||
self.bleCharacteristicInput = aChar;
|
||||
}
|
||||
else if ( [aChar.UUID isEqual:[CBUUID UUIDWithString:VALVE_REPORT_CHAR]] )
|
||||
{
|
||||
self.bleCharacteristicReport = aChar;
|
||||
[self.bleSteamController discoverDescriptorsForCharacteristic: aChar];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
|
||||
{
|
||||
static uint64_t s_ticksLastOverflowReport = 0;
|
||||
|
||||
// receiving an input report is the final indicator that the user accepted a pairing
|
||||
// request and that we successfully established notification. CoreBluetooth has no
|
||||
// notification of the pairing acknowledgement, which is a bad oversight.
|
||||
if ( self.ready == NO )
|
||||
{
|
||||
self.ready = YES;
|
||||
HIDBLEManager.sharedInstance.nPendingPairs -= 1;
|
||||
}
|
||||
|
||||
if ( [characteristic.UUID isEqual:_bleCharacteristicInput.UUID] )
|
||||
{
|
||||
NSData *data = [characteristic value];
|
||||
if ( data.length != 19 )
|
||||
{
|
||||
NSLog( @"HIDBLE: incoming data is %lu bytes should be exactly 19", (unsigned long)data.length );
|
||||
}
|
||||
if ( !RingBuffer_write( &_inputReports, (const uint8_t *)data.bytes ) )
|
||||
{
|
||||
uint64_t ticksNow = mach_approximate_time();
|
||||
if ( ticksNow - s_ticksLastOverflowReport > (5ull * NSEC_PER_SEC / 10) )
|
||||
{
|
||||
NSLog( @"HIDBLE: input report buffer overflow" );
|
||||
s_ticksLastOverflowReport = ticksNow;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( [characteristic.UUID isEqual:_bleCharacteristicReport.UUID] )
|
||||
{
|
||||
memset( _featureReport, 0, sizeof(_featureReport) );
|
||||
|
||||
if ( error != nil )
|
||||
{
|
||||
NSLog( @"HIDBLE: get_feature_report error: %@", error );
|
||||
_waitStateForReadFeatureReport = BLEDeviceWaitState_Error;
|
||||
}
|
||||
else
|
||||
{
|
||||
NSData *data = [characteristic value];
|
||||
if ( data.length != 20 )
|
||||
{
|
||||
NSLog( @"HIDBLE: incoming data is %lu bytes should be exactly 20", (unsigned long)data.length );
|
||||
}
|
||||
memcpy( _featureReport, data.bytes, MIN( data.length, sizeof(_featureReport) ) );
|
||||
_waitStateForReadFeatureReport = BLEDeviceWaitState_Complete;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
|
||||
{
|
||||
if ( [characteristic.UUID isEqual:[CBUUID UUIDWithString:VALVE_REPORT_CHAR]] )
|
||||
{
|
||||
if ( error != nil )
|
||||
{
|
||||
NSLog( @"HIDBLE: write_feature_report error: %@", error );
|
||||
_waitStateForWriteFeatureReport = BLEDeviceWaitState_Error;
|
||||
}
|
||||
else
|
||||
{
|
||||
_waitStateForWriteFeatureReport = BLEDeviceWaitState_Complete;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
|
||||
{
|
||||
NSLog( @"didUpdateNotifcationStateForCharacteristic %@ (%@)", characteristic, error );
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#pragma mark hid_api implementation
|
||||
|
||||
struct hid_device_ {
|
||||
void *device_handle;
|
||||
int blocking;
|
||||
hid_device *next;
|
||||
};
|
||||
|
||||
int HID_API_EXPORT HID_API_CALL hid_init(void)
|
||||
{
|
||||
return ( HIDBLEManager.sharedInstance == nil ) ? -1 : 0;
|
||||
}
|
||||
|
||||
int HID_API_EXPORT HID_API_CALL hid_exit(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void HID_API_EXPORT HID_API_CALL hid_ble_scan( int bStart )
|
||||
{
|
||||
HIDBLEManager *bleManager = HIDBLEManager.sharedInstance;
|
||||
if ( bStart )
|
||||
{
|
||||
[bleManager startScan:0];
|
||||
}
|
||||
else
|
||||
{
|
||||
[bleManager stopScan];
|
||||
}
|
||||
}
|
||||
|
||||
HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HID_API_EXPORT hid_device * HID_API_CALL hid_open_path( const char *path, int bExclusive /* = false */ )
|
||||
{
|
||||
hid_device *result = NULL;
|
||||
NSString *nssPath = [NSString stringWithUTF8String:path];
|
||||
HIDBLEManager *bleManager = HIDBLEManager.sharedInstance;
|
||||
NSEnumerator<HIDBLEDevice *> *devices = [bleManager.deviceMap objectEnumerator];
|
||||
|
||||
for ( HIDBLEDevice *device in devices )
|
||||
{
|
||||
// we have the device but it hasn't found its service or characteristics until it is connected
|
||||
if ( !device.ready || !device.connected || !device.bleCharacteristicInput )
|
||||
continue;
|
||||
|
||||
if ( [device.bleSteamController.identifier.UUIDString isEqualToString:nssPath] )
|
||||
{
|
||||
result = (hid_device *)malloc( sizeof( hid_device ) );
|
||||
memset( result, 0, sizeof( hid_device ) );
|
||||
result->device_handle = (void*)CFBridgingRetain( device );
|
||||
result->blocking = NO;
|
||||
// enable reporting input events on the characteristic
|
||||
[device.bleSteamController setNotifyValue:YES forCharacteristic:device.bleCharacteristicInput];
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs)
|
||||
{
|
||||
/* This function is identical to the Linux version. Platform independent. */
|
||||
struct hid_device_info *d = devs;
|
||||
while (d) {
|
||||
struct hid_device_info *next = d->next;
|
||||
free(d->path);
|
||||
free(d->serial_number);
|
||||
free(d->manufacturer_string);
|
||||
free(d->product_string);
|
||||
free(d);
|
||||
d = next;
|
||||
}
|
||||
}
|
||||
|
||||
int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
|
||||
{
|
||||
/* All Nonblocking operation is handled by the library. */
|
||||
dev->blocking = !nonblock;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
|
||||
{ @autoreleasepool {
|
||||
struct hid_device_info *root = NULL;
|
||||
const char *hint = SDL_GetHint(SDL_HINT_HIDAPI_IGNORE_DEVICES);
|
||||
|
||||
/* See if there are any devices we should skip in enumeration */
|
||||
if (hint) {
|
||||
char vendor_match[16], product_match[16];
|
||||
SDL_snprintf(vendor_match, sizeof(vendor_match), "0x%.4x/0x0000", VALVE_USB_VID);
|
||||
SDL_snprintf(product_match, sizeof(product_match), "0x%.4x/0x%.4x", VALVE_USB_VID, D0G_BLE2_PID);
|
||||
if (SDL_strcasestr(hint, vendor_match) || SDL_strcasestr(hint, product_match)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ( vendor_id == 0 && product_id == 0 ) ||
|
||||
( vendor_id == VALVE_USB_VID && product_id == D0G_BLE2_PID ) )
|
||||
{
|
||||
HIDBLEManager *bleManager = HIDBLEManager.sharedInstance;
|
||||
[bleManager updateConnectedSteamControllers:false];
|
||||
NSEnumerator<HIDBLEDevice *> *devices = [bleManager.deviceMap objectEnumerator];
|
||||
for ( HIDBLEDevice *device in devices )
|
||||
{
|
||||
// there are several brief windows in connecting to an already paired device and
|
||||
// one long window waiting for users to confirm pairing where we don't want
|
||||
// to consider a device ready - if we hand it back to SDL or another
|
||||
// Steam Controller consumer, their additional SC setup work will fail
|
||||
// in unusual/silent ways and we can actually corrupt the BLE stack for
|
||||
// the entire system and kill the appletv remote's Menu button (!)
|
||||
if ( device.bleSteamController.state != CBPeripheralStateConnected ||
|
||||
device.connected == NO || device.ready == NO )
|
||||
{
|
||||
if ( device.ready == NO && device.bleCharacteristicInput != nil )
|
||||
{
|
||||
// attempt to register for input reports. this call will silently fail
|
||||
// until the pairing finalizes with user acceptance. oh, apple.
|
||||
[device.bleSteamController setNotifyValue:YES forCharacteristic:device.bleCharacteristicInput];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
struct hid_device_info *device_info = (struct hid_device_info *)malloc( sizeof(struct hid_device_info) );
|
||||
memset( device_info, 0, sizeof(struct hid_device_info) );
|
||||
device_info->next = root;
|
||||
root = device_info;
|
||||
device_info->path = strdup( device.bleSteamController.identifier.UUIDString.UTF8String );
|
||||
device_info->vendor_id = VALVE_USB_VID;
|
||||
device_info->product_id = D0G_BLE2_PID;
|
||||
device_info->product_string = wcsdup( L"Steam Controller" );
|
||||
device_info->manufacturer_string = wcsdup( L"Valve Corporation" );
|
||||
}
|
||||
}
|
||||
return root;
|
||||
}}
|
||||
|
||||
int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
|
||||
{
|
||||
static wchar_t s_wszManufacturer[] = L"Valve Corporation";
|
||||
wcsncpy( string, s_wszManufacturer, sizeof(s_wszManufacturer)/sizeof(s_wszManufacturer[0]) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
|
||||
{
|
||||
static wchar_t s_wszProduct[] = L"Steam Controller";
|
||||
wcsncpy( string, s_wszProduct, sizeof(s_wszProduct)/sizeof(s_wszProduct[0]) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
|
||||
{
|
||||
static wchar_t s_wszSerial[] = L"12345";
|
||||
wcsncpy( string, s_wszSerial, sizeof(s_wszSerial)/sizeof(s_wszSerial[0]) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length)
|
||||
{
|
||||
HIDBLEDevice *device_handle = (__bridge HIDBLEDevice *)dev->device_handle;
|
||||
|
||||
if ( !device_handle.connected )
|
||||
return -1;
|
||||
|
||||
return [device_handle send_report:data length:length];
|
||||
}
|
||||
|
||||
void HID_API_EXPORT hid_close(hid_device *dev)
|
||||
{
|
||||
HIDBLEDevice *device_handle = CFBridgingRelease( dev->device_handle );
|
||||
|
||||
// disable reporting input events on the characteristic
|
||||
if ( device_handle.connected ) {
|
||||
[device_handle.bleSteamController setNotifyValue:NO forCharacteristic:device_handle.bleCharacteristicInput];
|
||||
}
|
||||
|
||||
free( dev );
|
||||
}
|
||||
|
||||
int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
|
||||
{
|
||||
HIDBLEDevice *device_handle = (__bridge HIDBLEDevice *)dev->device_handle;
|
||||
|
||||
if ( !device_handle.connected )
|
||||
return -1;
|
||||
|
||||
return [device_handle send_feature_report:(hidFeatureReport *)(void *)data];
|
||||
}
|
||||
|
||||
int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
|
||||
{
|
||||
HIDBLEDevice *device_handle = (__bridge HIDBLEDevice *)dev->device_handle;
|
||||
|
||||
if ( !device_handle.connected )
|
||||
return -1;
|
||||
|
||||
size_t written = [device_handle get_feature_report:data[0] into:data];
|
||||
|
||||
return written == length-1 ? (int)length : (int)written;
|
||||
}
|
||||
|
||||
int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length)
|
||||
{
|
||||
HIDBLEDevice *device_handle = (__bridge HIDBLEDevice *)dev->device_handle;
|
||||
|
||||
if ( !device_handle.connected )
|
||||
return -1;
|
||||
|
||||
return hid_read_timeout(dev, data, length, 0);
|
||||
}
|
||||
|
||||
int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
|
||||
{
|
||||
HIDBLEDevice *device_handle = (__bridge HIDBLEDevice *)dev->device_handle;
|
||||
|
||||
if ( !device_handle.connected )
|
||||
return -1;
|
||||
|
||||
if ( milliseconds != 0 )
|
||||
{
|
||||
NSLog( @"hid_read_timeout with non-zero wait" );
|
||||
}
|
||||
int result = (int)[device_handle read_input_report:data];
|
||||
#if FEATURE_REPORT_LOGGING
|
||||
NSLog( @"HIDBLE:hid_read_timeout (%d) [%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x]", result,
|
||||
data[1], data[2], data[3], data[4], data[5], data[6],
|
||||
data[7], data[8], data[9], data[10], data[11], data[12],
|
||||
data[13], data[14], data[15], data[16], data[17], data[18],
|
||||
data[19] );
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *dev)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* !SDL_HIDAPI_DISABLED */
|
|
@ -0,0 +1,8 @@
|
|||
*.o
|
||||
*.so
|
||||
*.la
|
||||
*.lo
|
||||
*.a
|
||||
.libs
|
||||
.deps
|
||||
hidtest-libusb
|
|
@ -0,0 +1,107 @@
|
|||
cmake_minimum_required(VERSION 3.6.3 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 additiona 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")
|
|
@ -10,6 +10,10 @@ ifeq ($(OS), FreeBSD)
|
|||
FILE=Makefile.freebsd
|
||||
endif
|
||||
|
||||
ifeq ($(OS), Haiku)
|
||||
FILE=Makefile.haiku
|
||||
endif
|
||||
|
||||
ifeq ($(FILE), )
|
||||
all:
|
||||
$(error Your platform ${OS} is not supported by hidapi/libusb at this time.)
|
||||
|
|
|
@ -21,7 +21,14 @@ libhidapi_la_LDFLAGS = $(LTLDFLAGS)
|
|||
libhidapi_la_LIBADD = $(LIBS_LIBUSB)
|
||||
endif
|
||||
|
||||
if OS_HAIKU
|
||||
lib_LTLIBRARIES = libhidapi.la
|
||||
libhidapi_la_SOURCES = hid.c
|
||||
libhidapi_la_LDFLAGS = $(LTLDFLAGS)
|
||||
libhidapi_la_LIBADD = $(LIBS_LIBUSB)
|
||||
endif
|
||||
|
||||
hdrdir = $(includedir)/hidapi
|
||||
hdr_HEADERS = $(top_srcdir)/hidapi/hidapi.h
|
||||
hdr_HEADERS = $(top_srcdir)/hidapi/hidapi.h hidapi_libusb.h
|
||||
|
||||
EXTRA_DIST = Makefile-manual
|
||||
|
|
|
@ -13,20 +13,16 @@ libs: libhidapi.so
|
|||
CC ?= cc
|
||||
CFLAGS ?= -Wall -g -fPIC
|
||||
|
||||
CXX ?= c++
|
||||
CXXFLAGS ?= -Wall -g
|
||||
|
||||
COBJS = hid.o
|
||||
CPPOBJS = ../hidtest/hidtest.o
|
||||
OBJS = $(COBJS) $(CPPOBJS)
|
||||
INCLUDES = -I../hidapi -I/usr/local/include
|
||||
COBJS = hid.o ../hidtest/test.o
|
||||
OBJS = $(COBJS)
|
||||
INCLUDES = -I../hidapi -I. -I/usr/local/include
|
||||
LDFLAGS = -L/usr/local/lib
|
||||
LIBS = -lusb -liconv -pthread
|
||||
|
||||
|
||||
# Console Test Program
|
||||
hidtest: $(OBJS)
|
||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS)
|
||||
|
||||
# Shared Libs
|
||||
libhidapi.so: $(COBJS)
|
||||
|
@ -36,9 +32,6 @@ libhidapi.so: $(COBJS)
|
|||
$(COBJS): %.o: %.c
|
||||
$(CC) $(CFLAGS) -c $(INCLUDES) $< -o $@
|
||||
|
||||
$(CPPOBJS): %.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c $(INCLUDES) $< -o $@
|
||||
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) hidtest libhidapi.so ../hidtest/hidtest.o
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
###########################################
|
||||
# Simple Makefile for HIDAPI test program
|
||||
#
|
||||
# Alan Ott
|
||||
# Signal 11 Software
|
||||
# 2010-06-01
|
||||
###########################################
|
||||
|
||||
all: hidtest libs
|
||||
|
||||
libs: libhidapi.so
|
||||
|
||||
CC ?= cc
|
||||
CFLAGS ?= -Wall -g -fPIC
|
||||
|
||||
COBJS = hid.o ../hidtest/test.o
|
||||
OBJS = $(COBJS)
|
||||
INCLUDES = -I../hidapi -I. -I/usr/local/include
|
||||
LDFLAGS = -L/usr/local/lib
|
||||
LIBS = -lusb -liconv -pthread
|
||||
|
||||
|
||||
# Console Test Program
|
||||
hidtest: $(OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS)
|
||||
|
||||
# Shared Libs
|
||||
libhidapi.so: $(COBJS)
|
||||
$(CC) $(LDFLAGS) -shared -Wl,-soname,$@.0 $^ -o $@ $(LIBS)
|
||||
|
||||
# Objects
|
||||
$(COBJS): %.o: %.c
|
||||
$(CC) $(CFLAGS) -c $(INCLUDES) $< -o $@
|
||||
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) hidtest libhidapi.so ../hidtest/hidtest.o
|
||||
|
||||
.PHONY: clean libs
|
|
@ -13,23 +13,19 @@ libs: libhidapi-libusb.so
|
|||
CC ?= gcc
|
||||
CFLAGS ?= -Wall -g -fpic
|
||||
|
||||
CXX ?= g++
|
||||
CXXFLAGS ?= -Wall -g -fpic
|
||||
|
||||
LDFLAGS ?= -Wall -g
|
||||
|
||||
COBJS_LIBUSB = hid.o
|
||||
COBJS = $(COBJS_LIBUSB)
|
||||
CPPOBJS = ../hidtest/hidtest.o
|
||||
OBJS = $(COBJS) $(CPPOBJS)
|
||||
COBJS = $(COBJS_LIBUSB) ../hidtest/test.o
|
||||
OBJS = $(COBJS)
|
||||
LIBS_USB = `pkg-config libusb-1.0 --libs` -lrt -lpthread
|
||||
LIBS = $(LIBS_USB)
|
||||
INCLUDES ?= -I../hidapi `pkg-config libusb-1.0 --cflags`
|
||||
INCLUDES ?= -I../hidapi -I. `pkg-config libusb-1.0 --cflags`
|
||||
|
||||
|
||||
# Console Test Program
|
||||
hidtest-libusb: $(COBJS_LIBUSB) $(CPPOBJS)
|
||||
$(CXX) $(LDFLAGS) $^ $(LIBS_USB) -o $@
|
||||
hidtest-libusb: $(COBJS)
|
||||
$(CC) $(LDFLAGS) $^ $(LIBS_USB) -o $@
|
||||
|
||||
# Shared Libs
|
||||
libhidapi-libusb.so: $(COBJS_LIBUSB)
|
||||
|
@ -39,9 +35,6 @@ libhidapi-libusb.so: $(COBJS_LIBUSB)
|
|||
$(COBJS): %.o: %.c
|
||||
$(CC) $(CFLAGS) -c $(INCLUDES) $< -o $@
|
||||
|
||||
$(CPPOBJS): %.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c $(INCLUDES) $< -o $@
|
||||
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) hidtest-libusb libhidapi-libusb.so ../hidtest/hidtest.o
|
||||
|
|
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.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
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
#define NAMESPACE HIDUSB
|
||||
#include "hid.c"
|
|
@ -0,0 +1,18 @@
|
|||
Debug
|
||||
Release
|
||||
*.exp
|
||||
*.ilk
|
||||
*.lib
|
||||
*.suo
|
||||
*.vcproj.*
|
||||
*.ncb
|
||||
*.suo
|
||||
*.dll
|
||||
*.pdb
|
||||
*.o
|
||||
*.so
|
||||
hidtest-hidraw
|
||||
.deps
|
||||
.libs
|
||||
*.lo
|
||||
*.la
|
|
@ -0,0 +1,38 @@
|
|||
cmake_minimum_required(VERSION 3.6.3 FATAL_ERROR)
|
||||
|
||||
add_library(hidapi_hidraw
|
||||
${HIDAPI_PUBLIC_HEADERS}
|
||||
hid.c
|
||||
)
|
||||
target_link_libraries(hidapi_hidraw PUBLIC hidapi_include)
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
include(FindPkgConfig)
|
||||
pkg_check_modules(libudev REQUIRED IMPORTED_TARGET libudev)
|
||||
|
||||
target_link_libraries(hidapi_hidraw PRIVATE PkgConfig::libudev Threads::Threads)
|
||||
|
||||
set_target_properties(hidapi_hidraw
|
||||
PROPERTIES
|
||||
EXPORT_NAME "hidraw"
|
||||
OUTPUT_NAME "hidapi-hidraw"
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
PUBLIC_HEADER "${HIDAPI_PUBLIC_HEADERS}"
|
||||
)
|
||||
|
||||
# compatibility with find_package()
|
||||
add_library(hidapi::hidraw ALIAS hidapi_hidraw)
|
||||
# compatibility with raw library link
|
||||
add_library(hidapi-hidraw ALIAS hidapi_hidraw)
|
||||
|
||||
if(HIDAPI_INSTALL_TARGETS)
|
||||
install(TARGETS hidapi_hidraw 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-hidraw.pc.in")
|
|
@ -13,23 +13,19 @@ libs: libhidapi-hidraw.so
|
|||
CC ?= gcc
|
||||
CFLAGS ?= -Wall -g -fpic
|
||||
|
||||
CXX ?= g++
|
||||
CXXFLAGS ?= -Wall -g -fpic
|
||||
|
||||
LDFLAGS ?= -Wall -g
|
||||
|
||||
|
||||
COBJS = hid.o
|
||||
CPPOBJS = ../hidtest/hidtest.o
|
||||
OBJS = $(COBJS) $(CPPOBJS)
|
||||
COBJS = hid.o ../hidtest/test.o
|
||||
OBJS = $(COBJS)
|
||||
LIBS_UDEV = `pkg-config libudev --libs` -lrt
|
||||
LIBS = $(LIBS_UDEV)
|
||||
INCLUDES ?= -I../hidapi `pkg-config libusb-1.0 --cflags`
|
||||
|
||||
|
||||
# Console Test Program
|
||||
hidtest-hidraw: $(COBJS) $(CPPOBJS)
|
||||
$(CXX) $(LDFLAGS) $^ $(LIBS_UDEV) -o $@
|
||||
hidtest-hidraw: $(COBJS)
|
||||
$(CC) $(LDFLAGS) $^ $(LIBS_UDEV) -o $@
|
||||
|
||||
# Shared Libs
|
||||
libhidapi-hidraw.so: $(COBJS)
|
||||
|
@ -39,11 +35,8 @@ libhidapi-hidraw.so: $(COBJS)
|
|||
$(COBJS): %.o: %.c
|
||||
$(CC) $(CFLAGS) -c $(INCLUDES) $< -o $@
|
||||
|
||||
$(CPPOBJS): %.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c $(INCLUDES) $< -o $@
|
||||
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) hidtest-hidraw libhidapi-hidraw.so ../hidtest/hidtest.o
|
||||
rm -f $(OBJS) hidtest-hidraw libhidapi-hidraw.so $(COBJS)
|
||||
|
||||
.PHONY: clean libs
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
|
||||
There are two implementations of HIDAPI for Linux. One (linux/hid.c) uses the
|
||||
Linux hidraw driver, and the other (libusb/hid.c) uses libusb. Which one you
|
||||
use depends on your application. Complete functionality of the hidraw
|
||||
version depends on patches to the Linux kernel which are not currently in
|
||||
the mainline. These patches have to do with sending and receiving feature
|
||||
reports. The libusb implementation uses libusb to talk directly to the
|
||||
device, bypassing any Linux HID driver. The disadvantage of the libusb
|
||||
version is that it will only work with USB devices, while the hidraw
|
||||
implementation will work with Bluetooth devices as well.
|
||||
|
||||
To use HIDAPI, simply drop either linux/hid.c or libusb/hid.c into your
|
||||
application and build using the build parameters in the Makefile.
|
||||
|
||||
|
||||
Libusb Implementation notes
|
||||
----------------------------
|
||||
For the libusb implementation, libusb-1.0 must be installed. Libusb 1.0 is
|
||||
different than the legacy libusb 0.1 which is installed on many systems. To
|
||||
install libusb-1.0 on Ubuntu and other Debian-based systems, run:
|
||||
sudo apt-get install libusb-1.0-0-dev
|
||||
|
||||
|
||||
Hidraw Implementation notes
|
||||
----------------------------
|
||||
For the hidraw implementation, libudev headers and libraries are required to
|
||||
build hidapi programs. To install libudev libraries on Ubuntu,
|
||||
and other Debian-based systems, run:
|
||||
sudo apt-get install libudev-dev
|
||||
|
||||
On Redhat-based systems, run the following as root:
|
||||
yum install libudev-devel
|
||||
|
||||
Unfortunately, the hidraw driver, which the linux version of hidapi is based
|
||||
on, contains bugs in kernel versions < 2.6.36, which the client application
|
||||
should be aware of.
|
||||
|
||||
Bugs (hidraw implementation only):
|
||||
-----------------------------------
|
||||
On Kernel versions < 2.6.34, if your device uses numbered reports, an extra
|
||||
byte will be returned at the beginning of all reports returned from read()
|
||||
for hidraw devices. This is worked around in the library. No action should be
|
||||
necessary in the client library.
|
||||
|
||||
On Kernel versions < 2.6.35, reports will only be sent using a Set_Report
|
||||
transfer on the CONTROL endpoint. No data will ever be sent on an Interrupt
|
||||
Out endpoint if one exists. This is fixed in 2.6.35. In 2.6.35, OUTPUT
|
||||
reports will be sent to the device on the first INTERRUPT OUT endpoint if it
|
||||
exists; If it does not exist, OUTPUT reports will be sent on the CONTROL
|
||||
endpoint.
|
||||
|
||||
On Kernel versions < 2.6.36, add an extra byte containing the report number
|
||||
to sent reports if numbered reports are used, and the device does not
|
||||
contain an INTERRPUT OUT endpoint for OUTPUT transfers. For example, if
|
||||
your device uses numbered reports and wants to send {0x2 0xff 0xff 0xff} to
|
||||
the device (0x2 is the report number), you must send {0x2 0x2 0xff 0xff
|
||||
0xff}. If your device has the optional Interrupt OUT endpoint, this does not
|
||||
apply (but really on 2.6.35 only, because 2.6.34 won't use the interrupt
|
||||
out endpoint).
|
File diff suppressed because it is too large
Load Diff
|
@ -1,3 +0,0 @@
|
|||
|
||||
#define NAMESPACE HIDRAW
|
||||
#include "hid.c"
|
|
@ -0,0 +1,5 @@
|
|||
# Ignore All, except pkg.m4, and of course this file.
|
||||
*
|
||||
!.gitignore
|
||||
!pkg.m4
|
||||
!ax_pthread.m4
|
|
@ -0,0 +1,17 @@
|
|||
Debug
|
||||
Release
|
||||
*.exp
|
||||
*.ilk
|
||||
*.lib
|
||||
*.suo
|
||||
*.vcproj.*
|
||||
*.ncb
|
||||
*.suo
|
||||
*.dll
|
||||
*.pdb
|
||||
*.o
|
||||
hidapi-hidtest
|
||||
.deps
|
||||
.libs
|
||||
*.la
|
||||
*.lo
|
|
@ -0,0 +1,48 @@
|
|||
cmake_minimum_required(VERSION 3.4.3 FATAL_ERROR)
|
||||
|
||||
list(APPEND HIDAPI_PUBLIC_HEADERS "hidapi_darwin.h")
|
||||
|
||||
add_library(hidapi_darwin
|
||||
${HIDAPI_PUBLIC_HEADERS}
|
||||
hid.c
|
||||
)
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
target_link_libraries(hidapi_darwin
|
||||
PUBLIC hidapi_include
|
||||
PRIVATE Threads::Threads
|
||||
PRIVATE "-framework IOKit" "-framework CoreFoundation" "-framework AppKit"
|
||||
)
|
||||
|
||||
set_target_properties(hidapi_darwin
|
||||
PROPERTIES
|
||||
EXPORT_NAME "darwin"
|
||||
OUTPUT_NAME "hidapi"
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
MACHO_COMPATIBILITY_VERSION ${PROJECT_VERSION_MAJOR}
|
||||
FRAMEWORK_VERSION ${PROJECT_VERSION_MAJOR}
|
||||
PUBLIC_HEADER "${HIDAPI_PUBLIC_HEADERS}"
|
||||
)
|
||||
|
||||
# compatibility with find_package()
|
||||
add_library(hidapi::darwin ALIAS hidapi_darwin)
|
||||
# compatibility with raw library link
|
||||
add_library(hidapi ALIAS hidapi_darwin)
|
||||
|
||||
set(PUBLIC_HEADER_DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
if(NOT CMAKE_FRAMEWORK)
|
||||
set(PUBLIC_HEADER_DESTINATION "${PUBLIC_HEADER_DESTINATION}/hidapi")
|
||||
endif()
|
||||
|
||||
if(HIDAPI_INSTALL_TARGETS)
|
||||
install(TARGETS hidapi_darwin EXPORT hidapi
|
||||
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
FRAMEWORK DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
PUBLIC_HEADER DESTINATION "${PUBLIC_HEADER_DESTINATION}"
|
||||
)
|
||||
endif()
|
||||
|
||||
hidapi_configure_pc("${PROJECT_ROOT}/pc/hidapi.pc.in")
|
|
@ -9,24 +9,19 @@
|
|||
all: hidtest
|
||||
|
||||
CC=gcc
|
||||
CXX=g++
|
||||
COBJS=hid.o
|
||||
CPPOBJS=../hidtest/hidtest.o
|
||||
OBJS=$(COBJS) $(CPPOBJS)
|
||||
CFLAGS+=-I../hidapi -Wall -g -c
|
||||
LIBS=-framework IOKit -framework CoreFoundation
|
||||
COBJS=hid.o ../hidtest/test.o
|
||||
OBJS=$(COBJS)
|
||||
CFLAGS+=-I../hidapi -I. -Wall -g -c
|
||||
LIBS=-framework IOKit -framework CoreFoundation -framework AppKit
|
||||
|
||||
|
||||
hidtest: $(OBJS)
|
||||
g++ -Wall -g $^ $(LIBS) -o hidtest
|
||||
$(CC) -Wall -g $^ $(LIBS) -o hidtest
|
||||
|
||||
$(COBJS): %.o: %.c
|
||||
$(CC) $(CFLAGS) $< -o $@
|
||||
|
||||
$(CPPOBJS): %.o: %.cpp
|
||||
$(CXX) $(CFLAGS) $< -o $@
|
||||
|
||||
clean:
|
||||
rm -f *.o hidtest $(CPPOBJS)
|
||||
rm -f *.o hidtest
|
||||
|
||||
.PHONY: clean
|
||||
|
|
1655
src/hidapi/mac/hid.c
1655
src/hidapi/mac/hid.c
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,98 @@
|
|||
/*******************************************************
|
||||
HIDAPI - Multi-Platform library for
|
||||
communication with HID devices.
|
||||
|
||||
libusb/hidapi Team
|
||||
|
||||
Copyright 2022, 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.12.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
|
||||
*/
|
||||
|
||||
#ifndef HIDAPI_DARWIN_H__
|
||||
#define HIDAPI_DARWIN_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "hidapi.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Get the location ID for a HID device.
|
||||
|
||||
Since version 0.12.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
|
||||
|
||||
@ingroup API
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param location_id The device's location ID on return.
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_darwin_get_location_id(hid_device *dev, uint32_t *location_id);
|
||||
|
||||
|
||||
/** @brief Changes the behavior of all further calls to @ref hid_open or @ref hid_open_path.
|
||||
|
||||
By default on Darwin platform all devices opened by HIDAPI with @ref hid_open or @ref hid_open_path
|
||||
are opened in exclusive mode (see kIOHIDOptionsTypeSeizeDevice).
|
||||
|
||||
Since version 0.12.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
|
||||
|
||||
@ingroup API
|
||||
@param open_exclusive When set to 0 - all further devices will be opened
|
||||
in non-exclusive mode. Otherwise - all further devices will be opened
|
||||
in exclusive mode.
|
||||
|
||||
@note During the initialisation by @ref hid_init - this property is set to 1 (TRUE).
|
||||
This is done to preserve full backward compatibility with previous behavior.
|
||||
|
||||
@note Calling this function before @ref hid_init or after @ref hid_exit has no effect.
|
||||
*/
|
||||
void HID_API_EXPORT_CALL hid_darwin_set_open_exclusive(int open_exclusive);
|
||||
|
||||
/** @brief Getter for option set by @ref hid_darwin_set_open_exclusive.
|
||||
|
||||
Since version 0.12.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
|
||||
|
||||
@ingroup API
|
||||
@return 1 if all further devices will be opened in exclusive mode.
|
||||
|
||||
@note Value returned by this function before calling to @ref hid_init or after @ref hid_exit
|
||||
is not reliable.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_darwin_get_open_exclusive(void);
|
||||
|
||||
/** @brief Check how the device was opened.
|
||||
|
||||
Since version 0.12.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
|
||||
|
||||
@ingroup API
|
||||
@param dev A device to get property from.
|
||||
|
||||
@return 1 if the device is opened in exclusive mode, 0 - opened in non-exclusive,
|
||||
-1 - if dev is invalid.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_darwin_is_device_open_exclusive(hid_device *dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,22 @@
|
|||
project('hidapi', meson_version: '>=0.57.0', version: files('VERSION'))
|
||||
|
||||
cmake = import('cmake')
|
||||
|
||||
hidapi_build_options = cmake.subproject_options()
|
||||
hidapi_build_options.set_install(true)
|
||||
|
||||
hidapi_build = cmake.subproject('hidapi_build_cmake', options: hidapi_build_options)
|
||||
|
||||
if (hidapi_build.target_list().contains('hidapi_winapi'))
|
||||
hidapi_winapi_dep = hidapi_build.dependency('hidapi_winapi')
|
||||
hidapi_dep = hidapi_winapi_dep
|
||||
elif (hidapi_build.target_list().contains('hidapi_darwin'))
|
||||
hidapi_darwin_dep = hidapi_build.dependency('hidapi_darwin')
|
||||
hidapi_dep = hidapi_darwin_dep
|
||||
elif (hidapi_build.target_list().contains('hidapi_hidraw'))
|
||||
hidapi_hidraw_dep = hidapi_build.dependency('hidapi_hidraw')
|
||||
hidapi_dep = hidapi_hidraw_dep
|
||||
elif (hidapi_build.target_list().contains('hidapi_libusb'))
|
||||
hidapi_libusb_dep = hidapi_build.dependency('hidapi_libusb')
|
||||
hidapi_dep = hidapi_libusb_dep
|
||||
endif
|
|
@ -0,0 +1 @@
|
|||
*.pc
|
|
@ -5,6 +5,7 @@ includedir=@includedir@
|
|||
|
||||
Name: hidapi-hidraw
|
||||
Description: C Library for USB/Bluetooth HID device access from Linux, Mac OS X, FreeBSD, and Windows. This is the hidraw implementation.
|
||||
URL: https://github.com/libusb/hidapi
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} -lhidapi-hidraw
|
||||
Cflags: -I${includedir}/hidapi
|
||||
|
|
|
@ -5,6 +5,7 @@ includedir=@includedir@
|
|||
|
||||
Name: hidapi-libusb
|
||||
Description: C Library for USB HID device access from Linux, Mac OS X, FreeBSD, and Windows. This is the libusb implementation.
|
||||
URL: https://github.com/libusb/hidapi
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} -lhidapi-libusb
|
||||
Cflags: -I${includedir}/hidapi
|
||||
|
|
|
@ -5,6 +5,7 @@ includedir=@includedir@
|
|||
|
||||
Name: hidapi
|
||||
Description: C Library for USB/Bluetooth HID device access from Linux, Mac OS X, FreeBSD, and Windows.
|
||||
URL: https://github.com/libusb/hidapi
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} -lhidapi
|
||||
Cflags: -I${includedir}/hidapi
|
||||
|
|
|
@ -0,0 +1,193 @@
|
|||
get_filename_component(PROJECT_ROOT "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE)
|
||||
|
||||
# Read version from file
|
||||
file(READ "${PROJECT_ROOT}/VERSION" RAW_VERSION_STR)
|
||||
string(REGEX MATCH "^([0-9]+\\.[0-9]+\\.[0-9]+)(.*)" VERSION_STR "${RAW_VERSION_STR}")
|
||||
|
||||
if(NOT VERSION_STR)
|
||||
message(FATAL_ERROR "Broken VERSION file, couldn't parse '${PROJECT_ROOT}/VERSION' with content: '${RAW_VERSION_STR}'")
|
||||
endif()
|
||||
|
||||
set(VERSION "${CMAKE_MATCH_1}")
|
||||
string(STRIP "${CMAKE_MATCH_2}" VERSION_SUFFIX)
|
||||
# compatibility with find_package() vs add_subdirectory
|
||||
set(hidapi_VERSION "${VERSION}" PARENT_SCOPE)
|
||||
#
|
||||
|
||||
if(DEFINED HIDAPI_PRINT_VERSION AND HIDAPI_PRINT_VERSION)
|
||||
set(HIDAPI_PRINT_VERSION "hidapi: v${VERSION}")
|
||||
if(VERSION_SUFFIX)
|
||||
set(HIDAPI_PRINT_VERSION "${HIDAPI_PRINT_VERSION} (${VERSION_SUFFIX})")
|
||||
endif()
|
||||
message(STATUS "${HIDAPI_PRINT_VERSION}")
|
||||
endif()
|
||||
|
||||
project(hidapi VERSION "${VERSION}" LANGUAGES C)
|
||||
|
||||
# Defaults and required options
|
||||
|
||||
if(NOT DEFINED HIDAPI_WITH_TESTS)
|
||||
set(HIDAPI_WITH_TESTS OFF)
|
||||
endif()
|
||||
if(NOT DEFINED BUILD_SHARED_LIBS)
|
||||
set(BUILD_SHARED_LIBS ON)
|
||||
endif()
|
||||
if(NOT DEFINED HIDAPI_INSTALL_TARGETS)
|
||||
set(HIDAPI_INSTALL_TARGETS OFF)
|
||||
endif()
|
||||
if(NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
endif()
|
||||
|
||||
get_directory_property(IS_EXCLUDE_FROM_ALL EXCLUDE_FROM_ALL)
|
||||
if(IS_EXCLUDE_FROM_ALL)
|
||||
if(HIDAPI_INSTALL_TARGETS)
|
||||
message(WARNING "Installing EXCLUDE_FROM_ALL targets in an undefined behavior in CMake.\nDon't add 'hidapi' sundirectory with 'EXCLUDE_FROM_ALL' property, or don't set 'HIDAPI_INSTALL_TARGETS' to TRUE.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Helper(s)
|
||||
|
||||
function(hidapi_configure_pc PC_IN_FILE)
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/pc")
|
||||
|
||||
set(VERSION "${VERSION}${VERSION_SUFFIX}")
|
||||
set(prefix "${CMAKE_INSTALL_PREFIX}")
|
||||
set(exec_prefix "\${prefix}")
|
||||
if(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}")
|
||||
set(libdir "${CMAKE_INSTALL_LIBDIR}")
|
||||
else()
|
||||
set(libdir "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}")
|
||||
endif()
|
||||
if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
set(includedir "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
else()
|
||||
set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
endif()
|
||||
|
||||
get_filename_component(PC_IN_FILENAME "${PC_IN_FILE}" NAME_WE)
|
||||
set(PC_FILE "${CMAKE_CURRENT_BINARY_DIR}/pc/${PC_IN_FILENAME}.pc")
|
||||
configure_file("${PC_IN_FILE}" "${PC_FILE}" @ONLY)
|
||||
|
||||
install(FILES "${PC_FILE}" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig/")
|
||||
endfunction()
|
||||
|
||||
# The library
|
||||
|
||||
if(HIDAPI_INSTALL_TARGETS)
|
||||
include(GNUInstallDirs)
|
||||
endif()
|
||||
|
||||
add_library(hidapi_include INTERFACE)
|
||||
target_include_directories(hidapi_include INTERFACE
|
||||
"$<BUILD_INTERFACE:${PROJECT_ROOT}/hidapi>"
|
||||
)
|
||||
if(APPLE AND CMAKE_FRAMEWORK)
|
||||
# FIXME: https://github.com/libusb/hidapi/issues/492: it is untrivial to set the include path for Framework correctly
|
||||
else()
|
||||
target_include_directories(hidapi_include INTERFACE
|
||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/hidapi>"
|
||||
)
|
||||
endif()
|
||||
set_target_properties(hidapi_include PROPERTIES EXPORT_NAME "include")
|
||||
set(HIDAPI_PUBLIC_HEADERS "${PROJECT_ROOT}/hidapi/hidapi.h")
|
||||
|
||||
add_library(hidapi::include ALIAS hidapi_include)
|
||||
|
||||
if(HIDAPI_INSTALL_TARGETS)
|
||||
install(TARGETS hidapi_include EXPORT hidapi)
|
||||
endif()
|
||||
|
||||
set(EXPORT_ALIAS)
|
||||
set(EXPORT_COMPONENTS)
|
||||
|
||||
set(HIDAPI_NEED_EXPORT_THREADS FALSE)
|
||||
set(HIDAPI_NEED_EXPORT_LIBUSB FALSE)
|
||||
set(HIDAPI_NEED_EXPORT_LIBUDEV FALSE)
|
||||
set(HIDAPI_NEED_EXPORT_ICONV FALSE)
|
||||
|
||||
if(WIN32)
|
||||
target_include_directories(hidapi_include INTERFACE
|
||||
"$<BUILD_INTERFACE:${PROJECT_ROOT}/windows>"
|
||||
)
|
||||
add_subdirectory("${PROJECT_ROOT}/windows" windows)
|
||||
set(EXPORT_ALIAS winapi)
|
||||
list(APPEND EXPORT_COMPONENTS winapi)
|
||||
elseif(APPLE)
|
||||
target_include_directories(hidapi_include INTERFACE
|
||||
"$<BUILD_INTERFACE:${PROJECT_ROOT}/mac>"
|
||||
)
|
||||
add_subdirectory("${PROJECT_ROOT}/mac" mac)
|
||||
set(EXPORT_ALIAS darwin)
|
||||
list(APPEND EXPORT_COMPONENTS darwin)
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
set(HIDAPI_NEED_EXPORT_THREADS TRUE)
|
||||
endif()
|
||||
else()
|
||||
if(NOT DEFINED HIDAPI_WITH_LIBUSB)
|
||||
set(HIDAPI_WITH_LIBUSB ON)
|
||||
endif()
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
if(NOT DEFINED HIDAPI_WITH_HIDRAW)
|
||||
set(HIDAPI_WITH_HIDRAW ON)
|
||||
endif()
|
||||
if(HIDAPI_WITH_HIDRAW)
|
||||
add_subdirectory("${PROJECT_ROOT}/linux" linux)
|
||||
list(APPEND EXPORT_COMPONENTS hidraw)
|
||||
set(EXPORT_ALIAS hidraw)
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
set(HIDAPI_NEED_EXPORT_THREADS TRUE)
|
||||
set(HIDAPI_NEED_EXPORT_LIBUDEV TRUE)
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
set(HIDAPI_WITH_LIBUSB ON)
|
||||
endif()
|
||||
if(HIDAPI_WITH_LIBUSB)
|
||||
target_include_directories(hidapi_include INTERFACE
|
||||
"$<BUILD_INTERFACE:${PROJECT_ROOT}/libusb>"
|
||||
)
|
||||
if(NOT DEFINED HIDAPI_NO_ICONV)
|
||||
set(HIDAPI_NO_ICONV OFF)
|
||||
endif()
|
||||
add_subdirectory("${PROJECT_ROOT}/libusb" libusb)
|
||||
list(APPEND EXPORT_COMPONENTS libusb)
|
||||
if(NOT EXPORT_ALIAS)
|
||||
set(EXPORT_ALIAS libusb)
|
||||
endif()
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
set(HIDAPI_NEED_EXPORT_THREADS TRUE)
|
||||
if(NOT TARGET usb-1.0)
|
||||
set(HIDAPI_NEED_EXPORT_LIBUSB TRUE)
|
||||
endif()
|
||||
endif()
|
||||
elseif(NOT TARGET hidapi_hidraw)
|
||||
message(FATAL_ERROR "Select at least one option to build: HIDAPI_WITH_LIBUSB or HIDAPI_WITH_HIDRAW")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_library(hidapi::hidapi ALIAS hidapi_${EXPORT_ALIAS})
|
||||
|
||||
if(HIDAPI_INSTALL_TARGETS)
|
||||
include(CMakePackageConfigHelpers)
|
||||
set(EXPORT_DENERATED_LOCATION "${CMAKE_BINARY_DIR}/export_generated")
|
||||
set(EXPORT_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/hidapi")
|
||||
write_basic_package_version_file("${EXPORT_DENERATED_LOCATION}/hidapi-config-version.cmake"
|
||||
COMPATIBILITY SameMajorVersion
|
||||
)
|
||||
configure_package_config_file("cmake/hidapi-config.cmake.in" "${EXPORT_DENERATED_LOCATION}/hidapi-config.cmake"
|
||||
INSTALL_DESTINATION "${EXPORT_DESTINATION}"
|
||||
NO_SET_AND_CHECK_MACRO
|
||||
)
|
||||
|
||||
install(EXPORT hidapi
|
||||
DESTINATION "${EXPORT_DESTINATION}"
|
||||
NAMESPACE hidapi::
|
||||
FILE "libhidapi.cmake"
|
||||
)
|
||||
install(FILES
|
||||
"${EXPORT_DENERATED_LOCATION}/hidapi-config-version.cmake"
|
||||
"${EXPORT_DENERATED_LOCATION}/hidapi-config.cmake"
|
||||
DESTINATION "${EXPORT_DESTINATION}"
|
||||
)
|
||||
endif()
|
|
@ -0,0 +1,61 @@
|
|||
@PACKAGE_INIT@
|
||||
|
||||
set(hidapi_VERSION_MAJOR "@hidapi_VERSION_MAJOR@")
|
||||
set(hidapi_VERSION_MINOR "@hidapi_VERSION_MINOR@")
|
||||
set(hidapi_VERSION_PATCH "@hidapi_VERSION_PATCH@")
|
||||
set(hidapi_VERSION "@hidapi_VERSION@")
|
||||
set(hidapi_VERSION_STR "@hidapi_VERSION@@VERSION_SUFFIX@")
|
||||
|
||||
set(hidapi_FOUND FALSE)
|
||||
|
||||
set(HIDAPI_NEED_EXPORT_THREADS @HIDAPI_NEED_EXPORT_THREADS@)
|
||||
set(HIDAPI_NEED_EXPORT_LIBUSB @HIDAPI_NEED_EXPORT_LIBUSB@)
|
||||
set(HIDAPI_NEED_EXPORT_LIBUDEV @HIDAPI_NEED_EXPORT_LIBUDEV@)
|
||||
set(HIDAPI_NEED_EXPORT_ICONV @HIDAPI_NEED_EXPORT_ICONV@)
|
||||
|
||||
if(HIDAPI_NEED_EXPORT_THREADS)
|
||||
if(CMAKE_VERSION VERSION_LESS 3.4.3)
|
||||
message(FATAL_ERROR "This file relies on consumers using CMake 3.4.3 or greater.")
|
||||
endif()
|
||||
find_package(Threads REQUIRED)
|
||||
endif()
|
||||
|
||||
if(HIDAPI_NEED_EXPORT_LIBUSB OR HIDAPI_NEED_EXPORT_LIBUDEV)
|
||||
if(CMAKE_VERSION VERSION_LESS 3.6.3)
|
||||
message(FATAL_ERROR "This file relies on consumers using CMake 3.6.3 or greater.")
|
||||
endif()
|
||||
find_package(PkgConfig)
|
||||
if(HIDAPI_NEED_EXPORT_LIBUSB)
|
||||
pkg_check_modules(libusb REQUIRED IMPORTED_TARGET libusb-1.0>=1.0.9)
|
||||
endif()
|
||||
if(HIDAPI_NEED_EXPORT_LIBUDEV)
|
||||
pkg_check_modules(libudev REQUIRED IMPORTED_TARGET libudev)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(HIDAPI_NEED_EXPORT_ICONV)
|
||||
if(CMAKE_VERSION VERSION_LESS 3.11)
|
||||
message(WARNING "HIDAPI requires CMake target Iconv::Iconv, make sure to provide it")
|
||||
else()
|
||||
find_package(Iconv REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/libhidapi.cmake")
|
||||
|
||||
set(hidapi_FOUND TRUE)
|
||||
|
||||
foreach(_component @EXPORT_COMPONENTS@)
|
||||
if(TARGET hidapi::${_component})
|
||||
set(hidapi_${_component}_FOUND TRUE)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
check_required_components(hidapi)
|
||||
|
||||
if(NOT TARGET hidapi::hidapi)
|
||||
add_library(hidapi::hidapi INTERFACE IMPORTED)
|
||||
set_target_properties(hidapi::hidapi PROPERTIES
|
||||
INTERFACE_LINK_LIBRARIES hidapi::@EXPORT_ALIAS@
|
||||
)
|
||||
endif()
|
|
@ -0,0 +1,2 @@
|
|||
This folder is used only to support [meson.build](../meson.build) `subproject` command
|
||||
which would only look for a subproject in a "subprojects" directory.
|
|
@ -0,0 +1,10 @@
|
|||
cmake_minimum_required(VERSION 3.1.3 FATAL_ERROR)
|
||||
project(hidapi LANGUAGES C)
|
||||
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/root")
|
||||
|
||||
foreach(ROOT_ELEMENT CMakeLists.txt hidapi src windows linux mac libusb pc VERSION)
|
||||
file(COPY "${CMAKE_CURRENT_LIST_DIR}/../../${ROOT_ELEMENT}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/root/")
|
||||
endforeach()
|
||||
|
||||
add_subdirectory("${CMAKE_CURRENT_BINARY_DIR}/root" hidapi_root)
|
|
@ -0,0 +1,20 @@
|
|||
Debug
|
||||
Release
|
||||
*.exp
|
||||
*.ilk
|
||||
*.lib
|
||||
*.suo
|
||||
*.vcproj.*
|
||||
*.ncb
|
||||
*.suo
|
||||
*.dll
|
||||
*.pdb
|
||||
*.o
|
||||
hidapi-testgui
|
||||
hidapi-hidraw-testgui
|
||||
hidapi-libusb-testgui
|
||||
.deps
|
||||
.libs
|
||||
*.la
|
||||
*.lo
|
||||
TestGUI.app
|
|
@ -14,7 +14,7 @@ COBJS=../windows/hid.o
|
|||
CPPOBJS=test.o
|
||||
OBJS=$(COBJS) $(CPPOBJS)
|
||||
CFLAGS=-I../hidapi -I../../hidapi-externals/fox/include -g -c
|
||||
LIBS= -mwindows -lsetupapi -L../../hidapi-externals/fox/lib -Wl,-Bstatic -lFOX-1.6 -Wl,-Bdynamic -lgdi32 -Wl,--enable-auto-import -static-libgcc -static-libstdc++ -lkernel32
|
||||
LIBS= -mwindows -L../../hidapi-externals/fox/lib -Wl,-Bstatic -lFOX-1.6 -Wl,-Bdynamic -lgdi32 -Wl,--enable-auto-import -static-libgcc -static-libstdc++ -lkernel32
|
||||
|
||||
|
||||
hidapi-testgui: $(OBJS)
|
||||
|
|
|
@ -77,9 +77,10 @@ function copydeps {
|
|||
}
|
||||
|
||||
rm -f $EXEPATH/*
|
||||
mkdir -p $EXEPATH
|
||||
|
||||
# Copy the binary into the bundle. Use ../libtool to do this if it's
|
||||
# available beacuse if $EXE_NAME was built with autotools, it will be
|
||||
# available because if $EXE_NAME was built with autotools, it will be
|
||||
# necessary. If ../libtool not available, just use cp to do the copy, but
|
||||
# only if $EXE_NAME is a binary.
|
||||
if [ -x ../libtool ]; then
|
||||
|
|
|
@ -1,134 +0,0 @@
|
|||
/*******************************
|
||||
Mac support for HID Test GUI
|
||||
|
||||
Alan Ott
|
||||
Signal 11 Software
|
||||
|
||||
Some of this code is from Apple Documentation, most notably
|
||||
http://developer.apple.com/legacy/mac/library/documentation/AppleScript/Conceptual/AppleEvents/AppleEvents.pdf
|
||||
*******************************/
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <fx.h>
|
||||
|
||||
|
||||
extern FXMainWindow *g_main_window;
|
||||
|
||||
static pascal OSErr HandleQuitMessage(const AppleEvent *theAppleEvent, AppleEvent
|
||||
*reply, long handlerRefcon)
|
||||
{
|
||||
puts("Quitting\n");
|
||||
FXApp::instance()->exit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static pascal OSErr HandleReopenMessage(const AppleEvent *theAppleEvent, AppleEvent
|
||||
*reply, long handlerRefcon)
|
||||
{
|
||||
puts("Showing");
|
||||
g_main_window->show();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static pascal OSErr HandleWildCardMessage(const AppleEvent *theAppleEvent, AppleEvent
|
||||
*reply, long handlerRefcon)
|
||||
{
|
||||
puts("WildCard\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
OSStatus AEHandler(EventHandlerCallRef inCaller, EventRef inEvent, void* inRefcon)
|
||||
{
|
||||
Boolean release = false;
|
||||
EventRecord eventRecord;
|
||||
OSErr ignoreErrForThisSample;
|
||||
|
||||
// Events of type kEventAppleEvent must be removed from the queue
|
||||
// before being passed to AEProcessAppleEvent.
|
||||
if (IsEventInQueue(GetMainEventQueue(), inEvent))
|
||||
{
|
||||
// RemoveEventFromQueue will release the event, which will
|
||||
// destroy it if we don't retain it first.
|
||||
RetainEvent(inEvent);
|
||||
release = true;
|
||||
RemoveEventFromQueue(GetMainEventQueue(), inEvent);
|
||||
}
|
||||
// Convert the event ref to the type AEProcessAppleEvent expects.
|
||||
ConvertEventRefToEventRecord(inEvent, &eventRecord);
|
||||
ignoreErrForThisSample = AEProcessAppleEvent(&eventRecord);
|
||||
if (release)
|
||||
ReleaseEvent(inEvent);
|
||||
// This Carbon event has been handled, even if no AppleEvent handlers
|
||||
// were installed for the Apple event.
|
||||
return noErr;
|
||||
}
|
||||
|
||||
static void HandleEvent(EventRecord *event)
|
||||
{
|
||||
//printf("What: %d message %x\n", event->what, event->message);
|
||||
if (event->what == osEvt) {
|
||||
if (((event->message >> 24) & 0xff) == suspendResumeMessage) {
|
||||
if (event->message & resumeFlag) {
|
||||
g_main_window->show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
switch (event->what)
|
||||
{
|
||||
case mouseDown:
|
||||
//HandleMouseDown(event);
|
||||
break;
|
||||
case keyDown:
|
||||
case autoKey:
|
||||
//HandleKeyPress(event);
|
||||
break;
|
||||
case kHighLevelEvent:
|
||||
puts("Calling ProcessAppleEvent\n");
|
||||
AEProcessAppleEvent(event);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
init_apple_message_system()
|
||||
{
|
||||
OSErr err;
|
||||
static const EventTypeSpec appleEvents[] =
|
||||
{
|
||||
{ kEventClassAppleEvent, kEventAppleEvent }
|
||||
};
|
||||
|
||||
/* Install the handler for Apple Events */
|
||||
InstallApplicationEventHandler(NewEventHandlerUPP(AEHandler),
|
||||
GetEventTypeCount(appleEvents), appleEvents, 0, NULL);
|
||||
|
||||
/* Install handlers for the individual Apple Events that come
|
||||
from the Dock icon: the Reopen (click), and the Quit messages. */
|
||||
err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
|
||||
NewAEEventHandlerUPP(HandleQuitMessage), 0, false);
|
||||
err = AEInstallEventHandler(kCoreEventClass, kAEReopenApplication,
|
||||
NewAEEventHandlerUPP(HandleReopenMessage), 0, false);
|
||||
#if 0
|
||||
// Left as an example of a wild card match.
|
||||
err = AEInstallEventHandler(kCoreEventClass, typeWildCard,
|
||||
NewAEEventHandlerUPP(HandleWildMessage), 0, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
check_apple_events()
|
||||
{
|
||||
RgnHandle cursorRgn = NULL;
|
||||
Boolean gotEvent=TRUE;
|
||||
EventRecord event;
|
||||
|
||||
while (gotEvent) {
|
||||
gotEvent = WaitNextEvent(everyEvent, &event, 0L/*timeout*/, cursorRgn);
|
||||
if (gotEvent) {
|
||||
HandleEvent(&event);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,10 +8,19 @@
|
|||
#include <fx.h>
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#ifndef MAC_OS_X_VERSION_10_12
|
||||
#define MAC_OS_X_VERSION_10_12 101200
|
||||
#endif
|
||||
|
||||
// macOS 10.12 deprecated NSAnyEventMask in favor of NSEventMaskAny
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12
|
||||
#define NSEventMaskAny NSAnyEventMask
|
||||
#endif
|
||||
|
||||
extern FXMainWindow *g_main_window;
|
||||
|
||||
|
||||
@interface MyAppDelegate : NSObject
|
||||
@interface MyAppDelegate : NSObject<NSApplicationDelegate>
|
||||
{
|
||||
}
|
||||
@end
|
||||
|
@ -77,7 +86,7 @@ check_apple_events()
|
|||
|
||||
NSAutoreleasePool *pool = [NSAutoreleasePool new];
|
||||
while (1) {
|
||||
NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
|
||||
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
|
||||
untilDate:nil
|
||||
inMode:NSDefaultRunLoopMode
|
||||
dequeue:YES];
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
#!/bin/bash
|
||||
xterm -e /Users/alan/work/hidapi/testgui/TestGUI.app/Contents/MacOS/tg
|
|
@ -1,20 +1,20 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual C++ Express 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testgui", "testgui.vcproj", "{08769AC3-785A-4DDC-BFC7-1775414B7AB7}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{08769AC3-785A-4DDC-BFC7-1775414B7AB7}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{08769AC3-785A-4DDC-BFC7-1775414B7AB7}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{08769AC3-785A-4DDC-BFC7-1775414B7AB7}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{08769AC3-785A-4DDC-BFC7-1775414B7AB7}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual C++ Express 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testgui", "testgui.vcproj", "{08769AC3-785A-4DDC-BFC7-1775414B7AB7}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{08769AC3-785A-4DDC-BFC7-1775414B7AB7}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{08769AC3-785A-4DDC-BFC7-1775414B7AB7}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{08769AC3-785A-4DDC-BFC7-1775414B7AB7}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{08769AC3-785A-4DDC-BFC7-1775414B7AB7}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -1,217 +1,217 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="testgui"
|
||||
ProjectGUID="{08769AC3-785A-4DDC-BFC7-1775414B7AB7}"
|
||||
RootNamespace="testgui"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="196613"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""..\..\hidapi-externals\fox\include";..\hidapi"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="setupapi.lib fox-1.6.lib"
|
||||
OutputFile="$(ProjectName).exe"
|
||||
LinkIncremental="2"
|
||||
AdditionalLibraryDirectories="..\hidapi\objfre_wxp_x86\i386;"..\..\hidapi-externals\fox\lib""
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
EntryPointSymbol="mainCRTStartup"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine=""
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
AdditionalIncludeDirectories=""..\..\hidapi-externals\fox\include";..\hidapi"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
|
||||
RuntimeLibrary="2"
|
||||
EnableFunctionLevelLinking="true"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="setupapi.lib fox-1.6.lib"
|
||||
OutputFile="$(ProjectName).exe"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories="..\hidapi\objfre_wxp_x86\i386;"..\..\hidapi-externals\fox\lib""
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
EntryPointSymbol="mainCRTStartup"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine=""
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\windows\hid.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\test.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\hidapi\hidapi.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\ReadMe.txt"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="testgui"
|
||||
ProjectGUID="{08769AC3-785A-4DDC-BFC7-1775414B7AB7}"
|
||||
RootNamespace="testgui"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="196613"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""..\..\hidapi-externals\fox\include";..\hidapi"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="fox-1.6.lib"
|
||||
OutputFile="$(ProjectName).exe"
|
||||
LinkIncremental="2"
|
||||
AdditionalLibraryDirectories="..\hidapi\objfre_wxp_x86\i386;"..\..\hidapi-externals\fox\lib""
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
EntryPointSymbol="mainCRTStartup"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine=""
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
AdditionalIncludeDirectories=""..\..\hidapi-externals\fox\include";..\hidapi"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
|
||||
RuntimeLibrary="2"
|
||||
EnableFunctionLevelLinking="true"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="fox-1.6.lib"
|
||||
OutputFile="$(ProjectName).exe"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories="..\hidapi\objfre_wxp_x86\i386;"..\..\hidapi-externals\fox\lib""
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
EntryPointSymbol="mainCRTStartup"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine=""
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\windows\hid.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\test.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\hidapi\hidapi.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\ReadMe.txt"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
# This is a sample udev file for HIDAPI devices which lets unprivileged
|
||||
# users who are physically present at the system (not remote users) access
|
||||
# HID devices.
|
||||
|
||||
# If you are using the libusb implementation of hidapi (libusb/hid.c), then
|
||||
# use something like the following line, substituting the VID and PID with
|
||||
# those of your device.
|
||||
|
||||
# HIDAPI/libusb
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="003f", TAG+="uaccess"
|
||||
|
||||
# If you are using the hidraw implementation (linux/hid.c), then do something
|
||||
# like the following, substituting the VID and PID with your device.
|
||||
|
||||
# HIDAPI/hidraw
|
||||
KERNEL=="hidraw*", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="003f", TAG+="uaccess"
|
||||
|
||||
# Once done, optionally rename this file for your application, and drop it into
|
||||
# /etc/udev/rules.d/.
|
||||
# NOTE: these rules must have priorty before 73-seat-late.rules.
|
||||
# (Small discussion/explanation in systemd repo:
|
||||
# https://github.com/systemd/systemd/issues/4288#issuecomment-348166161)
|
||||
# for example, name the file /etc/udev/rules.d/70-my-application-hid.rules.
|
||||
# Then, replug your device or run:
|
||||
# sudo udevadm control --reload-rules && sudo udevadm trigger
|
||||
|
||||
# Note that the hexadecimal values for VID and PID are case sensitive and
|
||||
# must be lower case.
|
||||
|
||||
# TAG+="uaccess" only gives permission to physically present users, which
|
||||
# is appropriate in most scenarios. If you require access to the device
|
||||
# from a remote session (e.g. over SSH), add
|
||||
# GROUP="plugdev", MODE="660"
|
||||
# to the end of the udev rule lines, add your user to the plugdev group with:
|
||||
# usermod -aG plugdev USERNAME
|
||||
# then log out and log back in (or restart the system).
|
|
@ -1,33 +0,0 @@
|
|||
# This is a sample udev file for HIDAPI devices which changes the permissions
|
||||
# to 0666 (world readable/writable) for a specified device on Linux systems.
|
||||
|
||||
|
||||
# If you are using the libusb implementation of hidapi (libusb/hid.c), then
|
||||
# use something like the following line, substituting the VID and PID with
|
||||
# those of your device. Note that for kernels before 2.6.24, you will need
|
||||
# to substitute "usb" with "usb_device". It shouldn't hurt to use two lines
|
||||
# (one each way) for compatibility with older systems.
|
||||
|
||||
# HIDAPI/libusb
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="003f", MODE="0666"
|
||||
|
||||
|
||||
# If you are using the hidraw implementation (linux/hid.c), then do something
|
||||
# like the following, substituting the VID and PID with your device. Busnum 1
|
||||
# is USB.
|
||||
|
||||
# HIDAPI/hidraw
|
||||
KERNEL=="hidraw*", ATTRS{busnum}=="1", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="003f", MODE="0666"
|
||||
|
||||
# Once done, optionally rename this file for your device, and drop it into
|
||||
# /etc/udev/rules.d and unplug and re-plug your device. This is all that is
|
||||
# necessary to see the new permissions. Udev does not have to be restarted.
|
||||
|
||||
# Note that the hexadecimal values for VID and PID are case sensitive and
|
||||
# must be lower case.
|
||||
|
||||
# If you think permissions of 0666 are too loose, then see:
|
||||
# http://reactivated.net/writing_udev_rules.html for more information on finer
|
||||
# grained permission setting. For example, it might be sufficient to just
|
||||
# set the group or user owner for specific devices (for example the plugdev
|
||||
# group on some systems).
|
|
@ -0,0 +1,17 @@
|
|||
Debug
|
||||
Release
|
||||
.vs/
|
||||
*.exp
|
||||
*.ilk
|
||||
*.lib
|
||||
*.suo
|
||||
*.vcproj.*
|
||||
*.vcxproj.*
|
||||
*.ncb
|
||||
*.suo
|
||||
*.dll
|
||||
*.pdb
|
||||
.deps
|
||||
.libs
|
||||
*.lo
|
||||
*.la
|
|
@ -0,0 +1,63 @@
|
|||
list(APPEND HIDAPI_PUBLIC_HEADERS "hidapi_winapi.h")
|
||||
|
||||
set(SOURCES
|
||||
hid.c
|
||||
hidapi_cfgmgr32.h
|
||||
hidapi_descriptor_reconstruct.c
|
||||
hidapi_descriptor_reconstruct.h
|
||||
hidapi_hidclass.h
|
||||
hidapi_hidpi.h
|
||||
hidapi_hidsdi.h
|
||||
)
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
list(APPEND SOURCES hidapi.rc)
|
||||
endif()
|
||||
|
||||
add_library(hidapi_winapi
|
||||
${HIDAPI_PUBLIC_HEADERS}
|
||||
${SOURCES}
|
||||
)
|
||||
target_link_libraries(hidapi_winapi
|
||||
PUBLIC hidapi_include
|
||||
)
|
||||
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
target_compile_definitions(hidapi_winapi
|
||||
# prevent marking functions as __declspec(dllexport) for static library build
|
||||
# #480: this should be refactored for v1.0
|
||||
PUBLIC HID_API_NO_EXPORT_DEFINE
|
||||
)
|
||||
endif()
|
||||
|
||||
set_target_properties(hidapi_winapi
|
||||
PROPERTIES
|
||||
EXPORT_NAME "winapi"
|
||||
OUTPUT_NAME "hidapi"
|
||||
VERSION ${PROJECT_VERSION}
|
||||
PUBLIC_HEADER "${HIDAPI_PUBLIC_HEADERS}"
|
||||
)
|
||||
|
||||
# compatibility with find_package()
|
||||
add_library(hidapi::winapi ALIAS hidapi_winapi)
|
||||
# compatibility with raw library link
|
||||
add_library(hidapi ALIAS hidapi_winapi)
|
||||
|
||||
if(HIDAPI_INSTALL_TARGETS)
|
||||
install(TARGETS hidapi_winapi EXPORT hidapi
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
||||
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.pc.in")
|
||||
|
||||
if(HIDAPI_WITH_TESTS)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
if(DEFINED HIDAPI_BUILD_PP_DATA_DUMP AND HIDAPI_BUILD_PP_DATA_DUMP)
|
||||
add_subdirectory(pp_data_dump)
|
||||
endif()
|
|
@ -8,7 +8,6 @@ hdrdir = $(includedir)/hidapi
|
|||
hdr_HEADERS = $(top_srcdir)/hidapi/hidapi.h
|
||||
|
||||
EXTRA_DIST = \
|
||||
ddk_build \
|
||||
hidapi.vcproj \
|
||||
hidtest.vcproj \
|
||||
Makefile-manual \
|
||||
|
|
|
@ -9,16 +9,14 @@
|
|||
all: hidtest libhidapi.dll
|
||||
|
||||
CC=gcc
|
||||
CXX=g++
|
||||
COBJS=hid.o
|
||||
CPPOBJS=../hidtest/hidtest.o
|
||||
OBJS=$(COBJS) $(CPPOBJS)
|
||||
CFLAGS=-I../hidapi -g -c
|
||||
LIBS= -lsetupapi
|
||||
DLL_LDFLAGS = -mwindows -lsetupapi
|
||||
COBJS=hid.o ../hidtest/test.o
|
||||
OBJS=$(COBJS)
|
||||
CFLAGS=-I../hidapi -I. -g -c
|
||||
LIBS=
|
||||
DLL_LDFLAGS = -mwindows
|
||||
|
||||
hidtest: $(OBJS)
|
||||
g++ -g $^ $(LIBS) -o hidtest
|
||||
$(CC) -g $^ $(LIBS) -o hidtest
|
||||
|
||||
libhidapi.dll: $(OBJS)
|
||||
$(CC) -g $^ $(DLL_LDFLAGS) -o libhidapi.dll
|
||||
|
@ -26,9 +24,6 @@ libhidapi.dll: $(OBJS)
|
|||
$(COBJS): %.o: %.c
|
||||
$(CC) $(CFLAGS) $< -o $@
|
||||
|
||||
$(CPPOBJS): %.o: %.cpp
|
||||
$(CXX) $(CFLAGS) $< -o $@
|
||||
|
||||
clean:
|
||||
rm *.o ../hidtest/*.o hidtest.exe
|
||||
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
LIBRARY hidapi
|
||||
EXPORTS
|
||||
hid_open @1
|
||||
hid_write @2
|
||||
hid_read @3
|
||||
hid_close @4
|
||||
hid_get_product_string @5
|
||||
hid_get_manufacturer_string @6
|
||||
hid_get_serial_number_string @7
|
||||
hid_get_indexed_string @8
|
||||
hid_error @9
|
||||
hid_set_nonblocking @10
|
||||
hid_enumerate @11
|
||||
hid_open_path @12
|
||||
hid_send_feature_report @13
|
||||
hid_get_feature_report @14
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
#############################################################################
|
||||
#
|
||||
# Copyright (C) Microsoft Corporation 1995, 1996
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# MAKEFILE for HID directory
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
!IFDEF WIN95_BUILD
|
||||
|
||||
ROOT=..\..\..\..
|
||||
|
||||
VERSIONLIST = debug retail
|
||||
IS_32 = TRUE
|
||||
IS_SDK = TRUE
|
||||
IS_PRIVATE = TRUE
|
||||
IS_SDK = TRUE
|
||||
IS_DDK = TRUE
|
||||
WIN32 = TRUE
|
||||
COMMONMKFILE = hidapi.mk
|
||||
|
||||
!include $(ROOT)\dev\master.mk
|
||||
|
||||
|
||||
!ELSE
|
||||
|
||||
#
|
||||
# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
|
||||
# file to this component. This file merely indirects to the real make file
|
||||
# that is shared by all the driver components of the Windows NT DDK
|
||||
#
|
||||
|
||||
!IF DEFINED(_NT_TARGET_VERSION)
|
||||
! IF $(_NT_TARGET_VERSION)>=0x501
|
||||
! INCLUDE $(NTMAKEENV)\makefile.def
|
||||
! ELSE
|
||||
# Only warn once per directory
|
||||
! INCLUDE $(NTMAKEENV)\makefile.plt
|
||||
! IF "$(BUILD_PASS)"=="PASS1"
|
||||
! message BUILDMSG: Warning : The sample "$(MAKEDIR)" is not valid for the current OS target.
|
||||
! ENDIF
|
||||
! ENDIF
|
||||
!ELSE
|
||||
! INCLUDE $(NTMAKEENV)\makefile.def
|
||||
!ENDIF
|
||||
|
||||
!ENDIF
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
TARGETNAME=hidapi
|
||||
TARGETTYPE=DYNLINK
|
||||
UMTYPE=console
|
||||
UMENTRY=main
|
||||
|
||||
MSC_WARNING_LEVEL=/W3 /WX
|
||||
|
||||
TARGETLIBS=$(SDK_LIB_PATH)\hid.lib \
|
||||
$(SDK_LIB_PATH)\setupapi.lib \
|
||||
$(SDK_LIB_PATH)\kernel32.lib \
|
||||
$(SDK_LIB_PATH)\comdlg32.lib
|
||||
|
||||
USE_MSVCRT=1
|
||||
|
||||
INCLUDES= ..\..\hidapi
|
||||
SOURCES= ..\hid.c \
|
||||
|
||||
|
||||
TARGET_DESTINATION=retail
|
||||
|
||||
MUI=0
|
||||
MUI_COMMENT="HID Interface DLL"
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,35 @@
|
|||
#include "winresrc.h"
|
||||
|
||||
#include "hidapi.h"
|
||||
|
||||
// English
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION HID_API_VERSION_MAJOR,HID_API_VERSION_MINOR,HID_API_VERSION_PATCH,0
|
||||
PRODUCTVERSION HID_API_VERSION_MAJOR,HID_API_VERSION_MINOR,HID_API_VERSION_PATCH,0
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
FILEFLAGS 0
|
||||
#ifdef _DEBUG
|
||||
| VS_FF_DEBUG
|
||||
#endif
|
||||
FILEOS VOS_NT_WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "04090000"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "libusb/hidapi Team"
|
||||
VALUE "FileDescription", "A multi-platform library to interface with HID devices (USB, Bluetooth, etc.)"
|
||||
VALUE "FileVersion", HID_API_VERSION_STR
|
||||
VALUE "ProductName", "HIDAPI"
|
||||
VALUE "ProductVersion", HID_API_VERSION_STR
|
||||
VALUE "Licence", "https://github.com/libusb/hidapi/blob/master/LICENSE.txt"
|
||||
VALUE "Comments", "https://github.com/libusb/hidapi"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 0
|
||||
END
|
||||
END
|
|
@ -1,29 +1,41 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual C++ Express 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hidapi", "hidapi.vcproj", "{A107C21C-418A-4697-BB10-20C3AA60E2E4}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hidtest", "hidtest.vcproj", "{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{A107C21C-418A-4697-BB10-20C3AA60E2E4} = {A107C21C-418A-4697-BB10-20C3AA60E2E4}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Release|Win32.Build.0 = Release|Win32
|
||||
{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.28307.136
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hidapi", "hidapi.vcxproj", "{A107C21C-418A-4697-BB10-20C3AA60E2E4}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hidtest", "hidtest.vcxproj", "{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug|x64.Build.0 = Debug|x64
|
||||
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Release|Win32.Build.0 = Release|Win32
|
||||
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Release|x64.ActiveCfg = Release|x64
|
||||
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Release|x64.Build.0 = Release|x64
|
||||
{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Debug|x64.Build.0 = Debug|x64
|
||||
{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Release|Win32.Build.0 = Release|Win32
|
||||
{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Release|x64.ActiveCfg = Release|x64
|
||||
{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {8749E535-9C65-4A89-840E-78D7578C7866}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -1,201 +1,200 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="hidapi"
|
||||
ProjectGUID="{A107C21C-418A-4697-BB10-20C3AA60E2E4}"
|
||||
RootNamespace="hidapi"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="196613"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\hidapi"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;HIDAPI_EXPORTS"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="setupapi.lib"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
AdditionalIncludeDirectories="..\hidapi"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;HIDAPI_EXPORTS"
|
||||
RuntimeLibrary="2"
|
||||
EnableFunctionLevelLinking="true"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="setupapi.lib"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\hid.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\hidapi\hidapi.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="hidapi"
|
||||
ProjectGUID="{A107C21C-418A-4697-BB10-20C3AA60E2E4}"
|
||||
RootNamespace="hidapi"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="196613"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\hidapi"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;HIDAPI_EXPORTS"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
AdditionalIncludeDirectories="..\hidapi"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;HIDAPI_EXPORTS"
|
||||
RuntimeLibrary="2"
|
||||
EnableFunctionLevelLinking="true"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="setupapi.lib"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\hid.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\hidapi\hidapi.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
|
|
|
@ -0,0 +1,200 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{A107C21C-418A-4697-BB10-20C3AA60E2E4}</ProjectGuid>
|
||||
<RootNamespace>hidapi</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)'=='11'">v110</PlatformToolset>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)'=='12'">v120</PlatformToolset>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)'=='14'">v140</PlatformToolset>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)'=='15'">v141</PlatformToolset>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)'=='16'">v142</PlatformToolset>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)'=='17'">v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)'=='11'">v110</PlatformToolset>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)'=='12'">v120</PlatformToolset>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)'=='14'">v140</PlatformToolset>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)'=='15'">v141</PlatformToolset>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)'=='16'">v142</PlatformToolset>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)'=='17'">v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)'=='11'">v110</PlatformToolset>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)'=='12'">v120</PlatformToolset>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)'=='14'">v140</PlatformToolset>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)'=='15'">v141</PlatformToolset>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)'=='16'">v142</PlatformToolset>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)'=='17'">v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)'=='11'">v110</PlatformToolset>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)'=='12'">v120</PlatformToolset>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)'=='14'">v140</PlatformToolset>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)'=='15'">v141</PlatformToolset>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)'=='16'">v142</PlatformToolset>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)'=='17'">v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>14.0.25431.1</_ProjectFileVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\hidapi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;HIDAPI_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>..\hidapi</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_DEBUG</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\hidapi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;HIDAPI_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>..\hidapi</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_DEBUG</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\hidapi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;HIDAPI_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>..\hidapi</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>NDEBUG</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\hidapi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;HIDAPI_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>..\hidapi</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>NDEBUG</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="hid.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\hidapi\hidapi.h" />
|
||||
<ClInclude Include="hidapi_winapi.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="hidapi.rc" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -28,18 +28,14 @@
|
|||
#include <propkey.h>
|
||||
|
||||
#else
|
||||
#ifndef PROPERTYKEY_DEFINED
|
||||
#define PROPERTYKEY_DEFINED
|
||||
typedef struct
|
||||
{
|
||||
GUID fmtid;
|
||||
DWORD pid;
|
||||
} PROPERTYKEY;
|
||||
#endif /* PROPERTYKEY_DEFINED */
|
||||
|
||||
/* This part of the header mimics cfgmgr32.h,
|
||||
but only what is used by HIDAPI */
|
||||
|
||||
#include <initguid.h>
|
||||
#include <devpropdef.h>
|
||||
#include <propkeydef.h>
|
||||
|
||||
typedef DWORD RETURN_TYPE;
|
||||
typedef RETURN_TYPE CONFIGRET;
|
||||
typedef DWORD DEVNODE, DEVINST;
|
||||
|
@ -59,18 +55,20 @@ typedef CONFIGRET(__stdcall* CM_Get_Parent_)(PDEVINST pdnDevInst, DEVINST dnDevI
|
|||
typedef CONFIGRET(__stdcall* CM_Get_DevNode_PropertyW_)(DEVINST dnDevInst, CONST DEVPROPKEY* PropertyKey, DEVPROPTYPE* PropertyType, PBYTE PropertyBuffer, PULONG PropertyBufferSize, ULONG ulFlags);
|
||||
typedef CONFIGRET(__stdcall* CM_Get_Device_Interface_PropertyW_)(LPCWSTR pszDeviceInterface, CONST DEVPROPKEY* PropertyKey, DEVPROPTYPE* PropertyType, PBYTE PropertyBuffer, PULONG PropertyBufferSize, ULONG ulFlags);
|
||||
typedef CONFIGRET(__stdcall* CM_Get_Device_Interface_List_SizeW_)(PULONG pulLen, LPGUID InterfaceClassGuid, DEVINSTID_W pDeviceID, ULONG ulFlags);
|
||||
typedef CONFIGRET(__stdcall* CM_Get_Device_Interface_ListW_)(LPGUID InterfaceClassGuid, DEVINSTID_W pDeviceID, WCHAR* Buffer, ULONG BufferLen, ULONG ulFlags);
|
||||
typedef CONFIGRET(__stdcall* CM_Get_Device_Interface_ListW_)(LPGUID InterfaceClassGuid, DEVINSTID_W pDeviceID, PZZWSTR Buffer, ULONG BufferLen, ULONG ulFlags);
|
||||
|
||||
// from devpkey.h
|
||||
static DEVPROPKEY DEVPKEY_NAME = { { 0xb725f130, 0x47ef, 0x101a, {0xa5, 0xf1, 0x02, 0x60, 0x8c, 0x9e, 0xeb, 0xac} }, 10 }; // DEVPROP_TYPE_STRING
|
||||
static DEVPROPKEY DEVPKEY_Device_InstanceId = { { 0x78c34fc8, 0x104a, 0x4aca, {0x9e, 0xa4, 0x52, 0x4d, 0x52, 0x99, 0x6e, 0x57} }, 256 }; // DEVPROP_TYPE_STRING
|
||||
//static DEVPROPKEY DEVPKEY_Device_HardwareIds = { { 0xa45c254e, 0xdf1c, 0x4efd, {0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0} }, 3 }; // DEVPROP_TYPE_STRING_LIST
|
||||
static DEVPROPKEY DEVPKEY_Device_CompatibleIds = { { 0xa45c254e, 0xdf1c, 0x4efd, {0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0} }, 4 }; // DEVPROP_TYPE_STRING_LIST
|
||||
//static DEVPROPKEY DEVPKEY_Device_ContainerId = { { 0x8c7ed206, 0x3f8a, 0x4827, {0xb3, 0xab, 0xae, 0x9e, 0x1f, 0xae, 0xfc, 0x6c} }, 2 }; // DEVPROP_TYPE_GUID
|
||||
DEFINE_DEVPROPKEY(DEVPKEY_NAME, 0xb725f130, 0x47ef, 0x101a, 0xa5, 0xf1, 0x02, 0x60, 0x8c, 0x9e, 0xeb, 0xac, 10); // DEVPROP_TYPE_STRING
|
||||
DEFINE_DEVPROPKEY(DEVPKEY_Device_Manufacturer, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 13); // DEVPROP_TYPE_STRING
|
||||
DEFINE_DEVPROPKEY(DEVPKEY_Device_InstanceId, 0x78c34fc8, 0x104a, 0x4aca, 0x9e, 0xa4, 0x52, 0x4d, 0x52, 0x99, 0x6e, 0x57, 256); // DEVPROP_TYPE_STRING
|
||||
DEFINE_DEVPROPKEY(DEVPKEY_Device_HardwareIds, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 3); // DEVPROP_TYPE_STRING_LIST
|
||||
DEFINE_DEVPROPKEY(DEVPKEY_Device_CompatibleIds, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 4); // DEVPROP_TYPE_STRING_LIST
|
||||
DEFINE_DEVPROPKEY(DEVPKEY_Device_ContainerId, 0x8c7ed206, 0x3f8a, 0x4827, 0xb3, 0xab, 0xae, 0x9e, 0x1f, 0xae, 0xfc, 0x6c, 2); // DEVPROP_TYPE_GUID
|
||||
|
||||
// from propkey.h
|
||||
static PROPERTYKEY PKEY_DeviceInterface_Bluetooth_DeviceAddress = { { 0x2bd67d8b, 0x8beb, 0x48d5, {0x87, 0xe0, 0x6c, 0xda, 0x34, 0x28, 0x04, 0x0a} }, 1 }; // DEVPROP_TYPE_STRING
|
||||
static PROPERTYKEY PKEY_DeviceInterface_Bluetooth_Manufacturer = { { 0x2bd67d8b, 0x8beb, 0x48d5, {0x87, 0xe0, 0x6c, 0xda, 0x34, 0x28, 0x04, 0x0a} }, 4 }; // DEVPROP_TYPE_STRING
|
||||
DEFINE_PROPERTYKEY(PKEY_DeviceInterface_Bluetooth_DeviceAddress, 0x2BD67D8B, 0x8BEB, 0x48D5, 0x87, 0xE0, 0x6C, 0xDA, 0x34, 0x28, 0x04, 0x0A, 1); // DEVPROP_TYPE_STRING
|
||||
DEFINE_PROPERTYKEY(PKEY_DeviceInterface_Bluetooth_Manufacturer, 0x2BD67D8B, 0x8BEB, 0x48D5, 0x87, 0xE0, 0x6C, 0xDA, 0x34, 0x28, 0x04, 0x0A, 4); // DEVPROP_TYPE_STRING
|
||||
DEFINE_PROPERTYKEY(PKEY_DeviceInterface_Bluetooth_ModelNumber, 0x2BD67D8B, 0x8BEB, 0x48D5, 0x87, 0xE0, 0x6C, 0xDA, 0x34, 0x28, 0x04, 0x0A, 5); // DEVPROP_TYPE_STRING
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -0,0 +1,987 @@
|
|||
/*******************************************************
|
||||
HIDAPI - Multi-Platform library for
|
||||
communication with HID devices.
|
||||
|
||||
libusb/hidapi Team
|
||||
|
||||
Copyright 2022, 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 "hidapi_descriptor_reconstruct.h"
|
||||
|
||||
/**
|
||||
* @brief References to report descriptor buffer.
|
||||
*
|
||||
*/
|
||||
struct rd_buffer {
|
||||
unsigned char* buf; /* Pointer to the array which stores the reconstructed descriptor */
|
||||
size_t buf_size; /* Size of the buffer in bytes */
|
||||
size_t byte_idx; /* Index of the next report byte to write to buf array */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Function that appends a byte to encoded report descriptor buffer.
|
||||
*
|
||||
* @param[in] byte Single byte to append.
|
||||
* @param rpt_desc Pointer to report descriptor buffer struct.
|
||||
*/
|
||||
static void rd_append_byte(unsigned char byte, struct rd_buffer* rpt_desc) {
|
||||
if (rpt_desc->byte_idx < rpt_desc->buf_size) {
|
||||
rpt_desc->buf[rpt_desc->byte_idx] = byte;
|
||||
rpt_desc->byte_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes a short report descriptor item according USB HID spec 1.11 chapter 6.2.2.2.
|
||||
*
|
||||
* @param[in] rd_item Enumeration identifying type (Main, Global, Local) and function (e.g Usage or Report Count) of the item.
|
||||
* @param[in] data Data (Size depends on rd_item 0,1,2 or 4bytes).
|
||||
* @param list Chained list of report descriptor bytes.
|
||||
*
|
||||
* @return Returns 0 if successful, -1 for error.
|
||||
*/
|
||||
static int rd_write_short_item(rd_items rd_item, LONG64 data, struct rd_buffer* rpt_desc) {
|
||||
if (rd_item & 0x03) {
|
||||
// Invalid input data, last to bits are reserved for data size
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rd_item == rd_main_collection_end) {
|
||||
// Item without data (1Byte prefix only)
|
||||
unsigned char oneBytePrefix = (unsigned char) rd_item + 0x00;
|
||||
rd_append_byte(oneBytePrefix, rpt_desc);
|
||||
}
|
||||
else if ((rd_item == rd_global_logical_minimum) ||
|
||||
(rd_item == rd_global_logical_maximum) ||
|
||||
(rd_item == rd_global_physical_minimum) ||
|
||||
(rd_item == rd_global_physical_maximum)) {
|
||||
// Item with signed integer data
|
||||
if ((data >= -128) && (data <= 127)) {
|
||||
// 1Byte prefix + 1Byte data
|
||||
unsigned char oneBytePrefix = (unsigned char) rd_item + 0x01;
|
||||
char localData = (char)data;
|
||||
rd_append_byte(oneBytePrefix, rpt_desc);
|
||||
rd_append_byte(localData & 0xFF, rpt_desc);
|
||||
}
|
||||
else if ((data >= -32768) && (data <= 32767)) {
|
||||
// 1Byte prefix + 2Byte data
|
||||
unsigned char oneBytePrefix = (unsigned char) rd_item + 0x02;
|
||||
INT16 localData = (INT16)data;
|
||||
rd_append_byte(oneBytePrefix, rpt_desc);
|
||||
rd_append_byte(localData & 0xFF, rpt_desc);
|
||||
rd_append_byte(localData >> 8 & 0xFF, rpt_desc);
|
||||
}
|
||||
else if ((data >= -2147483648LL) && (data <= 2147483647)) {
|
||||
// 1Byte prefix + 4Byte data
|
||||
unsigned char oneBytePrefix = (unsigned char) rd_item + 0x03;
|
||||
INT32 localData = (INT32)data;
|
||||
rd_append_byte(oneBytePrefix, rpt_desc);
|
||||
rd_append_byte(localData & 0xFF, rpt_desc);
|
||||
rd_append_byte(localData >> 8 & 0xFF, rpt_desc);
|
||||
rd_append_byte(localData >> 16 & 0xFF, rpt_desc);
|
||||
rd_append_byte(localData >> 24 & 0xFF, rpt_desc);
|
||||
}
|
||||
else {
|
||||
// Data out of 32 bit signed integer range
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Item with unsigned integer data
|
||||
if ((data >= 0) && (data <= 0xFF)) {
|
||||
// 1Byte prefix + 1Byte data
|
||||
unsigned char oneBytePrefix = (unsigned char) rd_item + 0x01;
|
||||
unsigned char localData = (unsigned char)data;
|
||||
rd_append_byte(oneBytePrefix, rpt_desc);
|
||||
rd_append_byte(localData & 0xFF, rpt_desc);
|
||||
}
|
||||
else if ((data >= 0) && (data <= 0xFFFF)) {
|
||||
// 1Byte prefix + 2Byte data
|
||||
unsigned char oneBytePrefix = (unsigned char) rd_item + 0x02;
|
||||
UINT16 localData = (UINT16)data;
|
||||
rd_append_byte(oneBytePrefix, rpt_desc);
|
||||
rd_append_byte(localData & 0xFF, rpt_desc);
|
||||
rd_append_byte(localData >> 8 & 0xFF, rpt_desc);
|
||||
}
|
||||
else if ((data >= 0) && (data <= 0xFFFFFFFF)) {
|
||||
// 1Byte prefix + 4Byte data
|
||||
unsigned char oneBytePrefix = (unsigned char) rd_item + 0x03;
|
||||
UINT32 localData = (UINT32)data;
|
||||
rd_append_byte(oneBytePrefix, rpt_desc);
|
||||
rd_append_byte(localData & 0xFF, rpt_desc);
|
||||
rd_append_byte(localData >> 8 & 0xFF, rpt_desc);
|
||||
rd_append_byte(localData >> 16 & 0xFF, rpt_desc);
|
||||
rd_append_byte(localData >> 24 & 0xFF, rpt_desc);
|
||||
}
|
||||
else {
|
||||
// Data out of 32 bit unsigned integer range
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct rd_main_item_node * rd_append_main_item_node(int first_bit, int last_bit, rd_node_type type_of_node, int caps_index, int collection_index, rd_main_items main_item_type, unsigned char report_id, struct rd_main_item_node **list) {
|
||||
struct rd_main_item_node *new_list_node;
|
||||
|
||||
// Determine last node in the list
|
||||
while (*list != NULL)
|
||||
{
|
||||
list = &(*list)->next;
|
||||
}
|
||||
|
||||
new_list_node = malloc(sizeof(*new_list_node)); // Create new list entry
|
||||
new_list_node->FirstBit = first_bit;
|
||||
new_list_node->LastBit = last_bit;
|
||||
new_list_node->TypeOfNode = type_of_node;
|
||||
new_list_node->CapsIndex = caps_index;
|
||||
new_list_node->CollectionIndex = collection_index;
|
||||
new_list_node->MainItemType = main_item_type;
|
||||
new_list_node->ReportID = report_id;
|
||||
new_list_node->next = NULL; // NULL marks last node in the list
|
||||
|
||||
*list = new_list_node;
|
||||
return new_list_node;
|
||||
}
|
||||
|
||||
static struct rd_main_item_node * rd_insert_main_item_node(int first_bit, int last_bit, rd_node_type type_of_node, int caps_index, int collection_index, rd_main_items main_item_type, unsigned char report_id, struct rd_main_item_node **list) {
|
||||
// Insert item after the main item node referenced by list
|
||||
struct rd_main_item_node *next_item = (*list)->next;
|
||||
(*list)->next = NULL;
|
||||
rd_append_main_item_node(first_bit, last_bit, type_of_node, caps_index, collection_index, main_item_type, report_id, list);
|
||||
(*list)->next->next = next_item;
|
||||
return (*list)->next;
|
||||
}
|
||||
|
||||
static struct rd_main_item_node * rd_search_main_item_list_for_bit_position(int search_bit, rd_main_items main_item_type, unsigned char report_id, struct rd_main_item_node **list) {
|
||||
// Determine first INPUT/OUTPUT/FEATURE main item, where the last bit position is equal or greater than the search bit position
|
||||
|
||||
while (((*list)->next->MainItemType != rd_collection) &&
|
||||
((*list)->next->MainItemType != rd_collection_end) &&
|
||||
!(((*list)->next->LastBit >= search_bit) &&
|
||||
((*list)->next->ReportID == report_id) &&
|
||||
((*list)->next->MainItemType == main_item_type))
|
||||
)
|
||||
{
|
||||
list = &(*list)->next;
|
||||
}
|
||||
return *list;
|
||||
}
|
||||
|
||||
int hid_winapi_descriptor_reconstruct_pp_data(void *preparsed_data, unsigned char *buf, size_t buf_size)
|
||||
{
|
||||
hidp_preparsed_data *pp_data = (hidp_preparsed_data *) preparsed_data;
|
||||
|
||||
// Check if MagicKey is correct, to ensure that pp_data points to an valid preparse data structure
|
||||
if (memcmp(pp_data->MagicKey, "HidP KDR", 8) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct rd_buffer rpt_desc = {
|
||||
.buf = buf,
|
||||
.buf_size = buf_size,
|
||||
.byte_idx = 0
|
||||
};
|
||||
|
||||
// Set pointer to the first node of link_collection_nodes
|
||||
phid_pp_link_collection_node link_collection_nodes = (phid_pp_link_collection_node)(((unsigned char*)&pp_data->caps[0]) + pp_data->FirstByteOfLinkCollectionArray);
|
||||
|
||||
// ****************************************************************************************************************************
|
||||
// Create lookup tables for the bit range of each report per collection (position of first bit and last bit in each collection)
|
||||
// coll_bit_range[COLLECTION_INDEX][REPORT_ID][INPUT/OUTPUT/FEATURE]
|
||||
// ****************************************************************************************************************************
|
||||
|
||||
// Allocate memory and initialize lookup table
|
||||
rd_bit_range ****coll_bit_range;
|
||||
coll_bit_range = malloc(pp_data->NumberLinkCollectionNodes * sizeof(*coll_bit_range));
|
||||
for (USHORT collection_node_idx = 0; collection_node_idx < pp_data->NumberLinkCollectionNodes; collection_node_idx++) {
|
||||
coll_bit_range[collection_node_idx] = malloc(256 * sizeof(*coll_bit_range[0])); // 256 possible report IDs (incl. 0x00)
|
||||
for (int reportid_idx = 0; reportid_idx < 256; reportid_idx++) {
|
||||
coll_bit_range[collection_node_idx][reportid_idx] = malloc(NUM_OF_HIDP_REPORT_TYPES * sizeof(*coll_bit_range[0][0]));
|
||||
for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
|
||||
coll_bit_range[collection_node_idx][reportid_idx][rt_idx] = malloc(sizeof(rd_bit_range));
|
||||
coll_bit_range[collection_node_idx][reportid_idx][rt_idx]->FirstBit = -1;
|
||||
coll_bit_range[collection_node_idx][reportid_idx][rt_idx]->LastBit = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fill the lookup table where caps exist
|
||||
for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
|
||||
for (USHORT caps_idx = pp_data->caps_info[rt_idx].FirstCap; caps_idx < pp_data->caps_info[rt_idx].LastCap; caps_idx++) {
|
||||
int first_bit, last_bit;
|
||||
first_bit = (pp_data->caps[caps_idx].BytePosition - 1) * 8
|
||||
+ pp_data->caps[caps_idx].BitPosition;
|
||||
last_bit = first_bit + pp_data->caps[caps_idx].ReportSize
|
||||
* pp_data->caps[caps_idx].ReportCount - 1;
|
||||
if (coll_bit_range[pp_data->caps[caps_idx].LinkCollection][pp_data->caps[caps_idx].ReportID][rt_idx]->FirstBit == -1 ||
|
||||
coll_bit_range[pp_data->caps[caps_idx].LinkCollection][pp_data->caps[caps_idx].ReportID][rt_idx]->FirstBit > first_bit) {
|
||||
coll_bit_range[pp_data->caps[caps_idx].LinkCollection][pp_data->caps[caps_idx].ReportID][rt_idx]->FirstBit = first_bit;
|
||||
}
|
||||
if (coll_bit_range[pp_data->caps[caps_idx].LinkCollection][pp_data->caps[caps_idx].ReportID][rt_idx]->LastBit < last_bit) {
|
||||
coll_bit_range[pp_data->caps[caps_idx].LinkCollection][pp_data->caps[caps_idx].ReportID][rt_idx]->LastBit = last_bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// *************************************************************************
|
||||
// -Determine hierachy levels of each collections and store it in:
|
||||
// coll_levels[COLLECTION_INDEX]
|
||||
// -Determine number of direct childs of each collections and store it in:
|
||||
// coll_number_of_direct_childs[COLLECTION_INDEX]
|
||||
// *************************************************************************
|
||||
int max_coll_level = 0;
|
||||
int *coll_levels = malloc(pp_data->NumberLinkCollectionNodes * sizeof(coll_levels[0]));
|
||||
int *coll_number_of_direct_childs = malloc(pp_data->NumberLinkCollectionNodes * sizeof(coll_number_of_direct_childs[0]));
|
||||
for (USHORT collection_node_idx = 0; collection_node_idx < pp_data->NumberLinkCollectionNodes; collection_node_idx++) {
|
||||
coll_levels[collection_node_idx] = -1;
|
||||
coll_number_of_direct_childs[collection_node_idx] = 0;
|
||||
}
|
||||
|
||||
{
|
||||
int actual_coll_level = 0;
|
||||
USHORT collection_node_idx = 0;
|
||||
while (actual_coll_level >= 0) {
|
||||
coll_levels[collection_node_idx] = actual_coll_level;
|
||||
if ((link_collection_nodes[collection_node_idx].NumberOfChildren > 0) &&
|
||||
(coll_levels[link_collection_nodes[collection_node_idx].FirstChild] == -1)) {
|
||||
actual_coll_level++;
|
||||
coll_levels[collection_node_idx] = actual_coll_level;
|
||||
if (max_coll_level < actual_coll_level) {
|
||||
max_coll_level = actual_coll_level;
|
||||
}
|
||||
coll_number_of_direct_childs[collection_node_idx]++;
|
||||
collection_node_idx = link_collection_nodes[collection_node_idx].FirstChild;
|
||||
}
|
||||
else if (link_collection_nodes[collection_node_idx].NextSibling != 0) {
|
||||
coll_number_of_direct_childs[link_collection_nodes[collection_node_idx].Parent]++;
|
||||
collection_node_idx = link_collection_nodes[collection_node_idx].NextSibling;
|
||||
}
|
||||
else {
|
||||
actual_coll_level--;
|
||||
if (actual_coll_level >= 0) {
|
||||
collection_node_idx = link_collection_nodes[collection_node_idx].Parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// *********************************************************************************
|
||||
// Propagate the bit range of each report from the child collections to their parent
|
||||
// and store the merged result for the parent
|
||||
// *********************************************************************************
|
||||
for (int actual_coll_level = max_coll_level - 1; actual_coll_level >= 0; actual_coll_level--) {
|
||||
for (USHORT collection_node_idx = 0; collection_node_idx < pp_data->NumberLinkCollectionNodes; collection_node_idx++) {
|
||||
if (coll_levels[collection_node_idx] == actual_coll_level) {
|
||||
USHORT child_idx = link_collection_nodes[collection_node_idx].FirstChild;
|
||||
while (child_idx) {
|
||||
for (int reportid_idx = 0; reportid_idx < 256; reportid_idx++) {
|
||||
for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
|
||||
// Merge bit range from childs
|
||||
if ((coll_bit_range[child_idx][reportid_idx][rt_idx]->FirstBit != -1) &&
|
||||
(coll_bit_range[collection_node_idx][reportid_idx][rt_idx]->FirstBit > coll_bit_range[child_idx][reportid_idx][rt_idx]->FirstBit)) {
|
||||
coll_bit_range[collection_node_idx][reportid_idx][rt_idx]->FirstBit = coll_bit_range[child_idx][reportid_idx][rt_idx]->FirstBit;
|
||||
}
|
||||
if (coll_bit_range[collection_node_idx][reportid_idx][rt_idx]->LastBit < coll_bit_range[child_idx][reportid_idx][rt_idx]->LastBit) {
|
||||
coll_bit_range[collection_node_idx][reportid_idx][rt_idx]->LastBit = coll_bit_range[child_idx][reportid_idx][rt_idx]->LastBit;
|
||||
}
|
||||
child_idx = link_collection_nodes[child_idx].NextSibling;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
// Determine child collection order of the whole hierachy, based on previously determined bit ranges
|
||||
// and store it this index coll_child_order[COLLECTION_INDEX][DIRECT_CHILD_INDEX]
|
||||
// *************************************************************************************************
|
||||
USHORT **coll_child_order;
|
||||
coll_child_order = malloc(pp_data->NumberLinkCollectionNodes * sizeof(*coll_child_order));
|
||||
{
|
||||
BOOLEAN *coll_parsed_flag;
|
||||
coll_parsed_flag = malloc(pp_data->NumberLinkCollectionNodes * sizeof(coll_parsed_flag[0]));
|
||||
for (USHORT collection_node_idx = 0; collection_node_idx < pp_data->NumberLinkCollectionNodes; collection_node_idx++) {
|
||||
coll_parsed_flag[collection_node_idx] = FALSE;
|
||||
}
|
||||
int actual_coll_level = 0;
|
||||
USHORT collection_node_idx = 0;
|
||||
while (actual_coll_level >= 0) {
|
||||
if ((coll_number_of_direct_childs[collection_node_idx] != 0) &&
|
||||
(coll_parsed_flag[link_collection_nodes[collection_node_idx].FirstChild] == FALSE)) {
|
||||
coll_parsed_flag[link_collection_nodes[collection_node_idx].FirstChild] = TRUE;
|
||||
coll_child_order[collection_node_idx] = malloc((coll_number_of_direct_childs[collection_node_idx]) * sizeof(*coll_child_order[0]));
|
||||
|
||||
{
|
||||
// Create list of child collection indices
|
||||
// sorted reverse to the order returned to HidP_GetLinkCollectionNodeschild
|
||||
// which seems to match teh original order, as long as no bit position needs to be considered
|
||||
USHORT child_idx = link_collection_nodes[collection_node_idx].FirstChild;
|
||||
int child_count = coll_number_of_direct_childs[collection_node_idx] - 1;
|
||||
coll_child_order[collection_node_idx][child_count] = child_idx;
|
||||
while (link_collection_nodes[child_idx].NextSibling) {
|
||||
child_count--;
|
||||
child_idx = link_collection_nodes[child_idx].NextSibling;
|
||||
coll_child_order[collection_node_idx][child_count] = child_idx;
|
||||
}
|
||||
}
|
||||
|
||||
if (coll_number_of_direct_childs[collection_node_idx] > 1) {
|
||||
// Sort child collections indices by bit positions
|
||||
for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
|
||||
for (int reportid_idx = 0; reportid_idx < 256; reportid_idx++) {
|
||||
for (int child_idx = 1; child_idx < coll_number_of_direct_childs[collection_node_idx]; child_idx++) {
|
||||
// since the coll_bit_range array is not sorted, we need to reference the collection index in
|
||||
// our sorted coll_child_order array, and look up the corresponding bit ranges for comparing values to sort
|
||||
int prev_coll_idx = coll_child_order[collection_node_idx][child_idx - 1];
|
||||
int cur_coll_idx = coll_child_order[collection_node_idx][child_idx];
|
||||
if ((coll_bit_range[prev_coll_idx][reportid_idx][rt_idx]->FirstBit != -1) &&
|
||||
(coll_bit_range[cur_coll_idx][reportid_idx][rt_idx]->FirstBit != -1) &&
|
||||
(coll_bit_range[prev_coll_idx][reportid_idx][rt_idx]->FirstBit > coll_bit_range[cur_coll_idx][reportid_idx][rt_idx]->FirstBit)) {
|
||||
// Swap position indices of the two compared child collections
|
||||
USHORT idx_latch = coll_child_order[collection_node_idx][child_idx - 1];
|
||||
coll_child_order[collection_node_idx][child_idx - 1] = coll_child_order[collection_node_idx][child_idx];
|
||||
coll_child_order[collection_node_idx][child_idx] = idx_latch;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
actual_coll_level++;
|
||||
collection_node_idx = link_collection_nodes[collection_node_idx].FirstChild;
|
||||
}
|
||||
else if (link_collection_nodes[collection_node_idx].NextSibling != 0) {
|
||||
collection_node_idx = link_collection_nodes[collection_node_idx].NextSibling;
|
||||
}
|
||||
else {
|
||||
actual_coll_level--;
|
||||
if (actual_coll_level >= 0) {
|
||||
collection_node_idx = link_collection_nodes[collection_node_idx].Parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
free(coll_parsed_flag);
|
||||
}
|
||||
|
||||
|
||||
// ***************************************************************************************
|
||||
// Create sorted main_item_list containing all the Collection and CollectionEnd main items
|
||||
// ***************************************************************************************
|
||||
struct rd_main_item_node *main_item_list = NULL; // List root
|
||||
// Lookup table to find the Collection items in the list by index
|
||||
struct rd_main_item_node **coll_begin_lookup = malloc(pp_data->NumberLinkCollectionNodes * sizeof(*coll_begin_lookup));
|
||||
struct rd_main_item_node **coll_end_lookup = malloc(pp_data->NumberLinkCollectionNodes * sizeof(*coll_end_lookup));
|
||||
{
|
||||
int *coll_last_written_child = malloc(pp_data->NumberLinkCollectionNodes * sizeof(coll_last_written_child[0]));
|
||||
for (USHORT collection_node_idx = 0; collection_node_idx < pp_data->NumberLinkCollectionNodes; collection_node_idx++) {
|
||||
coll_last_written_child[collection_node_idx] = -1;
|
||||
}
|
||||
|
||||
int actual_coll_level = 0;
|
||||
USHORT collection_node_idx = 0;
|
||||
struct rd_main_item_node *firstDelimiterNode = NULL;
|
||||
struct rd_main_item_node *delimiterCloseNode = NULL;
|
||||
coll_begin_lookup[0] = rd_append_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_collection, 0, &main_item_list);
|
||||
while (actual_coll_level >= 0) {
|
||||
if ((coll_number_of_direct_childs[collection_node_idx] != 0) &&
|
||||
(coll_last_written_child[collection_node_idx] == -1)) {
|
||||
// Collection has child collections, but none is written to the list yet
|
||||
|
||||
coll_last_written_child[collection_node_idx] = coll_child_order[collection_node_idx][0];
|
||||
collection_node_idx = coll_child_order[collection_node_idx][0];
|
||||
|
||||
// In a HID Report Descriptor, the first usage declared is the most preferred usage for the control.
|
||||
// While the order in the WIN32 capabiliy strutures is the opposite:
|
||||
// Here the preferred usage is the last aliased usage in the sequence.
|
||||
|
||||
if (link_collection_nodes[collection_node_idx].IsAlias && (firstDelimiterNode == NULL)) {
|
||||
// Alliased Collection (First node in link_collection_nodes -> Last entry in report descriptor output)
|
||||
firstDelimiterNode = main_item_list;
|
||||
coll_begin_lookup[collection_node_idx] = rd_append_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_delimiter_usage, 0, &main_item_list);
|
||||
coll_begin_lookup[collection_node_idx] = rd_append_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_delimiter_close, 0, &main_item_list);
|
||||
delimiterCloseNode = main_item_list;
|
||||
}
|
||||
else {
|
||||
// Normal not aliased collection
|
||||
coll_begin_lookup[collection_node_idx] = rd_append_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_collection, 0, &main_item_list);
|
||||
actual_coll_level++;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else if ((coll_number_of_direct_childs[collection_node_idx] > 1) &&
|
||||
(coll_last_written_child[collection_node_idx] != coll_child_order[collection_node_idx][coll_number_of_direct_childs[collection_node_idx] - 1])) {
|
||||
// Collection has child collections, and this is not the first child
|
||||
|
||||
int nextChild = 1;
|
||||
while (coll_last_written_child[collection_node_idx] != coll_child_order[collection_node_idx][nextChild - 1]) {
|
||||
nextChild++;
|
||||
}
|
||||
coll_last_written_child[collection_node_idx] = coll_child_order[collection_node_idx][nextChild];
|
||||
collection_node_idx = coll_child_order[collection_node_idx][nextChild];
|
||||
|
||||
if (link_collection_nodes[collection_node_idx].IsAlias && (firstDelimiterNode == NULL)) {
|
||||
// Alliased Collection (First node in link_collection_nodes -> Last entry in report descriptor output)
|
||||
firstDelimiterNode = main_item_list;
|
||||
coll_begin_lookup[collection_node_idx] = rd_append_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_delimiter_usage, 0, &main_item_list);
|
||||
coll_begin_lookup[collection_node_idx] = rd_append_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_delimiter_close, 0, &main_item_list);
|
||||
delimiterCloseNode = main_item_list;
|
||||
}
|
||||
else if (link_collection_nodes[collection_node_idx].IsAlias && (firstDelimiterNode != NULL)) {
|
||||
coll_begin_lookup[collection_node_idx] = rd_insert_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_delimiter_usage, 0, &firstDelimiterNode);
|
||||
}
|
||||
else if (!link_collection_nodes[collection_node_idx].IsAlias && (firstDelimiterNode != NULL)) {
|
||||
coll_begin_lookup[collection_node_idx] = rd_insert_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_delimiter_usage, 0, &firstDelimiterNode);
|
||||
coll_begin_lookup[collection_node_idx] = rd_insert_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_delimiter_open, 0, &firstDelimiterNode);
|
||||
firstDelimiterNode = NULL;
|
||||
main_item_list = delimiterCloseNode;
|
||||
delimiterCloseNode = NULL; // Last entry of alias has .IsAlias == FALSE
|
||||
}
|
||||
if (!link_collection_nodes[collection_node_idx].IsAlias) {
|
||||
coll_begin_lookup[collection_node_idx] = rd_append_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_collection, 0, &main_item_list);
|
||||
actual_coll_level++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
actual_coll_level--;
|
||||
coll_end_lookup[collection_node_idx] = rd_append_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_collection_end, 0, &main_item_list);
|
||||
collection_node_idx = link_collection_nodes[collection_node_idx].Parent;
|
||||
}
|
||||
}
|
||||
free(coll_last_written_child);
|
||||
}
|
||||
|
||||
|
||||
// ****************************************************************
|
||||
// Inserted Input/Output/Feature main items into the main_item_list
|
||||
// in order of reconstructed bit positions
|
||||
// ****************************************************************
|
||||
for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
|
||||
// Add all value caps to node list
|
||||
struct rd_main_item_node *firstDelimiterNode = NULL;
|
||||
struct rd_main_item_node *delimiterCloseNode = NULL;
|
||||
for (USHORT caps_idx = pp_data->caps_info[rt_idx].FirstCap; caps_idx < pp_data->caps_info[rt_idx].LastCap; caps_idx++) {
|
||||
struct rd_main_item_node *coll_begin = coll_begin_lookup[pp_data->caps[caps_idx].LinkCollection];
|
||||
int first_bit, last_bit;
|
||||
first_bit = (pp_data->caps[caps_idx].BytePosition - 1) * 8 +
|
||||
pp_data->caps[caps_idx].BitPosition;
|
||||
last_bit = first_bit + pp_data->caps[caps_idx].ReportSize *
|
||||
pp_data->caps[caps_idx].ReportCount - 1;
|
||||
|
||||
for (int child_idx = 0; child_idx < coll_number_of_direct_childs[pp_data->caps[caps_idx].LinkCollection]; child_idx++) {
|
||||
// Determine in which section before/between/after child collection the item should be inserted
|
||||
if (first_bit < coll_bit_range[coll_child_order[pp_data->caps[caps_idx].LinkCollection][child_idx]][pp_data->caps[caps_idx].ReportID][rt_idx]->FirstBit)
|
||||
{
|
||||
// Note, that the default value for undefined coll_bit_range is -1, which can't be greater than the bit position
|
||||
break;
|
||||
}
|
||||
coll_begin = coll_end_lookup[coll_child_order[pp_data->caps[caps_idx].LinkCollection][child_idx]];
|
||||
}
|
||||
struct rd_main_item_node *list_node;
|
||||
list_node = rd_search_main_item_list_for_bit_position(first_bit, (rd_main_items) rt_idx, pp_data->caps[caps_idx].ReportID, &coll_begin);
|
||||
|
||||
// In a HID Report Descriptor, the first usage declared is the most preferred usage for the control.
|
||||
// While the order in the WIN32 capabiliy strutures is the opposite:
|
||||
// Here the preferred usage is the last aliased usage in the sequence.
|
||||
|
||||
if (pp_data->caps[caps_idx].IsAlias && (firstDelimiterNode == NULL)) {
|
||||
// Alliased Usage (First node in pp_data->caps -> Last entry in report descriptor output)
|
||||
firstDelimiterNode = list_node;
|
||||
rd_insert_main_item_node(first_bit, last_bit, rd_item_node_cap, caps_idx, pp_data->caps[caps_idx].LinkCollection, rd_delimiter_usage, pp_data->caps[caps_idx].ReportID, &list_node);
|
||||
rd_insert_main_item_node(first_bit, last_bit, rd_item_node_cap, caps_idx, pp_data->caps[caps_idx].LinkCollection, rd_delimiter_close, pp_data->caps[caps_idx].ReportID, &list_node);
|
||||
delimiterCloseNode = list_node;
|
||||
} else if (pp_data->caps[caps_idx].IsAlias && (firstDelimiterNode != NULL)) {
|
||||
rd_insert_main_item_node(first_bit, last_bit, rd_item_node_cap, caps_idx, pp_data->caps[caps_idx].LinkCollection, rd_delimiter_usage, pp_data->caps[caps_idx].ReportID, &list_node);
|
||||
}
|
||||
else if (!pp_data->caps[caps_idx].IsAlias && (firstDelimiterNode != NULL)) {
|
||||
// Alliased Collection (Last node in pp_data->caps -> First entry in report descriptor output)
|
||||
rd_insert_main_item_node(first_bit, last_bit, rd_item_node_cap, caps_idx, pp_data->caps[caps_idx].LinkCollection, rd_delimiter_usage, pp_data->caps[caps_idx].ReportID, &list_node);
|
||||
rd_insert_main_item_node(first_bit, last_bit, rd_item_node_cap, caps_idx, pp_data->caps[caps_idx].LinkCollection, rd_delimiter_open, pp_data->caps[caps_idx].ReportID, &list_node);
|
||||
firstDelimiterNode = NULL;
|
||||
list_node = delimiterCloseNode;
|
||||
delimiterCloseNode = NULL; // Last entry of alias has .IsAlias == FALSE
|
||||
}
|
||||
if (!pp_data->caps[caps_idx].IsAlias) {
|
||||
rd_insert_main_item_node(first_bit, last_bit, rd_item_node_cap, caps_idx, pp_data->caps[caps_idx].LinkCollection, (rd_main_items) rt_idx, pp_data->caps[caps_idx].ReportID, &list_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ***********************************************************
|
||||
// Add const main items for padding to main_item_list
|
||||
// -To fill all bit gaps
|
||||
// -At each report end for 8bit padding
|
||||
// Note that information about the padding at the report end,
|
||||
// is not stored in the preparsed data, but in practice all
|
||||
// report descriptors seem to have it, as assumed here.
|
||||
// ***********************************************************
|
||||
{
|
||||
int last_bit_position[NUM_OF_HIDP_REPORT_TYPES][256];
|
||||
struct rd_main_item_node *last_report_item_lookup[NUM_OF_HIDP_REPORT_TYPES][256];
|
||||
for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
|
||||
for (int reportid_idx = 0; reportid_idx < 256; reportid_idx++) {
|
||||
last_bit_position[rt_idx][reportid_idx] = -1;
|
||||
last_report_item_lookup[rt_idx][reportid_idx] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct rd_main_item_node *list = main_item_list; // List root;
|
||||
|
||||
while (list->next != NULL)
|
||||
{
|
||||
if ((list->MainItemType >= rd_input) &&
|
||||
(list->MainItemType <= rd_feature)) {
|
||||
// INPUT, OUTPUT or FEATURE
|
||||
if (list->FirstBit != -1) {
|
||||
if ((last_bit_position[list->MainItemType][list->ReportID] + 1 != list->FirstBit) &&
|
||||
(last_report_item_lookup[list->MainItemType][list->ReportID] != NULL) &&
|
||||
(last_report_item_lookup[list->MainItemType][list->ReportID]->FirstBit != list->FirstBit) // Happens in case of IsMultipleItemsForArray for multiple dedicated usages for a multi-button array
|
||||
) {
|
||||
struct rd_main_item_node *list_node = rd_search_main_item_list_for_bit_position(last_bit_position[list->MainItemType][list->ReportID], list->MainItemType, list->ReportID, &last_report_item_lookup[list->MainItemType][list->ReportID]);
|
||||
rd_insert_main_item_node(last_bit_position[list->MainItemType][list->ReportID] + 1, list->FirstBit - 1, rd_item_node_padding, -1, 0, list->MainItemType, list->ReportID, &list_node);
|
||||
}
|
||||
last_bit_position[list->MainItemType][list->ReportID] = list->LastBit;
|
||||
last_report_item_lookup[list->MainItemType][list->ReportID] = list;
|
||||
}
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
// Add 8 bit padding at each report end
|
||||
for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
|
||||
for (int reportid_idx = 0; reportid_idx < 256; reportid_idx++) {
|
||||
if (last_bit_position[rt_idx][reportid_idx] != -1) {
|
||||
int padding = 8 - ((last_bit_position[rt_idx][reportid_idx] + 1) % 8);
|
||||
if (padding < 8) {
|
||||
// Insert padding item after item referenced in last_report_item_lookup
|
||||
rd_insert_main_item_node(last_bit_position[rt_idx][reportid_idx] + 1, last_bit_position[rt_idx][reportid_idx] + padding, rd_item_node_padding, -1, 0, (rd_main_items) rt_idx, (unsigned char) reportid_idx, &last_report_item_lookup[rt_idx][reportid_idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ***********************************
|
||||
// Encode the report descriptor output
|
||||
// ***********************************
|
||||
UCHAR last_report_id = 0;
|
||||
USAGE last_usage_page = 0;
|
||||
LONG last_physical_min = 0;// If both, Physical Minimum and Physical Maximum are 0, the logical limits should be taken as physical limits according USB HID spec 1.11 chapter 6.2.2.7
|
||||
LONG last_physical_max = 0;
|
||||
ULONG last_unit_exponent = 0; // If Unit Exponent is Undefined it should be considered as 0 according USB HID spec 1.11 chapter 6.2.2.7
|
||||
ULONG last_unit = 0; // If the first nibble is 7, or second nibble of Unit is 0, the unit is None according USB HID spec 1.11 chapter 6.2.2.7
|
||||
BOOLEAN inhibit_write_of_usage = FALSE; // Needed in case of delimited usage print, before the normal collection or cap
|
||||
int report_count = 0;
|
||||
while (main_item_list != NULL)
|
||||
{
|
||||
int rt_idx = main_item_list->MainItemType;
|
||||
int caps_idx = main_item_list->CapsIndex;
|
||||
if (main_item_list->MainItemType == rd_collection) {
|
||||
if (last_usage_page != link_collection_nodes[main_item_list->CollectionIndex].LinkUsagePage) {
|
||||
// Write "Usage Page" at the begin of a collection - except it refers the same table as wrote last
|
||||
rd_write_short_item(rd_global_usage_page, link_collection_nodes[main_item_list->CollectionIndex].LinkUsagePage, &rpt_desc);
|
||||
last_usage_page = link_collection_nodes[main_item_list->CollectionIndex].LinkUsagePage;
|
||||
}
|
||||
if (inhibit_write_of_usage) {
|
||||
// Inhibit only once after DELIMITER statement
|
||||
inhibit_write_of_usage = FALSE;
|
||||
}
|
||||
else {
|
||||
// Write "Usage" of collection
|
||||
rd_write_short_item(rd_local_usage, link_collection_nodes[main_item_list->CollectionIndex].LinkUsage, &rpt_desc);
|
||||
}
|
||||
// Write begin of "Collection"
|
||||
rd_write_short_item(rd_main_collection, link_collection_nodes[main_item_list->CollectionIndex].CollectionType, &rpt_desc);
|
||||
}
|
||||
else if (main_item_list->MainItemType == rd_collection_end) {
|
||||
// Write "End Collection"
|
||||
rd_write_short_item(rd_main_collection_end, 0, &rpt_desc);
|
||||
}
|
||||
else if (main_item_list->MainItemType == rd_delimiter_open) {
|
||||
if (main_item_list->CollectionIndex != -1) {
|
||||
// Write "Usage Page" inside of a collection delmiter section
|
||||
if (last_usage_page != link_collection_nodes[main_item_list->CollectionIndex].LinkUsagePage) {
|
||||
rd_write_short_item(rd_global_usage_page, link_collection_nodes[main_item_list->CollectionIndex].LinkUsagePage, &rpt_desc);
|
||||
last_usage_page = link_collection_nodes[main_item_list->CollectionIndex].LinkUsagePage;
|
||||
}
|
||||
}
|
||||
else if (main_item_list->CapsIndex != 0) {
|
||||
// Write "Usage Page" inside of a main item delmiter section
|
||||
if (pp_data->caps[caps_idx].UsagePage != last_usage_page) {
|
||||
rd_write_short_item(rd_global_usage_page, pp_data->caps[caps_idx].UsagePage, &rpt_desc);
|
||||
last_usage_page = pp_data->caps[caps_idx].UsagePage;
|
||||
}
|
||||
}
|
||||
// Write "Delimiter Open"
|
||||
rd_write_short_item(rd_local_delimiter, 1, &rpt_desc); // 1 = open set of aliased usages
|
||||
}
|
||||
else if (main_item_list->MainItemType == rd_delimiter_usage) {
|
||||
if (main_item_list->CollectionIndex != -1) {
|
||||
// Write aliased collection "Usage"
|
||||
rd_write_short_item(rd_local_usage, link_collection_nodes[main_item_list->CollectionIndex].LinkUsage, &rpt_desc);
|
||||
} if (main_item_list->CapsIndex != 0) {
|
||||
// Write aliased main item range from "Usage Minimum" to "Usage Maximum"
|
||||
if (pp_data->caps[caps_idx].IsRange) {
|
||||
rd_write_short_item(rd_local_usage_minimum, pp_data->caps[caps_idx].Range.UsageMin, &rpt_desc);
|
||||
rd_write_short_item(rd_local_usage_maximum, pp_data->caps[caps_idx].Range.UsageMax, &rpt_desc);
|
||||
}
|
||||
else {
|
||||
// Write single aliased main item "Usage"
|
||||
rd_write_short_item(rd_local_usage, pp_data->caps[caps_idx].NotRange.Usage, &rpt_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (main_item_list->MainItemType == rd_delimiter_close) {
|
||||
// Write "Delimiter Close"
|
||||
rd_write_short_item(rd_local_delimiter, 0, &rpt_desc); // 0 = close set of aliased usages
|
||||
// Inhibit next usage write
|
||||
inhibit_write_of_usage = TRUE;
|
||||
}
|
||||
else if (main_item_list->TypeOfNode == rd_item_node_padding) {
|
||||
// Padding
|
||||
// The preparsed data doesn't contain any information about padding. Therefore all undefined gaps
|
||||
// in the reports are filled with the same style of constant padding.
|
||||
|
||||
// Write "Report Size" with number of padding bits
|
||||
rd_write_short_item(rd_global_report_size, (main_item_list->LastBit - main_item_list->FirstBit + 1), &rpt_desc);
|
||||
|
||||
// Write "Report Count" for padding always as 1
|
||||
rd_write_short_item(rd_global_report_count, 1, &rpt_desc);
|
||||
|
||||
if (rt_idx == HidP_Input) {
|
||||
// Write "Input" main item - We know it's Constant - We can only guess the other bits, but they don't matter in case of const
|
||||
rd_write_short_item(rd_main_input, 0x03, &rpt_desc); // Const / Abs
|
||||
}
|
||||
else if (rt_idx == HidP_Output) {
|
||||
// Write "Output" main item - We know it's Constant - We can only guess the other bits, but they don't matter in case of const
|
||||
rd_write_short_item(rd_main_output, 0x03, &rpt_desc); // Const / Abs
|
||||
}
|
||||
else if (rt_idx == HidP_Feature) {
|
||||
// Write "Feature" main item - We know it's Constant - We can only guess the other bits, but they don't matter in case of const
|
||||
rd_write_short_item(rd_main_feature, 0x03, &rpt_desc); // Const / Abs
|
||||
}
|
||||
report_count = 0;
|
||||
}
|
||||
else if (pp_data->caps[caps_idx].IsButtonCap) {
|
||||
// Button
|
||||
// (The preparsed data contain different data for 1 bit Button caps, than for parametric Value caps)
|
||||
|
||||
if (last_report_id != pp_data->caps[caps_idx].ReportID) {
|
||||
// Write "Report ID" if changed
|
||||
rd_write_short_item(rd_global_report_id, pp_data->caps[caps_idx].ReportID, &rpt_desc);
|
||||
last_report_id = pp_data->caps[caps_idx].ReportID;
|
||||
}
|
||||
|
||||
// Write "Usage Page" when changed
|
||||
if (pp_data->caps[caps_idx].UsagePage != last_usage_page) {
|
||||
rd_write_short_item(rd_global_usage_page, pp_data->caps[caps_idx].UsagePage, &rpt_desc);
|
||||
last_usage_page = pp_data->caps[caps_idx].UsagePage;
|
||||
}
|
||||
|
||||
// Write only local report items for each cap, if ReportCount > 1
|
||||
if (pp_data->caps[caps_idx].IsRange) {
|
||||
report_count += (pp_data->caps[caps_idx].Range.DataIndexMax - pp_data->caps[caps_idx].Range.DataIndexMin);
|
||||
}
|
||||
|
||||
if (inhibit_write_of_usage) {
|
||||
// Inhibit only once after Delimiter - Reset flag
|
||||
inhibit_write_of_usage = FALSE;
|
||||
}
|
||||
else {
|
||||
if (pp_data->caps[caps_idx].IsRange) {
|
||||
// Write range from "Usage Minimum" to "Usage Maximum"
|
||||
rd_write_short_item(rd_local_usage_minimum, pp_data->caps[caps_idx].Range.UsageMin, &rpt_desc);
|
||||
rd_write_short_item(rd_local_usage_maximum, pp_data->caps[caps_idx].Range.UsageMax, &rpt_desc);
|
||||
}
|
||||
else {
|
||||
// Write single "Usage"
|
||||
rd_write_short_item(rd_local_usage, pp_data->caps[caps_idx].NotRange.Usage, &rpt_desc);
|
||||
}
|
||||
}
|
||||
|
||||
if (pp_data->caps[caps_idx].IsDesignatorRange) {
|
||||
// Write physical descriptor indices range from "Designator Minimum" to "Designator Maximum"
|
||||
rd_write_short_item(rd_local_designator_minimum, pp_data->caps[caps_idx].Range.DesignatorMin, &rpt_desc);
|
||||
rd_write_short_item(rd_local_designator_maximum, pp_data->caps[caps_idx].Range.DesignatorMax, &rpt_desc);
|
||||
}
|
||||
else if (pp_data->caps[caps_idx].NotRange.DesignatorIndex != 0) {
|
||||
// Designator set 0 is a special descriptor set (of the HID Physical Descriptor),
|
||||
// that specifies the number of additional descriptor sets.
|
||||
// Therefore Designator Index 0 can never be a useful reference for a control and we can inhibit it.
|
||||
// Write single "Designator Index"
|
||||
rd_write_short_item(rd_local_designator_index, pp_data->caps[caps_idx].NotRange.DesignatorIndex, &rpt_desc);
|
||||
}
|
||||
|
||||
if (pp_data->caps[caps_idx].IsStringRange) {
|
||||
// Write range of indices of the USB string descriptor, from "String Minimum" to "String Maximum"
|
||||
rd_write_short_item(rd_local_string_minimum, pp_data->caps[caps_idx].Range.StringMin, &rpt_desc);
|
||||
rd_write_short_item(rd_local_string_maximum, pp_data->caps[caps_idx].Range.StringMax, &rpt_desc);
|
||||
}
|
||||
else if (pp_data->caps[caps_idx].NotRange.StringIndex != 0) {
|
||||
// String Index 0 is a special entry of the USB string descriptor, that contains a list of supported languages,
|
||||
// therefore Designator Index 0 can never be a useful reference for a control and we can inhibit it.
|
||||
// Write single "String Index"
|
||||
rd_write_short_item(rd_local_string, pp_data->caps[caps_idx].NotRange.StringIndex, &rpt_desc);
|
||||
}
|
||||
|
||||
if ((main_item_list->next != NULL) &&
|
||||
((int)main_item_list->next->MainItemType == rt_idx) &&
|
||||
(main_item_list->next->TypeOfNode == rd_item_node_cap) &&
|
||||
(pp_data->caps[main_item_list->next->CapsIndex].IsButtonCap) &&
|
||||
(!pp_data->caps[caps_idx].IsRange) && // This node in list is no array
|
||||
(!pp_data->caps[main_item_list->next->CapsIndex].IsRange) && // Next node in list is no array
|
||||
(pp_data->caps[main_item_list->next->CapsIndex].UsagePage == pp_data->caps[caps_idx].UsagePage) &&
|
||||
(pp_data->caps[main_item_list->next->CapsIndex].ReportID == pp_data->caps[caps_idx].ReportID) &&
|
||||
(pp_data->caps[main_item_list->next->CapsIndex].BitField == pp_data->caps[caps_idx].BitField)
|
||||
) {
|
||||
if (main_item_list->next->FirstBit != main_item_list->FirstBit) {
|
||||
// In case of IsMultipleItemsForArray for multiple dedicated usages for a multi-button array, the report count should be incremented
|
||||
|
||||
// Skip global items until any of them changes, than use ReportCount item to write the count of identical report fields
|
||||
report_count++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
if ((pp_data->caps[caps_idx].Button.LogicalMin == 0) &&
|
||||
(pp_data->caps[caps_idx].Button.LogicalMax == 0)) {
|
||||
// While a HID report descriptor must always contain LogicalMinimum and LogicalMaximum,
|
||||
// the preparsed data contain both fields set to zero, for the case of simple buttons
|
||||
// Write "Logical Minimum" set to 0 and "Logical Maximum" set to 1
|
||||
rd_write_short_item(rd_global_logical_minimum, 0, &rpt_desc);
|
||||
rd_write_short_item(rd_global_logical_maximum, 1, &rpt_desc);
|
||||
}
|
||||
else {
|
||||
// Write logical range from "Logical Minimum" to "Logical Maximum"
|
||||
rd_write_short_item(rd_global_logical_minimum, pp_data->caps[caps_idx].Button.LogicalMin, &rpt_desc);
|
||||
rd_write_short_item(rd_global_logical_maximum, pp_data->caps[caps_idx].Button.LogicalMax, &rpt_desc);
|
||||
}
|
||||
|
||||
// Write "Report Size"
|
||||
rd_write_short_item(rd_global_report_size, pp_data->caps[caps_idx].ReportSize, &rpt_desc);
|
||||
|
||||
// Write "Report Count"
|
||||
if (!pp_data->caps[caps_idx].IsRange) {
|
||||
// Variable bit field with one bit per button
|
||||
// In case of multiple usages with the same items, only "Usage" is written per cap, and "Report Count" is incremented
|
||||
rd_write_short_item(rd_global_report_count, pp_data->caps[caps_idx].ReportCount + report_count, &rpt_desc);
|
||||
}
|
||||
else {
|
||||
// Button array of "Report Size" x "Report Count
|
||||
rd_write_short_item(rd_global_report_count, pp_data->caps[caps_idx].ReportCount, &rpt_desc);
|
||||
}
|
||||
|
||||
|
||||
// Buttons have only 1 bit and therefore no physical limits/units -> Set to undefined state
|
||||
if (last_physical_min != 0) {
|
||||
// Write "Physical Minimum", but only if changed
|
||||
last_physical_min = 0;
|
||||
rd_write_short_item(rd_global_physical_minimum, last_physical_min, &rpt_desc);
|
||||
}
|
||||
if (last_physical_max != 0) {
|
||||
// Write "Physical Maximum", but only if changed
|
||||
last_physical_max = 0;
|
||||
rd_write_short_item(rd_global_physical_maximum, last_physical_max, &rpt_desc);
|
||||
}
|
||||
if (last_unit_exponent != 0) {
|
||||
// Write "Unit Exponent", but only if changed
|
||||
last_unit_exponent = 0;
|
||||
rd_write_short_item(rd_global_unit_exponent, last_unit_exponent, &rpt_desc);
|
||||
}
|
||||
if (last_unit != 0) {
|
||||
// Write "Unit",but only if changed
|
||||
last_unit = 0;
|
||||
rd_write_short_item(rd_global_unit, last_unit, &rpt_desc);
|
||||
}
|
||||
|
||||
// Write "Input" main item
|
||||
if (rt_idx == HidP_Input) {
|
||||
rd_write_short_item(rd_main_input, pp_data->caps[caps_idx].BitField, &rpt_desc);
|
||||
}
|
||||
// Write "Output" main item
|
||||
else if (rt_idx == HidP_Output) {
|
||||
rd_write_short_item(rd_main_output, pp_data->caps[caps_idx].BitField, &rpt_desc);
|
||||
}
|
||||
// Write "Feature" main item
|
||||
else if (rt_idx == HidP_Feature) {
|
||||
rd_write_short_item(rd_main_feature, pp_data->caps[caps_idx].BitField, &rpt_desc);
|
||||
}
|
||||
report_count = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
if (last_report_id != pp_data->caps[caps_idx].ReportID) {
|
||||
// Write "Report ID" if changed
|
||||
rd_write_short_item(rd_global_report_id, pp_data->caps[caps_idx].ReportID, &rpt_desc);
|
||||
last_report_id = pp_data->caps[caps_idx].ReportID;
|
||||
}
|
||||
|
||||
// Write "Usage Page" if changed
|
||||
if (pp_data->caps[caps_idx].UsagePage != last_usage_page) {
|
||||
rd_write_short_item(rd_global_usage_page, pp_data->caps[caps_idx].UsagePage, &rpt_desc);
|
||||
last_usage_page = pp_data->caps[caps_idx].UsagePage;
|
||||
}
|
||||
|
||||
if (inhibit_write_of_usage) {
|
||||
// Inhibit only once after Delimiter - Reset flag
|
||||
inhibit_write_of_usage = FALSE;
|
||||
}
|
||||
else {
|
||||
if (pp_data->caps[caps_idx].IsRange) {
|
||||
// Write usage range from "Usage Minimum" to "Usage Maximum"
|
||||
rd_write_short_item(rd_local_usage_minimum, pp_data->caps[caps_idx].Range.UsageMin, &rpt_desc);
|
||||
rd_write_short_item(rd_local_usage_maximum, pp_data->caps[caps_idx].Range.UsageMax, &rpt_desc);
|
||||
}
|
||||
else {
|
||||
// Write single "Usage"
|
||||
rd_write_short_item(rd_local_usage, pp_data->caps[caps_idx].NotRange.Usage, &rpt_desc);
|
||||
}
|
||||
}
|
||||
|
||||
if (pp_data->caps[caps_idx].IsDesignatorRange) {
|
||||
// Write physical descriptor indices range from "Designator Minimum" to "Designator Maximum"
|
||||
rd_write_short_item(rd_local_designator_minimum, pp_data->caps[caps_idx].Range.DesignatorMin, &rpt_desc);
|
||||
rd_write_short_item(rd_local_designator_maximum, pp_data->caps[caps_idx].Range.DesignatorMax, &rpt_desc);
|
||||
}
|
||||
else if (pp_data->caps[caps_idx].NotRange.DesignatorIndex != 0) {
|
||||
// Designator set 0 is a special descriptor set (of the HID Physical Descriptor),
|
||||
// that specifies the number of additional descriptor sets.
|
||||
// Therefore Designator Index 0 can never be a useful reference for a control and we can inhibit it.
|
||||
// Write single "Designator Index"
|
||||
rd_write_short_item(rd_local_designator_index, pp_data->caps[caps_idx].NotRange.DesignatorIndex, &rpt_desc);
|
||||
}
|
||||
|
||||
if (pp_data->caps[caps_idx].IsStringRange) {
|
||||
// Write range of indices of the USB string descriptor, from "String Minimum" to "String Maximum"
|
||||
rd_write_short_item(rd_local_string_minimum, pp_data->caps[caps_idx].Range.StringMin, &rpt_desc);
|
||||
rd_write_short_item(rd_local_string_maximum, pp_data->caps[caps_idx].Range.StringMax, &rpt_desc);
|
||||
}
|
||||
else if (pp_data->caps[caps_idx].NotRange.StringIndex != 0) {
|
||||
// String Index 0 is a special entry of the USB string descriptor, that contains a list of supported languages,
|
||||
// therefore Designator Index 0 can never be a useful reference for a control and we can inhibit it.
|
||||
// Write single "String Index"
|
||||
rd_write_short_item(rd_local_string, pp_data->caps[caps_idx].NotRange.StringIndex, &rpt_desc);
|
||||
}
|
||||
|
||||
if ((pp_data->caps[caps_idx].BitField & 0x02) != 0x02) {
|
||||
// In case of an value array overwrite "Report Count"
|
||||
pp_data->caps[caps_idx].ReportCount = pp_data->caps[caps_idx].Range.DataIndexMax - pp_data->caps[caps_idx].Range.DataIndexMin + 1;
|
||||
}
|
||||
|
||||
|
||||
// Print only local report items for each cap, if ReportCount > 1
|
||||
if ((main_item_list->next != NULL) &&
|
||||
((int) main_item_list->next->MainItemType == rt_idx) &&
|
||||
(main_item_list->next->TypeOfNode == rd_item_node_cap) &&
|
||||
(!pp_data->caps[main_item_list->next->CapsIndex].IsButtonCap) &&
|
||||
(!pp_data->caps[caps_idx].IsRange) && // This node in list is no array
|
||||
(!pp_data->caps[main_item_list->next->CapsIndex].IsRange) && // Next node in list is no array
|
||||
(pp_data->caps[main_item_list->next->CapsIndex].UsagePage == pp_data->caps[caps_idx].UsagePage) &&
|
||||
(pp_data->caps[main_item_list->next->CapsIndex].NotButton.LogicalMin == pp_data->caps[caps_idx].NotButton.LogicalMin) &&
|
||||
(pp_data->caps[main_item_list->next->CapsIndex].NotButton.LogicalMax == pp_data->caps[caps_idx].NotButton.LogicalMax) &&
|
||||
(pp_data->caps[main_item_list->next->CapsIndex].NotButton.PhysicalMin == pp_data->caps[caps_idx].NotButton.PhysicalMin) &&
|
||||
(pp_data->caps[main_item_list->next->CapsIndex].NotButton.PhysicalMax == pp_data->caps[caps_idx].NotButton.PhysicalMax) &&
|
||||
(pp_data->caps[main_item_list->next->CapsIndex].UnitsExp == pp_data->caps[caps_idx].UnitsExp) &&
|
||||
(pp_data->caps[main_item_list->next->CapsIndex].Units == pp_data->caps[caps_idx].Units) &&
|
||||
(pp_data->caps[main_item_list->next->CapsIndex].ReportSize == pp_data->caps[caps_idx].ReportSize) &&
|
||||
(pp_data->caps[main_item_list->next->CapsIndex].ReportID == pp_data->caps[caps_idx].ReportID) &&
|
||||
(pp_data->caps[main_item_list->next->CapsIndex].BitField == pp_data->caps[caps_idx].BitField) &&
|
||||
(pp_data->caps[main_item_list->next->CapsIndex].ReportCount == 1) &&
|
||||
(pp_data->caps[caps_idx].ReportCount == 1)
|
||||
) {
|
||||
// Skip global items until any of them changes, than use ReportCount item to write the count of identical report fields
|
||||
report_count++;
|
||||
}
|
||||
else {
|
||||
// Value
|
||||
|
||||
// Write logical range from "Logical Minimum" to "Logical Maximum"
|
||||
rd_write_short_item(rd_global_logical_minimum, pp_data->caps[caps_idx].NotButton.LogicalMin, &rpt_desc);
|
||||
rd_write_short_item(rd_global_logical_maximum, pp_data->caps[caps_idx].NotButton.LogicalMax, &rpt_desc);
|
||||
|
||||
if ((last_physical_min != pp_data->caps[caps_idx].NotButton.PhysicalMin) ||
|
||||
(last_physical_max != pp_data->caps[caps_idx].NotButton.PhysicalMax)) {
|
||||
// Write range from "Physical Minimum" to " Physical Maximum", but only if one of them changed
|
||||
rd_write_short_item(rd_global_physical_minimum, pp_data->caps[caps_idx].NotButton.PhysicalMin, &rpt_desc);
|
||||
last_physical_min = pp_data->caps[caps_idx].NotButton.PhysicalMin;
|
||||
rd_write_short_item(rd_global_physical_maximum, pp_data->caps[caps_idx].NotButton.PhysicalMax, &rpt_desc);
|
||||
last_physical_max = pp_data->caps[caps_idx].NotButton.PhysicalMax;
|
||||
}
|
||||
|
||||
|
||||
if (last_unit_exponent != pp_data->caps[caps_idx].UnitsExp) {
|
||||
// Write "Unit Exponent", but only if changed
|
||||
rd_write_short_item(rd_global_unit_exponent, pp_data->caps[caps_idx].UnitsExp, &rpt_desc);
|
||||
last_unit_exponent = pp_data->caps[caps_idx].UnitsExp;
|
||||
}
|
||||
|
||||
if (last_unit != pp_data->caps[caps_idx].Units) {
|
||||
// Write physical "Unit", but only if changed
|
||||
rd_write_short_item(rd_global_unit, pp_data->caps[caps_idx].Units, &rpt_desc);
|
||||
last_unit = pp_data->caps[caps_idx].Units;
|
||||
}
|
||||
|
||||
// Write "Report Size"
|
||||
rd_write_short_item(rd_global_report_size, pp_data->caps[caps_idx].ReportSize, &rpt_desc);
|
||||
|
||||
// Write "Report Count"
|
||||
rd_write_short_item(rd_global_report_count, pp_data->caps[caps_idx].ReportCount + report_count, &rpt_desc);
|
||||
|
||||
if (rt_idx == HidP_Input) {
|
||||
// Write "Input" main item
|
||||
rd_write_short_item(rd_main_input, pp_data->caps[caps_idx].BitField, &rpt_desc);
|
||||
}
|
||||
else if (rt_idx == HidP_Output) {
|
||||
// Write "Output" main item
|
||||
rd_write_short_item(rd_main_output, pp_data->caps[caps_idx].BitField, &rpt_desc);
|
||||
}
|
||||
else if (rt_idx == HidP_Feature) {
|
||||
// Write "Feature" main item
|
||||
rd_write_short_item(rd_main_feature, pp_data->caps[caps_idx].BitField, &rpt_desc);
|
||||
}
|
||||
report_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Go to next item in main_item_list and free the memory of the actual item
|
||||
struct rd_main_item_node *main_item_list_prev = main_item_list;
|
||||
main_item_list = main_item_list->next;
|
||||
free(main_item_list_prev);
|
||||
}
|
||||
|
||||
// Free multidimensionable array: coll_bit_range[COLLECTION_INDEX][REPORT_ID][INPUT/OUTPUT/FEATURE]
|
||||
// Free multidimensionable array: coll_child_order[COLLECTION_INDEX][DIRECT_CHILD_INDEX]
|
||||
for (USHORT collection_node_idx = 0; collection_node_idx < pp_data->NumberLinkCollectionNodes; collection_node_idx++) {
|
||||
for (int reportid_idx = 0; reportid_idx < 256; reportid_idx++) {
|
||||
for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
|
||||
free(coll_bit_range[collection_node_idx][reportid_idx][rt_idx]);
|
||||
}
|
||||
free(coll_bit_range[collection_node_idx][reportid_idx]);
|
||||
}
|
||||
free(coll_bit_range[collection_node_idx]);
|
||||
if (coll_number_of_direct_childs[collection_node_idx] != 0) free(coll_child_order[collection_node_idx]);
|
||||
}
|
||||
free(coll_bit_range);
|
||||
free(coll_child_order);
|
||||
|
||||
// Free one dimensional arrays
|
||||
free(coll_begin_lookup);
|
||||
free(coll_end_lookup);
|
||||
free(coll_levels);
|
||||
free(coll_number_of_direct_childs);
|
||||
|
||||
return (int) rpt_desc.byte_idx;
|
||||
}
|
|
@ -0,0 +1,238 @@
|
|||
/*******************************************************
|
||||
HIDAPI - Multi-Platform library for
|
||||
communication with HID devices.
|
||||
|
||||
libusb/hidapi Team
|
||||
|
||||
Copyright 2022, 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 .
|
||||
********************************************************/
|
||||
#ifndef HIDAPI_DESCRIPTOR_RECONSTRUCT_H__
|
||||
#define HIDAPI_DESCRIPTOR_RECONSTRUCT_H__
|
||||
|
||||
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
|
||||
/* Do not warn about wcsncpy usage.
|
||||
https://docs.microsoft.com/cpp/c-runtime-library/security-features-in-the-crt */
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include "hidapi_winapi.h"
|
||||
|
||||
#if _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4200)
|
||||
#pragma warning(disable: 4201)
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "hidapi_hidsdi.h"
|
||||
|
||||
#define NUM_OF_HIDP_REPORT_TYPES 3
|
||||
|
||||
typedef enum rd_items_ {
|
||||
rd_main_input = 0x80, /* 1000 00 nn */
|
||||
rd_main_output = 0x90, /* 1001 00 nn */
|
||||
rd_main_feature = 0xB0, /* 1011 00 nn */
|
||||
rd_main_collection = 0xA0, /* 1010 00 nn */
|
||||
rd_main_collection_end = 0xC0, /* 1100 00 nn */
|
||||
rd_global_usage_page = 0x04, /* 0000 01 nn */
|
||||
rd_global_logical_minimum = 0x14, /* 0001 01 nn */
|
||||
rd_global_logical_maximum = 0x24, /* 0010 01 nn */
|
||||
rd_global_physical_minimum = 0x34, /* 0011 01 nn */
|
||||
rd_global_physical_maximum = 0x44, /* 0100 01 nn */
|
||||
rd_global_unit_exponent = 0x54, /* 0101 01 nn */
|
||||
rd_global_unit = 0x64, /* 0110 01 nn */
|
||||
rd_global_report_size = 0x74, /* 0111 01 nn */
|
||||
rd_global_report_id = 0x84, /* 1000 01 nn */
|
||||
rd_global_report_count = 0x94, /* 1001 01 nn */
|
||||
rd_global_push = 0xA4, /* 1010 01 nn */
|
||||
rd_global_pop = 0xB4, /* 1011 01 nn */
|
||||
rd_local_usage = 0x08, /* 0000 10 nn */
|
||||
rd_local_usage_minimum = 0x18, /* 0001 10 nn */
|
||||
rd_local_usage_maximum = 0x28, /* 0010 10 nn */
|
||||
rd_local_designator_index = 0x38, /* 0011 10 nn */
|
||||
rd_local_designator_minimum = 0x48, /* 0100 10 nn */
|
||||
rd_local_designator_maximum = 0x58, /* 0101 10 nn */
|
||||
rd_local_string = 0x78, /* 0111 10 nn */
|
||||
rd_local_string_minimum = 0x88, /* 1000 10 nn */
|
||||
rd_local_string_maximum = 0x98, /* 1001 10 nn */
|
||||
rd_local_delimiter = 0xA8 /* 1010 10 nn */
|
||||
} rd_items;
|
||||
|
||||
typedef enum rd_main_items_ {
|
||||
rd_input = HidP_Input,
|
||||
rd_output = HidP_Output,
|
||||
rd_feature = HidP_Feature,
|
||||
rd_collection,
|
||||
rd_collection_end,
|
||||
rd_delimiter_open,
|
||||
rd_delimiter_usage,
|
||||
rd_delimiter_close,
|
||||
} rd_main_items;
|
||||
|
||||
typedef struct rd_bit_range_ {
|
||||
int FirstBit;
|
||||
int LastBit;
|
||||
} rd_bit_range;
|
||||
|
||||
typedef enum rd_item_node_type_ {
|
||||
rd_item_node_cap,
|
||||
rd_item_node_padding,
|
||||
rd_item_node_collection,
|
||||
} rd_node_type;
|
||||
|
||||
struct rd_main_item_node {
|
||||
int FirstBit; /* Position of first bit in report (counting from 0) */
|
||||
int LastBit; /* Position of last bit in report (counting from 0) */
|
||||
rd_node_type TypeOfNode; /* Information if caps index refers to the array of button caps, value caps,
|
||||
or if the node is just a padding element to fill unused bit positions.
|
||||
The node can also be a collection node without any bits in the report. */
|
||||
int CapsIndex; /* Index in the array of caps */
|
||||
int CollectionIndex; /* Index in the array of link collections */
|
||||
rd_main_items MainItemType; /* Input, Output, Feature, Collection or Collection End */
|
||||
unsigned char ReportID;
|
||||
struct rd_main_item_node* next;
|
||||
};
|
||||
|
||||
typedef struct hid_pp_caps_info_ {
|
||||
USHORT FirstCap;
|
||||
USHORT NumberOfCaps; // Includes empty caps after LastCap
|
||||
USHORT LastCap;
|
||||
USHORT ReportByteLength;
|
||||
} hid_pp_caps_info, *phid_pp_caps_info;
|
||||
|
||||
typedef struct hid_pp_link_collection_node_ {
|
||||
USAGE LinkUsage;
|
||||
USAGE LinkUsagePage;
|
||||
USHORT Parent;
|
||||
USHORT NumberOfChildren;
|
||||
USHORT NextSibling;
|
||||
USHORT FirstChild;
|
||||
ULONG CollectionType : 8;
|
||||
ULONG IsAlias : 1;
|
||||
ULONG Reserved : 23;
|
||||
// Same as the public API structure HIDP_LINK_COLLECTION_NODE, but without PVOID UserContext at the end
|
||||
} hid_pp_link_collection_node, *phid_pp_link_collection_node;
|
||||
|
||||
typedef struct hidp_unknown_token_ {
|
||||
UCHAR Token; /* Specifies the one-byte prefix of a global item. */
|
||||
UCHAR Reserved[3];
|
||||
ULONG BitField; /* Specifies the data part of the global item. */
|
||||
} hidp_unknown_token, * phidp_unknown_token;
|
||||
|
||||
typedef struct hid_pp_cap_ {
|
||||
USAGE UsagePage;
|
||||
UCHAR ReportID;
|
||||
UCHAR BitPosition;
|
||||
USHORT ReportSize; // WIN32 term for this is BitSize
|
||||
USHORT ReportCount;
|
||||
USHORT BytePosition;
|
||||
USHORT BitCount;
|
||||
ULONG BitField;
|
||||
USHORT NextBytePosition;
|
||||
USHORT LinkCollection;
|
||||
USAGE LinkUsagePage;
|
||||
USAGE LinkUsage;
|
||||
|
||||
// Start of 8 Flags in one byte
|
||||
BOOLEAN IsMultipleItemsForArray:1;
|
||||
|
||||
BOOLEAN IsPadding:1;
|
||||
BOOLEAN IsButtonCap:1;
|
||||
BOOLEAN IsAbsolute:1;
|
||||
BOOLEAN IsRange:1;
|
||||
BOOLEAN IsAlias:1; // IsAlias is set to TRUE in the first n-1 capability structures added to the capability array. IsAlias set to FALSE in the nth capability structure.
|
||||
BOOLEAN IsStringRange:1;
|
||||
BOOLEAN IsDesignatorRange:1;
|
||||
// End of 8 Flags in one byte
|
||||
BOOLEAN Reserved1[3];
|
||||
|
||||
hidp_unknown_token UnknownTokens[4]; // 4 x 8 Byte
|
||||
|
||||
union {
|
||||
struct {
|
||||
USAGE UsageMin;
|
||||
USAGE UsageMax;
|
||||
USHORT StringMin;
|
||||
USHORT StringMax;
|
||||
USHORT DesignatorMin;
|
||||
USHORT DesignatorMax;
|
||||
USHORT DataIndexMin;
|
||||
USHORT DataIndexMax;
|
||||
} Range;
|
||||
struct {
|
||||
USAGE Usage;
|
||||
USAGE Reserved1;
|
||||
USHORT StringIndex;
|
||||
USHORT Reserved2;
|
||||
USHORT DesignatorIndex;
|
||||
USHORT Reserved3;
|
||||
USHORT DataIndex;
|
||||
USHORT Reserved4;
|
||||
} NotRange;
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
LONG LogicalMin;
|
||||
LONG LogicalMax;
|
||||
} Button;
|
||||
struct {
|
||||
BOOLEAN HasNull;
|
||||
UCHAR Reserved4[3];
|
||||
LONG LogicalMin;
|
||||
LONG LogicalMax;
|
||||
LONG PhysicalMin;
|
||||
LONG PhysicalMax;
|
||||
} NotButton;
|
||||
};
|
||||
ULONG Units;
|
||||
ULONG UnitsExp;
|
||||
|
||||
} hid_pp_cap, *phid_pp_cap;
|
||||
|
||||
typedef struct hidp_preparsed_data_ {
|
||||
UCHAR MagicKey[8];
|
||||
USAGE Usage;
|
||||
USAGE UsagePage;
|
||||
USHORT Reserved[2];
|
||||
|
||||
// CAPS structure for Input, Output and Feature
|
||||
hid_pp_caps_info caps_info[3];
|
||||
|
||||
USHORT FirstByteOfLinkCollectionArray;
|
||||
USHORT NumberLinkCollectionNodes;
|
||||
|
||||
#if defined(__MINGW32__) || defined(__CYGWIN__)
|
||||
// MINGW fails with: Flexible array member in union not supported
|
||||
// Solution: https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
|
||||
union {
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
hid_pp_cap caps[0];
|
||||
hid_pp_link_collection_node LinkCollectionArray[0];
|
||||
#pragma GCC diagnostic pop
|
||||
};
|
||||
#else
|
||||
union {
|
||||
hid_pp_cap caps[];
|
||||
hid_pp_link_collection_node LinkCollectionArray[];
|
||||
};
|
||||
#endif
|
||||
|
||||
} hidp_preparsed_data;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -29,6 +29,13 @@
|
|||
/* This part of the header mimics hidpi.h,
|
||||
but only what is used by HIDAPI */
|
||||
|
||||
typedef enum _HIDP_REPORT_TYPE
|
||||
{
|
||||
HidP_Input,
|
||||
HidP_Output,
|
||||
HidP_Feature
|
||||
} HIDP_REPORT_TYPE;
|
||||
|
||||
typedef struct _HIDP_PREPARSED_DATA * PHIDP_PREPARSED_DATA;
|
||||
|
||||
typedef struct _HIDP_CAPS
|
||||
|
|
|
@ -40,6 +40,8 @@ typedef struct _HIDD_ATTRIBUTES{
|
|||
USHORT VersionNumber;
|
||||
} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES;
|
||||
|
||||
typedef struct _HIDP_PREPARSED_DATA * PHIDP_PREPARSED_DATA;
|
||||
|
||||
typedef void (__stdcall *HidD_GetHidGuid_)(LPGUID hid_guid);
|
||||
typedef BOOLEAN (__stdcall *HidD_GetAttributes_)(HANDLE device, PHIDD_ATTRIBUTES attrib);
|
||||
typedef BOOLEAN (__stdcall *HidD_GetSerialNumberString_)(HANDLE device, PVOID buffer, ULONG buffer_len);
|
||||
|
@ -52,7 +54,6 @@ typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE handle, ULONG string_
|
|||
typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE handle, PHIDP_PREPARSED_DATA *preparsed_data);
|
||||
typedef BOOLEAN (__stdcall *HidD_FreePreparsedData_)(PHIDP_PREPARSED_DATA preparsed_data);
|
||||
typedef BOOLEAN (__stdcall *HidD_SetNumInputBuffers_)(HANDLE handle, ULONG number_buffers);
|
||||
typedef BOOLEAN (__stdcall *HidD_SetOutputReport_)(HANDLE handle, PVOID buffer, ULONG buffer_len);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*******************************************************
|
||||
HIDAPI - Multi-Platform library for
|
||||
communication with HID devices.
|
||||
|
||||
libusb/hidapi Team
|
||||
|
||||
Copyright 2022, 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.12.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
|
||||
*/
|
||||
|
||||
#ifndef HIDAPI_WINAPI_H__
|
||||
#define HIDAPI_WINAPI_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <guiddef.h>
|
||||
|
||||
#include "hidapi.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Get the container ID for a HID device.
|
||||
|
||||
Since version 0.12.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
|
||||
|
||||
This function returns the `DEVPKEY_Device_ContainerId` property of
|
||||
the given device. This can be used to correlate different
|
||||
interfaces/ports on the same hardware device.
|
||||
|
||||
@ingroup API
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param guid The device's container ID on return.
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_winapi_get_container_id(hid_device *dev, GUID *container_id);
|
||||
|
||||
/**
|
||||
* @brief Reconstructs a HID Report Descriptor from a Win32 HIDP_PREPARSED_DATA structure.
|
||||
* This reconstructed report descriptor is logical identical to the real report descriptor,
|
||||
* but not byte wise identical.
|
||||
*
|
||||
* @param[in] hidp_preparsed_data Pointer to the HIDP_PREPARSED_DATA to read, i.e.: the value of PHIDP_PREPARSED_DATA,
|
||||
* as returned by HidD_GetPreparsedData WinAPI function.
|
||||
* @param buf Pointer to the buffer where the report descriptor should be stored.
|
||||
* @param[in] buf_size Size of the buffer. The recommended size for the buffer is @ref HID_API_MAX_REPORT_DESCRIPTOR_SIZE bytes.
|
||||
*
|
||||
* @return Returns size of reconstructed report descriptor if successful, -1 for error.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_winapi_descriptor_reconstruct_pp_data(void *hidp_preparsed_data, unsigned char *buf, size_t buf_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,196 +1,196 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="hidtest"
|
||||
ProjectGUID="{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}"
|
||||
RootNamespace="hidtest"
|
||||
TargetFrameworkVersion="196613"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\hidapi"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="hidapi.lib"
|
||||
AdditionalLibraryDirectories="..\windows\Debug"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
Description="Copying hidapi.dll to the local direcotry."
|
||||
CommandLine=""
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
AdditionalIncludeDirectories="..\hidapi"
|
||||
RuntimeLibrary="2"
|
||||
EnableFunctionLevelLinking="true"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="hidapi.lib"
|
||||
AdditionalLibraryDirectories="..\windows\Release"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
Description="Copying hidapi.dll to the local direcotry."
|
||||
CommandLine=""
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\hidtest\hidtest.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="hidtest"
|
||||
ProjectGUID="{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}"
|
||||
RootNamespace="hidtest"
|
||||
TargetFrameworkVersion="196613"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\hidapi;."
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="hidapi.lib"
|
||||
AdditionalLibraryDirectories="..\windows\Debug"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
Description="Copying hidapi.dll to the local directory."
|
||||
CommandLine=""
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
AdditionalIncludeDirectories="..\hidapi;."
|
||||
RuntimeLibrary="2"
|
||||
EnableFunctionLevelLinking="true"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="hidapi.lib"
|
||||
AdditionalLibraryDirectories="..\windows\Release"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
Description="Copying hidapi.dll to the local directory."
|
||||
CommandLine=""
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\hidtest\test.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue